Build Seth's changes C1 to C11 (Gitea issues 1, 8, 18, 23, 24, 25, 27, 31, 32, 33, 36)
- C1 (issue 1): over target follows VISUAL ticket hours, not the timer. - C2 (issue 24): a Q.C. reject always needs a reason; accept needs an NCR number after a reject without one. - C3 (issue 25): an incomplete unit ITP blocks filing. - C4 (issue 27): prints open the print dialog on the page, no new tab. - C5 (issue 31): filing is blocked while VISUAL shows a work order open; the feed sets vclosed on VISUAL packets. - C6 (issue 8): the data book leaves out the history pages. - C7 (issue 18): the supervisor approves each received short; accept and filing wait for it. - C8 (issue 23): per-department checklists, edited by the department supervisor or Admin, frozen at START. - C9 (issue 32): Q.C. and Clerical may run the stamp check. - C10 (issue 33): the PM screen and reports are for PS-ProjectMgmt and Admin only. - C11 (issue 36): the Stall screen lists the packets assigned to the welder, at the supervisor's stall. Migration 0011. Docs: PLAN (also issue 9 confirmed, issue 4 asked), POLICY, SECURITY, SCHEMA, FEED, README, CHANGELOG. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
@@ -23,6 +23,7 @@ from psycopg.rows import dict_row
|
||||
from psycopg.types.json import Jsonb
|
||||
|
||||
from .. import audit, events, policy
|
||||
from ..domain import packets as packets_mod
|
||||
from ..domain import projects as projects_domain
|
||||
from ..text import LIMITS, RX_PROJECT, clean_opt
|
||||
from . import changes, materials
|
||||
@@ -1038,7 +1039,7 @@ def _observe(run: _Run, seen: Mapping[WoKey, str], labor: LaborMap | None) -> No
|
||||
with conn.cursor(row_factory=dict_row) as cur:
|
||||
legs = cur.execute(
|
||||
"SELECT w.id, w.packet_id, w.wo_base, w.lot, w.split, w.sub, w.seq, w.visual_status," # noqa: S608
|
||||
" p.status::text AS status, p.flags, p.visual_closed_at FROM packet_work_orders w"
|
||||
" p.status::text AS status, p.flags, p.visual_closed_at, p.vclosed_at FROM packet_work_orders w"
|
||||
f" JOIN packets p ON p.id = w.packet_id WHERE {_LIVE} AND w.packet_id IN (SELECT w2.packet_id"
|
||||
f" FROM packet_work_orders w2, {_UNNEST.replace('k(', 'k2(')} WHERE w2.wo_base = k2.b AND w2.lot = k2.l"
|
||||
" AND w2.split = k2.sp AND w2.sub = k2.su) ORDER BY w.packet_id, w.sort, w.id",
|
||||
@@ -1069,11 +1070,20 @@ def _observe(run: _Run, seen: Mapping[WoKey, str], labor: LaborMap | None) -> No
|
||||
head = pl[0]
|
||||
status = head["status"]
|
||||
flags = list(head["flags"] or [])
|
||||
if sts and all(s == "C" for s in sts) and head["visual_closed_at"] is None:
|
||||
# C5: the feed is the one writer of vclosed on a VISUAL packet. Every leg closed (or cancelled) sets it, and
|
||||
# the Clerical board moves the packet to "Ready for data book"; a leg seen open again clears it.
|
||||
done = bool(sts) and all(s in packets_mod.LEG_DONE for s in sts)
|
||||
all_closed = bool(sts) and all(s == "C" for s in sts)
|
||||
if (done and head["vclosed_at"] is None) or (all_closed and head["visual_closed_at"] is None):
|
||||
|
||||
def closed(sw: SysWrite) -> bool:
|
||||
sw.conn.execute("UPDATE packets SET visual_closed_at = now() WHERE id = %s", (sw.id,))
|
||||
sw.changed("visual_closed_at")
|
||||
def closed(sw: SysWrite, all_closed: bool = all_closed) -> bool:
|
||||
sw.conn.execute(
|
||||
"UPDATE packets SET vclosed_at = coalesce(vclosed_at, now()), vclosed_by = CASE WHEN vclosed_at"
|
||||
" IS NULL THEN NULL ELSE vclosed_by END, visual_closed_at = CASE WHEN %s THEN"
|
||||
" coalesce(visual_closed_at, now()) ELSE visual_closed_at END WHERE id = %s",
|
||||
(all_closed, sw.id),
|
||||
)
|
||||
sw.changed("vclosed", "visual_closed_at")
|
||||
return True
|
||||
|
||||
if run.guarded(
|
||||
@@ -1087,6 +1097,26 @@ def _observe(run: _Run, seen: Mapping[WoKey, str], labor: LaborMap | None) -> No
|
||||
closed,
|
||||
):
|
||||
run.counts["closed_observed"] += 1
|
||||
elif not done and any(s and s not in packets_mod.LEG_DONE for s in sts) and head["vclosed_at"] is not None:
|
||||
|
||||
def reopened(sw: SysWrite) -> bool:
|
||||
sw.conn.execute(
|
||||
"UPDATE packets SET vclosed_at = NULL, vclosed_by = NULL, visual_closed_at = NULL WHERE id = %s",
|
||||
(sw.id,),
|
||||
)
|
||||
sw.changed("vclosed", "visual_closed_at")
|
||||
return True
|
||||
|
||||
run.guarded(
|
||||
f"reopened {pid}",
|
||||
_flag_write,
|
||||
run,
|
||||
pid,
|
||||
status,
|
||||
"Open again in VISUAL (observed)",
|
||||
", ".join(packets_mod.open_wos({"legs": state_legs})) or None,
|
||||
reopened,
|
||||
)
|
||||
cancelled = any(s == "X" for s in sts)
|
||||
if cancelled and "cancelled" not in flags:
|
||||
|
||||
|
||||
Reference in New Issue
Block a user