# TANRAIL ONE — PHASE 5.2 PRE-IMPLEMENTATION AUDIT
## Stage 5.2 — Production Order & Inventory Assembly Engine

---

### 1. Executive Summary

This Pre-Implementation Audit defines the technical architecture for **Stage 5.2 — Production Order & Inventory Assembly Engine** under **Phase 5.0 — Reusable Capabilities**.

The current verified baseline is **100% green**:
- **257 / 257 tests passing**
- **519 assertions**
- **0 failures, 0 errors, 0 skipped**
- **Laravel Pint 100% clean**

Stage 5.2 builds the assembly and production order engine on top of the Phase 5.1 Bill of Materials (BOM) foundation. It converts raw materials into finished goods by creating production orders, snapshotting BOM requirements at confirmation time, validating stock availability, locking inventory rows during assembly, deducting raw materials, and receiving finished goods.

---

### 2. Inspection of Existing Architecture & Core Services

#### Inventory Engine (`app/Domains/Core/Services/InventoryService.php`)
- **Stock Movement Types**: `StockMovementType::OUT` (issue/consumption), `StockMovementType::IN` (receipt/production), `StockMovementType::TRANSFER`, `StockMovementType::ADJUSTMENT`.
- **Existing Methods to Reuse**:
  - `issueStock(InventoryLocation $location, Item $item, float\|string $quantity, ?Model $reference = null, ?string $notes = null, ?User $user = null): StockMovement`
  - `receiveStock(InventoryLocation $location, Item $item, float\|string $quantity, ?Model $reference = null, ?string $notes = null, ?User $user = null): StockMovement`
- **Core Modification Assessment**: `InventoryService` natively supports reference polymorphic association, atomic transactions, and stock movement logging. **`NO CORE MODIFICATION REQUIRED`**. `InventoryService` will be reused directly without altering Core logic.

#### Tenant Isolation & Security
- `OrganizationScope` and `BusinessUnitScope` apply globally to all production entities.
- `CrossOrganizationException` will be thrown if attempting cross-organization BOM selection, raw material deduction, or finished goods receipt.

---

### 3. Data Schema & BOM Snapshot Strategy

Stage 5.2 requires two new database tables:

1. **`production_orders`**:
   - `id`, `organization_id`, `business_unit_id`, `branch_id`, `bill_of_materials_id`, `finished_item_id`, `production_number`, `target_quantity`, `actual_quantity`, `status` (`DRAFT`, `CONFIRMED`, `IN_PROGRESS`, `COMPLETED`, `CANCELLED`), `source_location_id`, `destination_location_id`, `created_by`, `confirmed_by`, `completed_by`, `confirmed_at`, `completed_at`, `notes`, `timestamps`.
2. **`production_order_items` (BOM Component Snapshot)**:
   - `id`, `production_order_id`, `ingredient_item_id`, `required_quantity`, `actual_quantity`, `unit_id`, `scrap_percentage`, `timestamps`.

> [!IMPORTANT]
> **BOM Snapshot Invariant**: When a `ProductionOrder` transitions to `CONFIRMED`, the active BOM items are copied into `production_order_items` calculated for the order's `target_quantity`. Subsequent edits to the source `BillOfMaterials` will NEVER alter a confirmed `ProductionOrder`'s component snapshot.

---

### 4. Production Order State Machine

```text
DRAFT
  ↓ (confirmProductionOrder)
CONFIRMED (BOM component snapshot created)
  ↓ (startProduction)
IN_PROGRESS
  ↓ (completeProduction)
COMPLETED (Raw materials deducted, finished goods received, state locked)
```

- **Cancellation**: Orders in `DRAFT`, `CONFIRMED`, or `IN_PROGRESS` can be transitioned to `CANCELLED`.
- **Immutability Invariant**: Orders in `COMPLETED` or `CANCELLED` status cannot undergo further state transitions or property edits.
- **Physical Deletion**: Physical `delete()` operations on `COMPLETED` production orders are explicitly denied via `ProductionOrderPolicy`.

---

### 5. Concurrency & Pessimistic Row Locking

- **Row Locking**: During production completion (`completeProduction`), `ProductionOrder` and `StockBalance` records for source location ingredients are locked using pessimistic database locking (`lockForUpdate()`).
- **Race Condition Prevention**: If concurrent production orders request the same raw stock, the first transaction holds the lock until commitment; the second transaction evaluates the updated `StockBalance` post-commit and fails safely with an exception if stock is insufficient.

---

### 6. Atomic Transaction Boundary

The production completion process executes within a single `DB::transaction()`:
1. Lock `ProductionOrder` (`lockForUpdate()`).
2. Verify order status is `IN_PROGRESS` or `CONFIRMED`.
3. Lock all ingredient `StockBalance` records in `source_location_id`.
4. Validate sufficient stock for every snapshot component (`available >= required`).
5. Issue raw material stock (`InventoryService::issueStock()`) for each ingredient.
6. Receive finished goods stock (`InventoryService::receiveStock()`) into `destination_location_id`.
7. Update `ProductionOrder` status to `COMPLETED` and set completion metadata (`completed_at`, `completed_by`).
8. If ANY step fails, `DB::transaction()` automatically rolls back ALL stock movements and order state changes.

---

### 7. Security Policy & Authorization

- **`ProductionOrderPolicy`**: Enforces `hasAccessToScope(BusinessUnit::class, $buId)`.
- Enforces explicit checks for `viewAny`, `view`, `create`, `update`, `confirm`, `start`, `complete`, `cancel`, `delete`.
- Physical deletion of `COMPLETED` production orders is prohibited (`return false`).

---

### 8. Verification Strategy

- Existing baseline: **257 tests, 519 assertions**.
- New test suite: `tests/Feature/Modules/Phase52ProductionOrderTest.php`.
- Target: Complete lifecycle, BOM snapshot isolation, stock availability validation, stock movement logging, cross-tenant rejection, duplicate execution prevention, and policy enforcement.
- Code style formatting: 100% clean via Laravel Pint (`vendor/bin/pint --format agent`).
