# Customer Sales Pricing

## Overview

Customer Sales Pricing manages the customer- and channel-facing commercial rules that default onto sales order lines. A `SalesPriceList` groups reusable pricing conditions for one company, while `SalesPriceRule` defines the actual pricing logic for a given item and selling context, such as customer scope, channel scope, effective date, minimum quantity, currency, and unit of measure. These rules allow the sales organization to keep agreed sell prices in structured form instead of entering them manually on every order.

The feature is intentionally sales-specific rather than a full enterprise pricing engine. It focuses on "what price should this customer or channel receive for this item under these conditions?" and provides deterministic price selection when users or integrations create or revise sales orders. Promotions, coupon redemption, commissions, and settlement-time discount accounting remain explicit non-goals for the initial scope.

## Business Purpose

- Reduce manual entry by defaulting agreed customer or channel prices onto sales order lines
- Capture quantity breaks, date validity, and currency-specific selling rules
- Support differentiated pricing by customer, channel, or commercial program without duplicating item master data
- Preserve commercial history by snapshotting the applied rule onto the sales order at confirmation time
- Enable invoice validation and downstream analytics by keeping the ordered price independent from later rule edits
- Separate pricing logic from product definition and from downstream receivable settlement logic
- Keep sales-UoM pricing compatible with inventory execution by delegating unit conversion to shared primitives

## Process Flow

```mermaid
flowchart TD
    A[Create Sales Price List] --> B[Add Sales Price Rules]
    B --> C[Set customer or channel scope, dates, quantity breaks]
    C --> D[Activate list]
    D --> E[User or integration creates sales order line]
    E --> F[Resolve applicable rules]
    F --> G{Rule found?}
    G -->|Yes| H[Apply best matching rule]
    G -->|No| I[Manual price entry]
    H --> J[Snapshot applied price and rule reference on order line]
    I --> J
    J --> K[Order confirmed]
    K --> L[Invoice uses order price snapshot]
```

## Scenario Patterns

- **Standard price list**: A company maintains a default sell price list for all direct customers and applies it automatically to new orders
- **Customer contract pricing**: A strategic customer has a negotiated annual unit price for a specific item, and that rule overrides the default list
- **Channel-specific pricing**: The same item is sold on a marketplace and on a direct B2B channel at different prices, and the correct rule is selected from the originating channel
- **Quantity break pricing**: A customer receives a lower unit price when ordering more than a configured quantity threshold
- **Time-bounded commercial window**: A temporary seasonal price applies only within a specific effective date range, after which the regular price resumes
- **Multi-currency selling**: The same company sells one item in JPY on a domestic channel and USD on an export channel, and rules keep those conditions separate
- **Manual exception before confirmation**: The system defaults a contracted price, but the sales user overrides it on a draft order while retaining the matched-rule reference for auditability
- **Rule retirement**: An obsolete price list is deactivated when a new commercial agreement begins, preventing future orders from using stale pricing
- **Marketplace item mapping**: A listing points to an item that has a channel-specific price rule, allowing channel order sync to create sales orders without custom pricing logic in the integration layer

## Test Cases

- Creating a sales price list for an ACTIVE company should succeed
- A sales price rule must require a positive unit price and a valid item or defined pricing scope
- A quantity-break rule must not allow a negative minimum quantity
- A rule with an effective end date earlier than its start date should fail validation
- Inactive price lists or inactive rules must not be selected for new sales orders
- When multiple rules match the same order line, rule resolution must follow deterministic precedence based on company, customer scope, channel scope, item scope, UoM, minimum quantity, date, and explicit priority
- When no rule matches an order line, the system should allow manual pricing while marking the line as unmatched to a price rule
- Editing a price rule after a sales order is confirmed must not retroactively change the ordered unit price on that existing order
- A sales price list must be isolated by company when company-specific commercial policies differ
- Duplicate rules with indistinguishable precedence for the same item, customer or channel, date, and quantity context should be rejected or warned
- A sales price rule currency must reference a valid currency from the primitives module
- If a sales price rule UoM differs from the item's operational UoM, a valid conversion path from `primitives` must exist before the rule can be used operationally
- Only ACTIVE items should be assignable to newly created sales price rules
- A user should be able to override a defaulted price on a draft order while retaining audit information about the default rule
- Customer invoices should consume the sales order's snapshotted price even if the underlying rule is later deactivated
- Only authorized sales users should be able to create, update, activate, or deactivate sales price lists

## Reference Links

- [Odoo pricelists documentation](https://www.odoo.com/documentation/19.0/applications/sales/sales/products_prices/prices/pricing.html)
- [Oracle Pricing documentation](https://docs.oracle.com/en/cloud/saas/supply-chain-and-manufacturing/index.html)
- [SAP Sales pricing overview](https://help.sap.com/docs/SAP_S4HANA_CLOUD)
