# TANRAIL ONE — PHASE 5.1 PRE-IMPLEMENTATION AUDIT
## Stage 5.1 — Production Foundation & Bill of Materials (BOM)

---

### 1. Executive Summary

This Pre-Implementation Audit defines **Stage 5.1 — Production Foundation & Bill of Materials (BOM)** under **Phase 5.0 — Reusable Capabilities**.

The baseline starting state is **100% verified**:
- **247 / 247 tests passing**
- **498 assertions**
- **0 failures, 0 errors, 0 skipped**
- **Laravel Pint 100% clean**

Stage 5.1 introduces the reusable Bill of Materials (BOM) / Recipe foundation under `app/Domains/Modules/Production/`. A Bill of Materials represents the reusable formula/recipe defining the raw material components, quantities, and units required to produce a unit yield of a finished item.

---

### 2. Stage 5.1 Detailed Scope

1. **Database Schema**:
   - `bill_of_materials` table (`id`, `organization_id`, `business_unit_id`, `finished_item_id`, `name`, `code`, `yield_quantity`, `is_active`, `created_by`, `timestamps`).
   - `bill_of_materials_items` table (`id`, `bill_of_materials_id`, `ingredient_item_id`, `quantity`, `unit_id`, `scrap_percentage`, `timestamps`).
2. **Domain Entities & Scopes**:
   - `BillOfMaterials` model in `app/Domains/Modules/Production/Models/BillOfMaterials.php`.
   - `BillOfMaterialsItem` model in `app/Domains/Modules/Production/Models/BillOfMaterialsItem.php`.
   - `OrganizationScope` & `BusinessUnitScope` global scopes applied.
   - Cross-tenant validation: finished item and all ingredient items MUST belong to the same `organization_id` as the BOM.
3. **Service Layer**:
   - `BillOfMaterialsService` in `app/Domains/Modules/Production/Services/BillOfMaterialsService.php`.
   - Methods: `createBOM()`, `addItem()`, `removeItem()`, `toggleActive()`.
4. **Policy & Authorization**:
   - `BillOfMaterialsPolicy` in `app/Domains/Modules/Production/Policies/BillOfMaterialsPolicy.php` registered via `Gate::policy()`.
   - Policy checks `hasAccessToScope()` and denies cross-tenant or roleless manipulation.
5. **Automated Verification**:
   - `tests/Feature/Modules/Phase51BillOfMaterialsTest.php` suite testing creation, line management, cross-tenant component rejection, and policy authorization.

---

### 3. Architectural Placement

All Phase 5.1 code lives strictly within `app/Domains/Modules/Production/`:
- Models: `app/Domains/Modules/Production/Models/`
- Services: `app/Domains/Modules/Production/Services/`
- Policies: `app/Domains/Modules/Production/Policies/` with shims in `app/Policies/`
- Migration: `database/migrations/2026_09_05_000001_create_bill_of_materials_tables.php`

The Core domain (`app/Domains/Core/`) remains stable and untouched.

---

### 4. Database Schema Specification

```sql
CREATE TABLE bill_of_materials (
    id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    organization_id BIGINT UNSIGNED NOT NULL,
    business_unit_id BIGINT UNSIGNED NOT NULL,
    finished_item_id BIGINT UNSIGNED NOT NULL,
    name VARCHAR(255) NOT NULL,
    code VARCHAR(100) NOT NULL,
    yield_quantity DECIMAL(15, 4) NOT NULL DEFAULT 1.0000,
    is_active TINYINT(1) NOT NULL DEFAULT 1,
    created_by BIGINT UNSIGNED NULL,
    created_at TIMESTAMP NULL,
    updated_at TIMESTAMP NULL,
    FOREIGN KEY (organization_id) REFERENCES organizations(id),
    FOREIGN KEY (business_unit_id) REFERENCES business_units(id),
    FOREIGN KEY (finished_item_id) REFERENCES items(id),
    FOREIGN KEY (created_by) REFERENCES users(id),
    UNIQUE KEY bom_code_unique (organization_id, code)
);

CREATE TABLE bill_of_materials_items (
    id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    bill_of_materials_id BIGINT UNSIGNED NOT NULL,
    ingredient_item_id BIGINT UNSIGNED NOT NULL,
    quantity DECIMAL(15, 4) NOT NULL,
    unit_id BIGINT UNSIGNED NOT NULL,
    scrap_percentage DECIMAL(5, 2) NOT NULL DEFAULT 0.00,
    created_at TIMESTAMP NULL,
    updated_at TIMESTAMP NULL,
    FOREIGN KEY (bill_of_materials_id) REFERENCES bill_of_materials(id) ON DELETE CASCADE,
    FOREIGN KEY (ingredient_item_id) REFERENCES items(id),
    FOREIGN KEY (unit_id) REFERENCES units(id)
);
```

---

### 5. Security & Multi-Tenancy

- **Cross-Organization Protection**: Model observers and service methods throw `CrossOrganizationException` if an ingredient item or finished item belongs to a different Organization than the BOM.
- **Fail-Closed Authorization**: `BillOfMaterialsPolicy` returns `false` by default if user context is missing or if `hasAccessToScope()` fails.

---

### 6. Verification & Regression Strategy

- Old baseline: **247 tests, 498 assertions**
- New test suite: `tests/Feature/Modules/Phase51BillOfMaterialsTest.php`
- All tests must pass 100% green and code formatted via Laravel Pint.
