Fix product performance grouped JSON build
This commit is contained in:
@@ -5229,15 +5229,30 @@ func productPerformanceGroupedRawSnapshotSourceRows(ctx context.Context, pg *sql
|
|||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
if strings.TrimSpace(mode) == "idle" {
|
if strings.TrimSpace(mode) == "idle" {
|
||||||
|
normalizeProductPerformanceGroupedSourceScores(rows, mode)
|
||||||
return productPerformanceIdleSourceRows(rows), nil
|
return productPerformanceIdleSourceRows(rows), nil
|
||||||
}
|
}
|
||||||
if mode == "products" || mode == "product_detail" {
|
if mode == "products" || mode == "product_detail" {
|
||||||
rows = mergeProductPerformanceGeneralSnapshotMetrics(ctx, pg, rows)
|
rows = mergeProductPerformanceGeneralSnapshotMetrics(ctx, pg, rows)
|
||||||
rows = mergeProductPerformanceSalesSpreadKeys(ctx, pg, rows)
|
rows = mergeProductPerformanceSalesSpreadKeys(ctx, pg, rows)
|
||||||
}
|
}
|
||||||
|
normalizeProductPerformanceGroupedSourceScores(rows, mode)
|
||||||
return rows, nil
|
return rows, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func normalizeProductPerformanceGroupedSourceScores(rows []map[string]any, mode string) {
|
||||||
|
if !shouldCascadeProductPerformanceGroupedScores(mode) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for _, row := range rows {
|
||||||
|
deriveProductPerformanceGroupMetrics(row, "")
|
||||||
|
for _, suffix := range productPerformancePeriodSuffixes() {
|
||||||
|
row["performance_score_"+suffix] = productPerformanceSalesPeriodScore(row, suffix)
|
||||||
|
}
|
||||||
|
row["performance_score"] = row["performance_score_90d"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func mergeProductPerformanceGeneralSnapshotMetrics(ctx context.Context, pg *sql.DB, rows []map[string]any) []map[string]any {
|
func mergeProductPerformanceGeneralSnapshotMetrics(ctx context.Context, pg *sql.DB, rows []map[string]any) []map[string]any {
|
||||||
if len(rows) == 0 {
|
if len(rows) == 0 {
|
||||||
return rows
|
return rows
|
||||||
@@ -5518,9 +5533,82 @@ func buildProductPerformanceGroupedSnapshotRows(sourceRows []map[string]any, lev
|
|||||||
|
|
||||||
out := make([]map[string]any, 0, len(sourceRows))
|
out := make([]map[string]any, 0, len(sourceRows))
|
||||||
appendProductPerformanceGroupedSnapshotNodes(&out, roots, rootOrder)
|
appendProductPerformanceGroupedSnapshotNodes(&out, roots, rootOrder)
|
||||||
|
applyProductPerformanceGroupedChildScoreAverages(out, mode)
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func applyProductPerformanceGroupedChildScoreAverages(rows []map[string]any, mode string) {
|
||||||
|
if !shouldCascadeProductPerformanceGroupedScores(mode) || len(rows) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
byKey := make(map[string]map[string]any, len(rows))
|
||||||
|
children := map[string][]map[string]any{}
|
||||||
|
maxLevel := -1
|
||||||
|
for _, row := range rows {
|
||||||
|
key := stringFromMap(row, "key")
|
||||||
|
if key == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
byKey[key] = row
|
||||||
|
if level := intFromMap(row, "level"); level > maxLevel {
|
||||||
|
maxLevel = level
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, row := range rows {
|
||||||
|
key := stringFromMap(row, "key")
|
||||||
|
parentKey := productPerformanceParentGroupKey(key)
|
||||||
|
if parentKey == "" || byKey[parentKey] == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
children[parentKey] = append(children[parentKey], row)
|
||||||
|
}
|
||||||
|
for level := maxLevel - 1; level >= 0; level-- {
|
||||||
|
for _, row := range rows {
|
||||||
|
if intFromMap(row, "level") != level {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
childRows := children[stringFromMap(row, "key")]
|
||||||
|
if len(childRows) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
for _, suffix := range productPerformancePeriodSuffixes() {
|
||||||
|
field := "performance_score_" + suffix
|
||||||
|
if !productPerformanceRowsHaveField(childRows, field) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
row[field] = weightedAverageProductPerformanceScoreRows(childRows, field, suffix)
|
||||||
|
}
|
||||||
|
if score, ok := productPerformanceOptionalFloat(row, "performance_score_90d"); ok {
|
||||||
|
row["performance_score"] = score
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func shouldCascadeProductPerformanceGroupedScores(mode string) bool {
|
||||||
|
switch strings.TrimSpace(mode) {
|
||||||
|
case "products",
|
||||||
|
"product_detail",
|
||||||
|
"idle",
|
||||||
|
"sales_color_yaka_market_customer",
|
||||||
|
"sales_product_country_segment_market_customer",
|
||||||
|
"sales_market_customer_product",
|
||||||
|
"sales_country_segment_market_customer_product":
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func productPerformanceRowsHaveField(rows []map[string]any, field string) bool {
|
||||||
|
for _, row := range rows {
|
||||||
|
if _, ok := productPerformanceOptionalFloat(row, field); ok {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
func (n *productPerformanceGroupedSnapshotNode) add(row map[string]any) {
|
func (n *productPerformanceGroupedSnapshotNode) add(row map[string]any) {
|
||||||
n.Count++
|
n.Count++
|
||||||
if n.Image == nil && stringFromMap(row, "product_code") != "" {
|
if n.Image == nil && stringFromMap(row, "product_code") != "" {
|
||||||
|
|||||||
Reference in New Issue
Block a user