9.6 KiB
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:
CustomerIdCustomerCodeCustomerType(B2B,B2C,WalkIn)NameDisplayNamePhoneEmailAddressLine1AddressLine2CityCountryTaxRegistrationNoCreditLimitCreditDaysDefaultWarehouseIdStatusCreatedAtUpdatedAtRowVersion
SalesInvoice
Primary posted sales document.
Fields:
SalesInvoiceIdInvoiceNoInvoiceDateCustomerIdCustomerSnapshotNameCustomerSnapshotTaxNoWarehouseIdInvoiceType(B2B,B2C,Cash,Credit)Status(Draft,Posted,Cancelled)SubtotalDiscountTotalTaxTotalGrandTotalRoundOffNetPayablePaidAmountBalanceAmountCreatedByCreatedAtUpdatedAtRowVersion
SalesInvoiceLine
Invoice line with pricing, discount, and free issue support.
Fields:
SalesInvoiceLineIdSalesInvoiceIdItemIdDescriptionQtyFreeQtyUomIdWarehouseIdUnitPriceBaseCostPriceSourceDiscountPctDiscountAmountNetUnitPriceLineTotalTaxPctTaxAmountIsFreeIssueParentLineIdRowVersion
SalesSlip
Fast retail or counter-sale document.
Fields:
SalesSlipIdSlipNoSlipDateCustomerIdCustomerSnapshotNameWarehouseIdCashierUserIdStatusSubtotalDiscountTotalTaxTotalGrandTotalPaidAmountBalanceAmountCreatedAtUpdatedAtRowVersion
SalesSlipLine
Slip line with the same sales calculation rules as invoices.
Fields:
SalesSlipLineIdSalesSlipIdItemIdDescriptionQtyFreeQtyUomIdWarehouseIdUnitPriceBaseCostPriceSourceDiscountPctDiscountAmountNetUnitPriceLineTotalTaxPctTaxAmountIsFreeIssueParentLineIdRowVersion
Phase 1 Pricing Rule
Use the following order:
- fixed
Item.SalePrice - GRN-derived stock cost fallback
- 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
StockLedgerrows - maintain source document traceability
- update totals in the same transaction
Phase 1 API Route List
GET /api/v1/customersGET /api/v1/customers/{id}POST /api/v1/customersPUT /api/v1/customers/{id}PATCH /api/v1/customers/{id}/statusGET /api/v1/sales-invoicesGET /api/v1/sales-invoices/{id}POST /api/v1/sales-invoicesPUT /api/v1/sales-invoices/{id}POST /api/v1/sales-invoices/{id}/postPOST /api/v1/sales-invoices/{id}/cancelGET /api/v1/sales-invoices/{id}/print-previewGET /api/v1/sales-slipsGET /api/v1/sales-slips/{id}POST /api/v1/sales-slipsPOST /api/v1/sales-slips/{id}/postPOST /api/v1/sales-slips/{id}/cancelGET /api/v1/sales-reports/daily-summaryGET /api/v1/sales-reports/item-wiseGET /api/v1/sales-reports/customer-wiseGET /api/v1/sales-reports/warehouse-wiseGET /api/v1/sales-reports/discount-summaryGET /api/v1/sales-reports/free-issue-summaryGET /api/v1/sales-reports/margin-summary
Phase 1 Folder / Module Plan
Domain/Entities- add
Customer,SalesInvoice,SalesInvoiceLine,SalesSlip,SalesSlipLine
- add
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
- add
Services- implement the sales services with transaction-safe logic
Controllers- add
CustomersController,SalesInvoicesController,SalesSlipsController,SalesReportsController
- add
Infra/Persistence/Configurations- add EF Core mappings for all sales entities
Infra/Persistence/ErpDbContext.cs- register sales
DbSets
- register sales
Infra/Persistence/Migrations- add the sales schema migration after the model is defined
Phase 1 Implementation Order
- Customer master
- Sales invoice entity and DTOs
- Sales slip entity and DTOs
- Pricing resolver
- Discount computation
- Free issue handling
- Stock posting and ledger integration
- Basic sales reports
- 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-groupsPOST /api/v1/customer-groupsPUT /api/v1/customer-groups/{id}PATCH /api/v1/customer-groups/{id}/statusGET /api/v1/price-listsPOST /api/v1/price-listsPUT /api/v1/price-lists/{id}PATCH /api/v1/price-lists/{id}/statusGET /api/v1/price-lists/{id}/itemsPUT /api/v1/price-lists/{id}/itemsGET /api/v1/pricing/resolveGET /api/v1/promotionsPOST /api/v1/promotionsPUT /api/v1/promotions/{id}PATCH /api/v1/promotions/{id}/statusGET /api/v1/free-issue-schemesPOST /api/v1/free-issue-schemesPUT /api/v1/free-issue-schemes/{id}PATCH /api/v1/free-issue-schemes/{id}/statusPOST /api/v1/sales-ordersPOST /api/v1/sales-orders/{id}/reservePOST /api/v1/sales-orders/{id}/confirmPOST /api/v1/sales-paymentsPOST /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
- customer groups
- price lists
- promotions and free issue schemes
- sales orders and reservations
- payments and allocations
- advanced reports
- 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.
SalesInvoiceis the primary posted sales document.SalesSlipis 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.