52 lines
2.0 KiB
Markdown
52 lines
2.0 KiB
Markdown
# Commerce analytics core
|
|
|
|
`commerce` is the product-centric analytics boundary of EUSRR. It does not
|
|
replace an operational CRM or warehouse. External and future internal systems
|
|
all supply records to the same canonical product model.
|
|
|
|
## Stable model
|
|
|
|
- `Product` is one sellable or stockable SKU. `parent` groups variants.
|
|
- `SourceRecord` retains the latest raw payload with source provenance.
|
|
- `ProductBinding` maps a source product/offer identifier to `Product`.
|
|
- `Sale` and `SaleLine` contain normalized product-level sales facts.
|
|
- `Cost` contains commissions, delivery, advertising and other expenses.
|
|
- `StockSnapshot` contains point-in-time stock observations by source and
|
|
warehouse.
|
|
|
|
Money is never aggregated across currencies. Returns are represented as a
|
|
`Sale` with `event_type="return"`; line values remain positive and analytics
|
|
applies the sign.
|
|
|
|
## Integration contract
|
|
|
|
An adapter subclasses `commerce.integrations.SourceAdapter`, handles API
|
|
pagination internally and yields `ExternalRecord` objects. Register it in
|
|
`adapter_registry`, then invoke the Celery task `commerce.sync_source`.
|
|
|
|
Adapters must not store credentials in `SourceSystem.metadata`; secrets belong
|
|
in environment-backed configuration or a dedicated encrypted credential
|
|
store.
|
|
|
|
Source-specific code must not create alternative product models. It stores the
|
|
raw payload first and then resolves a product through `ProductBinding` or
|
|
`commerce.services.match_product` before writing normalized facts.
|
|
|
|
## API
|
|
|
|
The authenticated API is mounted at `/api/v1/commerce/`:
|
|
|
|
- `products/`
|
|
- `products/{id}/analytics/`
|
|
- `sources/`
|
|
- `product-bindings/`
|
|
- `sales/`
|
|
- `sale-lines/`
|
|
- `costs/`
|
|
- `stock-snapshots/`
|
|
|
|
All employees may read. Writes require staff status or the corresponding
|
|
Django model permission. The frontend management screen can bootstrap and
|
|
correct normalized records manually; integrations should still write them
|
|
through application services so raw provenance and idempotency are preserved.
|