product performance grouped kpi improvements
This commit is contained in:
@@ -2910,7 +2910,7 @@ FROM (
|
||||
COALESCE((ARRAY_AGG(NULLIF(urun_ana_grubu,'') ORDER BY performance_score DESC NULLS LAST))[1], '') AS urun_ana_grubu,
|
||||
COALESCE((ARRAY_AGG(NULLIF(urun_alt_grubu,'') ORDER BY performance_score DESC NULLS LAST))[1], '') AS urun_alt_grubu,
|
||||
COALESCE((ARRAY_AGG(NULLIF(market_key,'') ORDER BY performance_score DESC NULLS LAST))[1], '') AS market_key,
|
||||
COALESCE(SUM(stock_qty),0) AS stock_qty,
|
||||
COALESCE(SUM(CASE WHEN stock_variant_rank = 1 THEN stock_qty ELSE 0 END),0) AS stock_qty,
|
||||
COALESCE(SUM(sales_qty_90d),0) AS sales_qty_90d,
|
||||
COALESCE(SUM(sales_qty_180d),0) AS sales_qty_180d,
|
||||
COALESCE(SUM(sales_qty_365d),0) AS sales_qty_365d,
|
||||
@@ -2919,9 +2919,9 @@ FROM (
|
||||
COALESCE(SUM(sales_usd_365d),0) AS sales_usd_365d,
|
||||
CASE WHEN SUM(sales_qty_90d) > 0 THEN SUM(sales_usd_90d) / NULLIF(SUM(sales_qty_90d),0) ELSE 0 END AS avg_price_usd_90d,
|
||||
CASE WHEN SUM(sales_qty_180d) > 0 THEN SUM(sales_usd_180d) / NULLIF(SUM(sales_qty_180d),0) ELSE 0 END AS avg_price_usd_180d,
|
||||
CASE WHEN SUM(stock_qty) > 0 THEN SUM(cost_price_usd * stock_qty) / NULLIF(SUM(stock_qty),0) ELSE AVG(cost_price_usd) END AS cost_price_usd,
|
||||
CASE WHEN SUM(stock_qty) > 0 THEN SUM(base_price_usd * stock_qty) / NULLIF(SUM(stock_qty),0) ELSE AVG(base_price_usd) END AS base_price_usd,
|
||||
CASE WHEN SUM(stock_qty) > 0 THEN SUM(base_price_try * stock_qty) / NULLIF(SUM(stock_qty),0) ELSE AVG(base_price_try) END AS base_price_try,
|
||||
CASE WHEN SUM(CASE WHEN stock_variant_rank = 1 THEN stock_qty ELSE 0 END) > 0 THEN SUM(CASE WHEN stock_variant_rank = 1 THEN cost_price_usd * stock_qty ELSE 0 END) / NULLIF(SUM(CASE WHEN stock_variant_rank = 1 THEN stock_qty ELSE 0 END),0) ELSE AVG(cost_price_usd) END AS cost_price_usd,
|
||||
CASE WHEN SUM(CASE WHEN stock_variant_rank = 1 THEN stock_qty ELSE 0 END) > 0 THEN SUM(CASE WHEN stock_variant_rank = 1 THEN base_price_usd * stock_qty ELSE 0 END) / NULLIF(SUM(CASE WHEN stock_variant_rank = 1 THEN stock_qty ELSE 0 END),0) ELSE AVG(base_price_usd) END AS base_price_usd,
|
||||
CASE WHEN SUM(CASE WHEN stock_variant_rank = 1 THEN stock_qty ELSE 0 END) > 0 THEN SUM(CASE WHEN stock_variant_rank = 1 THEN base_price_try * stock_qty ELSE 0 END) / NULLIF(SUM(CASE WHEN stock_variant_rank = 1 THEN stock_qty ELSE 0 END),0) ELSE AVG(base_price_try) END AS base_price_try,
|
||||
COALESCE(SUM(gross_profit_usd_90d),0) AS gross_profit_usd_90d,
|
||||
COALESCE(SUM(gross_profit_usd_180d),0) AS gross_profit_usd_180d,
|
||||
CASE WHEN SUM(sales_usd_90d) > 0 THEN SUM(gross_profit_usd_90d) / NULLIF(SUM(sales_usd_90d),0) ELSE 0 END AS gross_margin_90d,
|
||||
@@ -2937,13 +2937,21 @@ FROM (
|
||||
CASE WHEN SUM(sales_qty_90d) > 0 THEN SUM(margin_index_90d * sales_qty_90d) / NULLIF(SUM(sales_qty_90d),0) ELSE AVG(margin_index_90d) END AS margin_index_90d,
|
||||
CASE WHEN SUM(sales_qty_90d) > 0 THEN SUM(performance_score * sales_qty_90d) / NULLIF(SUM(sales_qty_90d),0) ELSE AVG(performance_score) END AS performance_score,
|
||||
MODE() WITHIN GROUP (ORDER BY performance_bucket) AS performance_bucket,
|
||||
COALESCE(SUM(idle_cost_usd),0) AS idle_cost_usd
|
||||
FROM Source
|
||||
COALESCE(SUM(CASE WHEN stock_variant_rank = 1 THEN idle_cost_usd ELSE 0 END),0) AS idle_cost_usd
|
||||
FROM (
|
||||
SELECT
|
||||
Source.*,
|
||||
ROW_NUMBER() OVER (
|
||||
PARTITION BY COALESCE(NULLIF(%s,''), '-'), product_code, color_code, yaka_kodu
|
||||
ORDER BY performance_score DESC NULLS LAST
|
||||
) AS stock_variant_rank
|
||||
FROM Source
|
||||
%s
|
||||
) s
|
||||
GROUP BY COALESCE(NULLIF(%s,''), '-')
|
||||
) g
|
||||
ORDER BY group_value
|
||||
`, len(args)+1, len(args)+1, len(args)+1, len(args)+1, len(args)+1, len(args)+1, len(args)+1, len(args)+1, len(args)+1, groupExpr, whereSQL, groupExpr)
|
||||
`, len(args)+1, len(args)+1, len(args)+1, len(args)+1, len(args)+1, len(args)+1, len(args)+1, len(args)+1, len(args)+1, groupExpr, groupExpr, whereSQL, groupExpr)
|
||||
args = append(args, field)
|
||||
return queryProductPerformanceJSONRows(ctx, pg, query, args...)
|
||||
}
|
||||
@@ -3192,6 +3200,14 @@ func aggregateProductPerformanceRows(rows []map[string]any, groupField string) m
|
||||
if key == "row_key" || key == "key" {
|
||||
continue
|
||||
}
|
||||
if key == "stock_qty" {
|
||||
out[key] = distinctProductPerformanceVariantStockQty(rows)
|
||||
continue
|
||||
}
|
||||
if key == "idle_cost_usd" {
|
||||
out[key] = distinctProductPerformanceVariantStockCost(rows)
|
||||
continue
|
||||
}
|
||||
if shouldSumProductPerformanceField(key) {
|
||||
out[key] = floatFromAny(out[key]) + floatFromAny(value)
|
||||
} else if _, ok := out[key]; !ok && !shouldAverageProductPerformanceField(key) {
|
||||
@@ -3211,6 +3227,75 @@ func aggregateProductPerformanceRows(rows []map[string]any, groupField string) m
|
||||
return out
|
||||
}
|
||||
|
||||
func distinctProductPerformanceVariantStockQty(rows []map[string]any) float64 {
|
||||
seen := map[string]bool{}
|
||||
total := 0.0
|
||||
hasKey := false
|
||||
for _, row := range rows {
|
||||
key := productPerformanceMapVariantKey(row)
|
||||
if key == "" {
|
||||
continue
|
||||
}
|
||||
hasKey = true
|
||||
if seen[key] {
|
||||
continue
|
||||
}
|
||||
seen[key] = true
|
||||
total += floatFromMap(row, "stock_qty")
|
||||
}
|
||||
if hasKey {
|
||||
return total
|
||||
}
|
||||
for _, row := range rows {
|
||||
total += floatFromMap(row, "stock_qty")
|
||||
}
|
||||
return total
|
||||
}
|
||||
|
||||
func distinctProductPerformanceVariantStockCost(rows []map[string]any) float64 {
|
||||
seen := map[string]bool{}
|
||||
total := 0.0
|
||||
hasKey := false
|
||||
for _, row := range rows {
|
||||
key := productPerformanceMapVariantKey(row)
|
||||
if key == "" {
|
||||
continue
|
||||
}
|
||||
hasKey = true
|
||||
if seen[key] {
|
||||
continue
|
||||
}
|
||||
seen[key] = true
|
||||
total += floatFromMap(row, "stock_qty") * floatFromMap(row, "cost_price_usd")
|
||||
}
|
||||
if hasKey {
|
||||
return total
|
||||
}
|
||||
for _, row := range rows {
|
||||
total += floatFromMap(row, "idle_cost_usd")
|
||||
}
|
||||
return total
|
||||
}
|
||||
|
||||
func productPerformanceMapVariantKey(row map[string]any) string {
|
||||
productCode := stringFromMap(row, "product_code")
|
||||
if productCode == "" {
|
||||
productCode = stringFromMap(row, "image_product_code")
|
||||
}
|
||||
colorCode := stringFromMap(row, "color_code")
|
||||
if colorCode == "" {
|
||||
colorCode = stringFromMap(row, "image_color_code")
|
||||
}
|
||||
yakaKodu := stringFromMap(row, "yaka_kodu")
|
||||
if yakaKodu == "" {
|
||||
yakaKodu = stringFromMap(row, "image_yaka_kodu")
|
||||
}
|
||||
if productCode == "" && colorCode == "" && yakaKodu == "" {
|
||||
return ""
|
||||
}
|
||||
return productPerformanceVariantKey(productCode, colorCode, yakaKodu)
|
||||
}
|
||||
|
||||
func deriveProductPerformanceGroupMetrics(out map[string]any, groupField string) {
|
||||
for _, suffix := range []string{"90d", "180d", "365d", "total"} {
|
||||
sales := floatFromMap(out, "sales_usd_"+suffix)
|
||||
@@ -3243,6 +3328,9 @@ func deriveProductPerformanceGroupMetrics(out map[string]any, groupField string)
|
||||
if orderQty > 0 {
|
||||
out["avg_order_price_usd"] = orderUSD / orderQty
|
||||
}
|
||||
if _, ok := out["net_stock_after_order"]; ok || orderQty > 0 {
|
||||
out["net_stock_after_order"] = floatFromMap(out, "stock_qty") - orderQty
|
||||
}
|
||||
out["customer_score_90d"] = productPerformanceCustomerSalesPeriodScore(rowPeriodMetricMap(out, "90d"))
|
||||
out["customer_score_180d"] = productPerformanceCustomerSalesPeriodScore(rowPeriodMetricMap(out, "180d"))
|
||||
out["customer_score_365d"] = productPerformanceCustomerSalesPeriodScore(rowPeriodMetricMap(out, "365d"))
|
||||
|
||||
Reference in New Issue
Block a user