# 03 — Execution Layer (Technical Digest)

> Lossless digest of `manufacturing_spec/markdown/03_execution.md`. The Execution layer translates plans into actually-recorded events. The delta between planned and actual = variances (handled in file 04 / Costing). Inherits all cross-cutting rules from `00` (frozen snapshots, status state machines, many-to-many demand↔supply pegging, multi-level recursion, config-over-code, every actual event posts a GL entry, resource abstraction).

Four sequential components, executed in order:

```
Production Order → Material Issue → Confirmation → Goods Receipt
```

---

## 3.1 Production Order (PO)

**Purpose:** The internal contract authorizing production of a specific quantity. Every downstream document (Issue, Confirmation, Goods Receipt) links to a specific Production Order.

### Critical concept — Frozen Snapshot
On the transition `Planned → Released`, the order **snapshots** the currently-active BOM and Routing into order-local copies. Later changes to the master BOM/Routing do NOT affect this already-released order. This protects historical cost and the audit trail. The snapshot ids are stored on the header (`bom_snapshot_id`, `routing_snapshot_id`) and the snapshot rows live in `Order_Component` (BOM copy) and `Order_Operation` (Routing copy).

### Entity: `Production_Order_Header`
| Field | Type / Enum | Notes |
|---|---|---|
| `order_no` | PK | Document number |
| `order_type` | enum { Standard, Rework, Repair } | Type of production order |
| `product_id` | FK | What is being produced |
| `quantity` | number | Order quantity |
| `production_type` | enum { MakeToStock, MakeToOrder, TollManufacturing } | (master enum in 00 also lists AssembleToOrder) drives branching |
| `material_ownership` | enum { Own, Customer } | Customer = consignment / toll |
| `start_date` | date | Planned start |
| `finish_date` | date | Planned finish |
| `status` | enum { Planned, Released, InProcess, Completed, Closed } | State machine below |
| `bom_snapshot_id` | FK | Frozen BOM reference |
| `routing_snapshot_id` | FK | Frozen Routing reference |
| `tool_id` | FK | Assigned mold/die |
| `source_orders[]` | list | Pegging — which sales orders this order serves |
| `wip_account` | FK (GL) | WIP control account this order posts to |

### Entity: `Order_Component` (snapshot copy of BOM lines)
| Field | Notes |
|---|---|
| `component_id` | The material/component item |
| `required_quantity` | `= bom_qty × order_qty × (1 + scrap%)` |
| `issued_quantity` | Running total issued so far |
| `reserved_quantity` | Reserved at Release |
| `operation_seq` | Which operation consumes it |

**Formula:** `required_quantity = bom_qty × order_qty × (1 + scrap%)`

### Entity: `Order_Operation` (snapshot copy of Routing operations)
| Field | Notes |
|---|---|
| `operation_no` | Operation sequence id |
| `work_center_id` | Where it runs |
| `tool_id` | Tool/mold for this operation |
| `planned_setup_time`, `planned_run_time` | Standards |
| `actual_setup_time`, `actual_run_time` | Recorded actuals |
| `status` | enum { Waiting, Ready, InProgress, Completed } — consumed by SFC (file 05) |
| `actual_start_time`, `actual_end_time` | Timestamps |
| `confirmed_quantity`, `scrap_quantity` | Per-operation actuals |

### State machine (transitions + side-effects)
```
Planned → Released:    snapshot BOM + Routing; reserve materials; reserve tool & capacity
Released → InProcess:  first issue/confirmation begins; time tracking starts
InProcess → Completed: all operations done; confirmed_qty ≈ order_qty
Completed → Closed:    close WIP; compute final variances; block further postings
```

### Generic-design notes
- **Order network:** orders link parent ↔ child. A set-assembly order spawns piece-production orders, which spawn semi-finished (cutout) orders. Each order knows its parent and children. Delays are tracked by walking the network.
- **Confirmed quantity may be a grade distribution**, not a scalar (see 3.3). `confirmed_quantity` generalizes to `{ grade → qty }`.

### Toll branch (when `production_type == TollManufacturing`)
```
on Released:  do NOT reserve/purchase customer material; verify consignment sufficiency
on Closed:    output goes to CUSTOMER ownership (not own FG); cost = conversion only
```

---

## 3.2 Material Issue

**Purpose:** The first real accounting movement. Material moves from Raw Materials (RM) inventory to Work-In-Process (WIP).

### Entity: `Material_Issue_Header`
| Field | Type / Enum | Notes |
|---|---|---|
| `issue_no` | PK | |
| `issue_date` | date | |
| `issue_type` | enum { Manual, Backflush, AutoIssue } | Timing differs (below) |
| `issue_level` | enum { PerOrder, PerShift, PerOperation } | Granularity of issuing |
| `order_no` | FK | Owning production order |
| `operation_no` | FK | Owning operation (if per-operation) |
| `issuer_id` | FK | Who issued |
| `warehouse_from` | FK | Source warehouse |
| `status` | enum { Draft, Posted, Reversed } | State machine |

### Entity: `Material_Issue_Line`
| Field | Notes |
|---|---|
| `material_code` | Item |
| `quantity` | Issued qty |
| `batch_no` / `lot_no` | Lot tracking |
| `cost_price` | Per `costing_method` (FIFO/LIFO/Standard/Average) |
| `total_cost` | qty × cost_price |
| `bin_location` | Source bin |
| `ownership` | enum { Own, Customer } — consignment tracking |

### Issue types (timing differs)
```
Manual:    worker issues explicitly, when needed, actual qty. Most accurate, slowest.
Backflush: system auto-issues at confirmation; qty = produced × BOM. Diff → variance.
AutoIssue: all materials issued at Release, in one shot. Suits small orders.
```

### Algorithm
```
Material_Issue(target, material, qty):
  validate: order is Released/InProcess; available ≥ qty; material is in BOM snapshot
  cost_price = get_cost(material, costing_method)     # FIFO/LIFO/Standard/Average
  on_hand[material]  -= qty
  reserved[material]  -= qty
  WIP[order]         += qty × cost_price
  POST: Debit WIP  /  Credit Raw Materials   (qty × cost_price)
  order_component[material].issued += qty
```

### Toll branch (when `material.ownership == Customer`)
```
issue from separate customer (consignment) stock, NOT own stock
accounting differs: NO "Credit Raw Materials" at your cost (it is not your asset)
record a "customer material consumption" movement for tracking only
```

### Generic-design notes
- **`issue_level`** generalizes shift-level issuing: a worker draws a whole shift's material upfront; reconciliation at shift end produces the usage variance.
- Each BOM line chooses its own `issue_type` / `issue_level`: heavy/expensive → Manual; small → Backflush; negligible → treated as overhead, not issued at all.

### Melamine test case (shift-level manual issue)
```
Worker draws 16 kg powder; produces 300 dishes.
Theoretical = 300 × 0.15 × 1.03 = 46.4 kg ... (per-shift reconciliation):
Material Usage Variance = issued − (produced × BOM)  → surfaces powder waste
without per-piece tracking.
```
(Note: the 16 kg vs 46.4 kg figures are the spec's own illustrative numbers; the load-bearing point is the reconciliation formula, not the arithmetic.)

---

## 3.3 Confirmation

**Purpose:** Records that part of an order actually executed, **per operation**: how much was produced, labor/machine time used, scrap. The true source of "actuals" compared against standards.

### Entity: `Confirmation_Header`
| Field | Type / Enum | Notes |
|---|---|---|
| `confirmation_no` | PK | |
| `order_no`, `operation_no` | FK | What is being confirmed |
| `confirmation_type` | enum { Partial, Final, Reversal } | |
| `operator_id`, `work_center_id` | FK | |
| `shift` | value | Which shift |
| `timestamp` | datetime | |

### Entity: `Confirmation_Yield` (GENERALIZED — a distribution, not a scalar)
| Field | Notes |
|---|---|
| `grade_code` | A/B/C... or a single grade for normal factories |
| `quantity` | Qty at that grade |
| `unit_sale_price` | For joint-product NRV cost allocation |

### Entity: `Confirmation_Detail`
| Field | Notes |
|---|---|
| `scrap_quantity` | |
| `rework_quantity` | |
| `setup_time_actual`, `run_time_actual` | |
| `labor_hours`, `machine_hours` | |
| `reason_code` | for scrap/delay → Pareto analysis |

### Core rule (yield identity & KPIs)
```
Σ(grade quantities) + scrap = total_input
yield%      = Σgrades  / input
first_pass% = grade_A  / input     (key quality KPI)
```

### Algorithm (with backflush & GL postings)
```
Confirmation(order, operation, results):
  validate: order InProcess; operation open
  # backflush materials if configured on this operation
  if operation has backflush materials:
      consumed = total_input × BOM_qty ; auto Material_Issue
  # cost posting — labor depends on labor_calc
  labor_cost   = (labor_calc == Hourly) ? labor_hours × labor_rate
                                        : produced × piece_rate
  machine_cost = machine_hours × machine_rate
  overhead     = (labor_hours + machine_hours) × overhead_rate   # or qty × oh_rate
  POST:
    Debit  WIP                 (labor + machine + overhead)
    Credit Labor Applied       (labor_cost)
    Credit Machine Applied     (machine_cost)
    Credit Overhead Applied    (overhead)
  # scrap
  POST: Debit Scrap Expense / Credit WIP   (scrap × unit_cost)
  # advance the routing
  if Final: close operation; if not the last: mark next operation Ready  (→ SFC)
```

### Joint-products cost allocation (NRV method — at confirmation/receipt)
```
total_sale_value = Σ(grade.qty × grade.price)
for each grade:
  grade.allocated_cost = total_cost × (grade.qty × grade.price) / total_sale_value
  grade.unit_cost      = grade.allocated_cost / grade.qty
```
Higher-priced grade absorbs more cost (NRV). Normal factories use a single grade → this collapses to standard single-output behaviour.

### Generic-design notes
- **Three generalizations from Melamine:** (1) yield is a grade distribution; (2) labor may be piece-rate; (3) cost allocates across grades at confirmation.
- **`reason_code`** drives Pareto analysis of defects (the 20% of causes producing 80% of scrap).

---

## 3.4 Goods Receipt (GR)

**Purpose:** The last step — finished product enters inventory. Closes WIP, opens FG. Converts accumulated cost into ready-to-sell product cost.

### Entity: `Goods_Receipt_Header`
| Field | Type / Enum | Notes |
|---|---|---|
| `gr_no` | PK | |
| `gr_date` | date | |
| `order_no` | FK | |
| `receipt_type` | enum { Full, Partial } | |
| `warehouse_to` | FK | Destination FG warehouse |
| `receiver_id` | FK | |
| `status` | enum { Draft, Posted, Reversed } | |

### Entity: `Goods_Receipt_Line` (One-to-Many — a line per grade)
| Field | Notes |
|---|---|
| `item_id` | Finished item |
| `received_quantity` | |
| `grade_code` | Per-grade line |
| `batch_no` / `lot_no` | |
| `bin_location` | |
| `cost_per_unit` | `= allocated WIP / qty` |
| `quality_status` | enum { Released, OnHold, Rejected } |

### Algorithm
```
Goods_Receipt(order, received_qty):
  Total_WIP = Σ(material + labor + machine + overhead)
  # multi-grade: split into lines, each with allocated cost (see 3.3)
  for each grade line: FG_Inventory[item, grade] += qty  (at allocated unit cost)
  POST (standard costing):
    Debit  FG Inventory   (standard_cost × qty)
    Debit  Variance Acct  (difference)
    Credit WIP            (total_actual_cost)
  if Full: order → Completed
  if pegged to sales orders: allocate quantities to customers
  compute final variances; order → Closed
```

### Multi-grade receipt example (Melamine)
```
One press order of 100 dishes → 3 receipt lines + scrap:
  A: 70 @ 11.77 ,  B: 18 @ 7.06 ,  C: 7 @ 3.53 ,  scrap 5
POST:
  Debit FG-A 824 / FG-B 127 / FG-C 25 / Scrap 24 ; Credit WIP 1000
```

### Toll branch (when `production_type == TollManufacturing`)
```
output → CUSTOMER ownership (not own FG inventory)
revenue = conversion fee only:
  Debit Customer (receivable)  /  Credit Toll-service revenue
close conversion-WIP (labor + machine + overhead, NO material)
```

### Final variance gate
At Close, compute and decompose variances (price / usage / labor / overhead). This is the entry point to Costing (file 04).

---

## Enums introduced or used by this layer
| Enum | Values | Where |
|---|---|---|
| `order_type` | Standard, Rework, Repair | PO header |
| `production_type` | MakeToStock, MakeToOrder, TollManufacturing (00 adds AssembleToOrder) | PO header |
| `material_ownership` | Own, Customer | PO header, Issue line |
| `order_status` | Planned, Released, InProcess, Completed, Closed | PO header |
| `operation_status` | Waiting, Ready, InProgress, Completed | Order_Operation |
| `issue_type` | Manual, Backflush, AutoIssue | Issue header |
| `issue_level` | PerOrder, PerShift, PerOperation | Issue header |
| `issue/GR status` | Draft, Posted, Reversed | Issue & GR headers |
| `confirmation_type` | Partial, Final, Reversal | Confirmation header |
| `receipt_type` | Full, Partial | GR header |
| `quality_status` | Released, OnHold, Rejected | GR line |
| `costing_method` | Standard, Actual, Average, FIFO (00); 3.2 text also mentions LIFO/Standard | Issue costing |
| `labor_calc` | Hourly, PieceRate | Confirmation labor cost |

## GL postings introduced by this layer (every actual event posts)
1. **Material Issue:** Debit WIP / Credit Raw Materials (qty × cost_price). Toll/customer-owned: tracking movement only, no RM credit at own cost.
2. **Confirmation (conversion):** Debit WIP / Credit Labor Applied + Machine Applied + Overhead Applied.
3. **Confirmation (scrap):** Debit Scrap Expense / Credit WIP (scrap × unit_cost).
4. **Goods Receipt (standard costing):** Debit FG Inventory (std × qty) + Debit/Credit Variance Acct (diff) / Credit WIP (actual).
5. **Toll GR:** Debit Customer receivable / Credit Toll-service revenue; close conversion-WIP only.

---

## What this layer EXPECTS FROM THE HOST ERP (integration contract)
- **Inventory core:** on-hand & reserved quantities per item/warehouse/bin; decrement on issue, increment FG on receipt; lot/batch & bin tracking; reservation of materials at Release.
- **Costing/valuation service:** `get_cost(material, costing_method)` resolving FIFO/LIFO/Standard/Average unit costs (the layer does NOT compute inventory cost layers itself — it asks Inventory).
- **General Ledger:** ability to post arbitrary journal entries (WIP, Raw Materials, Labor/Machine/Overhead Applied, Scrap Expense, FG Inventory, Variance, Toll revenue/receivable). One JE per actual event.
- **Chart of accounts:** WIP control account (per order: `wip_account`), Raw Materials, FG Inventory, Labor/Machine/Overhead Applied, Scrap Expense, Variance accounts, Toll-service revenue.
- **Sales:** sales orders to peg against (`source_orders[]`), and allocation of received FG quantities back to those customer orders.
- **HR / labor rates:** `labor_rate`, `piece_rate` per operator/work center; `labor_hours` capture.
- **Work centers / resources & tools:** capacity & tool reservation at Release; work-center & tool master to reference.
- **Master Data (file 01):** active BOM and Routing to snapshot at Release; `scrap%`, `bom_qty`, overhead/machine rates.
- **SFC (file 05):** consumes `operation_status`; receives the "mark next operation Ready" signal on Final confirmation.
- **Costing (file 04):** receives the final variance decomposition at Close.
</content>
</invoke>
