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:
Mikhail Chusavitin
2026-07-10 10:25:46 +03:00
co-authored by Claude Opus 4.8
parent 498cbf5490
commit 70a3ff255f
10 changed files with 586 additions and 52 deletions
+8 -8
View File
@@ -165,7 +165,7 @@ func (s *LocalConfigurationService) ImportVendorWorkspaceToProject(projectUUID s
if len(imported.DirectItems) > 0 {
items = imported.DirectItems
estimatePricelist, _ := s.localDB.GetLatestLocalPricelistBySource("estimate")
estimatePricelist, _ := localdb.GetLatestLocalPricelistBySourceTx(tx, "estimate")
if estimatePricelist != nil {
estimatePricelistID = &estimatePricelist.ServerID
}
@@ -173,7 +173,7 @@ func (s *LocalConfigurationService) ImportVendorWorkspaceToProject(projectUUID s
totalPrice = &val
} else {
var prepErr error
groupRows, items, totalPrice, estimatePricelistID, prepErr = s.prepareImportedConfiguration(imported.Rows, imported.ServerCount, bookRepo)
groupRows, items, totalPrice, estimatePricelistID, prepErr = s.prepareImportedConfiguration(tx, imported.Rows, imported.ServerCount, bookRepo)
if prepErr != nil {
return fmt.Errorf("prepare imported configuration group %s: %w", imported.GroupID, prepErr)
}
@@ -219,7 +219,7 @@ func (s *LocalConfigurationService) ImportVendorWorkspaceToProject(projectUUID s
return result, nil
}
func (s *LocalConfigurationService) prepareImportedConfiguration(rows []localdb.VendorSpecItem, serverCount int, bookRepo *repository.PartnumberBookRepository) (localdb.VendorSpec, localdb.LocalConfigItems, *float64, *uint, error) {
func (s *LocalConfigurationService) prepareImportedConfiguration(tx *gorm.DB, rows []localdb.VendorSpecItem, serverCount int, bookRepo *repository.PartnumberBookRepository) (localdb.VendorSpec, localdb.LocalConfigItems, *float64, *uint, error) {
resolver := NewVendorSpecResolver(bookRepo)
resolved, err := resolver.Resolve(append([]localdb.VendorSpecItem(nil), rows...))
if err != nil {
@@ -242,13 +242,13 @@ func (s *LocalConfigurationService) prepareImportedConfiguration(rows []localdb.
canonical = append(canonical, row)
}
estimatePricelist, _ := s.localDB.GetLatestLocalPricelistBySource("estimate")
estimatePricelist, _ := localdb.GetLatestLocalPricelistBySourceTx(tx, "estimate")
var serverPricelistID *uint
if estimatePricelist != nil {
serverPricelistID = &estimatePricelist.ServerID
}
items := aggregateVendorSpecToItems(canonical, estimatePricelist, s.localDB)
items := aggregateVendorSpecToItemsTx(tx, canonical, estimatePricelist)
totalValue := items.Total()
if serverCount > 1 {
totalValue *= float64(serverCount)
@@ -257,7 +257,7 @@ func (s *LocalConfigurationService) prepareImportedConfiguration(rows []localdb.
return canonical, items, totalPrice, serverPricelistID, nil
}
func aggregateVendorSpecToItems(spec localdb.VendorSpec, estimatePricelist *localdb.LocalPricelist, local *localdb.LocalDB) localdb.LocalConfigItems {
func aggregateVendorSpecToItemsTx(tx *gorm.DB, spec localdb.VendorSpec, estimatePricelist *localdb.LocalPricelist) localdb.LocalConfigItems {
if len(spec) == 0 {
return localdb.LocalConfigItems{}
}
@@ -276,8 +276,8 @@ func aggregateVendorSpecToItems(spec localdb.VendorSpec, estimatePricelist *loca
sort.Strings(order)
var priceMap map[string]float64
if estimatePricelist != nil && local != nil && len(order) > 0 {
priceMap, _ = local.GetLocalPricesForLots(estimatePricelist.ID, order)
if estimatePricelist != nil && len(order) > 0 {
priceMap, _ = localdb.GetLocalPricesForLotsTx(tx, estimatePricelist.ID, order)
}
items := make(localdb.LocalConfigItems, 0, len(order))