# Supplier PO Approval Tracker

An internal tool that replaces email-and-spreadsheet purchase-order approvals with a clear, auditable workflow: create POs, route them for approval, and notify approvers by email — with a status dashboard for the ops team.

## Goals

- Give every PO a clear, auditable approval trail.
- Cut approval turnaround time with email notifications.
- Show PO status at a glance for the ops team.

## Features

- **PO creation** — Create a purchase order with supplier, lines and totals.
  - [ ] A PO can be created with at least one line item and a computed total.
  - [ ] Totals recalculate when line items change.
- **Approval workflow** — Submit for approval; approve/reject with a note.
  - [ ] Submitting a PO moves it to "pending" and records the submitter.
  - [ ] Approve/reject records the actor, timestamp and note.
- **Email notifications** — Notify approvers when action is needed.
  - [ ] Approvers receive an email when a PO is submitted for approval.
- **Status dashboard** — List and filter POs by status.
  - [ ] POs can be filtered by status and ordered by date.

## Data model

### PurchaseOrder

A purchase order routed through the approval workflow.

| Field | Type | Nullable | Notes |
| --- | --- | --- | --- |
| id | uuid | no |  |
| company_id | uuid | no | Multi-tenancy scope. |
| supplier | text | no |  |
| status | enum(draft\|pending\|approved\|rejected) | no |  |
| total | decimal(12,2) | no |  |
| note | text | yes |  |
| created_at | timestamptz | no |  |

**Relations:**
- has many PurchaseOrderLine
- belongs to User (submitter)

**Indexes:**
- (company_id, status)

### PurchaseOrderLine

A single line item on a purchase order.

| Field | Type | Nullable | Notes |
| --- | --- | --- | --- |
| id | uuid | no |  |
| purchase_order_id | uuid | no |  |
| description | text | no |  |
| quantity | integer | no |  |
| unit_price | decimal(12,2) | no |  |

**Relations:**
- belongs to PurchaseOrder

**Indexes:**
- (purchase_order_id)

## Pages

### `/purchase-orders`

List and filter purchase orders by status.

**Components:**
- StatusFilter
- PurchaseOrderTable

**States:** empty, loading

### `/purchase-orders/new`

Create a new purchase order with line items.

**Components:**
- PurchaseOrderForm
- LineItemEditor

### `/purchase-orders/[id]`

View a PO and approve/reject it.

**Components:**
- PurchaseOrderDetail
- ApprovalActions

## Milestones

1. **Foundation** — Stand up the app, DB and auth.
2. **PO & approval** — Core PO lifecycle and approvals.
3. **Notifications & dashboard** — Email + status visibility.

## Tasks

### Foundation

- **Scaffold Next.js app with Ensign defaults** _(Urgent · S)_
- **Wire Postgres + Drizzle** _(Urgent · S)_
- **Integrate ensign-sso auth (company_id scoping)** _(High · M)_

### PO & approval

- **Model PurchaseOrder + line items** _(Urgent · M)_
- **Build PO create/edit form** _(High · M)_
- **Implement submit / approve / reject with notes** _(High · M)_

### Notifications & dashboard

- **Send approval-needed emails** _(Medium · S)_
- **Build status dashboard with filters** _(Medium · M)_

## Non-functional requirements

- **Security** — All access gated by ensign-sso; every query scoped by company_id.
- **Auditability** — Approval events are append-only and never mutated.
- **Performance** — PO list paginated; p95 under 300ms at 10k POs.

## Risks

- **Email delivery failures leave approvers unaware of pending POs.** — Show a pending-approvals badge in-app so email is not the only channel.
- **Approval trail could be edited after the fact, undermining auditability.** — Append-only approval events; never mutate past decisions.

## Open questions

- Should approval thresholds vary by PO total?
- Who can create POs — any user, or a specific role?

## Out of scope

- Xero/Sage accounting integration
- Multi-step approval chains
- Supplier self-service portal
