Skip to content

Canonical Supply Reconciliation & Heal-on-Write

Status: Completed (operations 6.0.0) Tickets: PDEV-930 (reconciliation + healing), PDEV-928 (blank printed SUPPLIER), PDEV-944 (atomic single-supply update) Repositories: operations (6.0.0), api-test (item/canonical-supply collection), documentation

Connect Supply to Supplier (operations 5.0.0) introduced the SupplierReference → VENDOR-BusinessRole model. Dev verification then showed item/supply edits degraded supplier linkage rather than self-healing it (PDEV-930): the embedded projection drifted from the authoritative ItemSupply, a full-item update did not reverse-propagate a supplier rename, and an empty defaultSupply printed a blank SUPPLIER (PDEV-928). This follow-up makes the behavior canonical.

  • Unified canonical resolution. A full-item update and the dedicated supply route apply the same resolution; the embedded primarySupply/secondarySupply projection is re-derived from the authoritative ItemSupply instead of persisted from the request.
  • Heal-on-write. A write meeting an irregular stored pre-state heals it toward canonical form (re-link or reconcile-by-name, re-derive a stale projection, fill an empty supplier name from the business affiliate, clear a stale defaultSupply, keep a retired-vendor link without reactivating it). Data is never persisted less canonical than read; each heal records a system note.
  • Stale-write rejection (Q12). A write whose effective basis a later version has superseded is rejected as a 409 conflict.
  • Distinct slots (INV-A8). Primary and secondary must reference distinct supplies.
  • Canonical delete. Removing a referenced supply clears the referencing slot (and a dangling default) instead of failing.
  • Vendor rename/retire cascade. Confirmed end-to-end: a VENDOR rename refreshes linking items’ embedded supplier name; a removal marks them stale without reactivation.
  • Atomic single-supply update (PDEV-944). The supply write and parent-projection refresh share one transaction and write a single Item version.
  • Printed SUPPLIER fix (PDEV-928).
  • mutation-mode collapsed to PROPAGATE-only — the STRICT and LAX values were removed (the parameter is accepted-and-ignored). This supersedes DQ-011.
  • Item↔ItemSupply reverse dependency eliminated. ItemSupplyService became a pure child: the BA→item reaction returns updated supplies for the parent ItemService to project (via the new ItemVendorCascade), and the VENDOR-role observer moved to ItemSupplyRoleListener on the Item side. This revises the two-phase setParentService wiring originally taken from DQ-004.
  • Draft-optional REST update. The canonical write path closes any open draft and writes directly, so a no-draft update succeeds.