3.7 KiB
Change History
Architectural decisions and significant refactoring are recorded here. Every architectural decision MUST be documented in this file.
2026-02-20: Seen Registry Deduplication by Partnumber
Decision
Changed qt_vendor_partnumber_seen semantics to one row per partnumber (vendor/source are no longer part of uniqueness).
Rationale
- Eliminates duplicate seen rows when the same partnumber appears both with vendor and without vendor.
- Keeps ignore behavior consistent regardless of vendor presence.
- Simplifies operational cleanup and prevents re-creation of vendor/no-vendor duplicates.
Constraints
partnumberis now the unique key in seen registry.- Ignore checks are resolved by
partnumberonly. - Stock provenance must be preserved (
source_type='stock') when stock data exists for the partnumber.
Files
- Migration:
migrations/025_dedup_vendor_seen_by_partnumber.sql - Service:
internal/services/stock_import.go - Service:
internal/services/vendor_mapping.go - Model:
internal/models/lot.go
2026-02-18: Global Vendor Partnumber Mapping
Decision
Implemented global vendor partnumber → LOT mapping with bundle support and seen-based ignore logic.
Key rules
lot_partnumbersis the canonical mapping contract (1:1 per key).- Composite mappings use internal bundle tables (
qt_lot_bundles,qt_lot_bundle_items). - Ignore logic moved from
stock_ignore_rulestoqt_vendor_partnumber_seen.is_ignored. - Resolver order: exact
(vendor, partnumber)→ fallback(vendor='', partnumber).
Rationale
- Preserves external/client contracts (
lot_partnumbers, LOT-based pricelists). - Avoids multi-row ambiguity in
lot_partnumbers. - Supports complex assembled vendor SKUs without client-side changes.
- Centralizes ignore behavior across all sources via seen-registry.
Constraints
- Bundle LOT is internal and must stay hidden in regular LOT list by default.
- Resolver order is mandatory and fixed.
- Bundle allocation for missing estimate: fallback from previous active warehouse pricelist; if absent →
0.
Files
- Migration:
migrations/023_vendor_partnumber_global_mapping.sql - Backfill:
migrations/024_backfill_vendor_seen_from_stock_and_ignore.sql - Resolver:
internal/lotmatch/matcher.go - Service:
internal/services/vendor_mapping.go - Warehouse calc:
internal/warehouse/snapshot.go - Stock import:
internal/services/stock_import.go - API:
internal/handlers/pricing.go,cmd/pfs/main.go
2026-02-10: LOT Page Refactoring
Decision
Moved LOT management to a dedicated /lot page. Removed LOT tab from Pricing Admin.
What changed
- Created
web/templates/lot.html— two tabs: LOT (component management) and Mappings (partnumber ↔ LOT). - Removed LOT tab from
admin_pricing.html; default tab changed toestimate. - Removed "Сопоставление partnumber → LOT" section from Warehouse tab.
- Updated navigation: LOT →
/lot, Pricing Admin →/admin/pricing. - Added
Lot()handler ininternal/handlers/web.go. - Added
/lotroute incmd/pfs/main.go.
Rationale
Separation of concerns: LOT/component management is distinct from pricing administration.
Warehouse Pricing: Weighted Average
Decision
Warehouse pricelist uses weighted_avg (quantity-weighted average) as the sole price calculation method.
Commit edff712 switched from weighted_median to weighted_avg.
price_methodfield always contains"weighted_avg".- No
price_period_days,price_coefficient,manual_price,meta_pricesin warehouse pricelists.
Architecture Conventions
All future architectural decisions must be documented here with:
- Date
- Decision summary
- Rationale
- Constraints / invariants
- Affected files