Fix product performance grouped JSON build
This commit is contained in:
@@ -4592,10 +4592,10 @@ SELECT (
|
||||
'stock_days_180d', stock_days_180d,
|
||||
'stock_days_365d', stock_days_365d,
|
||||
'stock_days_total', stock_days_total,
|
||||
'stock_turnover_90d', CASE WHEN avg_stock_90d > 0 THEN sales_qty_90d / NULLIF(avg_stock_90d,0) * 4.0 ELSE 0 END,
|
||||
'stock_turnover_180d', CASE WHEN avg_stock_180d > 0 THEN sales_qty_180d / NULLIF(avg_stock_180d,0) * 2.0 ELSE 0 END,
|
||||
'stock_turnover_365d', CASE WHEN avg_stock_365d > 0 THEN sales_qty_365d / NULLIF(avg_stock_365d,0) ELSE 0 END,
|
||||
'stock_turnover_total', CASE WHEN avg_stock_total > 0 THEN sales_qty_total / NULLIF(avg_stock_total,0) * 360.0 / GREATEST(1, ((SELECT kpi_date FROM LatestKPIDate) - DATE '2022-01-01') + 1) ELSE 0 END
|
||||
'stock_turnover_90d', stock_turnover_90d,
|
||||
'stock_turnover_180d', stock_turnover_180d,
|
||||
'stock_turnover_365d', stock_turnover_365d,
|
||||
'stock_turnover_total', stock_turnover_total
|
||||
)
|
||||
) AS row_json
|
||||
FROM (
|
||||
@@ -4660,10 +4660,10 @@ FROM (
|
||||
CASE WHEN SUM(sales_qty_180d) > 0 THEN SUM(unit_profit_cost_180d * sales_qty_180d) / NULLIF(SUM(sales_qty_180d),0) ELSE 0 END AS unit_profit_cost_180d,
|
||||
CASE WHEN SUM(sales_qty_90d) > 0 THEN SUM(unit_profit_base_90d * sales_qty_90d) / NULLIF(SUM(sales_qty_90d),0) ELSE 0 END AS unit_profit_base_90d,
|
||||
CASE WHEN SUM(sales_qty_180d) > 0 THEN SUM(unit_profit_base_180d * sales_qty_180d) / NULLIF(SUM(sales_qty_180d),0) ELSE 0 END AS unit_profit_base_180d,
|
||||
COUNT(DISTINCT NULLIF(NULLIF(market_key,'STOK'),'')) FILTER (WHERE COALESCE(sales_usd_90d,0) > 0)::integer AS market_count_90d,
|
||||
COUNT(DISTINCT NULLIF(NULLIF(market_key,'STOK'),'')) FILTER (WHERE COALESCE(sales_usd_180d,0) > 0)::integer AS market_count_180d,
|
||||
COUNT(DISTINCT NULLIF(NULLIF(market_key,'STOK'),'')) FILTER (WHERE COALESCE(sales_usd_365d,0) > 0)::integer AS market_count_365d,
|
||||
COUNT(DISTINCT NULLIF(NULLIF(market_key,'STOK'),'')) FILTER (WHERE COALESCE(sales_usd_total,0) > 0)::integer AS market_count_total,
|
||||
COUNT(DISTINCT NULLIF(NULLIF(display_market_key,'STOK'),'')) FILTER (WHERE COALESCE(sales_usd_90d,0) > 0)::integer AS market_count_90d,
|
||||
COUNT(DISTINCT NULLIF(NULLIF(display_market_key,'STOK'),'')) FILTER (WHERE COALESCE(sales_usd_180d,0) > 0)::integer AS market_count_180d,
|
||||
COUNT(DISTINCT NULLIF(NULLIF(display_market_key,'STOK'),'')) FILTER (WHERE COALESCE(sales_usd_365d,0) > 0)::integer AS market_count_365d,
|
||||
COUNT(DISTINCT NULLIF(NULLIF(display_market_key,'STOK'),'')) FILTER (WHERE COALESCE(sales_usd_total,0) > 0)::integer AS market_count_total,
|
||||
COALESCE(SUM(CASE WHEN COALESCE(sales_usd_90d,0) > 0 THEN customer_count_90d ELSE 0 END),0)::integer AS customer_count_90d,
|
||||
COALESCE(SUM(CASE WHEN COALESCE(sales_usd_180d,0) > 0 THEN customer_count_180d ELSE 0 END),0)::integer AS customer_count_180d,
|
||||
COALESCE(SUM(CASE WHEN COALESCE(sales_usd_365d,0) > 0 THEN customer_count_365d ELSE 0 END),0)::integer AS customer_count_365d,
|
||||
@@ -4674,6 +4674,10 @@ FROM (
|
||||
CASE WHEN SUM(sales_qty_total) > 0 THEN SUM(sales_index_total * sales_qty_total) / NULLIF(SUM(sales_qty_total),0) ELSE 0 END AS sales_index_total,
|
||||
CASE WHEN SUM(sales_qty_90d) > 0 THEN SUM(price_index_90d * sales_qty_90d) / NULLIF(SUM(sales_qty_90d),0) ELSE 0 END AS price_index_90d,
|
||||
CASE WHEN SUM(sales_qty_90d) > 0 THEN SUM(margin_index_90d * sales_qty_90d) / NULLIF(SUM(sales_qty_90d),0) ELSE 0 END AS margin_index_90d,
|
||||
CASE WHEN SUM(sales_qty_90d) > 0 THEN SUM(stock_turnover_90d * sales_qty_90d) / NULLIF(SUM(sales_qty_90d),0) ELSE 0 END AS stock_turnover_90d,
|
||||
CASE WHEN SUM(sales_qty_180d) > 0 THEN SUM(stock_turnover_180d * sales_qty_180d) / NULLIF(SUM(sales_qty_180d),0) ELSE 0 END AS stock_turnover_180d,
|
||||
CASE WHEN SUM(sales_qty_365d) > 0 THEN SUM(stock_turnover_365d * sales_qty_365d) / NULLIF(SUM(sales_qty_365d),0) ELSE 0 END AS stock_turnover_365d,
|
||||
CASE WHEN SUM(sales_qty_total) > 0 THEN SUM(stock_turnover_total * sales_qty_total) / NULLIF(SUM(sales_qty_total),0) ELSE 0 END AS stock_turnover_total,
|
||||
CASE
|
||||
WHEN SUM(CASE
|
||||
WHEN COALESCE(sales_qty_90d,0) > 0 THEN sales_qty_90d
|
||||
@@ -4694,6 +4698,11 @@ FROM (
|
||||
FROM (
|
||||
SELECT
|
||||
Source.*,
|
||||
btrim(regexp_replace(COALESCE(Source.market_key,''), '^.*[|]', '')) AS display_market_key,
|
||||
CASE WHEN avg_stock_90d > 0 THEN sales_qty_90d / NULLIF(avg_stock_90d,0) * 4.0 ELSE 0 END AS stock_turnover_90d,
|
||||
CASE WHEN avg_stock_180d > 0 THEN sales_qty_180d / NULLIF(avg_stock_180d,0) * 2.0 ELSE 0 END AS stock_turnover_180d,
|
||||
CASE WHEN avg_stock_365d > 0 THEN sales_qty_365d / NULLIF(avg_stock_365d,0) ELSE 0 END AS stock_turnover_365d,
|
||||
CASE WHEN avg_stock_total > 0 THEN sales_qty_total / NULLIF(avg_stock_total,0) * 360.0 / GREATEST(1, ((SELECT kpi_date FROM LatestKPIDate) - DATE '2022-01-01') + 1) ELSE 0 END AS stock_turnover_total,
|
||||
ROW_NUMBER() OVER (
|
||||
PARTITION BY COALESCE(%s, ''), product_code, color_code, yaka_kodu
|
||||
ORDER BY performance_score DESC NULLS LAST
|
||||
@@ -4886,7 +4895,7 @@ func productPerformanceSQLGroupExpr(field string) (string, bool) {
|
||||
case "color_yaka":
|
||||
return "concat_ws('/', NULLIF(btrim(COALESCE(color_code,'')), ''), NULLIF(btrim(COALESCE(yaka_kodu,'')), ''))", true
|
||||
case "market_key":
|
||||
return "btrim(regexp_replace(COALESCE(market_key,''), '^.*\\|', ''))", true
|
||||
return "btrim(regexp_replace(COALESCE(market_key,''), '^.*[|]', ''))", true
|
||||
default:
|
||||
return "", false
|
||||
}
|
||||
@@ -5300,6 +5309,26 @@ Spread AS (
|
||||
s.color_code,
|
||||
s.yaka_kodu,
|
||||
s.market_key,
|
||||
COALESCE(jsonb_agg(DISTINCT display_market_key) FILTER (
|
||||
WHERE s.sales_date BETWEEN Latest.kpi_date - INTERVAL '89 days' AND Latest.kpi_date
|
||||
AND COALESCE(s.sales_usd,0) > 0
|
||||
AND display_market_key NOT IN ('', 'STOK', '-')
|
||||
), '[]'::jsonb) AS market_keys_90d,
|
||||
COALESCE(jsonb_agg(DISTINCT display_market_key) FILTER (
|
||||
WHERE s.sales_date BETWEEN Latest.kpi_date - INTERVAL '179 days' AND Latest.kpi_date
|
||||
AND COALESCE(s.sales_usd,0) > 0
|
||||
AND display_market_key NOT IN ('', 'STOK', '-')
|
||||
), '[]'::jsonb) AS market_keys_180d,
|
||||
COALESCE(jsonb_agg(DISTINCT display_market_key) FILTER (
|
||||
WHERE s.sales_date BETWEEN Latest.kpi_date - INTERVAL '359 days' AND Latest.kpi_date
|
||||
AND COALESCE(s.sales_usd,0) > 0
|
||||
AND display_market_key NOT IN ('', 'STOK', '-')
|
||||
), '[]'::jsonb) AS market_keys_365d,
|
||||
COALESCE(jsonb_agg(DISTINCT display_market_key) FILTER (
|
||||
WHERE s.sales_date BETWEEN DATE '2022-01-01' AND Latest.kpi_date
|
||||
AND COALESCE(s.sales_usd,0) > 0
|
||||
AND display_market_key NOT IN ('', 'STOK', '-')
|
||||
), '[]'::jsonb) AS market_keys_total,
|
||||
COALESCE(jsonb_agg(DISTINCT btrim(s.customer_code)) FILTER (
|
||||
WHERE s.sales_date BETWEEN Latest.kpi_date - INTERVAL '89 days' AND Latest.kpi_date
|
||||
AND COALESCE(s.sales_usd,0) > 0
|
||||
@@ -5320,7 +5349,12 @@ Spread AS (
|
||||
AND COALESCE(s.sales_usd,0) > 0
|
||||
AND btrim(COALESCE(s.customer_code,'')) NOT IN ('', '-')
|
||||
), '[]'::jsonb) AS customer_keys_total
|
||||
FROM mk_product_performance_sales_daily s
|
||||
FROM (
|
||||
SELECT
|
||||
s.*,
|
||||
btrim(regexp_replace(COALESCE(s.market_key,''), '^.*[|]', '')) AS display_market_key
|
||||
FROM mk_product_performance_sales_daily s
|
||||
) s
|
||||
CROSS JOIN Latest
|
||||
WHERE s.sales_date BETWEEN DATE '2022-01-01' AND Latest.kpi_date
|
||||
AND upper(translate(btrim(COALESCE(s.urun_ilk_grubu,'')), U&'\0130\015E\011E\00DC\00D6\00C7\0131\015F\011F\00FC\00F6\00E7', 'ISGUOCisguoc')) NOT IN ('MALZEMELI FASON', 'MALZEMESIZ FASON', 'MAZLEMELI FASON', 'MAZEMESIZ FASON', 'DIGER')
|
||||
@@ -5331,6 +5365,10 @@ SELECT jsonb_build_object(
|
||||
'color_code', color_code,
|
||||
'yaka_kodu', yaka_kodu,
|
||||
'market_key', market_key,
|
||||
'__market_keys_90d', market_keys_90d,
|
||||
'__market_keys_180d', market_keys_180d,
|
||||
'__market_keys_365d', market_keys_365d,
|
||||
'__market_keys_total', market_keys_total,
|
||||
'__customer_keys_90d', customer_keys_90d,
|
||||
'__customer_keys_180d', customer_keys_180d,
|
||||
'__customer_keys_365d', customer_keys_365d,
|
||||
@@ -5355,9 +5393,11 @@ FROM Spread`
|
||||
continue
|
||||
}
|
||||
for _, suffix := range productPerformancePeriodSuffixes() {
|
||||
field := "__customer_keys_" + suffix
|
||||
if value, ok := spread[field]; ok {
|
||||
row[field] = value
|
||||
for _, prefix := range []string{"__market_keys_", "__customer_keys_"} {
|
||||
field := prefix + suffix
|
||||
if value, ok := spread[field]; ok {
|
||||
row[field] = value
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5569,6 +5609,13 @@ func applyProductPerformanceGroupedChildScoreAverages(rows []map[string]any, mod
|
||||
}
|
||||
row[field] = weightedAverageProductPerformanceScoreRows(childRows, field, suffix)
|
||||
}
|
||||
for _, suffix := range productPerformancePeriodSuffixes() {
|
||||
field := "stock_turnover_" + suffix
|
||||
if !productPerformanceRowsHaveField(childRows, field) {
|
||||
continue
|
||||
}
|
||||
row[field] = weightedAverageProductPerformanceRows(childRows, field, "sales_qty_"+suffix)
|
||||
}
|
||||
if score, ok := productPerformanceOptionalFloat(row, "performance_score_90d"); ok {
|
||||
row["performance_score"] = score
|
||||
}
|
||||
@@ -5710,6 +5757,7 @@ func (n *productPerformanceGroupedSnapshotNode) addDistinctSpread(row map[string
|
||||
}
|
||||
}
|
||||
for _, suffix := range productPerformancePeriodSuffixes() {
|
||||
n.MarketSeen = productPerformanceAddSeenStrings(n.MarketSeen, suffix, productPerformanceStringSliceFromMap(row, "__market_keys_"+suffix))
|
||||
n.CustomerSeen = productPerformanceAddSeenStrings(n.CustomerSeen, suffix, productPerformanceStringSliceFromMap(row, "__customer_keys_"+suffix))
|
||||
}
|
||||
}
|
||||
@@ -5940,6 +5988,7 @@ func addProductPerformanceDistinctSpread(row map[string]any, marketSeen, custome
|
||||
}
|
||||
}
|
||||
for _, suffix := range productPerformancePeriodSuffixes() {
|
||||
marketSeen = productPerformanceAddSeenStrings(marketSeen, suffix, productPerformanceStringSliceFromMap(row, "__market_keys_"+suffix))
|
||||
customerSeen = productPerformanceAddSeenStrings(customerSeen, suffix, productPerformanceStringSliceFromMap(row, "__customer_keys_"+suffix))
|
||||
}
|
||||
}
|
||||
@@ -6135,6 +6184,7 @@ func deriveProductPerformanceGroupMetrics(out map[string]any, groupField string)
|
||||
}
|
||||
preservedCustomerScores := map[string]float64{}
|
||||
preservedProductScores := map[string]float64{}
|
||||
preservedStockTurnovers := map[string]float64{}
|
||||
for _, suffix := range productPerformancePeriodSuffixes() {
|
||||
if score, ok := productPerformanceOptionalFloat(out, "customer_score_"+suffix); ok {
|
||||
preservedCustomerScores[suffix] = score
|
||||
@@ -6142,6 +6192,11 @@ func deriveProductPerformanceGroupMetrics(out map[string]any, groupField string)
|
||||
if score, ok := productPerformanceOptionalFloat(out, "performance_score_"+suffix); ok {
|
||||
preservedProductScores[suffix] = score
|
||||
}
|
||||
if isGroup {
|
||||
if turnover, ok := productPerformanceOptionalFloat(out, "stock_turnover_"+suffix); ok {
|
||||
preservedStockTurnovers[suffix] = turnover
|
||||
}
|
||||
}
|
||||
}
|
||||
if score, ok := productPerformanceOptionalFloat(out, "performance_score"); ok {
|
||||
if _, exists := preservedProductScores["90d"]; !exists {
|
||||
@@ -6170,6 +6225,9 @@ func deriveProductPerformanceGroupMetrics(out map[string]any, groupField string)
|
||||
out["stock_days_"+suffix] = 0
|
||||
}
|
||||
out["stock_turnover_"+suffix] = productPerformanceAnnualizedStockTurnover(qty, turnoverBase, days)
|
||||
if turnover, ok := preservedStockTurnovers[suffix]; ok {
|
||||
out["stock_turnover_"+suffix] = turnover
|
||||
}
|
||||
if qty > 0 {
|
||||
out["avg_price_usd_"+suffix] = sales / qty
|
||||
}
|
||||
@@ -6775,6 +6833,9 @@ func productPerformanceMetricWeightField(field string) string {
|
||||
if productPerformanceUsesCostWeight(field) {
|
||||
return "__product_cost_weight"
|
||||
}
|
||||
if strings.HasPrefix(field, "stock_turnover") {
|
||||
return "sales_qty_" + productPerformanceScoreSuffix(field)
|
||||
}
|
||||
if strings.Contains(field, "_180d") {
|
||||
return "sales_qty_180d"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user