# TANRAIL ONE — Phase 3.2.4 Procurement Security

## 1. Business Unit Isolation
- **Purchase Orders** are rigorously isolated by `business_unit_id` using a Global Scope (`BusinessUnitScope`), identical to the `Order` model in Sales.
- Users operating under BU A can never retrieve, modify, or receive against a Purchase Order belonging to BU B.

## 2. Supplier Consistency
- Suppliers are scoped to the `Organization`.
- A Business Unit can only create a Purchase Order using a Supplier that belongs to the same Organization as the Business Unit. The `PurchaseService` validates this relationship.

## 3. Inventory Constraints
- Items added to a `PurchaseOrder` must strictly belong to the same `business_unit_id` as the Purchase Order's `branch`.
- When creating a `PurchaseReceipt`, the selected `inventory_location_id` MUST belong to a Branch within the SAME Business Unit.
- Negative quantities are strictly blocked at the Service layer.

## 4. Anti-Tampering (Immutability)
- **Mass Assignment:** Critical fields (`status`, `subtotal`, `tax_total`, `total`) are completely removed from the `$fillable` array on the `PurchaseOrder` model to prevent HTTP payload tampering.
- **Model Observers:**
  - `PurchaseOrderLine` prevents updates or deletion if the parent PO status is not `DRAFT` or `SUBMITTED`.
  - `PurchaseReceipt` and `PurchaseReceiptLine` are append-only. Deletion and modification are blocked in `booted()`.

## 5. Concurrency
- `PurchaseService::receiveGoods()` heavily relies on `lockForUpdate()` wrapped in `DB::transaction()`.
- If two users try to receive the same PO at exactly the same time, the locking mechanism prevents them from bypassing the over-receiving limit, ensuring mathematical integrity.
