Initial commit: PESCO NCR system

Complete Non-Conformance Report system replacing the PowerApps/SharePoint
prototype: FastAPI + SQLAlchemy 2 (async) + Alembic + MySQL 8 backend,
React 18 + Vite + TypeScript + MUI frontend, Entra ID auth (MSAL / JWKS,
group-gated), Microsoft Graph delegated Mail.Send notifications (OBO),
six-stage workflow state machine with server-side enforcement, atomic
NCR-YYYY-NNNN numbering, attachments with camera capture, immutable
field-level audit trail, admin reopen, reports + CSV export, WeasyPrint
PDF traveler, Power BI reporting views + read-only DB user, documented
VISUAL ERP job-lookup stub, pytest suite (26 tests), docker-compose
deployment.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
ang3l12
2026-07-13 11:41:22 -06:00
commit dea316b113
111 changed files with 13817 additions and 0 deletions

84
backend/app/domain.py Normal file
View File

@@ -0,0 +1,84 @@
"""Domain constants: roles, workflow stages, and the transition map.
Workflow note: an NCR in the "New Request" stage is awaiting Initial
Disposition — the initial-disposition review is the action a Disposition
Authority performs on a New Request, and it moves the NCR either to
Secondary Disposition (when secondary review is required) or straight to
Operations. All transitions are validated server-side against
ALLOWED_TRANSITIONS; anything else is rejected with HTTP 409.
"""
from enum import Enum
class Role(str, Enum):
REQUESTER = "requester"
DISPOSITION_AUTHORITY = "disposition_authority"
SECONDARY_DISPOSITION_AUTHORITY = "secondary_disposition_authority"
OPERATIONS = "operations"
QC_INSPECTOR = "qc_inspector"
COSTING = "costing"
ADMIN = "admin"
ALL_ROLES: set[str] = {r.value for r in Role}
ROLE_LABELS: dict[str, str] = {
Role.REQUESTER: "Requester",
Role.DISPOSITION_AUTHORITY: "Disposition Authority",
Role.SECONDARY_DISPOSITION_AUTHORITY: "Secondary Disposition Authority",
Role.OPERATIONS: "Operations",
Role.QC_INSPECTOR: "QC Inspector",
Role.COSTING: "Costing",
Role.ADMIN: "Admin",
}
class Stage(str, Enum):
NEW_REQUEST = "new_request"
SECONDARY_DISPOSITION = "secondary_disposition"
OPERATIONS = "operations"
QC_INSPECTION = "qc_inspection"
COSTING = "costing"
CLOSED = "closed"
STAGE_LABELS: dict[str, str] = {
Stage.NEW_REQUEST: "New Request",
Stage.SECONDARY_DISPOSITION: "Secondary Disposition",
Stage.OPERATIONS: "Operations",
Stage.QC_INSPECTION: "QC Inspection",
Stage.COSTING: "Costing",
Stage.CLOSED: "Closed",
}
# Stages an admin may reopen a closed NCR back into.
REOPEN_TARGET_STAGES: list[Stage] = [
Stage.NEW_REQUEST,
Stage.SECONDARY_DISPOSITION,
Stage.OPERATIONS,
Stage.QC_INSPECTION,
Stage.COSTING,
]
ALLOWED_TRANSITIONS: dict[Stage, set[Stage]] = {
Stage.NEW_REQUEST: {Stage.SECONDARY_DISPOSITION, Stage.OPERATIONS},
Stage.SECONDARY_DISPOSITION: {Stage.OPERATIONS},
Stage.OPERATIONS: {Stage.QC_INSPECTION},
Stage.QC_INSPECTION: {Stage.COSTING},
Stage.COSTING: {Stage.CLOSED},
# Reopen (admin only, reason required) — enforced separately.
Stage.CLOSED: set(REOPEN_TARGET_STAGES),
}
# Role allowed to act on the NCR in each stage (Admin is always allowed;
# Secondary Disposition additionally requires being an assigned authority).
STAGE_ACTING_ROLE: dict[Stage, Role] = {
Stage.NEW_REQUEST: Role.DISPOSITION_AUTHORITY,
Stage.SECONDARY_DISPOSITION: Role.SECONDARY_DISPOSITION_AUTHORITY,
Stage.OPERATIONS: Role.OPERATIONS,
Stage.QC_INSPECTION: Role.QC_INSPECTOR,
Stage.COSTING: Role.COSTING,
}
# Owners to notify when an admin reopens an NCR into a given stage.
STAGE_OWNER_ROLE: dict[Stage, Role] = STAGE_ACTING_ROLE