Files
ERP-core/docs/SALES_MODULE_PLAN.md
2026-08-04 17:19:30 +05:30

12 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.

Current Implementation Status

The Phase 1 core is implemented and wired across the backend and frontend for:

  • sales invoices
  • sales slips
  • free issues as a slip alias
  • bundle sales
  • sales posting to stock/FIFO

Shared backend services now centralize the repeated sales logic:

  • sales validation and pricing
  • sales posting checks and FIFO outbound posting
  • invoice/slip mapping and totals
  • shared draft edit/load workflow checks

Still intentionally separate:

  • bundle pricing and bundle margin behavior
  • production and GRN as upstream stock/cost sources
  • reservation/backorder flow
  • sales reports visibility in the frontend UI, which is currently hidden from the navigation but still implemented in the backend

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

Implemented Shared Services

  • ISalesDomainService
    • header validation
    • line validation
    • price resolution
    • line financial computation
    • stock-item classification
  • ISalesPostingService
    • invoice/slip/bundle posting checks
    • shared FIFO posting for stocked items
  • ISalesMappingService
    • invoice/slip totals mapping
    • invoice/slip DTO mapping
  • ISalesDocumentWorkflowService
    • shared editable-document load and concurrency checks for invoice/slip draft updates

Not in Scope for Phase 1

  • customer groups
  • price lists
  • promotions
  • reservations
  • sales payments allocation
  • approval workflow
  • returns and credit notes
  • advanced customer segmentation
  • fully unified sales provenance tracing across production, GRN, and sales documents

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

Sales document provenance is stored by document family:

  • SalesInvoice / SalesInvoiceLine
  • SalesSlip / SalesSlipLine
  • BundleSale / BundleSaleLine

Inventory movement provenance is stored in:

  • StockLayer
  • StockLedger via SourceDocType / SourceDocId
  • JournalEntryStub via SourceDocType / SourceDocId

Upstream cost/availability sources remain:

  • Grn / GrnLine for inbound purchasing cost
  • ProductionRun and stage tables for finished-goods production cost

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/free-issues
  • GET /api/v1/free-issues/{id}
  • POST /api/v1/free-issues
  • PUT /api/v1/free-issues/{id}
  • POST /api/v1/free-issues/{id}/post
  • POST /api/v1/free-issues/{id}/cancel
  • GET /api/v1/reports/sales
  • GET /api/v1/reports/sales/{reportId}
  • POST /api/v1/reports/sales/query

Note:

  • the sales report backend routes remain implemented
  • the frontend report entry points are currently hidden from navigation, but the screens and API contracts still exist

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 DbSets
  • 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
  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
  • bundle sales templates
  • bundle sales documents
  • 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.

BundleSaleTemplate

Fixed bundle composition definition.

BundleSaleTemplateLine

Component stock items and quantities inside a bundle template.

BundleSale

Posted or draft bundle sale header.

BundleSaleLine

Component lines expanded from a bundle template.

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 the frontend sales hub and sidebar only expose invoice, slip, and free-issue entry points while report pages remain reachable directly.
  • 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.