feat: implement business pricing service and money utilities

- 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.
This commit is contained in:
Sathira Sri Sathara
2026-09-03 19:25:13 +05:30
parent fd4e324571
commit 5643d89236
75 changed files with 663 additions and 1 deletions
@@ -0,0 +1,85 @@
# 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.