Pricing Module
Overview
The Pricing module is responsible for managing product pricing across different contexts.
It defines how prices are structured, overridden and accessed before they are used
by sales, quotations and order processing modules.
Pricing is required for:
- base product pricing (price lists)
- entity-specific price overrides (customer/supplier pricing)
- time-based pricing (promotional periods)
- product access control per entity
- multi-currency support
All operations are tenant-aware and scoped to the current tenant.
Services
The Pricing module consists of the following services:
- Price List - price list definitions and currency management
- Product Price - product pricing by price list and date range
- Entity Price Override - entity-specific price overrides
- Entity Product Access - product access control per entity
Models
This module exposes and consumes the following models.
Price List Model
Represents a price list definition with currency and default status.
Fields:
Id (type: long)- internal identifierName (type: string)- price list name (must be unique per currency)Currency (type: string)- currency code (e.g., "GBP", "USD", "EUR")IsDefault (type: bool?)- default price list flag for the currency
Validation:
IsReadyToAdd()- requires
Name - requires
Currency
- requires
IsReadyToUpdate()- requires
Id > 0 - requires
Name - requires
Currency
- requires
Notes:
- Only one price list can be marked as default per currency
- When a new default is set, the previous default for that currency is automatically unmarked
IsDefaultdefaults tofalseif not provided during creation
Product Price Model
Represents a product's price in a specific price list with time-based validity.
Fields:
PriceListId (type: long)- associated price list identifierProductId (type: long)- associated product identifierUnitPrice (type: decimal?)- product unit priceStartDate (type: DateOnly?)- price validity start dateEndDate (type: DateOnly?)- price validity end date (null for indefinite)
Validation:
IsReadyToAdd()- requires
PriceListId > 0 - requires
ProductId > 0 - requires
UnitPrice > 0
- requires
IsReadyToUpdate()- requires
PriceListId > 0 - requires
ProductId > 0 - requires
UnitPrice >= 0
- requires
Notes:
StartDatedefaults to current date (UTC) if not provided- Multiple prices can exist for the same
(ProductId, PriceListId)pair with different date ranges - Active price is determined by current date falling between
StartDateandEndDate - When retrieving active prices, the most recent
StartDateis prioritized if overlaps exist
Entity Price Override Model
Represents entity-specific pricing overrides (e.g., customer or supplier special pricing).
Fields:
EntityId (type: long)- associated entity identifier (customer/supplier)ProductId (type: long)- associated product identifierUnitPrice (type: decimal?)- override unit priceDiscountPercent (type: decimal?)- discount percentageStartDate (type: DateOnly)- override validity start dateEndDate (type: DateOnly)- override validity end date
Validation:
IsReadyToAdd()- requires
EntityId > 0 - requires
ProductId > 0 - requires
UnitPrice > 0ORDiscountPercent > 0
- requires
IsReadyToUpdate()- requires
EntityId > 0 - requires
ProductId > 0
- requires
Notes:
(EntityId, ProductId)must be unique (one override per entity-product pair)- Either
UnitPriceorDiscountPercentmust be provided (or both) - Entity price overrides take precedence over standard price list pricing
- Date ranges control when the override is active
Entity Product Access Model
Represents product access control for specific entities.
Fields:
EntityId (type: long?)- associated entity identifierProductId (type: long?)- associated product identifierAccess (type: string?)- access level or permission code
Validation:
IsEmpty()- returns
trueif:EntityIdis null, zero, or not providedProductIdis null, zero, or not providedAccessis null, empty, or whitespace
- returns
Notes:
(EntityId, ProductId)must be unique (one access record per entity-product pair)Accessfield defines the type of access granted (implementation-specific)- Used to control which entities (customers/suppliers) can view or purchase specific products
- Supports large datasets via batched reads when retrieving all access records for an entity
Notes
- All pricing operations support time-based validity through date ranges
- Price list defaults are automatically managed per currency
- Entity-specific overrides take precedence over standard pricing
- Product access control is enforced at the entity-product level
- Large dataset operations use batching for performance optimization
- Internal errors are logged and not exposed to API consumers