drawings: VISUAL's rev is the source of truth; attach it when M-Files holds it Effective or Retired
ci / frontend (pull_request) Successful in 43s
ci / server (pull_request) Successful in 11m3s
ci / image (pull_request) Skipped
ci / e2e (pull_request) Successful in 3m52s

When M-Files' Effective rev differs from the rev VISUAL calls, the drawing
job looks that rev up (MFilesKit DrawingLookup.revision). If M-Files has
it as Effective or Retired, the job copies it into drawing_revisions and
attaches it to the draft with no flag and no Clerical approval, so the
draft can auto-release. Past draft, already attached or with a hand
drawing: unchanged, no flag and no change order.

Any other status, or no document at that rev, still flags rev_mismatch
with a note saying why. Packet Station only ever attaches Effective or
Retired drawings. rev_approve stays for that case only.

This replaces the "Use rev V as VISUAL calls it" choice from #46: the
use=called path in rev-approve and its button are removed. A packet that
already kept the rev that way keeps it, since that rev is now used anyway.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
2026-10-19 16:05:57 -06:00
co-authored by Claude Opus 5.5
parent c5bf48ac50
commit ca407a2db3
16 changed files with 292 additions and 250 deletions
+3 -3
View File
@@ -291,8 +291,8 @@ The file is downloaded only when the object id and version or the file id and ve
| No released rev, but a drafting rev or a drafting assignment | `not_released` | `not_released` | Note "Not released in M-Files yet (sheet of <base>) - drafting status: rev N <where>". |
| No released rev and nothing in drafting | `not_found` | `not_found` | Note "Drawing not in M-Files - check the drawing number in VISUAL". |
| VISUAL's rev is not a whole number | `bad_rev` | `bad_rev` | Not attached. |
| Revs differ, and no approved rev matches M-Files | `rev_mismatch` | `rev_mismatch` | Note "Rev mismatch: VISUAL calls rev V, M-Files has rev N", plus the drafting status. The M-Files copy is fetched and staged for Clerical Supervisor approval. On a draft the rev VISUAL calls is looked up too: when M-Files still holds it (Retired, say), that copy is fetched into `drawing_revisions` and kept on the packet as `visual.called`, and the log note says "rev V is Retired in M-Files". When M-Files has no document at that rev, the note says "rev V is not in M-Files". No change order: VISUAL did not change. |
| Revs differ, but Clerical kept the rev VISUAL calls while M-Files' Effective rev is still the one they chose against | `unchanged` | none | The kept rev stays attached and confirmed. No flag and no change order, also past draft. A newer Effective rev in M-Files flags the packet again. |
| Revs differ, and no approved rev matches M-Files, and M-Files holds the rev VISUAL calls as Effective or Retired | `attach_called` | none | VISUAL is the source of truth. On a draft the rev VISUAL calls is fetched into `drawing_revisions` and attached, with no flag and no Clerical approval: `drawing_state` `attached`, rev confirmed, `visual.vault.controlled` set (for example Retired), `visual.called` recorded. Log "Drawing attached from M-Files" with the note "Rev V is Retired in M-Files; VISUAL calls it (M-Files has rev N)". Already attached, a hand drawing, or past draft: unchanged, no flag and no change order. The same holds when M-Files has no Effective rev at all. |
| Revs differ, and no approved rev matches M-Files, and M-Files has no document at the rev VISUAL calls, or has it at another status (Released, Obsolete) | `rev_mismatch` | `rev_mismatch` | Note "Rev mismatch: VISUAL calls rev V, M-Files has rev N", plus the drafting status, plus "rev V is not in M-Files" or "rev V is <status> in M-Files - not attached". Only an Effective or Retired drawing is ever attached. The M-Files copy is fetched and staged for Clerical Supervisor approval. No change order: VISUAL did not change. |
| Revs match (or the approved rev matches), draft | `attach` | none | Drawing pages attached, `drawing_state` `attached`, drawing flags cleared, rev confirmed. Log "Drawing attached from M-Files". |
| Revs match, draft with a hand drawing at the same rev | `unchanged` | none | The hand drawing stays. |
| Revs match, past draft, same file (same sha256) | `unchanged` | none | Nothing. |
@@ -323,7 +323,7 @@ Flags live in `packets.flags`. A draft with any flag shows in Clerical's Flagged
| Flag | Text shown | What Clerical does |
|---|---|---|
| `drawing_needed` | Made from VISUAL - drawing not attached yet | Usually nothing: the drawing job attaches it. Run now to hurry it. Upload by hand only if it stays stuck. |
| `rev_mismatch` | The M-Files note, for example "Rev mismatch: VISUAL calls rev 2, M-Files has rev 3" | Get the rev corrected in VISUAL. Or a Clerical Supervisor chooses, with a reason and a signature: the latest (Effective) rev in M-Files, or the rev VISUAL calls when M-Files still holds it (Retired). Both PDFs can be opened from the packet first. |
| `rev_mismatch` | The M-Files note, for example "Rev mismatch: VISUAL calls rev 2, M-Files has rev 3; rev 2 is not in M-Files" | M-Files has no usable copy of the rev VISUAL calls. Get the rev corrected in VISUAL, or a Clerical Supervisor approves the staged M-Files rev with a reason and a signature. (When M-Files holds the rev VISUAL calls as Effective or Retired, it is attached automatically and the packet is not flagged.) |
| `not_released` | The note: "Not released in M-Files yet ... drafting status: rev N <where>" | Wait for drafting to release it, or upload the drawing by hand with a reason and a signature. |
| `not_found` | Drawing not in M-Files - check the drawing number in VISUAL | Check the drawing number in VISUAL and have it fixed there. Or upload by hand. |
| `lookup_failed` | M-Files lookup failed: (the reason) | Nothing at first: the job retries with backoff. If it persists, tell IT. |
+1 -1
View File
@@ -867,7 +867,7 @@ What the feed may never write:
When M-Files has a different released rev from VISUAL, the drawing job stages the M-Files copy. A Clerical Supervisor (PS-Clerical-Supervisor) can approve it on a draft with rev_approve: a reason of at least 8 characters and a signature ("Approve the M-Files revision"). The pages are attached and the approval is kept on the packet (`visual.rev_ok`). With nothing staged the answer is 409 `nothing_staged`.
The same action, with `use: "called"`, keeps the rev VISUAL calls instead, when M-Files still holds that rev at another status (Retired). The drawing job copies it on a draft flagged `rev_mismatch`. The same role, reason and signature apply, and the signed content carries `use`. `visual.rev_ok` records `use: "called"`, the M-Files status of the kept rev and the Effective rev at the time (`latest`). The log says "Rev VISUAL calls kept by hand". The choice holds while M-Files' Effective rev stays `latest`: no flag and no change order. A newer Effective rev flags the packet again, and a new VISUAL rev clears the choice. With no copy of that rev the answer is 409 `nothing_staged`.
VISUAL is the source of truth for the rev. When M-Files holds the rev VISUAL calls as Effective or Retired, the drawing job attaches it to the draft with no flag, so there is nothing for Clerical to approve (see [FEED.md](FEED.md), the decision table). rev_approve is only for a mismatch where M-Files has no usable copy of that rev. Packet Station never attaches a drawing at any other M-Files status. A packet whose `visual.rev_ok` has `use: "called"` (Clerical kept the rev VISUAL calls by hand, in the build before this rule) keeps it: that rev is now used anyway.
### Hand uploads on flagged drafts
+1 -1
View File
@@ -377,7 +377,7 @@ Migration 0004. Every ID part is text (`wo_base`, `lot`, `split`, `sub`, part ID
- `visual_ignored_wos`: work orders kept out by the go-live date, unique on (`wo_base`, `lot`, `split`, `sub`). `rel`, `project`, `unit_number`, `res`, `dwg`, `first_seen_batch`, `last_seen_at`, and `pulled_in_at`, `pulled_in_by`, `pulled_in_reason` when Clerical pulls one in.
- `visual_resource_map`: `resource` (PK), `target` (`fold`, `ignore` or a two-digit department code, by CHECK), `confirmed`, `updated_at`, `updated_by`. Seeded from the old build's `visual_map.json`, every entry unconfirmed. "Electical" is spelled that way in VISUAL.
- `drawing_lookups`: one row per drawing number as VISUAL writes it (`dwg` PK, trimmed). The last answer: `checked_at`, `ok`, `rev` (released), `name`, `obj_id`, `obj_version`, `file_id`, `file_version`, `file_size`, `base` (H sheet), `draft_rev`, `draft_where`, `in_drafting`, `note`. Retry state: `fail_count`, `failing_since`, `next_check_at`. The fetched file: `asset_id`, `sha256`. `visual_rev_seen` is the VISUAL rev at the last lookup, so a rev change moves the drawing to the front of the queue. A rev mismatch keeps the staged M-Files copy here for approval.
- `drawing_revisions` (0009): other revs of a drawing that M-Files still holds, one row per (`dwg`, `rev`). The drawing job writes it when a draft's VISUAL rev differs from the Effective rev and M-Files has a document at the VISUAL rev. `controlled` (M-Files' Controlled Status, for example Retired), `state` (workflow state, for example Superseded), `checked_at`, `name`, the M-Files identity (`obj_id`, `obj_version`, `file_id`, `file_version`, `file_size`), `base` (H sheet), and the fetched copy (`asset_id`, `sha256`). rev_approve with `use: "called"` attaches from here.
- `drawing_revisions` (0009): other revs of a drawing that M-Files still holds, one row per (`dwg`, `rev`). The drawing job writes it when a packet's VISUAL rev differs from the Effective rev and M-Files has that rev as Effective or Retired, and attaches drafts from it. `controlled` (M-Files' Controlled Status, for example Retired), `state` (workflow state, for example Superseded), `checked_at`, `name`, the M-Files identity (`obj_id`, `obj_version`, `file_id`, `file_version`, `file_size`), `base` (H sheet), and the fetched copy (`asset_id`, `sha256`).
Column additions in 0004: