From b94dd3d0155962e80c0e99e2190338c2a94ef3c2 Mon Sep 17 00:00:00 2001 From: Mikhail Chusavitin Date: Wed, 18 Feb 2026 19:45:32 +0300 Subject: [PATCH] warehouse: switch stock pricing to weighted_avg --- .../pricelist/service_warehouse_test.go | 4 +-- internal/warehouse/snapshot.go | 27 +++++++++++++++++-- internal/warehouse/snapshot_test.go | 4 +-- 3 files changed, 29 insertions(+), 6 deletions(-) diff --git a/internal/services/pricelist/service_warehouse_test.go b/internal/services/pricelist/service_warehouse_test.go index 3a14fb1..98046a7 100644 --- a/internal/services/pricelist/service_warehouse_test.go +++ b/internal/services/pricelist/service_warehouse_test.go @@ -66,7 +66,7 @@ func TestCreateWarehousePricelistFromStockLog(t *testing.T) { if items[0].LotName != "CPU_X" { t.Fatalf("unexpected lot name: %s", items[0].LotName) } - if math.Abs(items[0].Price-200) > 0.001 { - t.Fatalf("expected weighted median price 200, got %f", items[0].Price) + if math.Abs(items[0].Price-180) > 0.001 { + t.Fatalf("expected weighted average price 180, got %f", items[0].Price) } } diff --git a/internal/warehouse/snapshot.go b/internal/warehouse/snapshot.go index 56a51c2..f6172ad 100644 --- a/internal/warehouse/snapshot.go +++ b/internal/warehouse/snapshot.go @@ -58,11 +58,11 @@ func ComputePricelistItemsFromStockLog(db *gorm.DB) ([]SnapshotItem, error) { items := make([]SnapshotItem, 0, len(grouped)) for lot, values := range grouped { - price := weightedMedian(values) + price := weightedAverage(values) if price <= 0 { continue } - items = append(items, SnapshotItem{LotName: lot, Price: price, PriceMethod: "weighted_median", Category: ""}) + items = append(items, SnapshotItem{LotName: lot, Price: price, PriceMethod: "weighted_avg", Category: ""}) } // Load categories for all lots in a single query @@ -272,3 +272,26 @@ func median(values []float64) float64 { } return cp[n/2] } +func weightedAverage(values []weightedPricePoint) float64 { + if len(values) == 0 { + return 0 + } + sumWeighted := 0.0 + sumWeight := 0.0 + prices := make([]float64, 0, len(values)) + for _, v := range values { + if v.price <= 0 { + continue + } + prices = append(prices, v.price) + if v.weight > 0 { + sumWeighted += v.price * v.weight + sumWeight += v.weight + } + } + if sumWeight > 0 { + return sumWeighted / sumWeight + } + return median(prices) +} + diff --git a/internal/warehouse/snapshot_test.go b/internal/warehouse/snapshot_test.go index abc8688..6714127 100644 --- a/internal/warehouse/snapshot_test.go +++ b/internal/warehouse/snapshot_test.go @@ -45,8 +45,8 @@ func TestComputePricelistItemsFromStockLog(t *testing.T) { if items[0].LotName != "CPU_X" { t.Fatalf("expected lot CPU_X, got %s", items[0].LotName) } - if math.Abs(items[0].Price-200) > 0.001 { - t.Fatalf("expected weighted median 200, got %f", items[0].Price) + if math.Abs(items[0].Price-190) > 0.001 { + t.Fatalf("expected weighted average 190, got %f", items[0].Price) } }