# Invoice Draft Library

**Date:** 2026-05-31  
**Status:** Draft  
**Spec:** 144  
**Tier:** All tiers  
**Depends on:** `invoices-core`, `customers-module`, `foundation-auth-rbac`  
**Referenced by:** `invoices-core`

---

## Overview

Spec 15 (`invoices-core`) defines the invoice list at `/invoices` but mixes DRAFT invoices with all other statuses. DRAFT invoices are works-in-progress — they shouldn't be interleaved with sent/approved/paid invoices in the main operational list. This spec defines a dedicated draft library view and a reusable invoice template flow.

---

## Route

`/invoices/drafts` — accessible from the invoices navigation.

---

## Page Layout

```
┌──────────────────────────────────────────────────────────────┐
│  Invoices > Drafts                                           │
│                                                              │
│  [+ New invoice]                     [Search drafts...]      │
│                                                              │
│  Drafts                                              (14)    │
│  ─────────────────────────────────────────────────────────  │
│  INV-DRAFT  Website Redesign         Acme Corp    ₪8,400     │
│  Created 3 days ago · Last edited today                      │
│  [Edit] [Send] [Delete]                                      │
│                                                              │
│  INV-DRAFT  Monthly Retainer         Beta Ltd     ₪4,200     │
│  Created 1 week ago · Last edited 5 days ago                 │
│  [Edit] [Send] [Delete]                                      │
│                                                              │
│  Templates                                           (3)     │
│  ─────────────────────────────────────────────────────────  │
│  ★ Standard Project Invoice          (5 line items)          │
│  ★ Monthly Retainer Template         (2 line items)          │
│  ★ Consulting Day Rate               (1 line item)           │
│  [+ New template]                                            │
└──────────────────────────────────────────────────────────────┘
```

---

## Draft Invoice Behavior

DRAFT invoices:
- Not visible in main `/invoices` list by default (filter excludes `DRAFT`)
- Main invoices list shows a "[X drafts]" pill linking to `/invoices/drafts`
- Can be edited freely
- `[Send]` transitions to `SENT` status (same flow as send from invoice detail)
- `[Delete]` permanently removes (no soft delete for drafts)
- Auto-numbered: `INV-DRAFT-{sequential}` prefix in UI; actual `invoice_number` assigned at send time

---

## Invoice Templates

Templates are DRAFT invoices marked `is_template = true`. `customer_id` must be nullable for templates — the schema delta relaxes the original NOT NULL constraint and adds a check:

```sql
ALTER TABLE invoices ALTER COLUMN customer_id DROP NOT NULL;
ALTER TABLE invoices
  ADD COLUMN IF NOT EXISTS is_template BOOLEAN NOT NULL DEFAULT false;
ALTER TABLE invoices
  ADD CONSTRAINT chk_invoice_requires_customer
  CHECK (is_template = true OR customer_id IS NOT NULL);
```

Template behavior:
- Never sent directly; used as a "copy from" base
- `[Use template]` → creates new DRAFT invoice with all line items, amounts, and notes copied
- Customer field cleared (templates are reusable across customers)
- Templates shown in separate "Templates" section below drafts

**[+ New template]** → same invoice editor but saves with `is_template = true` and `customer_id = NULL`.

---

## Create from Template

In the `[+ New invoice]` flow (spec 15), a new option:

```
┌──────────────────────────────────────────────────────────────┐
│  New invoice                                                 │
│                                                              │
│  Start from...                                               │
│  ● Blank invoice                                             │
│  ○ Template:  [Standard Project Invoice ▾]                   │
│              Monthly Retainer Template                       │
│              Consulting Day Rate                             │
│                                                              │
│  Customer   [Search customers...]                            │
│                                                              │
│  [Continue]                                                  │
└──────────────────────────────────────────────────────────────┘
```

---

## Main Invoice List Integration

In `/invoices` list, above the table:

```
  [All statuses ▾]  [+ New invoice]          ← existing filters
  
  14 drafts  →  [View drafts]                ← new pill link
```

The `DRAFT` status is removed from the default "All statuses" filter group in the main list. Users who want to see drafts go to `/invoices/drafts`.

---

## API

```
GET /api/invoices?status=DRAFT&is_template=false
    → list draft (non-template) invoices
      Requires: invoices:read

GET /api/invoices?is_template=true
    → list invoice templates
      Requires: invoices:read

POST /api/invoices/from-template/:templateId
     → create draft invoice from template
       body: { customer_id: string }
       Returns: new invoice (DRAFT status, line items copied)
       Requires: invoices:write

DELETE /api/invoices/:id
       → delete DRAFT invoice (only allowed if status = 'DRAFT')
         Returns: 409 if status != 'DRAFT'
         Requires: invoices:write
```

---

## Architecture Decisions

| Decision | Choice | Reason |
|----------|--------|--------|
| Templates as `is_template` flag | Not separate `invoice_templates` table | Templates share the exact same structure as invoices; a separate table would duplicate all columns or require a JSON blob pattern |
| Drafts separate from main list | Not inline filter | Operational invoice list is for tracking receivables; drafts are works-in-progress that clutter AR aging, status metrics, and payment tracking |
| `invoice_number` assigned at send | Not at draft creation | Invoice numbering in IL must be sequential without gaps; assigning at draft creation would create gaps if drafts are deleted |
