diff --git a/backend/slabs.py b/backend/slabs.py index 814c5b3..e3ca79e 100644 --- a/backend/slabs.py +++ b/backend/slabs.py @@ -95,9 +95,19 @@ def _check_taxonomy(conn, table: str, val: Any) -> bool: return conn.execute(f"SELECT 1 FROM {table} WHERE id=?", (val,)).fetchone() is not None +# Capture-only fields required to create a slab. The Review screen fills the +# taxonomy/content fields after create (CREATE.md §1: "every other field stays +# editable until create"), so create must accept a capture-math payload. +# client_rev is server-managed (set to 1 at create) — never required from the client. +REQUIRED_CREATE_FIELDS = [ + "id", "sku", "length_in", "thickness_in", "sqft", "bdft", + "width_min_in", "width_max_in", "width_avg_in", +] + + @router.post("", status_code=201) async def create_slab(payload: Dict[str, Any]) -> Dict[str, Any]: - missing = [f for f in ALLOWED_FIELDS if f not in payload] + missing = [f for f in REQUIRED_CREATE_FIELDS if f not in payload] if missing: return _err("validation", "missing fields", {"fields": missing}, status=400) conn = get_connection() @@ -105,9 +115,14 @@ async def create_slab(payload: Dict[str, Any]) -> Dict[str, Any]: return _err("duplicate_sku", "SKU already exists", {"sku": payload["sku"]}, status=409) now = _now_iso() data = _encode(payload) - cols = [f for f in ALLOWED_FIELDS if f in data] + ["status", "client_rev", "server_rev", "deleted_at", "created_at", "updated_at"] - vals = [data[f] for f in cols if f in data] + ["calibrated", 1, 1, None, now, now] + allowed_cols = [f for f in ALLOWED_FIELDS if f in data] + server_cols = ["status", "client_rev", "server_rev", "deleted_at", "created_at", "updated_at"] + server_vals = ["calibrated", 1, 1, None, now, now] + cols = allowed_cols + server_cols + # One value per col, in cols order: data values for the allowed fields, then the 6 server values. + vals = [data[f] for f in allowed_cols] + server_vals ph = ",".join(["?"] * len(cols)) + assert len(vals) == len(cols), f"create_slab binding mismatch: {len(vals)} vals vs {len(cols)} cols" conn.execute(f"INSERT INTO slabs ({', '.join(cols)}) VALUES ({ph})", vals) conn.commit() row = conn.execute("SELECT * FROM slabs WHERE id=?", (payload["id"],)).fetchone()