Skip to content

F25 (part 2): Sales lines sell products — unit factor snapshots, quantity_base, grade-mapped allocation #99

Closed

Description

@mforce

Spec §10.5 + §9.7 conversion rules. Second half of the Phase 1.1 product-catalog item; builds on the part-1 catalog (#97, PR #98).

Scope

Domain / persistence:

  • SalesOrderItem gains: ProductId, ProductTypeSnapshot (spec §10.5), Unit, BaseUnitFactor (eggs-per-unit snapshotted at line creation — §9.7: a later carton/case redefinition must never reinterpret existing orders), QuantityBase (always individual eggs: quantity × factor). Quantity becomes the unit count.
  • Data migration: for each egg grade referenced by existing order items, auto-create a product (grade name, unit Egg, mapped to that grade) if none maps to it yet; backfill existing lines with that product, Unit=Egg, BaseUnitFactor=1, QuantityBase=Quantity. Frozen history — no money changes.

Behavior:

  • Add-item takes productId + quantity + unit (defaults to the product's DefaultUnit). Factor resolves from the account's active EggUnitConversion row at line creation and is snapshotted; missing/inactive conversion → 422.
  • Product must be active and an egg product; allocation reserves QuantityBase eggs FIFO from lots of the product's mapped grade (mapping resolved at line creation — later re-pointing never rewrites existing lines).
  • Unit price defaults from the product's default price (per selling unit) when the request omits it; stock/overselling guard runs on QuantityBase.
  • Confirm/void/allocation release logic unchanged otherwise; version race tests per AGENTS.md.

SPA (SalesPage): line entry switches from grade picker to product picker (active products) + unit + quantity; shows resolved eggs-per-unit and line total; price prefilled from the product default, editable.

Sync: CSV export sales-order-items dataset gains the new columns; GLOSSARY (Product line, quantity_base) + Help (Customers & sales section) + Help TOC; audit filter untouched (no new actions).

Tests

  • Line snapshots: carton=12 at sale, redefine carton=30, old line keeps factor 12 / new line gets 30
  • quantity_base math + FIFO allocation from the mapped grade's lots; overselling guard on eggs
  • Product inactive / non-mapped / missing conversion → 422
  • Migration backfill: pre-existing grade-lines get auto-created products, factor 1, unchanged totals
  • Grade re-point after sale: old lines keep the original allocation
  • Worker can still record/confirm orders (production-side open); race tests
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions