fix: CSV экспорт — bundle (1 PN → N LOT) разворачивается в отдельные строки
buildPricingExportBlock теперь создаёт одну строку на каждый LOT mapping, а не одну строку на BOM-строку. BOM-цена ставится только в первую подстроку (как vendorOrig в фронтенде). Добавлен computeSingleLotTotal, удалён неиспользуемый formatLotDisplay. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -388,17 +388,37 @@ func (s *ExportService) buildPricingExportBlock(cfg *models.Configuration, opts
|
|||||||
description = componentDescriptions[rowMappings[0].LotName]
|
description = componentDescriptions[rowMappings[0].LotName]
|
||||||
}
|
}
|
||||||
|
|
||||||
pricingRow := ProjectPricingExportRow{
|
if len(rowMappings) == 0 {
|
||||||
LotDisplay: formatLotDisplay(rowMappings),
|
block.Rows = append(block.Rows, ProjectPricingExportRow{
|
||||||
VendorPN: row.VendorPartnumber,
|
LotDisplay: "н/д",
|
||||||
Description: description,
|
VendorPN: row.VendorPartnumber,
|
||||||
Quantity: exportPositiveInt(row.Quantity, 1),
|
Description: description,
|
||||||
BOMTotal: vendorRowTotal(row),
|
Quantity: exportPositiveInt(row.Quantity, 1),
|
||||||
Estimate: computeMappingTotal(priceMap, rowMappings, row.Quantity, func(p pricingLevels) *float64 { return p.Estimate }),
|
BOMTotal: vendorRowTotal(row),
|
||||||
Stock: computeMappingTotal(priceMap, rowMappings, row.Quantity, func(p pricingLevels) *float64 { return p.Stock }),
|
})
|
||||||
Competitor: computeMappingTotal(priceMap, rowMappings, row.Quantity, func(p pricingLevels) *float64 { return p.Competitor }),
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// One export row per LOT mapping so that bundles (1 PN → N LOTs) appear
|
||||||
|
// as separate lines, matching the frontend pricing table layout.
|
||||||
|
pnQty := exportPositiveInt(row.Quantity, 1)
|
||||||
|
for i, mapping := range rowMappings {
|
||||||
|
lotQty := pnQty * mapping.QuantityPerPN
|
||||||
|
var bomTotal *float64
|
||||||
|
if i == 0 {
|
||||||
|
bomTotal = vendorRowTotal(row)
|
||||||
|
}
|
||||||
|
block.Rows = append(block.Rows, ProjectPricingExportRow{
|
||||||
|
LotDisplay: mapping.LotName,
|
||||||
|
VendorPN: row.VendorPartnumber,
|
||||||
|
Description: description,
|
||||||
|
Quantity: lotQty,
|
||||||
|
BOMTotal: bomTotal,
|
||||||
|
Estimate: computeSingleLotTotal(priceMap, mapping.LotName, lotQty, func(p pricingLevels) *float64 { return p.Estimate }),
|
||||||
|
Stock: computeSingleLotTotal(priceMap, mapping.LotName, lotQty, func(p pricingLevels) *float64 { return p.Stock }),
|
||||||
|
Competitor: computeSingleLotTotal(priceMap, mapping.LotName, lotQty, func(p pricingLevels) *float64 { return p.Competitor }),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
block.Rows = append(block.Rows, pricingRow)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, item := range cfg.Items {
|
for _, item := range cfg.Items {
|
||||||
@@ -696,6 +716,14 @@ func computeMappingTotal(priceMap map[string]pricingLevels, mappings []localdb.V
|
|||||||
return floatPtr(total)
|
return floatPtr(total)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func computeSingleLotTotal(priceMap map[string]pricingLevels, lotName string, qty int, selector func(pricingLevels) *float64) *float64 {
|
||||||
|
price := selector(priceMap[lotName])
|
||||||
|
if price == nil || *price <= 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return floatPtr(*price * float64(qty))
|
||||||
|
}
|
||||||
|
|
||||||
func totalForUnitPrice(unitPrice *float64, quantity int) *float64 {
|
func totalForUnitPrice(unitPrice *float64, quantity int) *float64 {
|
||||||
if unitPrice == nil || *unitPrice <= 0 {
|
if unitPrice == nil || *unitPrice <= 0 {
|
||||||
return nil
|
return nil
|
||||||
@@ -789,16 +817,6 @@ func pricingConfigSummaryRow(cfg ProjectPricingExportConfig, opts ProjectPricing
|
|||||||
return record
|
return record
|
||||||
}
|
}
|
||||||
|
|
||||||
func formatLotDisplay(mappings []localdb.VendorSpecLotMapping) string {
|
|
||||||
switch len(mappings) {
|
|
||||||
case 0:
|
|
||||||
return "н/д"
|
|
||||||
case 1:
|
|
||||||
return mappings[0].LotName
|
|
||||||
default:
|
|
||||||
return fmt.Sprintf("%s +%d", mappings[0].LotName, len(mappings)-1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func formatMoneyValue(value *float64) string {
|
func formatMoneyValue(value *float64) string {
|
||||||
if value == nil {
|
if value == nil {
|
||||||
|
|||||||
Reference in New Issue
Block a user