Phase 6: Q.C. inspection, project folders, packet documents and the digital ITP
The Q.C. screen (KPIs, boards, project folders), the Q.C. tab on the packet page (check items from the qc_check_items settings row, visual exam per weld, NDE, hardness with the NACE label, notes), accept with a route and a signature gated by qc_missing_empty, reject with a reason or an NCR number closing the inspection into qc_history, Q.C. folder documents per project and unit with superseding revisions, packet documents as a closed set with take-out reasons, the digital ITP per unit from the frozen template (line initials with CAS, unsign, N/A, customer codes, rejects with NCR, block signatures, sign-off with the PDF hook, admin reopen, the ITP log), hold-point warnings by department page group, the scoped policy check for unit and project writes, migration 0007, tests, Playwright scenarios and docs. Co-Authored-By: Claude Fable 5.1 <[email protected]>
This commit is contained in:
@@ -91,6 +91,11 @@ class Action(StrEnum):
|
||||
CO_REJECT = "co_reject"
|
||||
CO_HOLD_TOGGLE = "co_hold_toggle"
|
||||
CO_VERIFY = "co_verify"
|
||||
QC_DOC_ADD = "qc_doc_add"
|
||||
ITP_START = "itp_start"
|
||||
ITP_LINE_SIGN = "itp_line_sign"
|
||||
ITP_LINE_UNSIGN = "itp_line_unsign"
|
||||
ITP_BLOCK_UNSIGN = "itp_block_unsign"
|
||||
ITP_EDIT_LINE = "itp_edit_line"
|
||||
ITP_BLOCK_SIGN = "itp_block_sign"
|
||||
ITP_SIGN_OFF = "itp_sign_off"
|
||||
@@ -270,6 +275,12 @@ RULES: dict[Action, Rule] = {
|
||||
),
|
||||
A.CO_HOLD_TOGGLE: Rule(Who.CL, ANY, None),
|
||||
A.CO_VERIFY: Rule(Who.CO_VERIFIER, ANY, None, signature="Verify a change order for the department"),
|
||||
# Q.C. folder documents and the ITP belong to a project or a unit, not a packet: engine.check_scoped decides them.
|
||||
A.QC_DOC_ADD: Rule(Who.CL_OR_QC, ANY, None),
|
||||
A.ITP_START: Rule(Who.QC, ANY, None),
|
||||
A.ITP_LINE_SIGN: Rule(Who.QC, ANY, None),
|
||||
A.ITP_LINE_UNSIGN: Rule(Who.QC, ANY, None),
|
||||
A.ITP_BLOCK_UNSIGN: Rule(Who.QC, ANY, None),
|
||||
A.ITP_EDIT_LINE: Rule(Who.QC, ANY, None),
|
||||
A.ITP_BLOCK_SIGN: Rule(Who.QC, ANY, None, signature="Sign an ITP block"),
|
||||
A.ITP_SIGN_OFF: Rule(Who.QC, ANY, None, signature="Sign off the ITP"),
|
||||
@@ -313,8 +324,41 @@ EDIT_WHAT: dict[Action, str] = {
|
||||
A.CO_REJECT: "change orders",
|
||||
A.CO_HOLD_TOGGLE: "change orders",
|
||||
A.CO_VERIFY: "change orders",
|
||||
A.QC_DOC_ADD: "the Q.C. folder",
|
||||
A.ITP_START: "the ITP",
|
||||
A.ITP_LINE_SIGN: "the ITP",
|
||||
A.ITP_LINE_UNSIGN: "the ITP",
|
||||
A.ITP_BLOCK_UNSIGN: "the ITP",
|
||||
A.ITP_EDIT_LINE: "the ITP",
|
||||
A.ITP_BLOCK_SIGN: "the ITP",
|
||||
A.ITP_SIGN_OFF: "the ITP",
|
||||
A.ITP_REOPEN: "the ITP",
|
||||
}
|
||||
|
||||
# The actions on a project or unit rather than a packet (check them with engine.check_scoped).
|
||||
SCOPED: frozenset[Action] = frozenset(
|
||||
{
|
||||
A.QC_DOC_ADD,
|
||||
A.ITP_START,
|
||||
A.ITP_LINE_SIGN,
|
||||
A.ITP_LINE_UNSIGN,
|
||||
A.ITP_EDIT_LINE,
|
||||
A.ITP_BLOCK_SIGN,
|
||||
A.ITP_BLOCK_UNSIGN,
|
||||
A.ITP_SIGN_OFF,
|
||||
A.ITP_REOPEN,
|
||||
}
|
||||
)
|
||||
|
||||
# Their labels (the audit and log texts name the event more exactly).
|
||||
SCOPED_LABELS: dict[Action, str] = {
|
||||
A.QC_DOC_ADD: "Q.C. document added",
|
||||
A.ITP_START: "ITP started",
|
||||
A.ITP_LINE_SIGN: "ITP line approved",
|
||||
A.ITP_LINE_UNSIGN: "ITP line initial removed",
|
||||
A.ITP_BLOCK_UNSIGN: "ITP block signature removed",
|
||||
A.ITP_EDIT_LINE: "ITP changed",
|
||||
A.ITP_BLOCK_SIGN: "ITP block signed",
|
||||
A.ITP_SIGN_OFF: "ITP signed off",
|
||||
A.ITP_REOPEN: "ITP reopened",
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user