Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 64 additions & 1 deletion PRD_Coloring_Up_Order_Management.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,66 @@ This document defines the requirements for building a **Coloring Up order manage

---

## Workflow Confirmation & Refinements (2026-06-12)

> **This section supersedes any conflicting statement below it.** It captures decisions locked in a workflow-confirmation session. Where the older text below assumes order-level status, a per-order trim sheet, or Wilcom PDF parsing, **this section wins.**

### Assembled state machine (per line item)

```
New ─► Awaiting Logo ─►[logo linked via NetSuite file-cabinet id, or triage]
┌───────────┴────────────┐
exact logo+style+color no match
match exists │
│ Color-Up In Progress ◄──────────┐
│ (self-serve pool; │
│ (optional) Internal Review │
│ ─ configurable gate ─ │
│ │ │
│ Needs Approver? ─► add inline │
│ │ │
│ Sent for Approval │
│ (hosted page; daily │
│ reminder × up to 5) │
│ ┌────┴─────┐ │
│ (5 unanswered) │ │
│ Phone Call │ │
│ │ ┌────┴────┐ │
│ └────►│ │ │
│ Approved Changes Requested ──┘
│ (cascades to (comment) ─► Revision
│ all lines using In Progress (honors gate,
│ this color-up) new immutable version)
│ │
└────────────────────────┤
Production Approval (production-side gate —
│ even zero customer-touch repeats)
Production Ready ──► In Production ──► Complete
```

### Decisions that supersede the older text

1. **Status grain = line item**, not order. The order header shows a rollup summary ("3 of 4 ready, 1 awaiting approval"). Rationale: Straight Down partially ships and rush-pulls complete work.
2. **Color-up match key = `logo + style_number + color_code`, exact match only.** A color code (e.g. MAL) is not physically consistent across styles, so all three must match to reuse an approved color-up.
3. **Approval grain = the color-up proof.** Customer approves/comments per color-up; approval cascades to every line item referencing it; sizes collapse into the group.
4. **Repeat / exact-match lines skip _customer_ approval but still pass a _production_ approval gate** before the floor (zero customer-touch, not zero-touch). A manual "send for approval anyway" override exists.
5. **Trim Sheet = a Production Batch** — an on-demand view (not a persisted object), keyed on `logo + placement + thread choices`, approved-only, never crossing customers. Operator works by Order # and decides grouping at the queue. **This replaces the per-order trim sheet described in Module 4.**
6. **Internal Review = configurable gate** (customer-level default + order-level override). Revisions honor the same setting.
7. **Proof delivery:** email → hosted approval page; approver selects their name from the customer's approver list; any listed approver can act, system records who. A customer **comment always bounces the proof to revision** (team may proxy-approve trivial comments — audit records it as team-proxy). Color-up versions are immutable and loadable per round.
8. **Reminders:** automated daily morning email until approved, capped at 5, then escalates to `Phone Call` status. One digest per customer per morning.
9. **Intake = satellite model.** This system references the NetSuite SO and owns logos / color-ups / approvals / batches. CSV/paste mass-import for orders. Logo identified via the **NetSuite file-cabinet logo id** (the Logo's external key); unknown → `Awaiting Logo` triage. DSTs have two entry points: added to an order then promoted to the customer library, or added directly to the library.
10. **Design technical data comes from the DST parse (POC 1), NOT Wilcom PDF parsing.** Stabilizer / runtime / machine-format become optional manual fields on the Logo. **This supersedes the Wilcom worksheet parsing in Module 4 and Module 1C.**

### New states added beyond the original docs
`Awaiting Logo` (no logo linked yet), `Phone Call` (5 unanswered reminders), `Needs Approver` (send-for-approval with no approver on file).

### Still open
End-to-end data sourcing / live NetSuite–VRLink boundary (TBD); whether non-DST production fields are hard must-haves.

---

## Core Workflow

The system supports the following end-to-end workflow:
Expand Down Expand Up @@ -158,7 +218,7 @@ Customer
| `customer_id` | FK → Customer | Which customer placed this order |
| `netsuite_order_number` | String (optional) | Link to NetSuite SO |
| `customer_po` | String | Customer PO number |
| `status` | Enum | See workflow states above |
| `status` | Enum | **Superseded:** status now lives on the line item; the order shows a rollup summary. See Workflow Confirmation (2026-06-12). |
| `priority` | Enum | Normal, Rush |
| `assigned_to` | String | Team member doing the color-up |
| `order_date` | Date | When the order was placed |
Expand All @@ -180,6 +240,7 @@ Customer
| `logo_id` | FK → Logo | Which logo is being embroidered on this line item |
| `colorup_id` | FK → Color-Up (optional) | Which approved color-up to use — null if new color-up needed |
| `placement` | Enum | Left Chest, Cap Front, Right Sleeve, etc. |
| `status` | Enum | **Added (2026-06-12):** workflow status lives here, per line item. States incl. Awaiting Logo, Color-Up In Progress, Internal Review, Needs Approver, Sent for Approval, Phone Call, Approved, Revision In Progress, Production Ready, In Production, Complete. |

Note: Multiple line items can share the same logo and color-up (e.g., five different black garment styles all getting the same logo in the same colors). Line items can also have different logos (e.g., a left chest logo and a separate sleeve logo would be separate line item groupings).

Expand Down Expand Up @@ -269,6 +330,8 @@ Generates a visual proof document showing the customer what their embroidery wil

### What It Does

> **Superseded grain (2026-06-12):** the Trim Sheet is a **Production Batch** — an on-demand view keyed on `logo + placement + thread choices`, approved-only, never crossing customers — not a per-order document. See Workflow Confirmation. Also: design technical data is sourced from the **DST parse (POC 1)**, not the Wilcom PDF parser described below; treat the Wilcom-parsing requirements here as out of scope.

Generates a consolidated **Trim Sheet** — the single production document that operators use on the floor. Today this information lives across two separate documents: a Wilcom Production Worksheet (design technical specs) and a Compact Trim Sheet from the existing system (order details, garment breakdown, thread sequence). This module combines both into one unified, printable document.

### Current State (What Exists Today)
Expand Down
104 changes: 91 additions & 13 deletions pocs/poc4_order_workflow/FINDINGS.md
Original file line number Diff line number Diff line change
@@ -1,27 +1,105 @@
# POC 4: Order-to-Approval Workflow — Findings

> Fill in as the POC progresses. Deliverable.
## What we built (Step 1 — 2026-06-12)

### Data layer
SQLite schema across 7 tables:

| Table | Purpose |
|-------|---------|
| `customers` | Account records; `internal_review_default` controls the IR gate |
| `approvers` | People authorised to approve proofs; `is_primary` + `active` flags |
| `logos` | Design files owned by a customer; `netsuite_file_cabinet_id` is the external key; all DST-parsed fields (`dst_stitch_count`, `dst_color_count`, `dst_width_mm/height_mm`, `dst_stop_count`, `dst_trim_count`) are nullable and populated by stub interface only |
| `color_ups` | Immutable versioned colour configurations — `(logo_id, style_number, color_code, version)` unique; `thread_sequence` stored as JSON; `approved_by_team_proxy` flag for proxy approvals |
| `orders` | NetSuite SO reference; deliberately **no `status` column** — status lives on line items |
| `order_line_items` | Per-line `status`; `size_quantities` JSON; `send_for_approval_override` flag |
| `status_history` | Immutable audit log with `actor`, `from_status`, `to_status`, `team_proxy`, `notes`, and `timestamp` |

Schema written migration-ready for PostgreSQL (comments inline in `schema.py` for every type mapping).

### State machine
12 states, explicitly enumerated transitions, no inferred edges:

```
New → Awaiting Logo → Color-Up In Progress → Internal Review ┐
└→ Production Ready ←──────────────────┘→ Needs Approver → Sent for Approval
↓ ↓ ↓
Approved Phone Call Revision In Progress
↓ ↓
Production Ready ←── Color-Up In Progress
In Production → Complete
```

Every `transition()` call validates the edge and writes to `status_history`. `bulk_transition()` skips items where the edge is invalid without raising.

### Match-key logic
`(logo_id, style_number, color_code)` — exact match only, per spec decision 2. A colour code is not portable across styles (spec decision 2 rationale).

`resolve_logo_for_line_item()` handles the Awaiting Logo → fork:
- Approved exact match AND no override → Production Ready (auto-assigns color-up FK)
- No match OR override → Color-Up In Progress

`cascade_approval()` marks the color-up Approved and advances every line item referencing it from `Sent for Approval`, `Phone Call`, or `Needs Approver` through `Approved → Production Ready` in a single call. Does not cross customers (each color-up belongs to one logo which belongs to one customer).

### Production batch query
`get_production_batches()` groups Production Ready line items by `(customer_id, logo_id, placement, thread_sequence_canonical)`. Thread sequences are normalised with `sort_keys=True` so insertion-order differences don't create phantom splits. Never crosses customers. Excludes non-Approved color-ups even if the line item is Production Ready (defensive guard for data-integrity edge cases).

### DST / editor stubs
`dst_stub.py` exports `parse_dst()` and `open_color_up_editor()`, both raising `DSTNotAvailableError(NotImplementedError)`. All tests that would require DST files or the POC 3 editor are in `test_dst_stub.py` and confirm the stub contract rather than skipping — no real DST files needed.

## Test results

```
65 passed in 0.24s
```

Coverage: state machine (pure + DB), CRUD for all entities, FK enforcement, match-key exact-match semantics, approval cascade, production batch grouping, and DST stub contract.

## What is stubbed / skipped and why

| Feature | Status | Reason |
|---------|--------|--------|
| DST file parse (POC 1) | Stubbed behind `DSTNotAvailableError` | DSTs are local-only; cloud sandbox has none |
| Color-up editor (POC 3) | Stubbed behind `DSTNotAvailableError` | POC 3 editor is local-only |
| FastAPI web layer | Not started | Step 2 scope |
| CSV/paste mass-import | Not started | Step 2 scope |
| Email / reminder logic | Not started | Step 5 scope |
| Production batch trim-sheet render | Not started | Step 6 scope |

## What we built
## What we measured

Step 1 is pure data layer + logic; no UI performance measurements apply yet.

## Scorecards

### Data storage

| Option | R | Q | S | F | Weighted |
|--------|---|---|---|---|----------|
| A. SQLite | | | | | |
| B. PostgreSQL | | | | | |
| C. JSON flat files | | | | | |
| Option | R (reliability) | Q (query power) | S (simplicity) | F (future path) | Weighted |
|--------|----------------|-----------------|----------------|-----------------|----------|
| A. SQLite | ✓ | Good (JSON cols) | ✓ easy | Needs migration | **Strong for POC** |
| B. PostgreSQL | ✓ | Best (JSONB ops) | Needs Docker | ✓ prod-ready | Overkill for POC |
| C. JSON flat files | Fragile | None | Trivial | Throwaway | Not recommended |

SQLite wins for the POC; the schema is written to migrate with minimal changes (all comments in `schema.py`).

### Web framework

| Option | R | Q | S | F | Weighted |
|--------|---|---|---|---|----------|
| A. FastAPI + HTMX | | | | | |
| B. FastAPI + React | | | | | |
| C. Flask + Jinja | | | | | |
Not yet evaluated — Step 2 work.

## What we learned

1. The `(logo + style_number + color_code)` exact-match key is clean to implement; the immutable-version pattern for color-ups is straightforward with a UNIQUE constraint.
2. Per-line status + order-header rollup (`order_status_rollup()`) is simple and flexible for the partial-ship scenarios.
3. Approval cascade across all matching line items in a single call keeps the controller thin.
4. Python 3.12 `detect_types=sqlite3.PARSE_DECLTYPES` conflicts with ISO-8601 timestamps (T separator vs space); dropped in favour of TEXT columns, no loss of functionality.

## Recommendation if shipping for real
## Open questions / followups

Keep SQLite for the POC through Step 4 (approval page). Migrate to PostgreSQL before Step 5 (reminders + notifications) where concurrent writes from the daily digest job will matter. The schema DDL is already annotated for the migration.

## Open questions / follow-ups

- NetSuite SO ↔ VRLink boundary: how does the SO number get into the system? (manual entry for POC, integration TBD)
- Non-DST production fields (stabilizer, runtime): are they hard must-haves before the floor will use trim sheets?
- `internal_review_default` is per-customer but some customers may want per-logo overrides — not modelled yet.
86 changes: 86 additions & 0 deletions pocs/poc4_order_workflow/NEXT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# POC 4 — Build Plan: Order-to-Production Workflow (full-workflow revision)

This supersedes the stripped-down five-state spec in root `POC_4_Order_Workflow.md`.
The authoritative process is the **"Workflow Confirmation & Refinements (2026-06-12)"**
section of `PRD_Coloring_Up_Order_Management.md` — read it first. It captures a
grilling session that confirmed the full production workflow and surfaced six
load-bearing changes the old spec didn't have.

## What changed vs. the old POC 4 spec

- **Status is per line item**, with a rollup summary at the order header (not order-level).
- **Color-up match key = `logo + style_number + color_code`, exact match only.**
- **Approval grain = the color-up proof**; approving cascades to every line item using it.
- **Repeat / exact-match lines skip _customer_ approval but pass a _production_ approval gate.**
- **Trim sheet = a Production Batch** — an on-demand view keyed on `logo + placement + thread choices`, approved-only, never crossing customers.
- **Internal Review = configurable gate** (customer default + order override).
- **New states:** `Awaiting Logo`, `Phone Call` (5 unanswered reminders), `Needs Approver`.
- **Satellite intake:** references the NetSuite SO; CSV/paste mass-import; logo auto-linked via the NetSuite file-cabinet logo id; DSTs added to an order *or* to the customer library.
- **Design data from the DST parse (POC 1), not Wilcom PDF parsing.**

## State machine (per line item)

```
New ─► Awaiting Logo ─►[logo linked via file-cabinet id, or triage]
├─ exact logo+style+color match ─► Production Approval ─► Production Ready ─► In Production ─► Complete
└─ no match ─► Color-Up In Progress ─►(opt) Internal Review ─► Needs Approver? ─► Sent for Approval
├─ Approved (cascades) ─► Production Approval ─► …
├─ 5 unanswered reminders ─► Phone Call
└─ Changes Requested (comment) ─► Revision In Progress (new immutable version) ─┘
```

## Tech stack (default — bake-off scorecard is a Step 7 deliverable)

- **Backend:** Python 3.10+ / FastAPI (consistent with POC 2 step 3).
- **Frontend:** Jinja2 + HTMX (server-rendered, no build step).
- **Storage:** SQLite for the POC (schema written migration-ready for PostgreSQL).
- **DST parse:** reuse `pocs/poc1_dst_renderer`. **Color-up editor:** reuse `pocs/poc3_color_up_editor` (DST/editor work is local-only — see cloud note).

## Build steps

### Step 1 — Data layer + state machine ← START HERE (cloud-friendly, no DST needed)
- SQLite schema: `customers`, `approvers`, `logos` (with `netsuite_file_cabinet_id`,
parsed DST fields, optional stabilizer/runtime), `color_ups` (immutable versions,
status, approved_by incl. team-proxy), `orders` (NetSuite SO ref, no status),
`order_line_items` (**per-line `status`**, style/color/size grid, logo+colorup FKs,
placement), `status_history` (actor, from/to, timestamp, team-proxy flag).
- State machine: all states above, transition validation, audit logging.
- Match-key logic (`logo + style_number + color_code`, exact) + approval **cascade**.
- Production-batch query: group ready line items by `logo + placement + thread-sequence`,
approved-only, within a single customer.
- CRUD + a thorough pure-Python test suite (no DST, no network → runs in cloud).

### Step 2 — Intake + dashboard
- CSV/paste mass-import → orders + line items.
- Order entry form; NetSuite SO reference; file-cabinet-id → logo auto-link.
- `Awaiting Logo` triage queue; two DST entry points (to-order, to-library).
- Dashboard: per-line status badges + order-header rollup; filters/search.
- DST upload → parse via POC 1 *(DST-dependent: stub + skip in cloud)*.

### Step 3 — Color-up editor integration *(POC 3 + DST dependent: local only)*
- Embed POC 3 editor; load order's logo/DST; wire save → state transitions.

### Step 4 — Proof + approval page
- Hosted approval page; approver selects name from customer's approver list (identity B).
- Per-color-up Approve / Request-Changes (+ comment); approval cascade; immutable versions.
- `Needs Approver` inline-add popup.

### Step 5 — Reminders + notifications
- Daily morning reminder digest per customer; cap 5 → `Phone Call` status.
- Customer response surfaces on assigned-artist **and** lead/manager dashboards.

### Step 6 — Production batch + trim sheet
- On-demand batch view (operator works by Order #, decides grouping at the queue).
- Trim sheet generation (design + thread sequence + garment run); `Production Approval`
gate (incl. on zero-customer-touch repeats); one-click In Production / Complete.

### Step 7 — Testing + evaluation
- All test scenarios; storage + framework bake-off scorecards; design recommendation.

## Cloud-agent scope note

The cloud sandbox has **no real DSTs and no POC 3 editor** (local-only by policy, see
`CLOUD_AGENTS.md`). A cloud run should implement **Step 1** in full and the data-light
parts of **Step 2** (CSV import, models, dashboard skeleton). All DST/editor integration
must be stubbed behind interfaces, and DST-dependent tests should **skip** with a clear
reason — that's expected, not a failure.
Loading