Files
2026-08-17 22:23:10 +02:00

12 KiB

EXPIRATION TRACKING — TASKS.md

Backend

EXP-BE-001

ID: EXP-BE-001 Title: Product expiration_tracking_enabled column Goal: Add boolean column to catalog_products Why: Products need to declare whether they require expiration tracking Dependencies: None Applications: Backend Modules: catalog_products table, Product domain, ProductRepository Database impact: ALTER TABLE catalog_products ADD COLUMN expiration_tracking_enabled boolean NOT NULL DEFAULT false API contracts: GET /products/:id returns field; PATCH /products/:id accepts field Permissions: admin Implementation: Add to NewProduct interface, ProductPatch type, pg-product-repository Tests: Unit — default false; Integration — column exists with correct default Migration: See MIGRATION.md Phase 1 Expected blast radius: Low — only affects new product queries Definition of Done: Column exists, defaults to false, persists on create/update

EXP-BE-002

ID: EXP-BE-002 Title: InventoryLot domain and repository Goal: New InventoryLot entity and InventoryLotRepository port + PgInventoryLotRepository Why: Core data model for lot-level stock Dependencies: EXP-BE-001 Applications: Backend Modules: inventory/domain, inventory/infrastructure Database impact: CREATE TABLE inventory_lots (see DESIGN.md) API contracts: None yet (repository only) Permissions: N/A Implementation: InventoryLot interface, CreateLotCommand, InventoryLotRepository port, PgInventoryLotRepository Tests: Unit — CRUD operations; Integration — table constraints, FK Expected blast radius: Low — new table, no existing data touched Definition of Done: Lot CRUD works, FK to catalog_variants enforced, CHECK constraint on expiration_date

EXP-BE-003

ID: EXP-BE-003 Title: LotService — create, update, delete, FEFO allocation Goal: Domain service handling lot business rules Why: Encapsulates expiration validation and FEFO logic Dependencies: EXP-BE-002 Applications: Backend Modules: inventory/application API contracts: None (domain service) Permissions: N/A Implementation: LotService class with createLot (validates expiry required), allocateLots (FEFO), adjustQuantity Tests: Unit — missing expiry rejected; past expiry rejected; FEFO order; partial lot allocation Expected blast radius: Low Definition of Done: LotService methods have correct business rules; FEFO allocates from earliest expiry first

EXP-BE-004

ID: EXP-BE-004 Title: InventoryLots API routes Goal: CRUD endpoints for lots + availability query with filter Why: Admin needs to manage lots; frontend needs to display them Dependencies: EXP-BE-003 Applications: Backend Modules: inventory/api API contracts: GET /inventory/lots, POST /inventory/lots, PATCH /inventory/lots/:id, DELETE /inventory/lots/:id (all admin) Permissions: admin role required Implementation: New route registrations in inventory module; serialize LotService results Tests: Integration — CRUD round-trip; filter=expiring|expired|all Expected blast radius: Low — new routes Definition of Done: All 5 routes respond correctly; filter parameters work; auth enforced

EXP-BE-005

ID: EXP-BE-005 Title: InventoryService — integrate LotService for expiration products Goal: Extend existing InventoryService to delegate to LotService when expiry is enabled Why: Preserve existing InventoryServicePort contract while adding expiration support Dependencies: EXP-BE-001, EXP-BE-003 Applications: Backend, Checkout Modules: inventory/application, checkout API contracts: Existing InventoryServicePort contract unchanged Permissions: N/A Implementation: In InventoryService, check product.expiration_tracking_enabled; if true, use LotService.getAvailableStock and LotService.allocateLots; feature flag gates behavior Tests: Unit — delegation to LotService for expiry products; existing path for non-expiry products Expected blast radius: Checkout uses InventoryServicePort — must not break Definition of Done: Checkout reserve/confirm still works for both expiry and non-expiry products; FEFO used for expiry products

EXP-BE-006

ID: EXP-BE-006 Title: Extend inventory_movements with lot operation types Goal: Track lot_create, lot_adjust, lot_delete in movement audit log Why: Full auditability of lot changes Dependencies: EXP-BE-002 Applications: Backend Modules: inventory/infrastructure, security Database impact: ALTER TABLE inventory_movements — new operation types + optional lot_id FK API contracts: Movement audit reflects lot operations Permissions: N/A Implementation: Add operation types in pg-inventory-repository insertMovement calls Tests: Integration — movements logged with correct operation type Expected blast radius: Low Definition of Done: Lot mutations produce audit entries

Database

EXP-DB-001

ID: EXP-DB-001 Title: Run expiration tracking migrations Goal: Apply all DB changes from MIGRATION.md Phase 1 Why: Infrastructure for lot model Dependencies: EXP-BE-001 (column on catalog_products), EXP-BE-002 (lots table) Applications: Database Modules: N/A Database impact: See MIGRATION.md Phase 1 API contracts: N/A Permissions: DBA Implementation: Add migration file or run raw SQL against dev DB; apply via docker-compose migration pipeline Tests: Verify schema after migration Expected blast radius: Low — additive changes Definition of Done: Migration runs without error; new columns/tables exist with correct constraints

Admin

EXP-ADM-001

ID: EXP-ADM-001 Title: Product Editor — expiration tracking toggle Goal: Add checkbox to General tab: "Track expiration dates" Why: Admin configures per-product policy Dependencies: EXP-BE-001 Applications: Admin Modules: ProductEditor, GeneralSection Database impact: None (uses EXP-BE-001) API contracts: PATCH /catalog/products/:id Permissions: products.write Implementation: Add toggle to GeneralSection; saves { expiration_tracking_enabled: boolean } on save Tests: Toggle saves correctly; shows/hides expiration UI based on state Expected blast radius: Low Definition of Done: Admin can enable/disable expiry tracking per product; toggle persists

EXP-ADM-002

ID: EXP-ADM-002 Title: Inventory — lot-level stock view Goal: Show lots table for expiry-tracking products in inventory page Why: Operational visibility into expiration state Dependencies: EXP-BE-004 Applications: Admin Modules: InventorySection, inventory page Database impact: None API contracts: GET /inventory/lots?variant_id=X Permissions: inventory.read Implementation: Extend InventorySection to show lots when product has expiry enabled; compute status (VALID/NEAR_EXPIRY/EXPIRED) client-side from FLAG_EXPIRY_WARNING_DAYS Tests: Lot table renders correctly; status computed from dates Expected blast radius: Low Definition of Done: Lots displayed with correct quantity, date, and status badge

EXP-ADM-003

ID: EXP-ADM-003 Title: Inventory — lot create/edit/delete Goal: Inline lot management in inventory section Why: Admin must be able to add/update/remove lots Dependencies: EXP-BE-004 Applications: Admin Modules: InventorySection Database impact: None API contracts: POST/PATCH/DELETE /inventory/lots/:id Permissions: inventory.write Implementation: Add lot form (quantity, expiration date); inline edit on lot row; delete confirmation Tests: Create lot with required expiry date; edit quantity; delete lot; 422 shown for missing expiry Expected blast radius: Low Definition of Done: Admin can fully manage lots; validation errors shown correctly

EXP-ADM-004

ID: EXP-ADM-004 Title: Inventory filters — expiring, expired, all, no-expiry Goal: Filter inventory page by expiration status Why: Operational efficiency for stock management Dependencies: EXP-BE-004 Applications: Admin Modules: inventory page Database impact: None API contracts: GET /inventory/lots?filter=expiring|expired|all|no-expiry Permissions: inventory.read Implementation: Add filter tabs/dropdown to inventory page; calls API with filter param Tests: Each filter returns correct lot subset Expected blast radius: Low Definition of Done: Filters work; filter state reflected in URL or UI

QA

EXP-QA-001

ID: EXP-QA-001 Title: Expiration tracking regression tests Goal: Ensure existing checkout flow is unbroken Why: No regressions on existing products Dependencies: EXP-BE-005, EXP-DB-001 Applications: QA Modules: E2E tests Tests:

  • Normal product (non-expiry) still checks out correctly
  • Expiry product with no lots: unavailable
  • Expiry product with valid lot: available and reservable
  • FEFO: earliest expiry lot consumed first
  • Expired lot: contributes zero sellable units Expected blast radius: N/A Definition of Done: All regression tests pass

EXP-QA-002

ID: EXP-QA-002 Title: Expiration tracking unit/integration tests Goal: Comprehensive test coverage for all new domain code Why: Business rules must be correct Dependencies: EXP-BE-003, EXP-BE-004, EXP-BE-005 Applications: QA Modules: Backend test suite Tests: See TESTS.md Expected blast radius: N/A Definition of Done: 100% pass rate on expiration-specific tests


Task Summary Table

Task Layer Feature Depends On Risk Parallel
EXP-BE-001 Backend Product expiry column Low *
EXP-BE-002 Backend Lot model + repository Low *
EXP-BE-003 Backend LotService domain EXP-BE-002 Low *
EXP-BE-004 Backend Lot API routes EXP-BE-003 Low *
EXP-BE-005 Backend InventoryService + LotService EXP-BE-001, EXP-BE-003 Medium *
EXP-BE-006 Backend Movement audit for lots EXP-BE-002 Low EXP-BE-004
EXP-DB-001 DB Run migrations EXP-BE-001, EXP-BE-002 Low *
EXP-ADM-001 Admin Product expiry toggle EXP-BE-001 Low *
EXP-ADM-002 Admin Lot stock view EXP-BE-004 Low *
EXP-ADM-003 Admin Lot CRUD EXP-BE-004 Low *
EXP-ADM-004 Admin Expiry filters EXP-BE-004 Low *
EXP-QA-001 QA Checkout regression EXP-BE-005, EXP-DB-001 Medium After backend
EXP-QA-002 QA Domain unit tests All BE tasks Low With backend

Parallel group: EXP-BE-001 and EXP-BE-002 can run in parallel. BE-003 depends on BE-002. BE-004 and BE-006 depend on BE-003. BE-005 depends on BE-001 + BE-003.

Recommended order:

  1. EXP-BE-001 + EXP-BE-002 (parallel, no dependencies)
  2. EXP-BE-003 (depends on BE-002)
  3. EXP-BE-004 + EXP-BE-006 (depend on BE-003, parallel)
  4. EXP-DB-001 (run after BE-001 + BE-002 code is deployed)
  5. EXP-BE-005 (depends on BE-001 + BE-003)
  6. EXP-ADM-001 (depends on BE-001)
  7. EXP-ADM-002 + EXP-ADM-003 + EXP-ADM-004 (depend on BE-004, parallel)
  8. EXP-QA-001 + EXP-QA-002 (after all backend + admin)

High-risk tasks: EXP-BE-005 (changes InventoryService contract internal behavior, affects checkout — thorough regression testing required).

MVP boundary: EXP-BE-001 through EXP-BE-005 + EXP-DB-001 + EXP-ADM-001 through EXP-ADM-004. EXP-BE-006 (audit) is low priority for MVP. EXP-QA-002 is bundled with implementation. EXP-QA-001 is blocking go-live.