/** * WPML compatibility functions * * @global array $duplicated_posts Array to store the posts being duplicated. * * @package Yoast\WP\Duplicate_Post * @since 3.2 */ add_action( 'admin_init', 'duplicate_post_wpml_init' ); /** * Add handlers for WPML compatibility. */ function duplicate_post_wpml_init() { if ( defined( 'ICL_SITEPRESS_VERSION' ) ) { add_action( 'dp_duplicate_page', 'duplicate_post_wpml_copy_translations', 10, 3 ); add_action( 'dp_duplicate_post', 'duplicate_post_wpml_copy_translations', 10, 3 ); add_action( 'shutdown', 'duplicate_wpml_string_packages', 11 ); } } global $duplicated_posts; // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals -- Reason: Renaming a global variable is a BC break. $duplicated_posts = []; /** * Copy post translations. * * @global SitePress $sitepress Instance of the Main WPML class. * @global array $duplicated_posts Array of duplicated posts. * * @param int $post_id ID of the copy. * @param WP_Post $post Original post object. * @param string $status Status of the new post. */ function duplicate_post_wpml_copy_translations( $post_id, $post, $status = '' ) { global $sitepress; global $duplicated_posts; remove_action( 'dp_duplicate_page', 'duplicate_post_wpml_copy_translations', 10 ); remove_action( 'dp_duplicate_post', 'duplicate_post_wpml_copy_translations', 10 ); $current_language = $sitepress->get_current_language(); $trid = $sitepress->get_element_trid( $post->ID ); if ( ! empty( $trid ) ) { $translations = $sitepress->get_element_translations( $trid ); $new_trid = $sitepress->get_element_trid( $post_id ); foreach ( $translations as $code => $details ) { if ( $code !== $current_language ) { if ( $details->element_id ) { $translation = get_post( $details->element_id ); if ( ! $translation ) { continue; } $new_post_id = duplicate_post_create_duplicate( $translation, $status ); if ( ! is_wp_error( $new_post_id ) ) { $sitepress->set_element_language_details( $new_post_id, 'post_' . $translation->post_type, $new_trid, $code, $current_language ); } } } } // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals -- Reason: see above. $duplicated_posts[ $post->ID ] = $post_id; } } /** * Duplicate string packages. * * @global array() $duplicated_posts Array of duplicated posts. */ function duplicate_wpml_string_packages() { // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals -- Reason: renaming the function would be a BC-break. global $duplicated_posts; foreach ( $duplicated_posts as $original_post_id => $duplicate_post_id ) { // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals -- Reason: using WPML native filter. $original_string_packages = apply_filters( 'wpml_st_get_post_string_packages', false, $original_post_id ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals -- Reason: using WPML native filter. $new_string_packages = apply_filters( 'wpml_st_get_post_string_packages', false, $duplicate_post_id ); if ( is_array( $original_string_packages ) ) { foreach ( $original_string_packages as $original_string_package ) { $translated_original_strings = $original_string_package->get_translated_strings( [] ); foreach ( $new_string_packages as $new_string_package ) { $cache = new WPML_WP_Cache( 'WPML_Package' ); $cache->flush_group_cache(); $new_strings = $new_string_package->get_package_strings(); foreach ( $new_strings as $new_string ) { if ( isset( $translated_original_strings[ $new_string->name ] ) ) { foreach ( $translated_original_strings[ $new_string->name ] as $language => $translated_string ) { do_action( // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals -- Reason: using WPML native filter. 'wpml_add_string_translation', $new_string->id, $language, $translated_string['value'], $translated_string['status'] ); } } } } } } } } neo4j yaml – Raqqa

neo4j yaml

openapi: 3.1.0
info:
  title: Management Accounting KPI + RCA Core API
  version: 0.1.0
  description: >
    Core contract for management accounting KPIs with month-over-month (MoM)
    deltas and hypothesis-ranked root-cause comments across Material, Process,
    and Skill. This spec intentionally focuses on user-visible outputs and
    stable domain semantics. Infrastructure and Cypher details are out of scope.

servers:
  - url: /api

tags:
  - name: Health
  - name: KPI
  - name: RCA
  - name: Dictionary
  - name: Status

# ------------------------------------------------------------
# Extension blocks to keep the whole design consistent
# ------------------------------------------------------------

x-scope:
  concept: "KPI calculation + MoM + hypothesis-ranked RCA comments"
  out_of_scope:
    - "Full accounting valuation reproduction"
    - "Enterprise-wide KPI coverage"
    - "Auto-human evaluation decisions"
    - "Complex ML scoring (PoC uses rules/thresholds)"

x-phases:
  - id: P0
    name: Docker bootstrap
    goals:
      - "Run Odoo + Postgres + Neo4j + API container in one network"
      - "Verify base connectivity"
  - id: P1
    name: Ontology minimal set
    goals:
      - "Fix KPI hierarchy and dependency semantics"
      - "Define enterprise-diff domains (org/step/skill/material/baselines)"
  - id: P2
    name: Data minimum requirements
    goals:
      - "Decide minimal Odoo sources per KPI"
      - "Fix period granularity (monthly)"
  - id: P3
    name: Minimal ETL
    goals:
      - "Load dictionaries + relations first"
      - "Load thin monthly aggregates"
  - id: P4
    name: KPI compute
    goals:
      - "Compute numeric KPIs reproducibly"
      - "Persist results (DB or Neo4j)"
  - id: P5
    name: Hypothesis ranking (rule-based)
    goals:
      - "Rank material/process/skill hypotheses"
      - "Generate MoM reason comments"
  - id: P6
    name: API visibility
    goals:
      - "Expose REST with Swagger (/docs)"
      - "Optionally expose GraphQL with GraphiQL"

x-ontology:
  # The ontology here is expressed as a pragmatic domain dictionary.
  # This is not a formal OWL spec; it is a product-facing semantic contract.
  entities:
    - name: KPI
      role: "Symptom/Outcome metrics and derived diagnosis anchors"
    - name: Component
      role: "Cost/Value structure elements composing KPI meaning"
    - name: Driver
      role: "Root-cause drivers grouped into Material, Process, Skill"
    - name: OrgUnit
      role: "Enterprise hierarchy units used for scope and allocation"
    - name: CostCenter
      role: "Accounting/controlling unit for cost attribution"
    - name: Step
      role: "Process/work step in manufacturing or service flow"
    - name: Skill
      role: "Capability required to execute Steps with quality/efficiency"
    - name: Material
      role: "Purchased/consumed input affecting cost and yield"

  relations:
    - "KPI USES Component"
    - "Component DECOMPOSES_TO Component"
    - "Component AFFECTED_BY Driver"
    - "Step USES_MATERIAL Material"
    - "Step REQUIRES_SKILL Skill"
    - "OrgUnit/Role OWNS Step (enterprise-specific)"
    - "CostCenter ROLLS_UP CostCenter (hierarchical allocation support)"

  hypothesis_categories:
    - MATERIAL
    - PROCESS
    - SKILL

x-kpi-hierarchy:
  # PoC minimal set. These codes should match DB seeds.
  symptom_kpis:
    - code: GM_RATE
      name: Gross Margin Rate
      formula_hint: "(Sales - COGS) / Sales"
    - code: COGS_RATE
      name: COGS Rate
      formula_hint: "COGS / Sales"
    - code: INV_TURN
      name: Inventory Turnover
      formula_hint: "COGS / AvgInventory"
    - code: INV_AGING
      name: Inventory Aging
      formula_hint: "Bucketized stock value/qty by age"

  cause_split_kpis:
    material:
      - code: MAT_RATE
        name: Material Cost Rate
      - code: PP_INDEX_MOM
        name: Purchase Price Index (MoM)
      - code: SCRAP_RATE
        name: Scrap Rate
    process:
      - code: PROC_RATE
        name: Process Cost Rate
      - code: LAB_EFF
        name: Labor Efficiency (Std vs Actual)
      - code: REWORK_RATE
        name: Rework Rate
      - code: DEFECT_RATE
        name: Defect Rate / FPY

x-enterprise-diff:
  # What customers must configure per company.
  dictionaries:
    - OrgUnit
    - CostCenter
    - Step
    - Skill
    - Material
  baselines:
    - StandardLaborHours
    - StandardMaterialUsage
  mappings:
    - "Odoo products -> Material"
    - "Odoo routings/workcenters -> Step (if available)"
    - "Org/Role -> Step ownership (optional for PoC)"

x-data-model:
  # PoC recommendation:
  # Create these tables in the same PostgreSQL instance used by Odoo,
  # but inside a dedicated schema (e.g., mgmt) to avoid collision.
  target:
    postgres:
      instance: "odoo_db"
      schema_recommended: "mgmt"
      isolation_policy:
        - "Do not modify Odoo core tables"
        - "Read-only access to Odoo schemas"
        - "Write only to mgmt schema"

  tables:
    - name: mgmt.kpi_def
      kind: "model"
      purpose: "KPI dictionary and hierarchy anchors"
      key:
        - kpi_code
      columns:
        - kpi_code
        - name
        - category  # SYMPTOM|MATERIAL|PROCESS|SKILL
        - unit
        - formula_hint
        - is_active
        - created_at
        - updated_at

    - name: mgmt.component_def
      kind: "model"
      purpose: "Component dictionary for cost/value decomposition"
      key:
        - component_code
      columns:
        - component_code
        - name
        - parent_component_code  # optional for tree
        - created_at
        - updated_at

    - name: mgmt.kpi_component_map
      kind: "relation"
      purpose: "KPI USES Component"
      key:
        - kpi_code
        - component_code
      columns:
        - kpi_code
        - component_code
        - weight_hint  # optional

    - name: mgmt.driver_def
      kind: "model"
      purpose: "Drivers for RCA scoring grouped by hypothesis category"
      key:
        - driver_code
      columns:
        - driver_code
        - name
        - hypothesis_category  # MATERIAL|PROCESS|SKILL
        - created_at
        - updated_at

    - name: mgmt.step_def
      kind: "dictionary"
      purpose: "Enterprise-specific process steps"
      key:
        - step_code
      columns:
        - step_code
        - name
        - org_key  # optional
        - created_at
        - updated_at

    - name: mgmt.skill_def
      kind: "dictionary"
      purpose: "Enterprise-specific skills"
      key:
        - skill_code
      columns:
        - skill_code
        - name
        - created_at
        - updated_at

    - name: mgmt.material_def
      kind: "dictionary"
      purpose: "Enterprise-specific material catalog (mapped from Odoo products)"
      key:
        - material_code
      columns:
        - material_code
        - name
        - odoo_product_id  # optional linkage
        - created_at
        - updated_at

    - name: mgmt.step_skill_map
      kind: "relation"
      purpose: "Step REQUIRES Skill"
      key:
        - step_code
        - skill_code
      columns:
        - step_code
        - skill_code
        - required_level_hint

    - name: mgmt.step_material_map
      kind: "relation"
      purpose: "Step USES Material"
      key:
        - step_code
        - material_code
      columns:
        - step_code
        - material_code
        - usage_weight_hint

    - name: mgmt.period_kpi_value
      kind: "fact"
      purpose: "Monthly KPI values by scope"
      key:
        - period
        - kpi_code
        - scope_type
        - scope_key
      columns:
        - period   # YYYY-MM
        - kpi_code
        - scope_type  # COMPANY|ORG|COSTCENTER|STEP|MATERIAL|SKILL
        - scope_key
        - value
        - currency
        - created_at

    - name: mgmt.period_kpi_mom
      kind: "fact"
      purpose: "MoM deltas and simple derived stats"
      key:
        - period
        - kpi_code
        - scope_type
        - scope_key
      columns:
        - period
        - kpi_code
        - scope_type
        - scope_key
        - value_current
        - value_prev
        - delta_abs
        - delta_pct
        - created_at

    - name: mgmt.period_rca_result
      kind: "fact"
      purpose: "Hypothesis-ranked RCA outputs used for comments"
      key:
        - period
        - kpi_code
        - scope_type
        - scope_key
      columns:
        - period
        - kpi_code
        - scope_type
        - scope_key
        - top_hypothesis  # MATERIAL|PROCESS|SKILL
        - hypothesis_scores_json
        - evidence_json  # top materials/steps/skills
        - comment_text
        - created_at

# ------------------------------------------------------------
# Paths (REST)
# ------------------------------------------------------------

paths:
  /health:
    get:
      tags: [Health]
      summary: Health check
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  status: { type: string }

  /status/summary:
    get:
      tags: [Status]
      summary: Summary of latest computed periods
      responses:
        "200":
          description: Summary
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/StatusSummary"

  /kpis:
    get:
      tags: [KPI]
      summary: List KPI definitions (hierarchy-aware)
      parameters:
        - $ref: "#/components/parameters/activeOnly"
      responses:
        "200":
          description: KPI definitions
          content:
            application/json:
              schema:
                type: object
                properties:
                  items:
                    type: array
                    items: { $ref: "#/components/schemas/KpiDef" }

  /kpis/values:
    get:
      tags: [KPI]
      summary: Get KPI values for a period and scope
      parameters:
        - $ref: "#/components/parameters/period"
        - $ref: "#/components/parameters/scopeType"
        - $ref: "#/components/parameters/scopeKey"
      responses:
        "200":
          description: KPI values
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PeriodKpiValueList"

  /kpis/mom:
    get:
      tags: [KPI]
      summary: Get month-over-month KPI deltas
      parameters:
        - $ref: "#/components/parameters/period"
        - $ref: "#/components/parameters/scopeType"
        - $ref: "#/components/parameters/scopeKey"
      responses:
        "200":
          description: MoM results
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PeriodKpiMoMList"

  /rca:
    get:
      tags: [RCA]
      summary: Get hypothesis-ranked RCA results with comment
      parameters:
        - $ref: "#/components/parameters/period"
        - $ref: "#/components/parameters/kpiCode"
        - $ref: "#/components/parameters/scopeType"
        - $ref: "#/components/parameters/scopeKey"
      responses:
        "200":
          description: RCA result
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PeriodRcaResult"

  /dictionary/steps:
    get:
      tags: [Dictionary]
      summary: List enterprise steps
      responses:
        "200":
          description: Steps
          content:
            application/json:
              schema:
                type: object
                properties:
                  items:
                    type: array
                    items: { $ref: "#/components/schemas/StepDef" }

  /dictionary/skills:
    get:
      tags: [Dictionary]
      summary: List enterprise skills
      responses:
        "200":
          description: Skills
          content:
            application/json:
              schema:
                type: object
                properties:
                  items:
                    type: array
                    items: { $ref: "#/components/schemas/SkillDef" }

  /dictionary/materials:
    get:
      tags: [Dictionary]
      summary: List enterprise materials
      responses:
        "200":
          description: Materials
          content:
            application/json:
              schema:
                type: object
                properties:
                  items:
                    type: array
                    items: { $ref: "#/components/schemas/MaterialDef" }

# ------------------------------------------------------------
# Components
# ------------------------------------------------------------

components:
  parameters:
    period:
      name: period
      in: query
      required: true
      schema:
        type: string
        pattern: "^[0-9]{4}-[0-9]{2}$"
      description: "Target period in YYYY-MM"

    kpiCode:
      name: kpi_code
      in: query
      required: true
      schema:
        type: string

    scopeType:
      name: scope_type
      in: query
      required: false
      schema:
        type: string
        enum: [COMPANY, ORG, COSTCENTER, STEP, MATERIAL, SKILL]
      description: "Scope type for aggregation"

    scopeKey:
      name: scope_key
      in: query
      required: false
      schema:
        type: string
      description: "Scope key for aggregation (id/code)"

    activeOnly:
      name: active_only
      in: query
      required: false
      schema:
        type: boolean
        default: true

  schemas:
    StatusSummary:
      type: object
      properties:
        latest_period:
          type: string
        computed_kpis:
          type: integer
        computed_rca:
          type: integer

    KpiDef:
      type: object
      properties:
        kpi_code: { type: string }
        name: { type: string }
        category:
          type: string
          enum: [SYMPTOM, MATERIAL, PROCESS, SKILL]
        unit: { type: string }
        formula_hint: { type: string }
        is_active: { type: boolean }

    StepDef:
      type: object
      properties:
        step_code: { type: string }
        name: { type: string }
        org_key: { type: string }

    SkillDef:
      type: object
      properties:
        skill_code: { type: string }
        name: { type: string }

    MaterialDef:
      type: object
      properties:
        material_code: { type: string }
        name: { type: string }
        odoo_product_id: { type: integer }

    PeriodKpiValue:
      type: object
      properties:
        period: { type: string }
        kpi_code: { type: string }
        scope_type: { type: string }
        scope_key: { type: string }
        value: { type: number }
        currency: { type: string }

    PeriodKpiValueList:
      type: object
      properties:
        items:
          type: array
          items: { $ref: "#/components/schemas/PeriodKpiValue" }

    PeriodKpiMoM:
      type: object
      properties:
        period: { type: string }
        kpi_code: { type: string }
        scope_type: { type: string }
        scope_key: { type: string }
        value_current: { type: number }
        value_prev: { type: number }
        delta_abs: { type: number }
        delta_pct: { type: number }

    PeriodKpiMoMList:
      type: object
      properties:
        items:
          type: array
          items: { $ref: "#/components/schemas/PeriodKpiMoM" }

    HypothesisScore:
      type: object
      properties:
        hypothesis:
          type: string
          enum: [MATERIAL, PROCESS, SKILL]
        score:
          type: number
        evidence:
          type: array
          items:
            type: string

    PeriodRcaResult:
      type: object
      properties:
        period: { type: string }
        kpi_code: { type: string }
        scope_type: { type: string }
        scope_key: { type: string }
        top_hypothesis:
          type: string
          enum: [MATERIAL, PROCESS, SKILL]
        hypothesis_scores:
          type: array
          items: { $ref: "#/components/schemas/HypothesisScore" }
        top_materials:
          type: array
          items: { type: string }
        top_steps:
          type: array
          items: { type: string }
        top_skills:
          type: array
          items: { type: string }
        comment_text:
          type: string

Comments

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です