From 94c83c38257c37c45616aabebffc39127b0c2d06 Mon Sep 17 00:00:00 2001 From: M_Kececi Date: Fri, 3 Jul 2026 03:34:55 +0300 Subject: [PATCH] product performance grouped kpi improvements --- svc/queries/product_performance.go | 52 ++++++++++++++----- .../pages/ProductPerformanceProfitability.vue | 15 +++++- 2 files changed, 54 insertions(+), 13 deletions(-) diff --git a/svc/queries/product_performance.go b/svc/queries/product_performance.go index 4701d93..b27d9a8 100644 --- a/svc/queries/product_performance.go +++ b/svc/queries/product_performance.go @@ -1380,11 +1380,11 @@ WITH OpenOrderLines AS ( SELECT AttributeDescription FROM cdItemAttributeDesc WITH(NOLOCK) WHERE cdItemAttributeDesc.ItemTypeCode = l.ItemTypeCode - AND cdItemAttributeDesc.AttributeTypeCode = 42 + AND cdItemAttributeDesc.AttributeTypeCode = 44 AND cdItemAttributeDesc.AttributeCode = ( SELECT TOP 1 AttributeCode FROM prItemAttribute WITH(NOLOCK) - WHERE AttributeTypeCode = 42 + WHERE AttributeTypeCode = 44 AND prItemAttribute.ItemTypeCode = l.ItemTypeCode AND prItemAttribute.ItemCode = l.ItemCode ) @@ -1404,15 +1404,16 @@ WITH OpenOrderLines AS ( ) AND cdItemAttributeDesc.LangCode = 'TR' ), SPACE(0))), - YasGrubu = dbo.HG_Temizlik(ISNULL(( + YasGrubu = '', + UrunIlkGrubu = dbo.HG_Temizlik(ISNULL(( SELECT AttributeDescription FROM cdItemAttributeDesc WITH(NOLOCK) WHERE cdItemAttributeDesc.ItemTypeCode = l.ItemTypeCode - AND cdItemAttributeDesc.AttributeTypeCode = 44 + AND cdItemAttributeDesc.AttributeTypeCode = 42 AND cdItemAttributeDesc.AttributeCode = ( SELECT TOP 1 AttributeCode FROM prItemAttribute WITH(NOLOCK) - WHERE AttributeTypeCode = 44 + WHERE AttributeTypeCode = 42 AND prItemAttribute.ItemTypeCode = l.ItemTypeCode AND prItemAttribute.ItemCode = l.ItemCode ) @@ -1531,6 +1532,7 @@ SELECT TOP (@p1) Seri = MAX(o.Seri), YasGrubu = MAX(o.YasGrubu), AskiliYan = MAX(o.AskiliYan), + UrunIlkGrubu = MAX(o.UrunIlkGrubu), UrunAnaGrubu = MAX(o.UrunAnaGrubu), UrunAltGrubu = MAX(o.UrunAltGrubu), o.MarketKey, @@ -1567,12 +1569,11 @@ ORDER BY SUM(o.AmountUSD) DESC, SUM(o.Qty) DESC, o.ProductCode, o.ColorCode, o.Y var r models.ProductPerformanceOrderAnalysisRow if err := rows.Scan( &r.ProductCode, &r.ColorCode, &r.YakaKodu, &r.ItemDescription, &r.Kategori, &r.Seri, &r.YasGrubu, &r.AskiliYan, - &r.UrunAnaGrubu, &r.UrunAltGrubu, &r.MarketKey, &r.OrderQty, &r.OrderUSD, &r.AvgOrderPriceUSD, + &r.UrunIlkGrubu, &r.UrunAnaGrubu, &r.UrunAltGrubu, &r.MarketKey, &r.OrderQty, &r.OrderUSD, &r.AvgOrderPriceUSD, &r.MarketCount, &r.CustomerCount, &r.OrderCount, &r.LineCount, &r.FirstOrderDate, &r.LastOrderDate, &r.EarliestDueDate, &r.OverdueQty, ); err != nil { return nil, err } - r.UrunIlkGrubu = r.YasGrubu out = append(out, r) if !seenProducts[r.ProductCode] { seenProducts[r.ProductCode] = true @@ -1607,11 +1608,21 @@ ORDER BY SUM(o.AmountUSD) DESC, SUM(o.Qty) DESC, o.ProductCode, o.ColorCode, o.Y if strings.TrimSpace(row.ItemDescription) == "" { row.ItemDescription = attr.itemDescription } - row.Kategori = attr.kategori - row.AskiliYan = attr.askiliYan - row.UrunIlkGrubu = attr.urunIlkGrubu - row.UrunAnaGrubu = attr.urunAnaGrubu - row.UrunAltGrubu = attr.urunAltGrubu + if strings.TrimSpace(row.Kategori) == "" { + row.Kategori = attr.kategori + } + if strings.TrimSpace(row.AskiliYan) == "" { + row.AskiliYan = attr.askiliYan + } + if strings.TrimSpace(row.UrunIlkGrubu) == "" { + row.UrunIlkGrubu = attr.urunIlkGrubu + } + if strings.TrimSpace(row.UrunAnaGrubu) == "" { + row.UrunAnaGrubu = attr.urunAnaGrubu + } + if strings.TrimSpace(row.UrunAltGrubu) == "" { + row.UrunAltGrubu = attr.urunAltGrubu + } row.CostPriceUSD = price.cost row.BasePriceUSD = price.base row.StockQty = stockByKey[productPerformanceVariantKey(row.ProductCode, row.ColorCode, row.YakaKodu)] @@ -3499,6 +3510,8 @@ func defaultProductPerformanceGroupLevels(mode string) []string { func mapGroupValue(row map[string]any, field string) string { switch field { + case "urun_ilk_grubu": + return cleanProductPerformanceFirstGroup(stringFromMap(row, "urun_ilk_grubu")) case "market_key": return displayProductPerformanceMarketName(stringFromMap(row, "market_key")) default: @@ -3583,6 +3596,9 @@ func dominantProductPerformanceValue(rows []map[string]any, field string) string counts := map[string]int{} for _, row := range rows { value := stringFromMap(row, field) + if field == "urun_ilk_grubu" { + value = cleanProductPerformanceFirstGroup(value) + } if value != "" { counts[value]++ } @@ -3657,6 +3673,18 @@ func stringFromMap(row map[string]any, field string) string { return strings.TrimSpace(fmt.Sprint(value)) } +func cleanProductPerformanceFirstGroup(value string) string { + value = strings.TrimSpace(value) + normalized := strings.ToUpper(value) + normalized = strings.NewReplacer("İ", "I", "Ş", "S", "Ğ", "G", "Ü", "U", "Ö", "O", "Ç", "C").Replace(normalized) + switch normalized { + case "YETISKIN", "YETISKIN/GARSON", "GARSON": + return "" + default: + return value + } +} + func floatFromMap(row map[string]any, field string) float64 { return floatFromAny(row[field]) } diff --git a/ui/src/pages/ProductPerformanceProfitability.vue b/ui/src/pages/ProductPerformanceProfitability.vue index 602791a..e77213d 100644 --- a/ui/src/pages/ProductPerformanceProfitability.vue +++ b/ui/src/pages/ProductPerformanceProfitability.vue @@ -3225,13 +3225,26 @@ function productCategoryValue (row) { } function productFirstGroupValue (row) { - return row?.urun_ilk_grubu || '' + return cleanProductFirstGroupValue(row?.urun_ilk_grubu) } function productMainGroupValue (row) { return row?.urun_ana_grubu || '' } +function cleanProductFirstGroupValue (value) { + const text = String(value || '').trim() + const normalized = text + .toLocaleUpperCase('tr-TR') + .replaceAll('İ', 'I') + .replaceAll('Ş', 'S') + .replaceAll('Ğ', 'G') + .replaceAll('Ü', 'U') + .replaceAll('Ö', 'O') + .replaceAll('Ç', 'C') + return ['YETISKIN', 'YETISKIN/GARSON', 'GARSON'].includes(normalized) ? '' : text +} + function rawProductCellValue (row, name) { switch (name) { case 'kategori': return productCategoryValue(row)