feat: add production templates API and documentation for manufacturing phase 2
- Implemented CRUD operations for production templates, including listing, retrieving, creating, updating, and deactivating templates. - Introduced a new API contract for production runs, detailing the lifecycle from creation to completion, including handling of stock inputs and outputs. - Documented the architecture, requirements, entity model, and API contract for the manufacturing phase 2, ensuring clarity on the production process and its integration with existing systems.
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
"""Run the whole manufacturing smoke suite in dependency order.
|
||||
|
||||
python Backend/smoke/run_all.py
|
||||
|
||||
Order matters: m4 creates the isolated SMOKE-PRD warehouse and drains it, m5 consumes the
|
||||
run m4 leaves with its terminal stage InProgress. Each script is individually re-runnable,
|
||||
but m5 deliberately refuses to run twice against an already-approved terminal stage — that
|
||||
guard is what stops it silently asserting against the wrong state.
|
||||
|
||||
Prerequisites: ERPCore on :5224 and AuthHex on :5602 (override with ERP_SMOKE_API /
|
||||
ERP_SMOKE_AUTH / ERP_SMOKE_USER / ERP_SMOKE_PASSWORD).
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
SCRIPTS = [
|
||||
("M2 templates + graph validation", "m2_templates.py"),
|
||||
("M3 run creation / board / quantities", "m3_runs.py"),
|
||||
("M4 stage start / complete / approve / transfer", "m4_stage_actions.py"),
|
||||
("M4b UOM conversion on stock inputs", "m4b_uom_conversion.py"),
|
||||
("M5 terminal receipt + cost pool", "m5_receipt.py"),
|
||||
("M6+M7 leftover / rework / cancel", "m6_m7_leftover_rework_cancel.py"),
|
||||
]
|
||||
|
||||
SUMMARY = re.compile(r"^(\S+): (\d+)/(\d+) assertions passed")
|
||||
|
||||
|
||||
def main() -> int:
|
||||
here = Path(__file__).parent
|
||||
results = []
|
||||
failed = False
|
||||
|
||||
for label, script in SCRIPTS:
|
||||
print(f"\n{'=' * 70}\n{label} ({script})\n{'=' * 70}", flush=True)
|
||||
proc = subprocess.run(
|
||||
[sys.executable, script, *sys.argv[1:]],
|
||||
cwd=here, capture_output=True, text=True, encoding="utf-8", errors="replace",
|
||||
)
|
||||
sys.stdout.write(proc.stdout)
|
||||
if proc.stderr.strip():
|
||||
sys.stderr.write(proc.stderr)
|
||||
|
||||
passed = total = 0
|
||||
for line in proc.stdout.splitlines():
|
||||
m = SUMMARY.match(line.strip())
|
||||
if m:
|
||||
passed, total = int(m.group(2)), int(m.group(3))
|
||||
results.append((label, passed, total, proc.returncode))
|
||||
if proc.returncode != 0:
|
||||
failed = True
|
||||
|
||||
print(f"\n{'=' * 70}\nSUITE SUMMARY\n{'=' * 70}")
|
||||
grand_passed = grand_total = 0
|
||||
for label, passed, total, rc in results:
|
||||
grand_passed += passed
|
||||
grand_total += total
|
||||
state = "OK " if rc == 0 else "FAIL"
|
||||
print(f" [{state}] {label:<48} {passed}/{total}")
|
||||
print(f"\n TOTAL: {grand_passed}/{grand_total} assertions"
|
||||
+ (" — ALL GREEN" if not failed else " (SUITE FAILED)"))
|
||||
return 1 if failed else 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
Reference in New Issue
Block a user