diff --git a/bible-local/README.md b/bible-local/README.md index 2b1b8bc..eca6cda 100644 --- a/bible-local/README.md +++ b/bible-local/README.md @@ -16,6 +16,7 @@ Project-specific architecture and operational contracts. | [09-vendor-spec.md](09-vendor-spec.md) | Vendor BOM and CFXML import contract | | [10-agent-api-guide.md](10-agent-api-guide.md) | End-to-end API guide for agents pricing servers from a TZ | | [11-lot-suggestions.md](11-lot-suggestions.md) | lot_suggestion column in qt_vendor_partnumber_seen — write/read contract for manual UI mappings | +| [decisions/](decisions/README.md) | Architectural decision log, one file per decision | ## Rules diff --git a/bible-local/decisions/2026-07-10-world-pricelist-fallback.md b/bible-local/decisions/2026-07-10-world-pricelist-fallback.md index 97a68b4..23dc8ec 100644 --- a/bible-local/decisions/2026-07-10-world-pricelist-fallback.md +++ b/bible-local/decisions/2026-07-10-world-pricelist-fallback.md @@ -43,3 +43,7 @@ is missing or ≤ 0: "latest active `world` pricelist," not a per-configuration pin. - If no `world` pricelist exists locally, behavior is unchanged (missing prices stay "—", no error). +- How the footer totals surface this fallback is decided separately in + [2026-07-24-pricing-total-world-share.md](2026-07-24-pricing-total-world-share.md); + membership of world LOTs in the configurator's LOT set is decided in + [2026-07-24-component-universe-world-union.md](2026-07-24-component-universe-world-union.md). diff --git a/bible-local/decisions/2026-07-24-pricing-total-world-share.md b/bible-local/decisions/2026-07-24-pricing-total-world-share.md new file mode 100644 index 0000000..c6735ae --- /dev/null +++ b/bible-local/decisions/2026-07-24-pricing-total-world-share.md @@ -0,0 +1,47 @@ +# Decision: pricing totals signal the world-fallback share, not row coverage + +**Date:** 2026-07-24 +**Status:** active + +## Context + +The footer totals of both "Ценообразование" tables used to mean one thing: a red number +with a trailing `*` said "prices are missing for some positions (N of M)". Two problems: + +- the asterisk was a separate `` after the number and wrapped onto its own line, + pushing the footer layout around; +- coverage was the wrong thing to warn about. Since + [2026-07-10-world-pricelist-fallback.md](2026-07-10-world-pricelist-fallback.md) a + missing price is silently filled from the `world` pricelist, so the total is rarely + incomplete — it is *contaminated*. A sum resting on world stand-in prices looked exactly + like a sum of real ones. + +## Decision + +`_setPricingTotal` in `web/templates/index.html` renders every footer total for Estimate, +Склад and Конкуренты in both tables (buy and sale): + +- No asterisk, ever. The number stands alone. +- The total is red **if and only if** part of it was computed from `world` prices — that + is, `worldTotal > 0`. A clean sum is not coloured. Red is a contamination signal, not a + coverage signal. +- The world share per column is accumulated from the same per-row flags that tint the + cells amber (`estWorld` / `whWorld` / `compWorld`), summed over line totals, not unit + prices. +- Hovering the total opens a styled popup (`.pricing-total-tip` in `web/static/app.css`), + not a `title=` tooltip — the native one appears too late to notice on a number the user + is meant to distrust. It states the exact percentage and, when prices are genuinely + missing for some rows, adds the coverage line that the asterisk used to carry. +- "Ручная цена" is not part of this: it is user input, never world-derived. + +## Consequences + +- Red in the pricing footer means "part of this sum is a stand-in price", nothing else. + Do not reuse it for coverage, staleness or any other condition. +- The colour and popup classes are re-applied on every render and stripped first, so they + never accumulate across re-renders. +- The totals are written with `innerHTML` (number plus popup element). Nothing may read + `textContent` off `#pricing-total-*-estimate|warehouse|competitor`; the vendor-price + column and row `data-` attributes remain the read path for `applyCustomPrice` and + `_getPricingEstimateTotal`. +- The old `_setPartialTotal` helper is gone; do not reintroduce a coverage-only signal.