# Promotions Foundation v16

## Purpose

Promotions are independent from base pricing and from Sales.

Intended runtime order:

Base Price
-> Pricing Resolution
-> Promotion Eligibility
-> Promotion Calculation
-> Final Line/Basket Price

## Normalized storage

Normalized tables:
- promotions.campaigns
- promotions.scopes
- promotions.targets
- promotions.conditions
- promotions.rewards
- promotions.usage_counters

`compiled_rule` JSONB is a runtime projection only.
It is not the authoritative source of the promotion definition.

## Scope

Supported scope:
- tenant
- company
- branch
- customer group
- customer

Customer/group references remain external keys until CRM exists.

## Targets

Supported:
- all
- product family
- variant
- category

## Conditions

Initial conditions:
- minimum quantity
- minimum basket amount

## Rewards

Initial rewards:
- percentage discount
- fixed discount
- buy X get Y foundation

Actual cart allocation and free-item materialization belong to Sales/Cart integration.

## Priority and stacking

Each campaign has:
- priority
- exclusive flag

v16 preserves these semantics and returns them during eligibility evaluation.
The final multi-campaign stacking engine will be integrated with Cart so the Sales domain
owns the authoritative final applied-discount snapshot.

## Usage

Campaigns may have:
- max total uses
- max uses per customer

Usage counters are separate mutable counters.
Authoritative redemption will later be incremented transactionally during checkout.

## APIs

- GET/POST /api/v1/promotions/campaigns
- POST /api/v1/promotions/campaigns/{id}/scopes
- POST /api/v1/promotions/campaigns/{id}/targets
- GET /api/v1/promotions/campaigns/{id}/evaluate

## Permissions

- promotions.view
- promotions.manage

## Audit

- promotions.campaign.created
- promotions.scope.attached
- promotions.target.attached
