Product Price Service
Overview
Product Prices represent time-based pricing for products within specific price lists.
Each Product Price defines:
- product identifier (
ProductId) - price list identifier (
PriceListId) - unit price (
UnitPrice) - validity period (
StartDate,EndDate)
Product Prices enable time-based pricing strategies, promotional pricing, and price history tracking. Multiple prices can exist for the same product-price list combination with different date ranges, allowing for scheduled price changes and promotional periods.
All product price operations are tenant-aware and fully audited.
Endpoints
GET
/api/v1/ProductPrice/GetAllProductPrices/{productId}/{priceListId}
Returns all product prices for a given product in a specific price list.
Route parameters:
productId(long, required)priceListId(long, required)
Behavior:
- Filters by
ProductIdandPriceListId - Returns all prices regardless of date validity
- Ordered by
StartDate - Supports large datasets via internal batching:
- reads in batches of
BATCH_SIZEto optimize performance
- reads in batches of
- Returns
404if no prices exist for the product-price list combination
Response:
List<ProductPriceModel>
Authorization:
- Requires Bearer Token
GET
/api/v1/ProductPrice/GetActiveProductPrice/{productId}/{priceListId}
Returns the currently active product price based on the current date.
Route parameters:
productId(long, required)priceListId(long, required)
Behavior:
- Filters by
ProductIdandPriceListId - Returns only prices where current date (UTC) falls between
StartDateandEndDate - If multiple overlapping prices exist, returns the one with the most recent
StartDate - Returns
404if no active price exists
Response:
ProductPriceModel
Authorization:
- Requires Bearer Token
POST
/api/v1/ProductPrice/AddNewProductPrice
Creates a new product price.
Request body (ProductPriceModel):
ProductId(long, required, must be > 0)PriceListId(long, required, must be > 0)UnitPrice(decimal?, required, must be > 0)StartDate(DateOnly?, optional, defaults to current date UTC if not provided)EndDate(DateOnly?, optional, null for indefinite validity)
Behavior:
- Validation is enforced in the service layer (
IsReadyToAdd()) StartDatedefaults to current date (UTC) if not providedEndDateis optional and can be null for prices with indefinite validity- Multiple prices can exist for the same
(ProductId, PriceListId)with different date ranges - Successful creation writes an audit log entry
Errors:
- Returns
400if:- request body is invalid (
IsReadyToAdd()is false) - database insert - or other internal error occurs
- request body is invalid (
Response:
200 OKwith message:"New product price added"400 Bad Requestwith message:"Add new product price failed"
Authorization:
- Requires Bearer Token
DELETE
/api/v1/ProductPrice/DeleteProductPriceById/{id}
Deletes a product price by its ID.
Route parameters:
id(int, required)
Behavior:
- Performs a hard delete
- Successful deletion writes an audit log entry
Errors:
- Returns
400with message"ProductPrice not found"if the product price does not exist
Response:
200 OKwith message:"ProductPrice deleted successfully"400 Bad Requestwith message:"ProductPrice not found"
Authorization:
- Requires Bearer Token
Notes
- Validation is enforced in the service layer, not via model attributes
- Multiple prices can exist for the same
(ProductId, PriceListId)with different date ranges StartDatedefaults to current date (UTC) if not provided during creationEndDatecan be null for indefinite validity- Active price determination uses current date (UTC) and prioritizes most recent
StartDateif overlaps exist - Large dataset reads are automatically batched for performance optimization
- No update endpoint exists - price changes are typically handled by creating new price records
- Internal errors are logged and not exposed to API consumers