sku and item fix
This commit is contained in:
Binary file not shown.
Binary file not shown.
@@ -1 +1 @@
|
||||
{"runId": 64, "templateId": 2, "warehouseId": 4, "assembleStageId": 118, "finishedItemId": 13, "rawItemId": 18, "packItemId": 14}
|
||||
{"runId": 20, "templateId": 6, "warehouseId": 4, "assembleStageId": 30, "finishedItemId": 1, "rawItemId": 4, "packItemId": 3}
|
||||
@@ -35,6 +35,13 @@ SEED_BOTTLES = 100
|
||||
UNIT_COST = 3.0
|
||||
|
||||
|
||||
def production_reason(c, code):
|
||||
for r in c.get("/reason-codes?context=Production&pageSize=50").body["items"]:
|
||||
if r["code"] == code:
|
||||
return r["reasonCodeId"]
|
||||
sys.exit(f"FATAL: Production reason {code} not seeded.")
|
||||
|
||||
|
||||
def ensure_warehouse(c):
|
||||
for w in c.get(f"/warehouses?q={WAREHOUSE_CODE}&pageSize=50").body["items"]:
|
||||
if w["code"] == WAREHOUSE_CODE:
|
||||
@@ -72,9 +79,17 @@ def ensure_item(c, sku, name, content_qty, content_unit):
|
||||
return created.body
|
||||
|
||||
|
||||
def save_template(c, raw_item, finished_item, qty_per_batch, qty_unit):
|
||||
def save_template(c, raw_item, finished_item, qty_per_batch, qty_unit, suffix):
|
||||
"""
|
||||
One template per section, never a shared one.
|
||||
|
||||
Each section starts a run and leaves it InProgress, and a template with a live run is
|
||||
edit-locked (FR-MFG-06, 409 TEMPLATE_IN_USE) — so re-saving a single shared code would
|
||||
fail from the second section onward for reasons that have nothing to do with content units.
|
||||
"""
|
||||
code = f"{TEMPLATE_CODE}-{suffix}"
|
||||
payload = {
|
||||
"code": TEMPLATE_CODE, "name": "Content-unit smoke line",
|
||||
"code": code, "name": f"Content-unit smoke line ({suffix})",
|
||||
"stages": [{
|
||||
"key": "tmp-mix", "name": "Mix", "estimatedMinutes": 5, "posX": 0, "posY": 0,
|
||||
"fieldDefs": [],
|
||||
@@ -85,8 +100,8 @@ def save_template(c, raw_item, finished_item, qty_per_batch, qty_unit):
|
||||
}],
|
||||
"edges": [],
|
||||
}
|
||||
existing = next((t for t in c.get(f"/production-templates?q={TEMPLATE_CODE}").body["items"]
|
||||
if t["code"] == TEMPLATE_CODE), None)
|
||||
existing = next((t for t in c.get(f"/production-templates?q={code}").body["items"]
|
||||
if t["code"] == code), None)
|
||||
if existing:
|
||||
head = c.get(f"/production-templates/{existing['templateId']}")
|
||||
return c.put(f"/production-templates/{existing['templateId']}", payload, if_match=head.etag)
|
||||
@@ -134,10 +149,39 @@ def consume_once(c, chk, tid, wh, target_qty, label, expected_packs):
|
||||
chk.check(f"{label}: ledger qtyBase matches the consumption",
|
||||
round(abs(float(rows[0]["qtyBase"])), 4), expected_packs)
|
||||
|
||||
# Cancel so the script is re-runnable. A run left InProgress edit-locks its template
|
||||
# (FR-MFG-06), so the next execution could not re-save it and would fail with a 409 that
|
||||
# says nothing about content units. Cancelling also returns the consumed stock (FR-MFG-17),
|
||||
# which keeps the seeded on-hand stable across runs.
|
||||
c.post(f"/production-runs/{run['runId']}/cancel",
|
||||
{"reasonCodeId": production_reason(c, "PRD-CANCEL"), "note": "m4c cleanup"})
|
||||
|
||||
|
||||
def cancel_stale_runs(c):
|
||||
"""
|
||||
Cancel any InProgress run this script left behind previously.
|
||||
|
||||
Self-healing rather than merely tidy: a live run edit-locks its template, so without this
|
||||
a re-run (or an earlier interrupted run) fails at template save with 409 TEMPLATE_IN_USE —
|
||||
a failure that looks like a content-unit bug and is not one.
|
||||
"""
|
||||
ours = {t["templateId"] for t in c.get(f"/production-templates?q={TEMPLATE_CODE}&pageSize=50").body["items"]
|
||||
if t["code"].startswith(TEMPLATE_CODE)}
|
||||
if not ours:
|
||||
return
|
||||
stale = [r for r in c.get("/production-runs?status=InProgress&pageSize=200").body["items"]
|
||||
if r["templateId"] in ours]
|
||||
for r in stale:
|
||||
c.post(f"/production-runs/{r['runId']}/cancel",
|
||||
{"reasonCodeId": production_reason(c, "PRD-CANCEL"), "note": "m4c stale cleanup"})
|
||||
if stale:
|
||||
print(f"cancelled {len(stale)} stale run(s) from a previous execution")
|
||||
|
||||
|
||||
def main():
|
||||
c, chk, args = bootstrap(__doc__)
|
||||
print(f"API {args.api}")
|
||||
cancel_stale_runs(c)
|
||||
|
||||
bottle = ensure_item(c, SKU, "Smoke syrup 500ml bottle", CONTENT_QTY, "Ml")
|
||||
plain = ensure_item(c, PLAIN_SKU, "Smoke item with no content", None, None)
|
||||
@@ -155,23 +199,23 @@ def main():
|
||||
|
||||
# ------------------------------------------------- whole packs out of content units
|
||||
chk.section("1. A content quantity resolves to whole packs (2000 ml / 500 ml = 4)")
|
||||
saved = save_template(c, bottle["itemId"], finished["itemId"], 2000, "Content")
|
||||
saved = save_template(c, bottle["itemId"], finished["itemId"], 2000, "Content", "whole")
|
||||
if saved_ok(chk, "save the Content template", saved):
|
||||
consume_once(c, chk, saved.body["templateId"], wh, 1, "2000 ml", 4.0)
|
||||
|
||||
# --------------------------------------------------------------- fractional packs
|
||||
chk.section("2. A content quantity below one pack consumes a FRACTION of one (300 ml = 0.6)")
|
||||
saved = save_template(c, bottle["itemId"], finished["itemId"], 300, "Content")
|
||||
saved = save_template(c, bottle["itemId"], finished["itemId"], 300, "Content", "frac")
|
||||
if saved_ok(chk, "save the fractional Content template", saved):
|
||||
consume_once(c, chk, saved.body["templateId"], wh, 1, "300 ml", 0.6)
|
||||
|
||||
# ------------------------------------------------------------------ the guard rail
|
||||
chk.section("3. Content units are refused on an item that has no content size")
|
||||
refused = save_template(c, plain["itemId"], finished["itemId"], 100, "Content")
|
||||
refused = save_template(c, plain["itemId"], finished["itemId"], 100, "Content", "nocontent")
|
||||
chk.status("Content input on a contentless item", refused, 422)
|
||||
|
||||
chk.section("4. The same item still works when the formula is written in packs")
|
||||
saved = save_template(c, bottle["itemId"], finished["itemId"], 3, "Pack")
|
||||
saved = save_template(c, bottle["itemId"], finished["itemId"], 3, "Pack", "pack")
|
||||
if saved_ok(chk, "save the Pack template", saved):
|
||||
consume_once(c, chk, saved.body["templateId"], wh, 1, "3 bottles", 3.0)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user