implemnet customer master used for both B2B and B2C.
This commit is contained in:
@@ -0,0 +1,383 @@
|
||||
# Sales Module Plan
|
||||
|
||||
## Summary
|
||||
This sales module is split into two phases:
|
||||
- **Phase 1**: basic, standard sales features that fit the current ERP architecture
|
||||
- **Phase 2**: enterprise extensions that can be added after the core flow is stable
|
||||
|
||||
The design stays aligned with the existing backend patterns:
|
||||
- controller thinness
|
||||
- service-based business rules
|
||||
- repository + unit of work
|
||||
- ETag concurrency
|
||||
- audit logging
|
||||
- stock FIFO and ledger posting
|
||||
|
||||
Returns, credit notes, and sales returns are **out of scope for Phase 1**.
|
||||
|
||||
---
|
||||
|
||||
## Phase 1 - Basic Standard Sales Module
|
||||
|
||||
### Goal
|
||||
Implement the minimum sales flow needed for both B2B and B2C:
|
||||
- maintain customers
|
||||
- create sales invoices
|
||||
- create sales slips
|
||||
- support fixed sale price fallback and GRN-based cost fallback
|
||||
- support discounts by percentage and value
|
||||
- support free issue lines
|
||||
- post stock movement and ledger entries
|
||||
- generate basic sales reports
|
||||
|
||||
### In Scope
|
||||
- Customer master
|
||||
- Sales invoice
|
||||
- Sales invoice lines
|
||||
- Sales slip
|
||||
- Sales slip lines
|
||||
- Pricing resolver
|
||||
- Discount calculation
|
||||
- Free issue handling
|
||||
- Stock posting
|
||||
- Basic sales reports
|
||||
|
||||
### Not in Scope for Phase 1
|
||||
- customer groups
|
||||
- price lists
|
||||
- promotions
|
||||
- reservations
|
||||
- sales payments allocation
|
||||
- approval workflow
|
||||
- returns and credit notes
|
||||
- advanced customer segmentation
|
||||
|
||||
### Phase 1 Entity Design
|
||||
|
||||
#### `Customer`
|
||||
Basic customer master used for both B2B and B2C.
|
||||
|
||||
Fields:
|
||||
- `CustomerId`
|
||||
- `CustomerCode`
|
||||
- `CustomerType` (`B2B`, `B2C`, `WalkIn`)
|
||||
- `Name`
|
||||
- `DisplayName`
|
||||
- `Phone`
|
||||
- `Email`
|
||||
- `AddressLine1`
|
||||
- `AddressLine2`
|
||||
- `City`
|
||||
- `Country`
|
||||
- `TaxRegistrationNo`
|
||||
- `CreditLimit`
|
||||
- `CreditDays`
|
||||
- `DefaultWarehouseId`
|
||||
- `Status`
|
||||
- `CreatedAt`
|
||||
- `UpdatedAt`
|
||||
- `RowVersion`
|
||||
|
||||
#### `SalesInvoice`
|
||||
Primary posted sales document.
|
||||
|
||||
Fields:
|
||||
- `SalesInvoiceId`
|
||||
- `InvoiceNo`
|
||||
- `InvoiceDate`
|
||||
- `CustomerId`
|
||||
- `CustomerSnapshotName`
|
||||
- `CustomerSnapshotTaxNo`
|
||||
- `WarehouseId`
|
||||
- `InvoiceType` (`B2B`, `B2C`, `Cash`, `Credit`)
|
||||
- `Status` (`Draft`, `Posted`, `Cancelled`)
|
||||
- `Subtotal`
|
||||
- `DiscountTotal`
|
||||
- `TaxTotal`
|
||||
- `GrandTotal`
|
||||
- `RoundOff`
|
||||
- `NetPayable`
|
||||
- `PaidAmount`
|
||||
- `BalanceAmount`
|
||||
- `CreatedBy`
|
||||
- `CreatedAt`
|
||||
- `UpdatedAt`
|
||||
- `RowVersion`
|
||||
|
||||
#### `SalesInvoiceLine`
|
||||
Invoice line with pricing, discount, and free issue support.
|
||||
|
||||
Fields:
|
||||
- `SalesInvoiceLineId`
|
||||
- `SalesInvoiceId`
|
||||
- `ItemId`
|
||||
- `Description`
|
||||
- `Qty`
|
||||
- `FreeQty`
|
||||
- `UomId`
|
||||
- `WarehouseId`
|
||||
- `UnitPrice`
|
||||
- `BaseCost`
|
||||
- `PriceSource`
|
||||
- `DiscountPct`
|
||||
- `DiscountAmount`
|
||||
- `NetUnitPrice`
|
||||
- `LineTotal`
|
||||
- `TaxPct`
|
||||
- `TaxAmount`
|
||||
- `IsFreeIssue`
|
||||
- `ParentLineId`
|
||||
- `RowVersion`
|
||||
|
||||
#### `SalesSlip`
|
||||
Fast retail or counter-sale document.
|
||||
|
||||
Fields:
|
||||
- `SalesSlipId`
|
||||
- `SlipNo`
|
||||
- `SlipDate`
|
||||
- `CustomerId`
|
||||
- `CustomerSnapshotName`
|
||||
- `WarehouseId`
|
||||
- `CashierUserId`
|
||||
- `Status`
|
||||
- `Subtotal`
|
||||
- `DiscountTotal`
|
||||
- `TaxTotal`
|
||||
- `GrandTotal`
|
||||
- `PaidAmount`
|
||||
- `BalanceAmount`
|
||||
- `CreatedAt`
|
||||
- `UpdatedAt`
|
||||
- `RowVersion`
|
||||
|
||||
#### `SalesSlipLine`
|
||||
Slip line with the same sales calculation rules as invoices.
|
||||
|
||||
Fields:
|
||||
- `SalesSlipLineId`
|
||||
- `SalesSlipId`
|
||||
- `ItemId`
|
||||
- `Description`
|
||||
- `Qty`
|
||||
- `FreeQty`
|
||||
- `UomId`
|
||||
- `WarehouseId`
|
||||
- `UnitPrice`
|
||||
- `BaseCost`
|
||||
- `PriceSource`
|
||||
- `DiscountPct`
|
||||
- `DiscountAmount`
|
||||
- `NetUnitPrice`
|
||||
- `LineTotal`
|
||||
- `TaxPct`
|
||||
- `TaxAmount`
|
||||
- `IsFreeIssue`
|
||||
- `ParentLineId`
|
||||
- `RowVersion`
|
||||
|
||||
### Phase 1 Pricing Rule
|
||||
Use the following order:
|
||||
1. fixed `Item.SalePrice`
|
||||
2. GRN-derived stock cost fallback
|
||||
3. FIFO valuation fallback
|
||||
|
||||
Important:
|
||||
- use a weighted average when deriving from multiple GRNs
|
||||
- keep the resolved source in `PriceSource`
|
||||
- allow manual override only if permitted by business rule
|
||||
|
||||
### Phase 1 Discount Rule
|
||||
Support:
|
||||
- percentage discount
|
||||
- fixed value discount
|
||||
|
||||
Discount must be computed server-side and stored in line and document totals.
|
||||
|
||||
### Phase 1 Free Issue Rule
|
||||
Support free issue lines in the same invoice/slip document.
|
||||
|
||||
Rules:
|
||||
- free quantity must be separate from paid quantity
|
||||
- free issue still reduces stock
|
||||
- free issue must be visible in reports
|
||||
- free issue should not be merged into discount
|
||||
|
||||
### Phase 1 Stock Posting Rule
|
||||
When an invoice or slip is posted:
|
||||
- reduce stock from the selected warehouse
|
||||
- consume FIFO layers
|
||||
- write `StockLedger` rows
|
||||
- maintain source document traceability
|
||||
- update totals in the same transaction
|
||||
|
||||
### Phase 1 API Route List
|
||||
- `GET /api/v1/customers`
|
||||
- `GET /api/v1/customers/{id}`
|
||||
- `POST /api/v1/customers`
|
||||
- `PUT /api/v1/customers/{id}`
|
||||
- `PATCH /api/v1/customers/{id}/status`
|
||||
- `GET /api/v1/sales-invoices`
|
||||
- `GET /api/v1/sales-invoices/{id}`
|
||||
- `POST /api/v1/sales-invoices`
|
||||
- `PUT /api/v1/sales-invoices/{id}`
|
||||
- `POST /api/v1/sales-invoices/{id}/post`
|
||||
- `POST /api/v1/sales-invoices/{id}/cancel`
|
||||
- `GET /api/v1/sales-invoices/{id}/print-preview`
|
||||
- `GET /api/v1/sales-slips`
|
||||
- `GET /api/v1/sales-slips/{id}`
|
||||
- `POST /api/v1/sales-slips`
|
||||
- `POST /api/v1/sales-slips/{id}/post`
|
||||
- `POST /api/v1/sales-slips/{id}/cancel`
|
||||
- `GET /api/v1/sales-reports/daily-summary`
|
||||
- `GET /api/v1/sales-reports/item-wise`
|
||||
- `GET /api/v1/sales-reports/customer-wise`
|
||||
- `GET /api/v1/sales-reports/warehouse-wise`
|
||||
- `GET /api/v1/sales-reports/discount-summary`
|
||||
- `GET /api/v1/sales-reports/free-issue-summary`
|
||||
- `GET /api/v1/sales-reports/margin-summary`
|
||||
|
||||
### Phase 1 Folder / Module Plan
|
||||
- `Domain/Entities`
|
||||
- add `Customer`, `SalesInvoice`, `SalesInvoiceLine`, `SalesSlip`, `SalesSlipLine`
|
||||
- `Domain/Enums`
|
||||
- add sales status enums and invoice/slip type enums
|
||||
- `Dtos/Sales`
|
||||
- add request and response DTOs for customer, invoice, slip, and reports
|
||||
- `Services/Interfaces`
|
||||
- add `ICustomerService`, `ISalesInvoiceService`, `ISalesSlipService`, `ISalesPricingService`, `ISalesReportService`
|
||||
- `Services`
|
||||
- implement the sales services with transaction-safe logic
|
||||
- `Controllers`
|
||||
- add `CustomersController`, `SalesInvoicesController`, `SalesSlipsController`, `SalesReportsController`
|
||||
- `Infra/Persistence/Configurations`
|
||||
- add EF Core mappings for all sales entities
|
||||
- `Infra/Persistence/ErpDbContext.cs`
|
||||
- register sales `DbSet`s
|
||||
- `Infra/Persistence/Migrations`
|
||||
- add the sales schema migration after the model is defined
|
||||
|
||||
### Phase 1 Implementation Order
|
||||
1. Customer master
|
||||
2. Sales invoice entity and DTOs
|
||||
3. Sales slip entity and DTOs
|
||||
4. Pricing resolver
|
||||
5. Discount computation
|
||||
6. Free issue handling
|
||||
7. Stock posting and ledger integration
|
||||
8. Basic sales reports
|
||||
9. Controllers and swagger wiring
|
||||
|
||||
---
|
||||
|
||||
## Phase 2 - Enterprise Extensions
|
||||
|
||||
### Goal
|
||||
Add richer commercial features after Phase 1 is stable and tested.
|
||||
|
||||
### In Scope
|
||||
- customer groups
|
||||
- price lists
|
||||
- promotions
|
||||
- free issue schemes
|
||||
- reservations
|
||||
- payment allocation
|
||||
- approval flow
|
||||
- advanced reporting dimensions
|
||||
|
||||
### Phase 2 Entity Additions
|
||||
|
||||
#### `CustomerGroup`
|
||||
Used only if group-level pricing or segmentation is needed.
|
||||
|
||||
#### `PriceList`
|
||||
Customer, group, warehouse, or global price policies.
|
||||
|
||||
#### `PriceListItem`
|
||||
Per-item pricing rows inside a price list.
|
||||
|
||||
#### `Promotion`
|
||||
Promotional header.
|
||||
|
||||
#### `PromotionRule`
|
||||
Buy-X-get-Y, discount, or reward rules.
|
||||
|
||||
#### `FreeIssueScheme`
|
||||
Separate free issue header.
|
||||
|
||||
#### `FreeIssueSchemeLine`
|
||||
Rule lines for free issue behavior.
|
||||
|
||||
#### `SalesReservation`
|
||||
Stock reservation header for B2B order fulfillment.
|
||||
|
||||
#### `SalesReservationLine`
|
||||
Reserved item quantities.
|
||||
|
||||
#### `SalesPayment`
|
||||
Payment header for cash or credit settlement.
|
||||
|
||||
#### `SalesPaymentAllocation`
|
||||
Allocation of a payment across invoices.
|
||||
|
||||
### Phase 2 API Routes
|
||||
- `GET /api/v1/customer-groups`
|
||||
- `POST /api/v1/customer-groups`
|
||||
- `PUT /api/v1/customer-groups/{id}`
|
||||
- `PATCH /api/v1/customer-groups/{id}/status`
|
||||
- `GET /api/v1/price-lists`
|
||||
- `POST /api/v1/price-lists`
|
||||
- `PUT /api/v1/price-lists/{id}`
|
||||
- `PATCH /api/v1/price-lists/{id}/status`
|
||||
- `GET /api/v1/price-lists/{id}/items`
|
||||
- `PUT /api/v1/price-lists/{id}/items`
|
||||
- `GET /api/v1/pricing/resolve`
|
||||
- `GET /api/v1/promotions`
|
||||
- `POST /api/v1/promotions`
|
||||
- `PUT /api/v1/promotions/{id}`
|
||||
- `PATCH /api/v1/promotions/{id}/status`
|
||||
- `GET /api/v1/free-issue-schemes`
|
||||
- `POST /api/v1/free-issue-schemes`
|
||||
- `PUT /api/v1/free-issue-schemes/{id}`
|
||||
- `PATCH /api/v1/free-issue-schemes/{id}/status`
|
||||
- `POST /api/v1/sales-orders`
|
||||
- `POST /api/v1/sales-orders/{id}/reserve`
|
||||
- `POST /api/v1/sales-orders/{id}/confirm`
|
||||
- `POST /api/v1/sales-payments`
|
||||
- `POST /api/v1/sales-payments/{id}/allocate`
|
||||
- extended reporting routes for channel, cashier, tax, and credit views
|
||||
|
||||
### Phase 2 Folder / Module Plan
|
||||
- extend the same sales folders rather than creating a separate module
|
||||
- add new entities and DTOs under the same sales namespace
|
||||
- add new service interfaces and service implementations next to Phase 1 sales services
|
||||
- add new controllers only for the advanced routes
|
||||
- add migrations incrementally so Phase 1 tables remain stable
|
||||
|
||||
### Phase 2 Implementation Order
|
||||
1. customer groups
|
||||
2. price lists
|
||||
3. promotions and free issue schemes
|
||||
4. sales orders and reservations
|
||||
5. payments and allocations
|
||||
6. advanced reports
|
||||
7. permissions and approval workflow
|
||||
|
||||
---
|
||||
|
||||
## Test Plan
|
||||
- Verify customer CRUD with ETag concurrency and status changes.
|
||||
- Verify invoice and slip create/update/post flows.
|
||||
- Verify fixed sale price fallback works.
|
||||
- Verify GRN-derived fallback uses weighted average.
|
||||
- Verify discounts calculate correctly by percentage and fixed value.
|
||||
- Verify free issue lines post stock and appear in reports.
|
||||
- Verify stock ledger entries are created once per posted document.
|
||||
- Verify Phase 1 routes remain stable before Phase 2 is added.
|
||||
|
||||
## Assumptions
|
||||
- Phase 1 is intentionally minimal and should not include customer groups or price lists.
|
||||
- `SalesInvoice` is the primary posted sales document.
|
||||
- `SalesSlip` is a simplified retail document.
|
||||
- Returns are deferred to a later step.
|
||||
- Existing ERP patterns must be preserved: repository, unit of work, audit, ETag, and FIFO stock posting.
|
||||
Reference in New Issue
Block a user