Phase 4: Warehouse screen, pull table, shorts, MTRs and the upload pipeline
The Warehouse home with the numbers, the Open shorts table, the find bar and the five-column task board (waiting, being pulled, on hold, pulled, released in the last 3 days) with buttons, hold reasons and drag. Every role sees the warehouse stage on a packet as the WH pill and the line under it. The pull table on the Materials tab: Pulled with auto-start, issued, location, heat with Enter to the next line, shorts with receipts, N/A, MTR per line with a viewer. Send back to Clerical with a reason. Release to supervisor stays blocked until every line is pulled or short and every pulled line has a heat. Server: the heats_recorded precondition on WH_RELEASE, receive by custody, server-validated hold and short reasons, the old packet history texts, GET /api/warehouse/board, cards with the warehouse stage and pull counts. Uploads typed by content per kind (drawing, mtr, document, bom with XLSX and CSV), limits per kind, optional ClamAV behind the clamav compose profile, a storage quota alert on the new notification_events table (migration 0005) shown on the Admin Storage tab. Tests: every warehouse action as every role, the release gate, the short-receive exception, the heat pattern, upload sniffing and limits, the ClamAV path with a fake scanner, the quota alert; frontend board and pull table tests; Playwright scenarios for the board and the pull flow. Verified on docker-1 in the CI stack: 3557 server tests, 106 frontend tests, 17 Playwright scenarios. Docs updated; D5 closed. Co-Authored-By: Claude Fable 5.1 <[email protected]>
This commit is contained in:
+101
-1
@@ -79,7 +79,7 @@ Statuses in workflow order: draft, warehouse, ready, assigned, in_progress, revi
|
||||
| send_draft_to_qc | CL | draft | qc | no | | heat_map_answered, drawing_attached | | |
|
||||
| wh_send_back | WH | warehouse | draft | no | | reason_given | | yes |
|
||||
| return_to_clerical | DEPT_LEAD | ready, only when wh_skipped | draft | no | | reason_given | | yes |
|
||||
| wh_release | WH | warehouse | ready | no | yes | bom_all_pulled_or_short | | |
|
||||
| wh_release | WH | warehouse | ready | no | yes | bom_all_pulled_or_short, heats_recorded | | |
|
||||
| send_back_to_warehouse | DEPT_LEAD | ready | warehouse | no | | reason_given | | yes |
|
||||
| assign | DEPT_LEAD | ready | assigned | no | | welder_set | | |
|
||||
| unassign | DEPT_LEAD | assigned | ready | no | | | | |
|
||||
@@ -101,6 +101,8 @@ Statuses in workflow order: draft, warehouse, ready, assigned, in_progress, revi
|
||||
| edit_wos | CL | draft | | | | | | |
|
||||
| edit_bom | HOLDER | draft, warehouse, SHOP | | | | | | |
|
||||
| wh_receive_short | WH | any | | | | short_open | | |
|
||||
|
||||
A holder of the packet who is not in the warehouse receives a short through edit_bom (see "Receive by custody").
|
||||
| edit_heats | HOLDER | warehouse, SHOP | | | | | | |
|
||||
| edit_heat_table | HOLDER | warehouse, SHOP | | | | | | |
|
||||
| edit_welds | HOLDER | SHOP | | | | | | |
|
||||
@@ -141,6 +143,7 @@ Each precondition is a named predicate over the packet state and the request inp
|
||||
| heat_map_answered | heat_map is yes or no | Say whether this packet needs a heat map. |
|
||||
| drawing_attached | a drawing is attached | Attach the drawing first. |
|
||||
| bom_all_pulled_or_short | every line not marked n/a is pulled or has an open short | Pull every material line or mark it short first. |
|
||||
| heats_recorded | no line needs a heat: every line that is not N/A, not a sub-assembly, is pulled and issued pieces has a heat | Scan or type the heat number of every pulled line first. Use N/A for a part with no traceability. |
|
||||
| short_open | at least one BOM line has an open short (the old whCanReceive) | No part is short on this packet. |
|
||||
| welder_set (input) | the request gives station_id and welder_id | Pick a station and a welder. |
|
||||
| checklist_complete | every key of the department checklist is done | Finish the checklist first. |
|
||||
@@ -199,6 +202,101 @@ Every packet read returns:
|
||||
|
||||
`can(principal, state, assume_it_reason=True) -> (list[Action], dict[Action, list[str]])`. For an admin the IT reason is assumed, so the list shows what the admin may do once they give one. `evaluate(principal, state, action)` returns the read-mode decision with `admin_bypass` set, so the screen knows to ask for the reason. System-only actions are never listed. CO_VERIFY needs a department in the request, so it is not listed; the change order list says which departments the person can verify.
|
||||
|
||||
## Warehouse (phase 4)
|
||||
|
||||
### Stages
|
||||
|
||||
The warehouse stage is `packet_wh`, separate from the packet status. SET_WH_STAGE (WH, status warehouse) moves it, compare-and-set on `expect_stage` (409 `stale_step` when it moved on).
|
||||
|
||||
| From | To |
|
||||
|---|---|
|
||||
| incoming | pulling, hold |
|
||||
| pulling | pulled, hold |
|
||||
| hold | pulling |
|
||||
| pulled | pulling |
|
||||
|
||||
A move to the same stage, or one not in the table, is 409 `wh_transition`. A packet with no `packet_wh` row is at incoming. The first Pulled tick on a line while the stage is incoming or on hold starts pulling by itself (`auto` true).
|
||||
|
||||
### Hold reasons
|
||||
|
||||
A closed set, checked on the server:
|
||||
|
||||
- Waiting on material (not in stock)
|
||||
- Waiting on purchasing / PO
|
||||
- Question for engineering or clerical
|
||||
- Drawing / BOM problem
|
||||
- Other
|
||||
|
||||
Any other text is 400 `invalid_reason` "Pick one of the hold reasons." "Other" needs a note, else 400 `reason_required` "Say what it's waiting on." The note is cleaned and cut to 200 characters.
|
||||
|
||||
### Short reasons
|
||||
|
||||
A closed set, checked on the server:
|
||||
|
||||
- Not in stock
|
||||
- On order
|
||||
- Back-ordered
|
||||
- Damaged / rejected
|
||||
- Wrong part received
|
||||
- Needs cutting / prep
|
||||
- Other
|
||||
|
||||
Any other text is 400 `invalid_reason` "Pick one of the short reasons." A short has a quantity from 1 to the line quantity, a reason, an optional PO or requisition, an optional expected date, an optional note, and the optional heat of the pieces that were pulled (never on an N/A line). Opening, editing and clearing a short is edit_bom, so the holder decides. In practice that is the warehouse.
|
||||
|
||||
### The release gate
|
||||
|
||||
WH_RELEASE checks two preconditions, in this order:
|
||||
|
||||
1. `bom_all_pulled_or_short`: every line not N/A is pulled or has an open short.
|
||||
2. `heats_recorded`: no line needs a heat. A line needs a heat when it is not N/A, not a sub-assembly (`sub` is `Y`; its heat is on its own packet), is pulled, has issued more than 0 and has no heat.
|
||||
|
||||
Both are state preconditions, so `blocked.wh_release` lists the failing message and the screen shows Release disabled with it. Heat numbers are checked against the old pattern: letters, numbers, space . / # _ - only, up to 40 characters, starting with a letter or a number. A bad heat is 422 `invalid_heat`.
|
||||
|
||||
### Receive by custody
|
||||
|
||||
Receiving short parts (`POST .../bom/{item}/short/receipts`) picks its action from the person:
|
||||
|
||||
- A member of the warehouse (WH in `support`) receives through WH_RECEIVE_SHORT, in any status but filed, while the line has an open short. The warehouse does not need to hold the packet.
|
||||
- Anyone else receives through EDIT_BOM, so only the holder may: the lead or supervisor of the department that has the packet, Q.C. at Q.C., Clerical in draft.
|
||||
- Everyone else is refused by the policy (403 `forbidden`).
|
||||
|
||||
The warehouse still cannot change any other field of a packet it no longer holds. EDIT_BOM stays the holder's. A receipt needs a heat unless the line is N/A, and its quantity is 1 to what is still open.
|
||||
|
||||
### MTR files
|
||||
|
||||
The MTR on a line must be an asset whose type is PDF, PNG or JPEG. Anything else, or an asset that is not there, is 422 `invalid_asset`. Clearing the MTR is allowed.
|
||||
|
||||
### Packet log texts
|
||||
|
||||
The `action` column of `packet_log` for each warehouse write. `{item}` is the BOM item number.
|
||||
|
||||
| Write | action | note |
|
||||
|---|---|---|
|
||||
| Heat typed or scanned | `Heat recorded · item {item}` | the heat |
|
||||
| Heat cleared | `Heat cleared · item {item}` | |
|
||||
| Pulled ticked | `Pulled · item {item}` | |
|
||||
| Pulled unticked | `Pulled undone · item {item}` | |
|
||||
| N/A ticked | `Marked N/A · item {item}` | |
|
||||
| N/A unticked | `Traceable again · item {item}` | |
|
||||
| Issued only | `Issued qty changed · item {item}` | `{issued} of {qty}` |
|
||||
| Location only | `Location set · item {item}` | the location |
|
||||
| Several fields | `Line changed · item {item}` | |
|
||||
| MTR attached | `MTR attached · item {item}` | |
|
||||
| MTR removed | `MTR removed · item {item}` | |
|
||||
| Short opened | `Short recorded · item {item}` | `{qty} of {need} short · {reason} · {ref} · ETA {eta}`, parts present only |
|
||||
| Short edited | `Short updated · item {item}` | the same as recorded |
|
||||
| Not short after all | `Short cleared · item {item}` | |
|
||||
| Short received | `Short received · item {item}` | `{qty} pc · heat {heat} · {still} still short` or `... · short closed`, then ` · packet {status}` (lower case) and ` in {station}` when at a station |
|
||||
| Stage incoming to pulling | `Warehouse: Started pulling` | |
|
||||
| Stage to hold | `Warehouse: Put on hold` | `{reason} · {note}` |
|
||||
| Stage pulling to pulled | `Warehouse: Marked pulled, ready for production` | |
|
||||
| Stage hold to pulling | `Warehouse: Pulling resumed` | |
|
||||
| Stage pulled to pulling | `Warehouse: Back to pulling` | |
|
||||
| wh_release | `Released to supervisor`, or `Released to supervisor with {n} short` when shorts are open | `{heats} heats recorded`, plus ` · SHORT: item {item} ×{qty_open} ({reason}), ...` when shorts are open |
|
||||
| wh_send_back | `Sent back to Clerical` | the reason |
|
||||
|
||||
When a Pulled tick starts pulling by itself, there is no separate stage row in the log: the line's own row gets ` · started pulling` or ` · pulling resumed` on its note. Every write above also writes its audit row through the write pipeline, with `detail.item`, `wh_from` and `wh_to` as before, and `detail.qty` on short writes.
|
||||
|
||||
## Worker writes (phase 3)
|
||||
|
||||
The worker has no session. It writes through the same policy as a person, as the system principal `Principal(user_id=None, system="visual-feed")`. Each write locks the packet row (`FOR UPDATE SKIP LOCKED`; a row locked by someone else is left for the next run), builds the packet state, runs `policy.check()`, makes its change, bumps `version`, and writes a `packet_log` row (by nobody, by name "VISUAL feed", role `system`), an audit row (`packet.<action>`, role `system`) and a change event. See [FEED.md](FEED.md) for when each write happens.
|
||||
@@ -256,6 +354,8 @@ The old policy was looser than the old screens in places. The rebuild follows th
|
||||
| Anyone could set the data book date, even on a filed packet. | SET_DATABOOK_AT is Clerical or Q.C. only (open question 17). It stays allowed on a filed packet. | The data book date is a Clerical and Q.C. record. | Yes |
|
||||
| Change-order verifications were stored in the packet document, with no rule against changing them later. | Verifications are insert-only and cannot be withdrawn (open question 18). | A signed verification is a record. | Yes |
|
||||
| The old policy did not look at the BOM when the warehouse released a packet. | WH_RELEASE needs every BOM line not marked n/a to be pulled or to have an open short. | A packet should reach the shop with its material, or with the shorts on record. | Yes |
|
||||
| The old screen asked for a heat number on every pulled line before release, but the policy did not check it. | WH_RELEASE also needs a heat on every pulled line that issued pieces, unless the line is N/A or a sub-assembly (`heats_recorded`), checked on the server. | Traceability is the point of the pull. The screen alone could be skipped. | Yes |
|
||||
| Hold reasons and short reasons were any text the screen sent. | Both are closed sets checked on the server. "Other" on a hold needs a note. | The board and the shorts table group and report on the reason, so it must be one of the list. | Yes |
|
||||
| A hand draft could leave Clerical with no drawing (the packet PDF upload stood in for it). | A hand draft needs a drawing attached before any send from Clerical. | There is no packet PDF upload in the rebuild. | Yes |
|
||||
| Attaching drawing pages by hand needed no signature. | Attaching a drawing by hand needs a signature ("Attach a drawing by hand"). | It replaces what M-Files would supply, so a person stands behind it. | Yes |
|
||||
| Admin could write anything on a filed packet with an IT reason. | Admin cannot write a filed packet except through ADMIN_REOPEN (with a reason and a signature), and SET_DATABOOK_AT. | A filed packet is sealed. A change breaks the seal on purpose, on record. | No |
|
||||
|
||||
Reference in New Issue
Block a user