# WP4 [FIN] — Sales Delivery Note

## Goal
Wire the Delivery Note. It is a **dead enum case today** (`ApprovalDocumentType:11`) — configurable in the UI, enforcing nothing.

Its commit is **`confirm()`** (`SalesDeliveryNoteController:303` → `ConfirmDeliveryNote`), which **deducts stock — but ONLY when `sales.stock_deduction_point === 'delivery'`** (`ConfirmDeliveryNote.php:33-35`).

`ship()` (`:333`) and `deliver()` (`:363`) are **pure status/metadata writes** — no stock, no GL. **Do NOT guard them**; blocking them buys nothing and only annoys users.

## Approved shape
Same Shape 1 as WP2/WP3. Copy WP2's controller pattern exactly.

## Exact files
### BE
- `Modules/Core/app/Services/ApprovalWorkflowService.php:382-391` — **add the `delivery_note` row** (the enum case exists; the missing row is precisely why it does nothing today).
- `Modules/Sales/app/Http/Controllers/SalesDeliveryNoteController.php` — `use DrivesApprovalWorkflow`; add `submit`; guard **`confirm()` only** with `assertApprovedForPost`; engine approve/reject routing.
- `Modules/Sales/app/Enums/DeliveryNoteStatus.php` — add `PendingApproval` (no migration; status is a string).
- The DN model — virtual `total` accessor if it has no `total`/`grand_total` (precedent `PurchaseRequest.php:128-136`).

### FE
- `features/sales/delivery-notes/*` — drop in `<app-approval-actions>` (WP1 shared component); submit button when `approval.required && draft`; hide **Confirm** while pending (leave Ship/Deliver alone).
- `core/models/sales-delivery-note.model.ts` — add `approval?: DocumentApprovalState` (it currently has none).
- Also connect the **GRN screen** to the shared component if WP3 didn't already.

## Acceptance criteria
- [ ] **INVARIANT (test):** a pending DN, in a company with `stock_deduction_point='delivery'`, moves **ZERO stock**.
- [ ] **NO REGRESSION (test):** no workflow → unchanged.
- [ ] **Both settings modes tested:** `delivery` (confirm deducts stock → approval protects stock) and `invoice` (confirm deducts nothing → approval is authorization over the customer commitment, not stock protection). Document the latter for the owner — the approval is still meaningful, just not stock-protecting.
- [ ] `ship()`/`deliver()` are NOT gated.
- [ ] `delivery_note` returns `wired: true` from the document-types endpoint; renders in the inbox with number + amount.
- [ ] `ng build` green.

## Tests
Pest: pending-blocks-confirm; pending → no stock (delivery mode); no-workflow unchanged; ship/deliver still work while... (they are only reachable after confirm, so assert they are not independently gated). Re-run `Modules/Sales/tests` — no NEW failures vs baseline.

## Flags
- **[FIN]** — can deduct stock. Fable consult on the setting-dependent behaviour.
- **Migration:** none.

## Out of scope
Inventory documents (WP2/WP3). Config screen + inbox (WP5).
