# 03 — Execution Layer

> Reality. Translates plans into actual recorded events. The gap between planned and actual = variances (file 04). Inherits all rules from `00`. Four sequential components.

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

---

## 3.1 Component: Production Order (PO)

**Purpose:** The internal contract authorizing production of a specific quantity. Everything after (issue, confirm, receipt) links to a specific order.

### Critical concept — Frozen Snapshot
On `Planned → Released`, the order snapshots the active BOM and Routing. Later master-data changes do NOT affect this order. Protects historical cost & audit trail.

### Production_Order entities
```
Production_Order_Header:
  - order_no (PK)
  - order_type ∈ { Standard, Rework, Repair }
  - product_id, quantity
  - production_type ∈ { MakeToStock, MakeToOrder, TollManufacturing }
  - material_ownership ∈ { Own, Customer }
  - start_date, finish_date
  - status ∈ { Planned, Released, InProcess, Completed, Closed }
  - bom_snapshot_id, routing_snapshot_id
  - tool_id                 (assigned mold/die)
  - source_orders []        (Pegging — which sales orders this serves)
  - wip_account

Order_Component:   (snapshot copy of BOM lines)
  - component_id, required_quantity, issued_quantity, reserved_quantity, operation_seq
  # required_quantity = bom_qty × order_qty × (1 + scrap%)

Order_Operation:   (snapshot copy of Routing operations)
  - operation_no, work_center_id, tool_id
  - planned_setup_time, planned_run_time
  - actual_setup_time, actual_run_time
  - status ∈ { Waiting, Ready, InProgress, Completed }   ← used by SFC (file 05)
  - actual_start_time, actual_end_time
  - confirmed_quantity, scrap_quantity
```

### Status state machine
```
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 knows its parent and children. Track delays 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
```
if 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 Component: Material Issue

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

### Entities
```
Material_Issue_Header:
  - issue_no, issue_date
  - issue_type ∈ { Manual, Backflush, AutoIssue }
  - issue_level ∈ { PerOrder, PerShift, PerOperation }
  - order_no, operation_no, issuer_id, warehouse_from
  - status ∈ { Draft, Posted, Reversed }

Material_Issue_Line:
  - material_code, quantity, batch_no/lot_no
  - cost_price (per costing_method), total_cost, bin_location
  - ownership ∈ { 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 Released/InProcess; available ≥ qty; material 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
```
if material.ownership == Customer:
  issue from separate customer (consignment) stock, NOT own stock
  accounting differs: no "Credit Raw Materials" at your cost (not your asset)
  record a "customer material consumption" movement for tracking only
```

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

### Melamine test case
```
Shift-level manual issue of powder: worker draws 16kg; produces 300 dishes.
Theoretical = 300 × 0.15 × 1.03 = 46.4kg... (per-shift reconciliation):
issued − (produced × BOM) = Material Usage Variance → surfaces powder waste
without per-piece tracking.
```

---

## 3.3 Component: Confirmation

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

### Entities
```
Confirmation_Header:
  - confirmation_no, order_no, operation_no
  - confirmation_type ∈ { Partial, Final, Reversal }
  - operator_id, work_center_id, shift, timestamp

Confirmation_Yield:   (GENERALIZED — a distribution, not a scalar)
  - grade_code        (A/B/C... or single grade for normal factories)
  - quantity
  - unit_sale_price   (for joint-products NRV allocation)

Confirmation_Detail:
  - scrap_quantity, rework_quantity
  - setup_time_actual, run_time_actual
  - labor_hours, machine_hours
  - reason_code       (for scrap/delay → Pareto analysis)
```

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

### Algorithm (with backflush & postings)
```
Confirmation(order, operation, results):
  validate: order InProcess; operation open
  # backflush if configured
  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
  if Final: close operation; if not last: mark next operation Ready (→ SFC)
```

### Joint-products cost allocation (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 method). Normal factories use a single grade → collapses to standard 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 (focus on the 20% of causes making 80% of scrap).

---

## 3.4 Component: Goods Receipt (GR)

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

### Entities
```
Goods_Receipt_Header:
  - gr_no, gr_date, order_no
  - receipt_type ∈ { Full, Partial }
  - warehouse_to, receiver_id
  - status ∈ { Draft, Posted, Reversed }

Goods_Receipt_Line:   (One-to-Many — a line per grade)
  - item_id, received_quantity, grade_code
  - batch_no/lot_no, bin_location
  - cost_per_unit (= allocated WIP / qty)
  - quality_status ∈ { 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 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 (Melamine)
```
One press order 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
```
if 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).
