feat: world-прайслист как заглушка для отсутствующих цен
Там, где для LOT нет цены в estimate/warehouse/competitor, подставляется цена из world-прайслиста. Такие ячейки в таблицах «Цена покупки»/«Цена продажи» подсвечиваются (amber), участвуют в «Итого» и убирают красную «*». В CSV-экспорте добавлена колонка «Заглушка (world)» с перечнем столбцов, где сработал фолбэк. Добавлены Tx-версии GetLatestLocalPricelistBySource/GetLocalPricesForLots, чтобы резолв прайслистов внутри транзакции не дедлочил single-connection пул. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
498cbf5490
commit
70a3ff255f
@@ -50,7 +50,7 @@
|
||||
| --- | --- | --- |
|
||||
| `POST` | `/api/quote/validate` | validate config items |
|
||||
| `POST` | `/api/quote/calculate` | calculate quote totals |
|
||||
| `POST` | `/api/quote/price-levels` | resolve estimate/warehouse/competitor prices |
|
||||
| `POST` | `/api/quote/price-levels` | resolve estimate/warehouse/competitor prices (falls back to `world` source per column, see [decisions/2026-07-10-world-pricelist-fallback.md](decisions/2026-07-10-world-pricelist-fallback.md)) |
|
||||
| `POST` | `/api/export/csv` | export a single configuration |
|
||||
| `GET` | `/api/configs/:uuid/export` | export a stored configuration |
|
||||
| `GET` | `/api/projects/:uuid/export` | legacy project BOM export |
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
# Decision: `world` pricelist as a fallback stub for missing prices
|
||||
|
||||
**Date:** 2026-07-10
|
||||
**Status:** active
|
||||
|
||||
## Context
|
||||
|
||||
Four pricelist `source` values sync from the server: `estimate`, `warehouse`, `competitor`,
|
||||
`world`. Only the first three were ever read — `world` synced into `local_pricelists` /
|
||||
`local_pricelist_items` but nothing consumed it, so LOTs with no warehouse/competitor price
|
||||
showed as "—" in the "Ценообразование" tab, which also broke the "Итого" coverage (red "*").
|
||||
|
||||
## Decision
|
||||
|
||||
`world` is a fallback stub, applied per-column, only when the native price for that column
|
||||
is missing or ≤ 0:
|
||||
|
||||
- Resolution order per column: native source price → `world` price → still missing.
|
||||
- Applies to all three Buy columns (Estimate, Склад, Конкуренты), the Sale table (same
|
||||
unit prices, multiplied by the existing sale coefficients), and CSV export.
|
||||
- A world-fallback price counts toward "Итого" like a native price (closes the red "*" gap).
|
||||
- UI marks only the specific cell that used a fallback, with `bg-amber-50 text-amber-700`
|
||||
(amber was chosen because `applyCustomPrice()` strips `gray/green/red/blue` text-color
|
||||
classes via regex on vendor-price cells — amber survives that).
|
||||
- CSV keeps price values untouched (no suffixes) and adds one trailing comment column,
|
||||
"Заглушка (world)", listing which columns used the fallback per row (e.g.
|
||||
`world: Stock, Конкуренты`), always present regardless of export options so column counts
|
||||
stay aligned across header/rows/summary.
|
||||
- `world` is resolved independently in each call site (`quote.go` `CalculatePriceLevels`,
|
||||
`export.go` `resolvePricingTotals`) via "explicit ID → latest active → latest local", same
|
||||
pattern as the other three sources. It is intentionally NOT added to `levelBySource` /
|
||||
`ResolvedPricelistIDs` as a fourth on-screen level.
|
||||
- `NormalizePricelistSource("world")` returns `PricelistSourceWorld`, not `estimate` — it must
|
||||
not collapse into the estimate source.
|
||||
|
||||
## Consequences
|
||||
|
||||
- `PriceLevelsItem` (API `POST /api/quote/price-levels`) carries three new bools:
|
||||
`estimate_from_world`, `warehouse_from_world`, `competitor_from_world`.
|
||||
- `price_missing` on that endpoint only lists a source when BOTH the native and the
|
||||
`world` price are unavailable.
|
||||
- No new config-level column (e.g. `world_pricelist_id`) — world always resolves to
|
||||
"latest active `world` pricelist," not a per-configuration pin.
|
||||
- If no `world` pricelist exists locally, behavior is unchanged (missing prices stay "—",
|
||||
no error).
|
||||
Reference in New Issue
Block a user