# Phase 5 — Automatic Invoice Report

**Status:** Complete — awaiting approval to start Phase 6  
**Date:** 2026-10-07  
**Scope:** Milestone approve → event → job → same `ProjectInvoiceService` (config-gated). No UI / payments.

---

## Flow

```text
Milestone approve (draft|pending → approved)
   ↓
ContractMilestoneApproved event (only on first approve)
   ↓
QueueAutomaticMilestoneInvoiceOnApproved listener
   ↓
GenerateAutomaticMilestoneInvoiceJob
   ↓
if contract.auto_invoice_on_milestone_approval
and eligible and remaining > 0
and no active automatic invoice for milestone
   ↓
ProjectInvoiceService::createMilestoneWise (source=automatic, amount=remaining)
```

---

## Added APIs

| Method | Path | Notes |
|--------|------|--------|
| GET | `/contracts/{contractId}/milestones` | List |
| POST | `/milestones` | Create (draft) |
| GET | `/milestones/{id}` | Show + invoiceability fields |
| POST | `/milestones/{id}/approve` | Approve + fire event |

Permissions: `project.milestones-view|manage|approve`

---

## Duplicate / safety guards

1. Re-approve does **not** re-dispatch event  
2. Job no-ops when auto flag is false  
3. Job no-ops when remaining = 0 (manual already fully billed)  
4. Job no-ops when an active `source=automatic` invoice already allocates the milestone  
5. Partial manual before auto → auto invoices **remaining only**  
6. Failures logged and rethrown (queue retries)

---

## Tests

`AutomaticMilestoneInvoiceTest` — **6 passed**

---

## Explicitly NOT done

- Platform ApprovalEngine multi-step workflows (status approve is the invoiceability gate; engine can call same `approve()` later)  
- Invoice UI (Phase 6)  
- Payments (Phase 7)  

---

## STOP

Phase 5 complete. **Awaiting explicit approval for Phase 6 — Invoice Management UI/API.**
