363 lines
30 KiB
Markdown
363 lines
30 KiB
Markdown
# ERP Distribution — Master Plan
|
||
|
||
## What Already Exists
|
||
|
||
| Area | Status | Notes |
|
||
|---|---|---|
|
||
| JWT Authentication | Done | Token generation, claims, 120-min expiry |
|
||
| Permission-based Authorization | Done | Dynamic policy provider, role → permission mapping |
|
||
| User Management | Done | CRUD, role assignment, scope assignment (region/route/store) |
|
||
| Role Management | Done (read-only) | 6 roles seeded, no create/update via API |
|
||
| Region / Route / Vehicle CRUD | Done | Full API surface with permission checks |
|
||
| Store / Warehouse CRUD | Done | Full API surface with permission checks |
|
||
| Order CRUD | Done | Scope-aware (user only sees their assigned stores) |
|
||
| Unit of Work + Repositories | Done | Transaction support throughout |
|
||
| Soft Deletes | Done | IsActive pattern on all entities |
|
||
| Price Lists / Suppliers | Done | Region-scoped price lists + supplier master; see [14_pricing_and_suppliers.md](./14_pricing_and_suppliers.md) |
|
||
|
||
## Known Gaps in Existing System (Pre-Work)
|
||
|
||
These are not new features — they are fixable holes in what's already built.
|
||
They must be resolved before new feature steps begin because later steps depend on correct foundations.
|
||
|
||
| Gap | Impact |
|
||
|---|---|
|
||
| Route DTOs missing RegionId | Can't link routes to regions via API |
|
||
| Store DTOs missing RouteId | Can't link stores to routes via API |
|
||
| Role endpoints have no [Authorize] | Anyone can read roles without authentication |
|
||
| JWT key & DB credentials in appsettings.json | Security risk in any shared/production environment |
|
||
| No input validation on any DTO | Bad data can enter the system silently |
|
||
| Item model is empty (no properties) | OrderItems reference items that have no data |
|
||
|
||
---
|
||
|
||
## Feature Steps
|
||
|
||
| # | Feature | Status | Depends On | Detail File |
|
||
|---|---|---|---|---|
|
||
| 00 | Existing Gap Fixes | Done | — | [00_existing_gaps.md](./00_existing_gaps.md) |
|
||
| 01 | Item Catalog | Done | 00 | [01_item_catalog.md](./01_item_catalog.md) |
|
||
| 02 | Stock Ledger | Done | 01 | [02_stock_ledger.md](./02_stock_ledger.md) |
|
||
| 03 | Ride Lifecycle | Done | 02 | [03_ride_lifecycle.md](./03_ride_lifecycle.md) |
|
||
| 04 | Loading Event | Not Started | 03 | [04_loading_event.md](./04_loading_event.md) |
|
||
| 05 | Delivery Ride Execution | Not Started | 04 | [05_delivery_ride.md](./05_delivery_ride.md) |
|
||
| 06 | Sale Ride Execution | Not Started | 04 | [06_sale_ride.md](./06_sale_ride.md) |
|
||
| 07 | Ride Close & Reconciliation | Not Started | 05, 06 | [07_ride_reconciliation.md](./07_ride_reconciliation.md) |
|
||
| 08 | Sales Agent Controls | Not Started | 07 | [08_sales_agent_controls.md](./08_sales_agent_controls.md) |
|
||
| 09 | Fraud Controls & Audit Trail | Not Started | 08 | [09_fraud_controls.md](./09_fraud_controls.md) |
|
||
| 10 | Region Management (Beyond CRUD) | Not Started | 00 | [10_region_management.md](./10_region_management.md) |
|
||
| 11 | Route & Sales Visit Management | Not Started | 00 | [11_route_sales_management.md](./11_route_sales_management.md) |
|
||
| 12 | Store Management (Beyond CRUD) | In Progress | 00 | [12_store_management.md](./12_store_management.md) |
|
||
| 13 | Fleet Management (Beyond CRUD) | Not Started | 00 | [13_fleet_management.md](./13_fleet_management.md) |
|
||
| 14 | Pricing & Supplier Master Data | Done | 01 | [14_pricing_and_suppliers.md](./14_pricing_and_suppliers.md) |
|
||
| 15 | Procurement / Purchasing | Not Started | 01, 14 | [15_procurement.md](./15_procurement.md) |
|
||
| 16 | Sales Force Automation / CRM | Not Started | 12 | [16_sfa_crm.md](./16_sfa_crm.md) |
|
||
| 17 | Promotions & Trade Scheme Management | Not Started | 01, 14 | [17_promotions_schemes.md](./17_promotions_schemes.md) |
|
||
| 18 | Returns & Claims Management | Not Started | 05, 06 | [18_returns_claims.md](./18_returns_claims.md) |
|
||
| 19 | Finance & Accounting | Not Started | 05, 06, 18 | [19_finance_accounting.md](./19_finance_accounting.md) |
|
||
| 20 | Reporting, Analytics & BI | Not Started | all prior | [20_reporting_analytics.md](./20_reporting_analytics.md) |
|
||
| 21 | Notifications & Alerts | Not Started | 02, 12, 08 | [21_notifications_alerts.md](./21_notifications_alerts.md) |
|
||
| 22 | Integration & API Layer | Not Started | 19, 13 | [22_integration_api.md](./22_integration_api.md) |
|
||
| 23 | Mobile & Offline Capability | Not Started | 05, 06 | [23_mobile_offline.md](./23_mobile_offline.md) |
|
||
|
||
Steps 00–09 are the original ride/stock-ledger roadmap and keep their strict dependency order.
|
||
Steps 10–23 fill in every remaining area from the [Function Reference by Feature](#function-reference-by-feature)
|
||
section above that wasn't already covered by 00–09; they depend only on the specific earlier steps
|
||
noted above, not on the full 00–09 chain, and can be resequenced relative to each other as
|
||
priorities become clearer.
|
||
|
||
---
|
||
|
||
## Function Reference by Feature
|
||
|
||
Reference only, not a build plan — background material to consult while planning/implementing the
|
||
steps above and below. Service-layer function names and what each should do when implemented.
|
||
Names are illustrative (camelCase) — adapt to your language/framework conventions. None of the
|
||
functions below are implemented yet unless noted. User Management/RBAC functions aren't repeated
|
||
here — see `SRS_User_Management_Module.pdf`.
|
||
|
||
### 1. Order Management
|
||
|
||
| Function | What it does | Status |
|
||
|---|---|---|
|
||
| `createOrder(storeId, items[], salesRepId)` | Validates stock/credit, creates a new order in `pending` state. | Partially implemented - `OrderService.CreateAsync` exists, enforces store scope, blocks inactive stores, and applies the unverified-KYC order threshold from config. It still has no stock validation, credit-limit validation, approval flow, or order state machine. |
|
||
| `validateCreditLimit(storeId, orderAmount)` | Checks store's outstanding balance + new order value against its credit limit. | Not implemented - `Store` now has `CreditLimit` and `OutstandingBalance`, but there is no dedicated validator or order-time credit-limit enforcement yet. |
|
||
| `checkStockAvailability(items[])` | Confirms requested SKUs/quantities are available at the fulfilling warehouse. | Not implemented — depends on [02_stock_ledger.md](./02_stock_ledger.md). |
|
||
| `applyPricingAndDiscounts(orderId)` | Runs the active price list and eligible scheme rules against order lines. | Partially implemented — `OrderService.CreateAsync` resolves the price-list half via `PriceListService.ResolveUnitPriceAsync` (region-scoped → global → `Item.SalePrice`, or a caller-supplied `UnitPrice`); the scheme-discount half still depends on §11 Promotions below. |
|
||
| `submitOrderForApproval(orderId)` | Routes the order to the correct approver based on its value/discount threshold. | Not implemented — depends on [08_sales_agent_controls.md](./08_sales_agent_controls.md). |
|
||
| `approveOrder(orderId, approverId)` / `rejectOrder(orderId, reason)` | Moves order to `approved` or `rejected`, logging the actor. | Not implemented. |
|
||
| `updateOrderStatus(orderId, status)` | Transitions order through `pending → approved → picked → dispatched → delivered → invoiced`. | Not implemented — `Order` has no status field or state machine today. |
|
||
| `convertOrderToInvoice(orderId)` | Generates the invoice once the order is dispatched/delivered. | Not implemented — depends on §13 Finance & Accounting. |
|
||
| `createBackorder(orderId, unfulfilledItems[])` | Splits unfulfillable quantity into a linked backorder. | Not implemented. |
|
||
| `cancelOrder(orderId, reason)` | Cancels an order pre-dispatch and releases any reserved stock. | Not implemented — `OrderController` supports soft delete only, no reason code or stock release. |
|
||
| `getOrdersByStore(storeId)` / `getOrdersBySalesRep(salesRepId)` | Scoped order listings. | `getOrdersByStore` implemented (`GET /api/orders/store/{storeId}`). `getOrdersBySalesRep` not implemented. |
|
||
| `getOrderAnalytics(filters)` | Returns fill rate, average order value, rejection rate over a period. | Not implemented. |
|
||
|
||
### 2. Region Management
|
||
|
||
| Function | What it does | Status |
|
||
|---|---|---|
|
||
| `createRegion(name, boundaries)` | Creates a new region record. | Partially implemented — `RegionController` supports create with `Name` only, no `boundaries` field. |
|
||
| `assignAreaToRegion(areaId, regionId)` | Links an existing area under a region. | Not implemented — no `Area` entity exists in the schema. |
|
||
| `setRegionalTarget(regionId, period, targetValue)` | Sets the sales target for a region for a given period. | Not implemented. |
|
||
| `setRegionalBudget(regionId, period, budgetAmount)` | Allocates budget at the regional level. | Not implemented. |
|
||
| `mapAgencyToRegion(agencyId, regionId)` | Assigns a Regional Agency's contract scope to a region. | Not implemented — `RegionalAgency` is currently a `Role`, not a distinct agency entity; scope is via `UserRegionScope`. |
|
||
| `setRegionalTaxRule(regionId, ruleConfig)` | Overrides tax/pricing rules for a specific region. | Not implemented. |
|
||
| `getRegionHierarchy(regionId)` | Returns all areas/territories nested under a region. | Not implemented — see [user_management_PLAN.md](../user_management_PLAN.md) territory hierarchy prerequisite. |
|
||
| `getRegionDashboard(regionId, period)` | Aggregated KPIs: sales, fill rate, agency performance for the region. | Not implemented. |
|
||
|
||
### 3. Route Management
|
||
|
||
| Function | What it does | Status |
|
||
|---|---|---|
|
||
| `createRoute(name, areaId)` | Creates a new sales visit route within an area. | Partially implemented — `RouteController` supports create, but by `RegionId` not `areaId` (no `Area` entity exists). |
|
||
| `assignOutletsToRoute(routeId, outletIds[])` | Maps a set of stores to a route. | Partially implemented — a `Store` has a single `FK_RouteId`, set via `StoreController` create/update; no bulk-assign endpoint. |
|
||
| `assignRouteToSalesRep(routeId, salesRepId)` | Assigns ownership of a route to an SR. | Not implemented — only `UserRouteScope` exists (scope grant), not a single-owner assignment. |
|
||
| `optimizeRouteSequence(routeId)` | Reorders the visit sequence for efficiency (distance/priority-based). | Not implemented. |
|
||
| `recordRouteCheckIn(routeId, outletId, gpsCoords, timestamp)` | Logs an SR's arrival at an outlet. | Not implemented. |
|
||
| `recordRouteCheckOut(routeId, outletId, timestamp)` | Logs departure and closes out the visit. | Not implemented. |
|
||
| `getRouteAdherence(routeId, date)` | Compares planned vs. actual visits for a route/day. | Not implemented — depends on check-in/check-out above. |
|
||
| `reassignRoute(routeId, newSalesRepId)` | Moves a route to a different SR. | Not implemented. |
|
||
| `getRoutePerformance(routeId, period)` | Sales per route, strike rate, missed-visit count. | Not implemented. |
|
||
| `planDeliveryRoute(warehouseId, orderIds[])` | Builds the warehouse-to-outlet dispatch route (separate from the sales visit route). | Not implemented — this is the `DeliveryRun` concept; see [03_ride_lifecycle.md](./03_ride_lifecycle.md). |
|
||
|
||
### 4. Store (Outlet) Management
|
||
|
||
| Function | What it does | Status |
|
||
|---|---|---|
|
||
| `createStore(storeData, kycDocs)` | Onboards a new outlet with required KYC. | Partially implemented - store create exists, and KYC documents can now be uploaded/listed via separate `/api/stores/{id}/kyc-documents` endpoints rather than inline on create. |
|
||
| `verifyStoreKyc(storeId)` | Marks KYC as verified/rejected by an approver. | Implemented - `PUT /api/stores/{id}/kyc/verify` updates `Store.KycStatus`. |
|
||
| `updateStoreCreditLimit(storeId, newLimit, approverId)` | Changes a store's credit limit, subject to approval authority. | Implemented - `PUT /api/stores/{id}/credit-limit` updates `Store.CreditLimit` and requires the `stores.credit.update` permission plus role level >= 20. |
|
||
| `getStoreOutstandingBalance(storeId)` | Returns current receivables against the store. | Partially implemented - `GET /api/stores/{id}/outstanding-balance` returns the cached `OutstandingBalance`, `CreditLimit`, and available credit. It is not yet driven by Finance events or invoice/payment records. |
|
||
| `classifyStore(storeId, segment)` | Sets/updates the store's segment (key account, general trade, etc.). | Implemented - `PUT /api/stores/{id}/segment` updates the free-text `Store.Segment` field. |
|
||
| `deactivateStore(storeId, reason)` | Soft-deletes a store, blocking new orders against it. | Partially implemented — `DELETE /api/stores/{id}` soft-deletes via `IsActive`, no reason code captured. |
|
||
| `getStoreVisitHistory(storeId)` | Returns visit compliance history from Route Management. | Placeholder only - endpoint exists (`GET /api/stores/{id}/visit-history`) but currently returns an empty list until Route/Sales Visit Management lands. |
|
||
| `checkStoreSchemeEligibility(storeId, schemeId)` | Evaluates whether a store qualifies for a given promotion. | Placeholder only - endpoint exists (`GET /api/stores/{id}/schemes/{schemeId}/eligibility`) but currently returns a default eligible response until Promotions is implemented. |
|
||
| `getStoreSalesDashboard(storeId, period)` | Store-level sales and outstanding summary. | Partially implemented - `GET /api/stores/{id}/dashboard` aggregates order count, total order value, and last order date for the selected month. It does not yet include full sales/outstanding analytics from Finance. |
|
||
|
||
### 5. Vehicle / Fleet Management
|
||
|
||
| Function | What it does | Status |
|
||
|---|---|---|
|
||
| `registerVehicle(vehicleData)` | Creates the vehicle master record (registration, capacity, ownership). | Partially implemented — `VehicleController` create exists with `RegNumber`/`NumberPlate` only, no capacity/ownership fields. |
|
||
| `assignVehicleToRoute(vehicleId, routeId)` | Assigns a vehicle to a delivery/sales route. | Not implemented — `Vehicle` has no route link; only `DeliveryRun.FK_RouteId`/`FK_VehicleId` model this, and `DeliveryRun` is unwired (see [03_ride_lifecycle.md](./03_ride_lifecycle.md)). |
|
||
| `assignDriverToVehicle(vehicleId, driverId)` | Links a driver to a vehicle, checking license validity. | Not implemented — no `Driver` entity exists yet (`DeliveryRun.FK_DriverId` is commented out in the model). |
|
||
| `scheduleMaintenance(vehicleId, maintenanceType, dueAt)` | Sets up a preventive maintenance task (mileage/calendar-based). | Not implemented. |
|
||
| `logFuelExpense(vehicleId, amount, liters, date)` | Records a fuel transaction against the vehicle. | Not implemented. |
|
||
| `recordVehicleTelemetry(vehicleId, gpsCoords, speed, timestamp)` | Ingests telematics data (location, driver behavior). | Not implemented — see §16 Integration. |
|
||
| `checkDriverCompliance(driverId)` | Validates license/permit status before dispatch. | Not implemented — depends on a `Driver` entity. |
|
||
| `calculateLoadPlan(vehicleId, orderIds[])` | Matches order volume/weight to available vehicle capacity. | Not implemented — depends on [04_loading_event.md](./04_loading_event.md). |
|
||
| `getVehicleUtilization(vehicleId, period)` | Utilization and cost-per-delivery metrics. | Not implemented. |
|
||
| `retireVehicle(vehicleId, reason)` | Removes a vehicle from active fleet, retaining history. | Partially implemented — `DELETE /api/vehicles/{id}` soft-deletes via `IsActive`, no reason code captured. |
|
||
|
||
### 6. Warehouse Management
|
||
|
||
| Function | What it does | Status |
|
||
|---|---|---|
|
||
| `createGoodsReceipt(poId, receivedItems[])` | Records inbound stock against a purchase order (GRN). | Not implemented — depends on §9 Procurement. |
|
||
| `inspectGoodsReceipt(grnId, inspectionResult)` | Logs quality-check outcome before putaway. | Not implemented. |
|
||
| `putawayStock(grnId, locationAssignments[])` | Assigns received stock to warehouse locations (zone/ABC-based). | Not implemented — depends on [02_stock_ledger.md](./02_stock_ledger.md). |
|
||
| `getStockByLocation(warehouseId, sku)` | Returns real-time quantity and location for a SKU. | Not implemented — depends on [02_stock_ledger.md](./02_stock_ledger.md). |
|
||
| `generatePickList(orderIds[])` | Creates a pick list/task for one or more orders. | Not implemented — overlaps with [04_loading_event.md](./04_loading_event.md). |
|
||
| `confirmPicking(pickListId, pickedItems[])` | Marks items as picked, decrementing available stock. | Not implemented. |
|
||
| `packOrder(orderId, packageDetails)` | Records packing completion and package details. | Not implemented. |
|
||
| `createCrossDockTransfer(inboundId, outboundOrderId)` | Routes inbound stock directly to an outbound order, skipping storage. | Not implemented. |
|
||
| `runCycleCount(warehouseId, zoneId)` | Initiates a scheduled partial stock count. | Not implemented — overlaps with [07_ride_reconciliation.md](./07_ride_reconciliation.md) physical count concept. |
|
||
| `reconcileStock(warehouseId, countResults)` | Adjusts system stock to match physical count results. | Not implemented — see [07_ride_reconciliation.md](./07_ride_reconciliation.md). |
|
||
| `buildDispatchLoad(vehicleId, orderIds[])` | Groups orders into a dispatch load for a specific vehicle/route. | Not implemented — see [04_loading_event.md](./04_loading_event.md). |
|
||
| `receiveReturn(returnId, items[], condition)` | Processes returned goods back into the warehouse. | Not implemented — see §12 Returns & Claims. |
|
||
| `getWarehouseKpis(warehouseId, period)` | Dock-to-stock time, pick accuracy, turnover rate. | Not implemented. |
|
||
|
||
### 7. Master Data Management
|
||
|
||
| Function | What it does | Status |
|
||
|---|---|---|
|
||
| `createProduct(skuData)` | Creates a SKU with category, UOM, barcode, pack hierarchy. | Not implemented — `Item` model exists but has no properties; see [01_item_catalog.md](./01_item_catalog.md). |
|
||
| `deactivateSku(sku, reason)` | Retires a SKU from active ordering. | Not implemented. |
|
||
| `createPriceList(name, region, effectiveDates)` | Defines a new price list scoped to a region/date range. | Implemented — `POST /api/price-lists`, see [14_pricing_and_suppliers.md](./14_pricing_and_suppliers.md). |
|
||
| `updateProductPricing(sku, priceListId, price)` | Sets/updates the price of a SKU within a price list. | Implemented — `PUT /api/price-lists/{id}/items/{sku}`. |
|
||
| `createSupplierMaster(supplierData)` | Registers a new supplier/vendor. | Implemented — `POST /api/suppliers`. `PerformanceScore` stays null until [15_procurement.md](./15_procurement.md)'s `evaluateSupplier` exists. |
|
||
|
||
### 8. Enterprise-wide Inventory & Stock
|
||
|
||
| Function | What it does | Status |
|
||
|---|---|---|
|
||
| `getMultiLocationStock(sku)` | Returns stock levels for a SKU across all warehouses/agencies. | Not implemented — see [02_stock_ledger.md](./02_stock_ledger.md). |
|
||
| `setReorderPoint(sku, warehouseId, threshold)` | Configures the auto-replenishment trigger level. | Not implemented. |
|
||
| `createStockTransfer(fromWarehouseId, toWarehouseId, items[])` | Initiates an inter-warehouse stock movement. | Not implemented. |
|
||
| `trackBatchExpiry(sku, batchNo, expiryDate)` | Registers batch/expiry data for FEFO enforcement. | Not implemented. |
|
||
| `calculateStockValuation(warehouseId, method)` | Computes stock value using FIFO/weighted-average. | Not implemented. |
|
||
|
||
### 9. Procurement / Purchasing
|
||
|
||
| Function | What it does | Status |
|
||
|---|---|---|
|
||
| `createPurchaseRequisition(items[], requestedBy)` | Raises an internal request to purchase stock. | Not implemented — no procurement entities exist. |
|
||
| `createPurchaseOrder(supplierId, items[])` | Issues a PO to a supplier. | Not implemented. |
|
||
| `matchInvoiceToPO(invoiceId, poId, grnId)` | Performs the 3-way match (PO–GRN–Invoice) before payment. | Not implemented. |
|
||
| `evaluateSupplier(supplierId, criteria)` | Scores a supplier on delivery/quality/price performance. | Not implemented. |
|
||
| `createPurchaseReturn(poId, items[], reason)` | Initiates a return of received goods to the supplier. | Not implemented. |
|
||
|
||
### 10. Sales Force Automation (SFA) / CRM
|
||
|
||
| Function | What it does | Status |
|
||
|---|---|---|
|
||
| `logCustomerInteraction(storeId, notes)` | Records a visit note or customer interaction. | Not implemented. |
|
||
| `trackTargetVsAchievement(userId, period)` | Compares a user's sales target to actuals. | Not implemented. |
|
||
| `calculateIncentive(userId, period)` | Computes commission/incentive payout based on performance. | Not implemented. |
|
||
| `createLead(prospectData)` | Captures a prospective new outlet. | Not implemented — no `Lead` entity exists. |
|
||
| `convertLeadToStore(leadId)` | Converts a qualified lead into an active store record. | Not implemented. |
|
||
|
||
### 11. Promotions & Trade Scheme Management
|
||
|
||
| Function | What it does | Status |
|
||
|---|---|---|
|
||
| `createScheme(schemeRules, eligibility, dateRange)` | Defines a promotion (buy-X-get-Y, slab discount, etc.). | Not implemented — no scheme entity exists. |
|
||
| `evaluateSchemeEligibility(storeId, orderId)` | Checks whether an order qualifies for a scheme. | Not implemented. |
|
||
| `applySchemeDiscount(orderId, schemeId)` | Applies the scheme's discount to order pricing. | Not implemented. |
|
||
| `trackSchemeSpend(schemeId)` | Aggregates total discount value given under a scheme. | Not implemented. |
|
||
| `getSchemeROI(schemeId)` | Compares scheme spend against incremental sales generated. | Not implemented. |
|
||
|
||
### 12. Returns & Claims Management
|
||
|
||
| Function | What it does | Status |
|
||
|---|---|---|
|
||
| `createReturnRequest(orderId, items[], reasonCode)` | Initiates a return against a delivered order. | Not implemented — see [09_fraud_controls.md](./09_fraud_controls.md) for the fraud-control angle on returns. |
|
||
| `approveReturn(returnId, approverId)` | Approves/rejects the return request. | Not implemented. |
|
||
| `generateCreditNote(returnId)` | Issues a credit note against the original invoice. | Not implemented. |
|
||
| `createClaim(agencyId, claimDetails)` | Raises a claim against a Regional Agency (e.g., damaged stock). | Not implemented. |
|
||
| `settleClaim(claimId, settlementAmount)` | Closes out a claim with a final settlement amount. | Not implemented. |
|
||
|
||
### 13. Finance & Accounting
|
||
|
||
| Function | What it does | Status |
|
||
|---|---|---|
|
||
| `createInvoice(orderId)` | Generates a formal invoice from a fulfilled order. | Not implemented — no invoice entity exists. |
|
||
| `recordPayment(invoiceId, amount, method)` | Logs a payment/collection against an invoice. | Not implemented. |
|
||
| `postToGeneralLedger(transactionId)` | Posts a financial transaction to the GL. | Not implemented. |
|
||
| `generateTaxInvoice(invoiceId, jurisdiction)` | Produces a tax-compliant invoice (GST/VAT e-invoicing). | Not implemented. |
|
||
| `getFinancialReport(entityId, period, reportType)` | Returns P&L/cash-flow reports scoped to a region/area. | Not implemented. |
|
||
|
||
### 14. Reporting, Analytics & BI
|
||
|
||
| Function | What it does | Status |
|
||
|---|---|---|
|
||
| `getDashboardData(role, scope)` | Returns the role-appropriate dashboard payload. | Not implemented. |
|
||
| `generateKpiReport(kpiType, filters)` | Produces a specific KPI report (fill rate, OOS%, credit risk, etc.). | Not implemented. |
|
||
| `getPredictiveAlert(type, scope)` | Returns AI-flagged issues, e.g. a region's declining fill rate. | Not implemented. |
|
||
|
||
### 15. Notifications & Alerts
|
||
|
||
| Function | What it does | Status |
|
||
|---|---|---|
|
||
| `sendLowStockAlert(warehouseId, sku)` | Notifies relevant roles when stock drops below the reorder point. | Not implemented. |
|
||
| `sendCreditLimitBreachAlert(storeId)` | Notifies approvers when a store exceeds its credit limit. | Not implemented. |
|
||
| `sendApprovalPendingNotification(approverId, requestId)` | Notifies an approver of a pending action. | Not implemented. |
|
||
| `sendRouteDeviationAlert(routeId, salesRepId)` | Flags when an SR deviates materially from the planned route. | Not implemented — see [09_fraud_controls.md](./09_fraud_controls.md) geofencing check. |
|
||
|
||
### 16. Integration & API Layer
|
||
|
||
| Function | What it does | Status |
|
||
|---|---|---|
|
||
| `syncToAccountingSystem(transactionId, targetSystem)` | Pushes a transaction to an external accounting platform (QuickBooks/SAP/Xero). | Not implemented. |
|
||
| `syncTelematicsData(vehicleId, provider)` | Pulls GPS/telematics data from a third-party provider. | Not implemented. |
|
||
| `pushOrderToDistributorPortal(orderId)` | Syncs order status to a distributor-facing B2B portal. | Not implemented. |
|
||
|
||
### 17. Mobile & Offline Capability
|
||
|
||
| Function | What it does | Status |
|
||
|---|---|---|
|
||
| `queueOfflineOrder(orderData)` | Stores an order locally on the device when offline. | Not implemented — no mobile client in this repository. |
|
||
| `syncOfflineQueue(deviceId)` | Pushes queued offline actions to the server once connectivity returns. | Not implemented. |
|
||
| `scanBarcode(barcodeValue)` | Resolves a scanned barcode to a SKU or warehouse location. | Not implemented. |
|
||
|
||
### 18. Compliance & Audit
|
||
|
||
| Function | What it does | Status |
|
||
|---|---|---|
|
||
| `logAuditEvent(userId, action, entityType, entityId)` | Writes an immutable audit trail entry for a state-changing action. | Not implemented — see [09_fraud_controls.md](./09_fraud_controls.md), which scopes an audit log as part of Fraud Controls. |
|
||
| `checkLicenseCompliance(entityId, licenseType)` | Validates a required license/permit is current (e.g., regulated goods). | Not implemented. |
|
||
| `generateComplianceReport(period)` | Produces a report of compliance status across the org for a period. | Not implemented. |
|
||
|
||
---
|
||
|
||
## Feature Summaries
|
||
|
||
### 00 — Existing Gap Fixes
|
||
Fix all known holes in the current codebase before new features are layered on top.
|
||
Includes DTO field gaps, missing authorization on role endpoints, secrets management,
|
||
and adding input validation across all existing endpoints.
|
||
**Gate**: All existing API endpoints behave correctly and securely before step 01 begins.
|
||
|
||
### 01 — Item Catalog
|
||
Define the Item entity with real properties (name, SKU, unit of measure, category, price tiers).
|
||
Items are the unit of stock — nothing in the stock ledger makes sense without them.
|
||
This step also covers the Item CRUD API and how items relate to orders.
|
||
**Gate**: An item can be created, updated, and referenced in an order with quantity and price.
|
||
|
||
### 02 — Stock Ledger
|
||
Introduce the concept of stock per location. Every warehouse (fixed or vehicle) holds a quantity
|
||
of each item. Stock is never edited directly — all changes happen through movement transactions
|
||
(load, sale, return, damage, adjustment). The current balance is always the running sum.
|
||
This is the single most important architectural decision for the whole system.
|
||
**Gate**: Stock balance for any item at any location can be queried. Every change is a traceable transaction.
|
||
|
||
### 03 — Ride Lifecycle
|
||
A ride is a session that turns a vehicle into a temporary warehouse. It has a state machine:
|
||
Draft → Open → Active → Closed. A vehicle can only be on one active ride at a time.
|
||
Two ride types exist: Delivery (pre-orders) and Sale (van sales). The ride tracks who is driving,
|
||
which route, which vehicle, and when it started and ended.
|
||
**Gate**: A ride can be created, opened, and closed. A vehicle's stock ledger is created when a ride opens.
|
||
|
||
### 04 — Loading Event
|
||
When a ride opens, stock must be physically loaded from a source warehouse onto the vehicle.
|
||
This is a two-party event: warehouse manager confirms what was dispatched, driver confirms what was received.
|
||
Discrepancies between the two are flagged immediately and require resolution before the ride goes active.
|
||
The loading event creates stock movement transactions that debit the warehouse and credit the vehicle.
|
||
**Gate**: Stock moves from warehouse to vehicle via a confirmed loading event. Any discrepancy is logged.
|
||
|
||
### 05 — Delivery Ride Execution
|
||
On a delivery ride, the driver fulfills pre-confirmed orders. Each order becomes a delivery task.
|
||
The driver marks each as delivered, partially delivered, or failed. Partially delivered orders
|
||
generate a credit note for the undelivered quantity. Customer confirmation (signature or OTP)
|
||
is required to mark a delivery complete. Stock movements are created per delivery event.
|
||
**Gate**: A delivery ride can execute all orders on its route and produce a delivery report.
|
||
|
||
### 06 — Sale Ride Execution
|
||
On a sale ride, the driver visits customers and creates invoices on the spot. No pre-orders exist.
|
||
The driver selects items, quantities, and prices (within approved discount limits), and the invoice
|
||
is generated immediately. Payment is collected (cash or credit) at the point of sale.
|
||
The vehicle's stock ledger decreases with each sale. The driver cannot sell more than what is loaded.
|
||
**Gate**: A sale ride can generate invoices in the field. Stock on vehicle decreases with each sale.
|
||
|
||
### 07 — Ride Close & Reconciliation
|
||
When a ride ends, the system performs a full reconciliation. The equation must balance:
|
||
Opening Stock − Sales − Damages + Returns = Closing Stock (physical count)
|
||
Cash Collected + Credit Extended = Total Sales − Returns
|
||
Any variance must be approved by a supervisor with a reason code before the ride can close.
|
||
Unresolved variances are logged as discrepancies against the agent's record.
|
||
**Gate**: A ride cannot close with an unexplained variance. All discrepancies are permanently recorded.
|
||
|
||
### 08 — Sales Agent Controls
|
||
Agents operate within boundaries set by their role level. This step wires role levels to business rules:
|
||
discount limits per agent level, credit limits per customer, maximum single-transaction value,
|
||
and approval chains for exceptions. Supervisors can grant one-time overrides logged against their account.
|
||
**Gate**: An agent cannot exceed their limits without a logged, authorized override.
|
||
|
||
### 09 — Fraud Controls & Audit Trail
|
||
A dedicated audit log records every sensitive event (who, what, when, from where).
|
||
Automated checks flag: returns without a matching prior sale, sales outside the geofenced route,
|
||
agents with consistently high variance rates, and cash collected below invoiced amounts.
|
||
Return approval requires supervisor sign-off before stock is credited. Anomaly reports are
|
||
surfaced to area managers on a scheduled basis.
|
||
**Gate**: Every sensitive event is logged immutably. Automated flags surface to the right level of management.
|
||
|
||
---
|
||
|
||
## Rules
|
||
|
||
1. A feature file must be filled in and reviewed before implementation begins on that step.
|
||
2. Status must be updated in this file whenever a step transitions.
|
||
3. If implementation reveals a design change, the feature file is updated and this plan is revised.
|
||
4. Steps must be done in dependency order — no skipping.
|