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:
@@ -0,0 +1,77 @@
|
||||
"""Change C2 (Gitea issue 24): a Q.C. reject always needs a detailed reason, and a packet rejected without an NCR
|
||||
number cannot be accepted until the NCR number is given with the accept (QC_ACCEPT and QC_ACCEPT_AND_ROUTE).
|
||||
|
||||
The packet read says `ncr_required`; can() does not block on it (the NCR comes with the step); the server refuses
|
||||
the step without it, 422 ncr_required. The accept stores the NCR on its inspection and in the log."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from collections.abc import Iterator
|
||||
|
||||
import pytest
|
||||
from fakedir import FakeDirectory
|
||||
from pkthelpers import step
|
||||
from pshelpers import needs_pg
|
||||
from qchelpers import NCR, accept, at_qc, finish_inspection, reject, to_qc
|
||||
from shophelpers import SIGN, Shop, fresh, last_log, ok, one, open_shop, refused
|
||||
|
||||
from packetstation.settings import Settings
|
||||
|
||||
pytestmark = needs_pg
|
||||
|
||||
REASON = "Weld 2 undercut too deep"
|
||||
MSG = "Enter the NCR number of the reject first."
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def shop(pg_settings: Settings, fake_dir: FakeDirectory, dev_visual: None) -> Iterator[Shop]:
|
||||
yield from open_shop(pg_settings, fake_dir)
|
||||
|
||||
|
||||
def test_accept_after_a_reject_without_ncr_needs_one(shop: Shop) -> None:
|
||||
pkt = at_qc(shop)
|
||||
assert pkt["ncr_required"] is False
|
||||
out = ok(reject(shop, pkt, REASON))
|
||||
assert out["ncr_required"] is True and out["qc_last"]["ncr"] is None
|
||||
pkt = finish_inspection(shop, to_qc(shop, fresh(shop("sup.wes"), pkt["id"])))
|
||||
assert pkt["ncr_required"] is True
|
||||
# can() does not block on it: the NCR is input with the step
|
||||
assert {"qc_accept", "qc_accept_and_route"} <= set(pkt["can"]) and "qc_accept" not in pkt["blocked"]
|
||||
refused(accept(shop, pkt), 422, "ncr_required", MSG)
|
||||
refused(step(shop("qc.quinn"), pkt, "qc_accept_and_route", dept="09", sign=SIGN), 422, "ncr_required", MSG)
|
||||
refused(step(shop("qc.quinn"), pkt, "qc_accept", routed_to="databook", ncr=" ", sign=SIGN), 422, "ncr_required")
|
||||
refused(
|
||||
step(shop("qc.quinn"), pkt, "qc_accept", routed_to="databook", ncr="NCR-26-1", sign=SIGN), 422, "invalid_ncr"
|
||||
)
|
||||
assert fresh(shop("qc.quinn"), pkt["id"])["status"] == "qc"
|
||||
out = ok(step(shop("qc.quinn"), pkt, "qc_accept", routed_to="databook", ncr=" ncr-2026-0021 ", sign=SIGN))
|
||||
assert out["status"] == "complete" and out["ncr_required"] is False
|
||||
assert out["qc_last"]["result"] == "accepted" and out["qc_last"]["ncr"] == NCR
|
||||
row = one(
|
||||
shop.settings,
|
||||
"SELECT ncr, result FROM qc_inspections WHERE packet_id = %s ORDER BY id DESC LIMIT 1",
|
||||
(pkt["id"],),
|
||||
)
|
||||
assert tuple(row) == (NCR, "accepted")
|
||||
log = last_log(shop("qc.quinn"), pkt["id"])
|
||||
assert log["action"] == "Q.C. accepted → Clerical – Data Book"
|
||||
assert log["note"] == f"Quinn QC [Q1] · 2 welds VT accepted · {NCR}", log
|
||||
|
||||
|
||||
def test_accept_and_route_carries_the_ncr(shop: Shop) -> None:
|
||||
pkt = at_qc(shop)
|
||||
ok(reject(shop, pkt, REASON))
|
||||
pkt = finish_inspection(shop, to_qc(shop, fresh(shop("sup.wes"), pkt["id"])))
|
||||
out = ok(step(shop("qc.quinn"), pkt, "qc_accept_and_route", dept="09", ncr=NCR, sign=SIGN))
|
||||
assert out["status"] == "ready" and out["ncr_required"] is False and out["qc_last"]["ncr"] == NCR
|
||||
log = last_log(shop("qc.quinn"), pkt["id"])
|
||||
assert log["note"] == f"Quinn QC [Q1] · from 03 Weld Parts · {NCR}", log
|
||||
|
||||
|
||||
def test_a_reject_with_its_ncr_needs_none_at_accept(shop: Shop) -> None:
|
||||
pkt = at_qc(shop)
|
||||
out = ok(reject(shop, pkt, REASON, ncr=NCR))
|
||||
assert out["ncr_required"] is False and out["return_note"] == f"{NCR} · {REASON}"
|
||||
pkt = finish_inspection(shop, to_qc(shop, fresh(shop("sup.wes"), pkt["id"])))
|
||||
out = ok(accept(shop, pkt))
|
||||
assert out["status"] == "complete" and out["qc_last"]["ncr"] is None
|
||||
Reference in New Issue
Block a user