# 15 · BACKEND — Bundle Sales API > **Authoritative for:** fixed-composition bundle sales, templates, posting, and print data. > **Navigation:** start from `00-CORE.md`. This module follows the same repository/UoW/ETag/audit patterns as invoices and slips. --- ## 1. Concept Bundle sales are a separate sales document family for fixed bundle compositions. Rules: - a bundle sale is created from a bundle template - the bundle template defines fixed component stock lines - posting consumes stock from the component items, not from a synthetic bundle SKU - the bundle header carries the commercial sale value - print views show both bundle summary and component breakdown --- ## 2. API ### `GET /api/v1/bundle-sales` Query: - `page` - `pageSize` - `q` - `customerId` - `warehouseId` ### `GET /api/v1/bundle-sales/{bundleSaleId}` Returns the bundle sale header and all component lines. ### `GET /api/v1/bundle-sales/{bundleSaleId}/posting-check` Validates component stock before posting. ### `POST /api/v1/bundle-sales` Creates a draft bundle sale from a fixed bundle template. ### `PUT /api/v1/bundle-sales/{bundleSaleId}` Updates a draft bundle sale. Requires `If-Match`. ### `POST /api/v1/bundle-sales/{bundleSaleId}/post` Consumes stock from included component lines and marks the bundle as posted. ### `POST /api/v1/bundle-sales/{bundleSaleId}/cancel` Cancels a draft bundle sale. --- ## 3. Template Rules - bundle templates are fixed in composition - each template line maps to one component stock item - component quantities are expanded into the sale draft at creation time - price override is allowed only when the caller is permitted by business rules --- ## 4. Data Model ### `BundleSaleTemplate` - `BundleSaleTemplateId` - `TemplateCode` - `TemplateName` - `Description` - `Status` - `CreatedAt` - `UpdatedAt` - `RowVersion` ### `BundleSaleTemplateLine` - `BundleSaleTemplateLineId` - `BundleSaleTemplateId` - `ItemId` - `UomId` - `WarehouseId` - `Qty` - `UnitPrice` - `IncludeInBundle` - `SortOrder` ### `BundleSale` - `BundleSaleId` - `BundleNo` - `BundleDate` - `CustomerId` - `CustomerSnapshotName` - `WarehouseId` - `CashierUserId` - `BundleSaleTemplateId` - `BundleName` - `BundleCode` - `Status` - `ComponentSubtotal` - `BundlePrice` - `MarginAmount` - `DiscountTotal` - `TaxTotal` - `GrandTotal` - `CreatedAt` - `UpdatedAt` - `RowVersion` ### `BundleSaleLine` - `BundleSaleLineId` - `BundleSaleId` - `ItemId` - `Description` - `Qty` - `UomId` - `WarehouseId` - `UnitPrice` - `LineTotal` - `IncludeInBundle` - `IsComponent` - `ParentLineId` - `RowVersion` --- ## 5. Posting Posting behavior: - validate each included component line has sufficient stock - consume FIFO layers from the component items - write stock ledger rows for each component - mark the bundle as posted in the same transaction --- ## 6. Notes - This module is intentionally separate from invoices and slips. - Bundle sales are for fixed compositions only in this phase. - Print views should mirror the existing sales document print behavior without the dashboard shell.