# Asset & Inventory Management — WBS

**Status:** Execution breakdown for V1. Does not authorize code until [Section N](./ASSET_MANAGEMENT_IMPLEMENTATION_PLAN.md#n-approval-checkpoints) decisions and each phase STOP are accepted.  
**Source of truth (architecture):** [ASSET_MANAGEMENT_IMPLEMENTATION_PLAN.md](./ASSET_MANAGEMENT_IMPLEMENTATION_PLAN.md)  
**Schema DDL:** [ASSET_MANAGEMENT_DATABASE_SCHEMA.md](./ASSET_MANAGEMENT_DATABASE_SCHEMA.md)  
**Task cards:** [ASSET_MANAGEMENT_TASK_CARDS.md](./ASSET_MANAGEMENT_TASK_CARDS.md)  
**Task SQL seed:** [ASSET_MANAGEMENT_TASKS_INSERT.sql](./ASSET_MANAGEMENT_TASKS_INSERT.sql)  
**Created:** 27 Sep 2026

---

## Dependency map

```text
1.0 (governance)
  ↓
1.1 → 1.2 → 1.3 ─┬→ 1.5 (quantity-only sessions may start after 1.3)
                 └→ 1.4 → 1.5 (full verification with holder checks)
1.2 + 1.3 + 1.4 + 1.5 → 1.6
1.2 → 1.7 → 1.9
1.3 + 1.6.5 → 1.8 → 1.10
1.1 … 1.10 → 1.11 → 1.12

1.13 = out of V1 (do not schedule into 1.1–1.12)
```

**Hard rules**

- Phases 1.1–1.3 do **not** write `assets` or `employee_assets`.
- No dual writable asset registers. Bridge + freeze old writer happen in the same release (1.4).
- Verification never posts stock. Draft adjustments only (1.5); posting is 1.6.4.
- No new approval engine. Use platform `ApprovalGateway` + executors.

---

## 1  ERPFlow Asset & Inventory Management

### 1.0  Governance & Decisions

| ID | Work package |
|----|----------------|
| 1.0.1 | Phase 0 plan review & sign-off |
| 1.0.2 | Section N decisions (blockers before the named phase) |
| 1.0.3 | Phase STOP gate reviews (per phase) |
| 1.0.4 | Release & rollback coordination |
| 1.0.5 | Optional: permission matrix baseline (or register permissions per phase as below) |

#### 1.0.2 Section N decisions

| Decision | Needed before |
|----------|----------------|
| Legacy asset register (one-way bridge + freeze writer; reject dual writable) | 1.4 |
| Item master owner = Asset | 1.1 |
| Location grain (`asset_locations` under `work_locations`; no Configuration schema change) | 1.1 |
| Serial mandatory + exceptions list | 1.2 |
| Proxy handover acknowledgement | 1.4 |
| Adjustment approval default (company setting may leave approval off) | 1.6 |
| Temporary service provider table (Asset-owned, not global vendor) | 1.7 |
| Overlapping warranty allowed or not | 1.7 |
| Import template sign-off | 1.8 |
| No depreciation in Asset (Finance sign-off; outbox only) | 1.10 |
| Negative stock stays hard-blocked (no config flag in V1) | 1.3 STOP |

---

### 1.1  Phase 1 — Domain Foundation

| ID | Work package |
|----|----------------|
| 1.1.0 / AST-SCHEMA-MIG | **Full V1 schema migrations** (all Asset tables) — after 1.1.1 skeleton + SCHEMA-1 |
| 1.1.1 | Module skeleton (nwidart, `module.json`, `modules_statuses`, service provider bindings) |
| 1.1.2 | Permissions (`actions.php` asset section, sync) |
| 1.1.3 | Category (migration, model, repo, service, API) + tree cycle check |
| 1.1.4 | Unit of measure |
| 1.1.5 | Item + tracking mode (`SERIALIZED` \| `QUANTITY`; immutability once stock/instances exist) |
| 1.1.6 | Attribute definitions, options, item default values |
| 1.1.7 | Asset locations (FK `work_locations` / branches; floor / room / store tree) |
| 1.1.8 | Frontend master screens |
| 1.1.9 | Tests + STOP |

**Constraints:** No writes to Employee `assets` / `employee_assets`. Catalog and locations only.

**Schema rule:** Domain `CREATE TABLE` migrations are **only** in `AST-SCHEMA-MIG`. Later Phase 1–9 BE cards use existing tables (models/services/APIs only).

**STOP:** Confirm catalog shape and location grain before any instance or stock table.

---

### 1.2  Phase 2 — Serialized Registry & Tags

| ID | Work package |
|----|----------------|
| 1.2.1 | `serialized_assets` (code, serial, cost, location) |
| 1.2.2 | Status machine (non-assignment edges only) + condition |
| 1.2.3 | Instance attribute values |
| 1.2.4 | Tag token, tag events (issue / replace / void) |
| 1.2.5 | QR library selection + image endpoint |
| 1.2.6 | Label print (single + bulk) |
| 1.2.7 | Authenticated scan resolve (permission-based response) |
| 1.2.8 | Frontend asset list, detail, scan page |
| 1.2.9 | Tests + STOP |

**1.2.2 scope:** Assignment, transfer, dispose, and write-off edges are **deferred** to 1.4 / 1.6. Do not expose those APIs here.

**STOP:** Confirm status list and whether serial is mandatory (or exception list).

---

### 1.3  Phase 3 — Quantity Ledger

| ID | Work package |
|----|----------------|
| 1.3.1 | `inventory_transactions` (append-only, idempotency key) |
| 1.3.2 | `inventory_balances` projection (lock, negative block) |
| 1.3.3 | `asset_receipt_inbox` |
| 1.3.4 | Ledger service (receipt, issue, return, damage, disposal, **`OPENING_BALANCE`**) |
| 1.3.5 | Transfer (out/in pair, id-order locking) |
| 1.3.6 | `AssetReceiptService` (shared: manual / import / future GRN) |
| 1.3.7 | Manual receipt API + UI |
| 1.3.8 | Stock-by-location UI |
| 1.3.9 | Tests (including concurrency) + STOP |

**Note:** `OPENING_BALANCE` type exists here; posting of opening import files is 1.8 (via the same receipt service).

**STOP:** Confirm negative stock stays hard-blocked; unit cost is informational only.

---

### 1.4  Phase 4 — Assignment & Handover

| ID | Work package |
|----|----------------|
| 1.4.1 | Legacy data analysis (`assets` / `employee_assets`) |
| 1.4.2 | Bridge migration (one-way copy; collision = fail) |
| 1.4.3 | Freeze old writer / repoint Employee `AssetTab` (**same release as new assignment API; no dual writers**) |
| 1.4.4 | Assignments (employee / department, one-open rule) |
| 1.4.5 | Handover (issue, return, acknowledge, reject, proxy) |
| 1.4.6 | `EmployeeDirectoryPort` + `EmployeeTimelinePort` |
| 1.4.7 | Exit outstanding-asset report |
| 1.4.8 | Employee self view (own assets, own handovers) |
| 1.4.9 | Frontend assign / return / acknowledge |
| 1.4.10 | Tests + STOP (real employee data check) |

**Depends on:** 1.0.2 legacy + proxy decisions; Phase 1.2.

**STOP:** One real employee’s old assignments appear once; old assign button cannot create a second register.

---

### 1.5  Phase 5 — Verification & Stock Count

| ID | Work package |
|----|----------------|
| 1.5.1 | Sessions (snapshot of expected set at start) |
| 1.5.2 | Lines + results (found, missing, extra, wrong location/holder, damaged) |
| 1.5.3 | Scan-to-verify flow |
| 1.5.4 | Quantity count + variance |
| 1.5.5 | Complete & review — creates **draft** adjustments only; **posting = 1.6.4** |
| 1.5.6 | Frontend session / scan / count screens |
| 1.5.7 | Tests + STOP (one scan session + one chair count) |

**Optional early path:** Quantity-only sessions after 1.3 without waiting for 1.4. Full wrong-holder checks need 1.4.

**STOP:** Finished session lists variances; balances unchanged.

---

### 1.6  Phase 6 — Approval

| ID | Work package |
|----|----------------|
| 1.6.1 | Transfer document + executor |
| 1.6.2 | Disposal document + executor |
| 1.6.3 | Write-off document + executor |
| 1.6.4 | Inventory adjustment document + executor (posts ledger from Phase 5 drafts) |
| 1.6.5 | `asset_finance_events` outbox (written by disposal / write-off) |
| 1.6.6 | Module action registration + executor registration |
| 1.6.7 | Frontend request screens |
| 1.6.8 | Tests (on/off, reject, stale, double dispose) + STOP |

**Depends on:** 1.2, 1.3, 1.5; 1.4 for transfers of held assets. Approver resolution must use an **existing** platform resolver — do not invent one.

**STOP:** One approved transfer and one rejected adjustment demonstrated.

---

### 1.7  Phase 7 — Warranty & AMC

| ID | Work package |
|----|----------------|
| 1.7.1 | Service providers (temporary, minimal) |
| 1.7.2 | Warranties (+ file) |
| 1.7.3 | Service contracts + covered assets |
| 1.7.4 | Contract files |
| 1.7.5 | Frontend warranty / AMC on asset |
| 1.7.6 | Tests + STOP |

**Anti-scope:** Do not reuse Project `contracts`. Do not build a global vendor master.

**STOP:** Confirm overlapping coverages policy from 1.0.2.

---

### 1.8  Phase 8 — Opening Balance Import

| ID | Work package |
|----|----------------|
| 1.8.1 | Template design (serialized sheet, quantity sheet, optional warranty sheet) |
| 1.8.2 | Upload + staging (batches, rows) |
| 1.8.3 | Validation + error report file |
| 1.8.4 | Confirm (all / valid-only); queued job for large files |
| 1.8.5 | Acquisition finance events on confirm (**depends on 1.6.5**) |
| 1.8.6 | Reversal script (guarded) |
| 1.8.7 | [Opening import dry-run on data copy](./OPENING_BALANCE_IMPORT_DRY_RUN_SPIKE.md) |
| 1.8.8 | Tests + STOP (template sign-off) |

**Depends on:** 1.1–1.3; 1.6.5 for acquisition events; 1.4 if the file includes assignees; 1.7 if warranty sheet is included.

**Rules:** Reject-on-duplicate. No update-in-place (unlike Employee import). Confirm required. Idempotent via receipt inbox.

**STOP:** Template columns signed off before any production file.

---

### 1.9  Phase 9 — Maintenance Handoff

| ID | Work package |
|----|----------------|
| 1.9.1 | `asset_service_events` (thin log) |
| 1.9.2 | `UNDER_MAINTENANCE` transitions |
| 1.9.3 | `AssetContextPort` (asset, status, warranty, AMC) |
| 1.9.4 | Service history on asset page |
| 1.9.5 | Tests + STOP |

**Anti-scope:** No technicians, schedules, meters, or work orders (1.13 / future Maintenance module).

**STOP:** History visible on asset page; port returns coverage.

---

### 1.10 Phase 10 — Finance Facts

| ID | Work package |
|----|----------------|
| 1.10.1 | Frozen-amount rule on events |
| 1.10.2 | `AssetFinanceEventWriter` (receipt, disposal, write-off) |
| 1.10.3 | Pending events read API |
| 1.10.4 | Cost-field permission (`asset.finance.view`) |
| 1.10.5 | Tests + STOP (Finance owner sign-off) |

**Anti-scope:** No journals, capitalization, or depreciation. API name = finance events, not journals.

**STOP:** Finance confirms outbox is enough for V1.

---

### 1.11 Phase 11 — Reporting & Hardening

| ID | Work package |
|----|----------------|
| 1.11.1 | Asset reports (register, by employee, by location, history) |
| 1.11.2 | Verification reports (results, missing, wrong location) |
| 1.11.3 | Inventory reports (on hand, movement, variance, adjustments) |
| 1.11.4 | Warranty / AMC expiry lists, acquisition cost list |
| 1.11.5 | Streaming export |
| 1.11.6 | Index tuning (measured only) |
| 1.11.7 | Security pass (cost columns, company scope) |
| 1.11.8 | Concurrency regression suite |
| 1.11.9 | STOP (report list acceptance) |

**Note:** No net book value report (no depreciation). Report slices may ship with their owning phase; this phase finishes and hardens the set.

---

### 1.12 Rollout

| ID | Work package |
|----|----------------|
| 1.12.0 | Feature flags / module enable order |
| 1.12.1 | Module documentation (`AI/` docs, API docs) |
| 1.12.2 | UAT per phase |
| 1.12.3 | Production data migration (bridge + opening import) |
| 1.12.4 | Label printing & tagging drive (physical) |
| 1.12.5 | [First physical verification cycle](./FIRST_PHYSICAL_VERIFICATION_CYCLE_RUNBOOK.md) |
| 1.12.6 | User training (manager, custodian, auditor, employee) |

---

### 1.13 Future Roadmap (out of V1)

Do **not** schedule these into 1.1–1.12:

- Parent/child components (add / remove / replace)
- Employee asset request → approval → issue → handover
- Temporary loan / reservation / overdue
- Gate pass
- Meter-based maintenance
- Lost/stolen case, investigation, insurance (status `LOST` remains V1; case file does not)
- Reorder level + purchase suggestion
- Automated notifications
- Lot / batch tracking
- E-sign for handover
- Procurement GRN caller (uses `asset_receipt_inbox`)
- Maintenance work orders (take over service history)
- Finance journals / capitalization / depreciation / gain-loss (consume `asset_finance_events`)
- Move `asset_service_providers` into a real vendor master

---

## Cross-reference

| WBS | Plan section |
|-----|----------------|
| 1.0 | N, K |
| 1.1–1.11 | L Phases 1–11 |
| 1.12 | Implied ops / safety |
| 1.13 | M |
