[T06] Import Manufactured Numbers
Summary
Tenant-scoped entry bookend of the manufactured-numbers async import flow. A stock operator uploads the CSV/XLSX their manufacturer returned (sequence + number + barcode triples) and hands off to C05 for processing. The exit bookend is T07. Mirrors E06 in structure but with one defining difference: the column schema is fixed (sequence, number, barcode are non-negotiable), so there is no source-system dropdown and C05’s column-mapping stage is auto-applied silently — see C05's Fixed-schema imports design decision.
Actor & Context
Actor: stock operator (tenant-admin assistant). Same actor as C02; T06 is the file-based alternative when the manufacturer ships a digital deliverable instead of physical-sequence-only stock.
Frequency: bursty per delivery — once per manufactured batch, then idle.
Precondition:
-
User has
TENANT_ADMINpermission. -
WS3 (US #478a) is in production:
RaceNumber.tag_idFK exists. -
ImportType.NUMBER_ONBOARDINGis registered andNumberOnboardingRowProcessoris live (Track 3 backend deliverable). -
The operator has a CSV/XLSX file conforming to the fixed schema.
Entry point: tenant sidebar → Inventory → Onboard → Import (route /inventory/numbers/onboard/import). Resume from My imports for a paused job.
Main Flow
-
Upload screen. Single full-screen page.
-
Page title: "Import manufactured numbers — <tenant name>".
-
Fixed-schema banner — prominent, top-of-page: "This import expects a fixed schema. Required columns:
sequence,number,barcode. Other columns are ignored. No mapping step required." A smallDownload templatebutton next to the banner serves a tenant-neutral CSV template with the three headers and one example row. -
File picker (CSV/XLSX) with drag-and-drop zone.
-
NumberType picker (REQUIRED) — dropdown listing the tenant’s NumberType rows. Drives which inventory the imported rows land under. Helper text: "Which catalogue does this batch belong to?"
-
No source-system dropdown. Numbers do not have a source-system concept; the file is always understood as "raw manufacturer output". The C05 target-field filter does not apply to T06.
-
Recent imports list below the inputs — date, filename, NumberType, row count, status. Clicking a row opens the matching T07 read-only.
-
Right-rail "About this screen" panel — collapsible; default expanded; per-screen
localStoragekey. Copy explains the fixed schema, whatbarcodemay be (RFID/chip vs absent), and what state the rows will land in. -
Primary action: Upload — disabled until file picked AND NumberType picked. Tooltip on the disabled button explains whichever requirement is missing.
-
-
Submit.
POST /api/imports?importType=NUMBER_ONBOARDING&numberTypeId=X(multipart). On 201, take the returneduuidand writelocalStorage.setItem('importCaller:' + uuid, 't06'). Navigate to C05 at/imports/{uuid}. -
Mapping flow (delegated). C05 auto-applies the fixed-schema column mapping silently — Stage 1 (Columns) renders briefly with a stage-bar pill labelled
Auto-appliedand immediately advances. Stage 2 (Cells) only runs if any rows reference an unknown FK (e.g. anumberTypeKeycolumn that didn’t match server-side; for T06’s three-column schema this is rare). Stages 3-5 (Verifying / Processing / Done) follow the standard C05 contract — note that Verifying is always skipped for T06 because the fingerprint check is identity-flag-driven and T06 has nois_self/trustPKsflags. TheVerifyingpill renders SKIPPED with the standard "skipped — file is from an external system" tooltip. -
Terminal redirect. C05 reads
importCaller:{uuid}onCOMPLETED/FAILED/CANCELLEDand redirects to T07 at/inventory/numbers/onboard/imports/{uuid}/summary.
Alternative Flows
-
AF-1 — File missing required column. The fixed-schema validator rejects the upload at
POST /api/importswith 400 + a message identifying the absent column. Upload screen surfaces the rejection inline; file is not consumed. -
AF-2 — Barcode column has empty cells. Permitted: rows without a barcode are accepted as
MANUFACTUREDwithtag_idleft NULL — these get paired later via C02. The summary screen reports the count under "rows imported without a tag". -
AF-3 — Duplicate
(numberType, sequence)within the file. Detected during validation; the import job lands inPROCESSINGbut the duplicate rows accumulate in the row-results bucket and surface in T07's "duplicate sequence" section. -
AF-4 —
(numberType, sequence)already exists in the database. Idempotent — the row is treated as a no-op (state-log entry recorded for audit, no schema change). T07 reports the count under "rows already on file". -
AF-5 — Cancel during PROCESSING. Standard C05 cancel; T07 renders with
CANCELLEDstate and the partial breakdown. -
AF-6 — Pause / resume. Standard async-import behaviour; resume via
My imports.
Acceptance Criteria
-
Use-case page authored (this page).
-
Status
design-todo → in-design → handoff-readyafter Claude Design pass and Coordination Backlog resolution. -
:design-url:populated. -
Fixed-schema banner is visible at the top of the upload screen and identifies the three required columns.
-
No source-system dropdown is rendered.
-
NumberType picker is required; Upload button is disabled without it.
-
On submit the caller key
importCaller:{uuid}is written with literal't06'. -
C05 column-mapping stage transparently auto-applies (per the Fixed-schema imports decision in C05).
-
Rows without a barcode are accepted and counted separately in T07.
API Surface
| Call | Purpose |
|---|---|
|
Create the import job. Multipart upload (file). Server validates the fixed-schema header up-front and returns 400 with the missing column name if invalid. |
|
Populate the NumberType picker. |
|
Drives the "Recent imports" list (filtered to T06’s importType). |
|
Serves the static "Download template" CSV. Tenant-neutral; schema only. (Optional — could be a shipped static asset rather than a dynamic endpoint.) |
(delegates to C05 for column / cell / progress) |
Shared mapping flow with auto-applied column mapping. |
Out of Scope
-
The mapping middle steps — C05.
-
The summary screen — T07.
-
Scanner-based onboarding — C02.
-
Manufacturer-data-file export (the upstream "send sequence to manufacturer" tool) — separate Track 3 screen, not yet authored.
-
Per-tenant fixed-schema variants (e.g. additional
colour/additionalInfooptional columns) — backend already accepts these but the .adoc spec keeps the banner copy strict to avoid operator confusion. The optional columns are listed in the Notes section as a forward-looking item.
Design Anchors
Design Decisions
-
Fixed schema, no source-system selector (2026-05-07). Numbers do not have a provenance concept analogous to participants — there is no "WPCA Legacy vs Entry Ninja" axis for manufactured stock. The schema is dictated by the manufacturer’s deliverable shape and is the same across every tenant. Implication for C05: the Fixed-schema imports path applies (see C05’s design decision); column mapping auto-applies silently and the operator never sees Stage 1 as a working step.
-
NumberType is the one required selector (2026-05-07). The CSV doesn’t carry NumberType per row because manufactured batches are NumberType-homogeneous (one batch = one bib design = one type). Putting NumberType on the upload screen avoids a mandatory
numberTypeKeycolumn inside the file that the operator would have to populate identically on every row. -
Barcode column is optional per row (2026-05-07). A row without a barcode is acceptable — it lands as
MANUFACTUREDwithtag_idNULL and is later paired via C02. This is the default state for tag-less stock (race medals, T-shirts that double as numbers, etc.) and the mixed case where some bibs have RFID chips and some don’t. -
Idempotent re-import (2026-05-07).
(numberTypeId, sequence)is the natural key. Re-importing the same file (or a corrected file with overlapping sequences) is a no-op for already-imported rows, with a state-log entry recorded for audit. Rationale: manufacturers occasionally re-send the file with corrections; making T06 idempotent removes a footgun. -
No update mode (2026-05-07). Unlike E06's
Overwrite/Appenddistinction, T06 has no such toggle. The semantics are always "create-on-miss, no-op-on-hit". If the operator wants to change a paired tag, that’s C02's re-pair flow (AF-2). If the operator wants to dispose of stock, that’s T04. Each lifecycle action has one canonical screen. -
No identity flags / no fingerprint stage (2026-05-07). T06 carries no
trustPKs/updatePII/is_selfflags. The C05 Verifying pill renders SKIPPED with the existing tooltip pattern (per project memoryfeedback_explain_disabled_ui.md). Tooltip text: "Skipped — manufactured-number imports do not need fingerprint verification."
Notes
|
Backend dependency: requires |
The fixed schema may grow optional columns over time:
-
colour— for tenants that order multi-colour bibs and want the colour recorded against eachRaceNumber. -
additionalInfo— free-text per-row note (e.g. batch-internal lot number).
These are out of the current spec. The banner copy stays strict ("Required columns: sequence, number, `barcode`") so the operator’s mental model is uncluttered; if a future delivery introduces an optional column, the banner is updated explicitly rather than hedging now.
Resolved Decisions
Q-E3 and Q-E4 (the questions parked during initial authoring) were resolved by Coordination Decision CD-8 in the number/tag UI orchestration on 2026-05-07. Both took the proposed Default leans:
-
Q-E3 (backend endpoint): the template CSV ships as
GET /api/race-numbers/templates/manufactured-numbers.csv, served by admin-service through the gateway. The SPA download link in the upload screen targets that path. Implementation lives in the backend US (US #733). -
Q-E4 (row-level validation):
sequencevalidation is row-level (positive integer, up-to-bound check) and surfaced in T07's "Other issues" bucket. Matches the rest of the import flow’s validate-at-row-level convention.