5643d89236
- Added `businessPricing.service.js` to handle business customer pricing logic. - Introduced `money.js` for money parsing, formatting, and calculations. - Created `pricing.service.js` to manage variant quoting and promotion application. - Updated validation schemas in `catalogue.schemas.js` and `inventoryMerchandising.schemas.js` for new pricing and inventory features. - Implemented cron job for inventory reservation expiry in `inventoryReservationExpiry.cron.js`. - Created database migrations for catalogue and inventory structures. - Added unit tests for catalogue localization, validation, and inventory merchandising functionalities.
86 lines
4.3 KiB
Markdown
86 lines
4.3 KiB
Markdown
# ZUMRI Phase 5 Inventory and Merchandising
|
|
|
|
## Objective
|
|
Provide authoritative multi-warehouse stock, reservation primitives, wholesale pricing, price quotes, promotions, coupons, and scheduled localized banners for Phase 6 consumers.
|
|
|
|
## Existing Components Reused
|
|
ProductVariant, BusinessCustomer, Upload, authorization middleware, audit queue, cron bootstrap, Zod, Sequelize, and catalogue localization are reused.
|
|
|
|
## Inventory Architecture
|
|
Catalogue never stores stock. `InventoryBalance` is authoritative per warehouse/variant; availability is `onHand - reserved`. All writes pass through one service and append an immutable ledger event.
|
|
|
|
## Warehouses
|
|
Multiple active/inactive warehouses and a transactionally selected default are supported. Default warehouse selection is deterministic.
|
|
|
|
## Inventory Balance
|
|
Quantities are integers. Service invariants prevent negative stock and `reserved > onHand`.
|
|
|
|
## Inventory Ledger
|
|
Every adjustment, reservation lifecycle event, and transfer has a unique event ID. There is no ledger update API.
|
|
|
|
## Stock Adjustments
|
|
Adjustments lock balances, enforce invariants, append a ledger row, support HTTP idempotency keys, and emit audit events.
|
|
|
|
## Transfers
|
|
Synchronous transfers lock warehouse IDs in sorted order, then create paired OUT/IN ledger rows.
|
|
|
|
## Reservation Architecture
|
|
Unique reservation keys make reserve/release/consume idempotent. Generic references avoid premature cart/order coupling.
|
|
|
|
## Reservation Concurrency
|
|
MySQL transactions and row-level `FOR UPDATE` locks serialize competitors for final units. Real multi-connection InnoDB validation remains a staging prerequisite.
|
|
|
|
## Reservation Expiry
|
|
A no-overlap minute cron reconciles up to 100 expired ACTIVE records per run; each record is locked and the database state is authoritative.
|
|
|
|
## Availability Projection
|
|
Public responses expose status and boolean sale availability only. Out-of-stock catalogue items remain visible.
|
|
|
|
## Low Stock
|
|
Low stock is centrally defined as available quantity less than or equal to the configured balance threshold.
|
|
|
|
## Business Pricing
|
|
Wholesale rules remain separate from retail base price and are limited to approved ACTIVE business accounts.
|
|
|
|
## Business Tiers
|
|
Business customers may reference an active tier; customer-specific negotiated rules are also supported.
|
|
|
|
## MOQ
|
|
MOQ belongs to a wholesale rule and never applies to retail fallback.
|
|
|
|
## Volume Pricing
|
|
Integer, non-overlapping ranges select the greatest eligible minimum quantity; final maximum may be null.
|
|
|
|
## Pricing Precedence
|
|
Retail -> eligible customer override (preferred over tier) -> volume tier -> highest-priority automatic promotion -> permitted coupon. Effective price floors at zero.
|
|
|
|
## Promotions
|
|
Percentage, fixed amount, and fixed price campaigns support dates, priority, minimum quantity, audiences, stacking, and normalized targets.
|
|
|
|
## Coupons
|
|
Codes are uppercase and validated against coupon/promotion state and schedule. Redemption counters are not fabricated before orders.
|
|
|
|
## Banners
|
|
Placements are string-configurable. Status, schedule, sort order, audience, and optional business tier drive projection.
|
|
|
|
## Localization
|
|
Banner translations use `en`, `si`, and `ta`, with requested locale then English fallback.
|
|
|
|
## Permissions
|
|
Inventory read/adjust/transfer/reservation/warehouse, business pricing read/manage, promotion read/manage, and banner manage permissions were added.
|
|
|
|
## Audit Events
|
|
Warehouse, adjustment, transfer, business-price, promotion, coupon, and banner mutations enqueue sanitized Phase 2 audit activities.
|
|
|
|
## Database Changes
|
|
The forward-only `20260903050000` migration adds 13 domain tables and the BusinessCustomer tier reference. Earlier migrations are unchanged.
|
|
|
|
## Tests
|
|
Unit coverage verifies decimal precision, zero floor, availability states, strict input, coupon normalization, and permission boundaries. Existing regression tests remain green.
|
|
|
|
## Remaining Known Issues
|
|
Patch endpoints for promotion/coupon/banner/business pricing and real infrastructure integration tests remain follow-up hardening. No production migration was run.
|
|
|
|
## Phase 6 Prerequisites
|
|
Run legacy-data prechecks and migration on staging; validate constraints and concurrent reservations using two real InnoDB connections; verify cron in a multi-instance deployment; seed permissions and warehouse data.
|