Fix product performance grouped JSON build

This commit is contained in:
M_Kececi
2026-08-28 20:45:11 +03:00
parent 945868d83d
commit b7131ac6ce
3 changed files with 102 additions and 31 deletions
+56 -23
View File
@@ -799,42 +799,68 @@ type ArgeBaggiDepotEntryTotals struct {
Yelek float64 Yelek float64
} }
type ArgeBaggiDepotEntryLookup struct {
WorkOrder string
ModelCode string
}
func ArgeBaggiDepotEntryKey(workOrder string, modelCode string) string {
return strings.TrimSpace(workOrder) + "\x1f" + normalizeArgeBaggiModelCode(modelCode)
}
func normalizeArgeBaggiModelCode(modelCode string) string {
normalizedModelCode := strings.ToUpper(strings.TrimSpace(modelCode))
if separatorIndex := strings.LastIndex(normalizedModelCode, "-"); separatorIndex >= 0 && separatorIndex+1 < len(normalizedModelCode) {
return strings.TrimSpace(normalizedModelCode[separatorIndex+1:])
}
return normalizedModelCode
}
// GetArgeBaggiDepotEntryTotals returns operation 985/986/987 quantities keyed // GetArgeBaggiDepotEntryTotals returns operation 985/986/987 quantities keyed
// by production work order. The requested work orders are queried in one batch // by production work order AND product model. A row contributes only when both
// to avoid an ArgeBAGGI round trip for every list row. // MN.model_adi (work order) and MD.model_code (model) match the requested pair.
func GetArgeBaggiDepotEntryTotals(ctx context.Context, argeDB *sql.DB, workOrders []string) (map[string]ArgeBaggiDepotEntryTotals, error) { func GetArgeBaggiDepotEntryTotals(ctx context.Context, argeDB *sql.DB, lookups []ArgeBaggiDepotEntryLookup) (map[string]ArgeBaggiDepotEntryTotals, error) {
out := make(map[string]ArgeBaggiDepotEntryTotals) out := make(map[string]ArgeBaggiDepotEntryTotals)
if argeDB == nil || len(workOrders) == 0 { if argeDB == nil || len(lookups) == 0 {
return out, nil return out, nil
} }
seen := make(map[string]struct{}, len(workOrders)) seen := make(map[string]struct{}, len(lookups))
values := make([]string, 0, len(workOrders)) values := make([]ArgeBaggiDepotEntryLookup, 0, len(lookups))
for _, raw := range workOrders { for _, lookup := range lookups {
value := strings.TrimSpace(raw) workOrder := strings.TrimSpace(lookup.WorkOrder)
if value == "" || value == "0" { modelCode := normalizeArgeBaggiModelCode(lookup.ModelCode)
if workOrder == "" || workOrder == "0" || modelCode == "" {
continue continue
} }
if _, exists := seen[value]; exists { key := ArgeBaggiDepotEntryKey(workOrder, modelCode)
if _, exists := seen[key]; exists {
continue continue
} }
seen[value] = struct{}{} seen[key] = struct{}{}
values = append(values, value) values = append(values, ArgeBaggiDepotEntryLookup{WorkOrder: workOrder, ModelCode: modelCode})
} }
if len(values) == 0 { if len(values) == 0 {
return out, nil return out, nil
} }
placeholders := make([]string, 0, len(values)) valueRows := make([]string, 0, len(values))
args := make([]any, 0, len(values)) args := make([]any, 0, len(values)*2)
for i, value := range values { for i, value := range values {
placeholders = append(placeholders, fmt.Sprintf("@p%d", i+1)) workOrderParam := i*2 + 1
args = append(args, value) modelCodeParam := workOrderParam + 1
valueRows = append(valueRows, fmt.Sprintf("(@p%d, @p%d)", workOrderParam, modelCodeParam))
args = append(args, value.WorkOrder, value.ModelCode)
} }
sqlText := fmt.Sprintf(` sqlText := fmt.Sprintf(`
WITH RequestedPairs (IsEmriNo, ModelKodu) AS (
SELECT V.IsEmriNo, V.ModelKodu
FROM (VALUES %s) V (IsEmriNo, ModelKodu)
)
SELECT SELECT
LTRIM(RTRIM(CONVERT(VARCHAR(64), MN.model_adi))) AS IsEmriNo, RP.IsEmriNo,
RP.ModelKodu,
SUM(CASE WHEN O.oper_num = 985 THEN CONVERT(float, B.adet) ELSE 0 END) AS CeketDepoGiris, SUM(CASE WHEN O.oper_num = 985 THEN CONVERT(float, B.adet) ELSE 0 END) AS CeketDepoGiris,
SUM(CASE WHEN O.oper_num = 986 THEN CONVERT(float, B.adet) ELSE 0 END) AS PantolonDepoGiris, SUM(CASE WHEN O.oper_num = 986 THEN CONVERT(float, B.adet) ELSE 0 END) AS PantolonDepoGiris,
SUM(CASE WHEN O.oper_num = 987 THEN CONVERT(float, B.adet) ELSE 0 END) AS YelekDepoGiris SUM(CASE WHEN O.oper_num = 987 THEN CONVERT(float, B.adet) ELSE 0 END) AS YelekDepoGiris
@@ -846,12 +872,14 @@ INNER JOIN dbo.model_num MN ON I.model_num = MN.model_num
INNER JOIN dbo.bant_no BN ON I.bant_num = BN.bant_no INNER JOIN dbo.bant_no BN ON I.bant_num = BN.bant_no
INNER JOIN dbo.model_oper MO ON O.oper_num = MO.oper_num AND MD.mdef_num = MO.model_num INNER JOIN dbo.model_oper MO ON O.oper_num = MO.oper_num AND MD.mdef_num = MO.model_num
INNER JOIN dbo.model_oper_tkp_def TD ON MO.tkp_cik = TD.tkp_cik INNER JOIN dbo.model_oper_tkp_def TD ON MO.tkp_cik = TD.tkp_cik
INNER JOIN RequestedPairs RP
ON RP.IsEmriNo = LTRIM(RTRIM(CONVERT(VARCHAR(64), MN.model_adi)))
AND RP.ModelKodu = UPPER(LTRIM(RTRIM(CONVERT(VARCHAR(64), MD.model_code))))
WHERE B.tarih >= '2025-01-01' WHERE B.tarih >= '2025-01-01'
AND TD.tkp_cik IN (1,2,3,4,5) AND TD.tkp_cik IN (1,2,3,4,5)
AND O.oper_num IN (985,986,987) AND O.oper_num IN (985,986,987)
AND LTRIM(RTRIM(CONVERT(VARCHAR(64), MN.model_adi))) IN (%s) GROUP BY RP.IsEmriNo, RP.ModelKodu
GROUP BY LTRIM(RTRIM(CONVERT(VARCHAR(64), MN.model_adi))) `, strings.Join(valueRows, ","))
`, strings.Join(placeholders, ","))
rows, err := argeDB.QueryContext(ctx, sqlText, args...) rows, err := argeDB.QueryContext(ctx, sqlText, args...)
if err != nil { if err != nil {
@@ -860,13 +888,18 @@ GROUP BY LTRIM(RTRIM(CONVERT(VARCHAR(64), MN.model_adi)))
defer rows.Close() defer rows.Close()
for rows.Next() { for rows.Next() {
var workOrder string var workOrder string
var modelCode string
var totals ArgeBaggiDepotEntryTotals var totals ArgeBaggiDepotEntryTotals
if err := rows.Scan(&workOrder, &totals.Ceket, &totals.Pantolon, &totals.Yelek); err != nil { if err := rows.Scan(&workOrder, &modelCode, &totals.Ceket, &totals.Pantolon, &totals.Yelek); err != nil {
return nil, err return nil, err
} }
out[strings.TrimSpace(workOrder)] = totals out[ArgeBaggiDepotEntryKey(workOrder, modelCode)] = totals
} }
return out, rows.Err() if err := rows.Err(); err != nil {
return nil, err
}
return out, nil
} }
func GetProductionHasCostProducts( func GetProductionHasCostProducts(
@@ -0,0 +1,32 @@
package queries
import "testing"
func TestNormalizeArgeBaggiModelCode(t *testing.T) {
tests := []struct {
name string
modelCode string
want string
}{
{name: "tam urun kodu", modelCode: "M038-TKX60788", want: "TKX60788"},
{name: "arge model kodu", modelCode: "TKX60788", want: "TKX60788"},
{name: "bosluk ve kucuk harf", modelCode: " m038-tkx60788 ", want: "TKX60788"},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := normalizeArgeBaggiModelCode(tt.modelCode)
if got != tt.want {
t.Fatalf("normalizeArgeBaggiModelCode(%q) = %q, want %q", tt.modelCode, got, tt.want)
}
})
}
}
func TestArgeBaggiDepotEntryKeyNormalizesPair(t *testing.T) {
got := ArgeBaggiDepotEntryKey(" 217655 ", " m038-ckk60281 ")
want := "217655\x1fCKK60281"
if got != want {
t.Fatalf("ArgeBaggiDepotEntryKey() = %q, want %q", got, want)
}
}
+14 -8
View File
@@ -159,18 +159,21 @@ func GetProductionNoCostProductsHandler(w http.ResponseWriter, r *http.Request)
} }
if argeDB := db.GetArgeBaggiDB(); argeDB != nil && len(list) > 0 { if argeDB := db.GetArgeBaggiDB(); argeDB != nil && len(list) > 0 {
workOrders := make([]string, 0, len(list)) lookups := make([]queries.ArgeBaggiDepotEntryLookup, 0, len(list))
for i := range list { for i := range list {
workOrders = append(workOrders, list[i].UrtSiparisNo) lookups = append(lookups, queries.ArgeBaggiDepotEntryLookup{
WorkOrder: list[i].UrtSiparisNo,
ModelCode: list[i].MModelKodu,
})
} }
argeCtx, cancelArge := context.WithTimeout(r.Context(), 15*time.Second) argeCtx, cancelArge := context.WithTimeout(r.Context(), 15*time.Second)
totalsByWorkOrder, argeErr := queries.GetArgeBaggiDepotEntryTotals(argeCtx, argeDB, workOrders) totalsByWorkOrderModel, argeErr := queries.GetArgeBaggiDepotEntryTotals(argeCtx, argeDB, lookups)
cancelArge() cancelArge()
if argeErr != nil { if argeErr != nil {
log.Printf("[ProductionNoCost] ArgeBAGGI enrichment error: %v", argeErr) log.Printf("[ProductionNoCost] ArgeBAGGI enrichment error: %v", argeErr)
} else { } else {
for i := range list { for i := range list {
totals := totalsByWorkOrder[strings.TrimSpace(list[i].UrtSiparisNo)] totals := totalsByWorkOrderModel[queries.ArgeBaggiDepotEntryKey(list[i].UrtSiparisNo, list[i].MModelKodu)]
list[i].CeketDepoGiris = totals.Ceket list[i].CeketDepoGiris = totals.Ceket
list[i].PantolonDepoGiris = totals.Pantolon list[i].PantolonDepoGiris = totals.Pantolon
list[i].YelekDepoGiris = totals.Yelek list[i].YelekDepoGiris = totals.Yelek
@@ -244,18 +247,21 @@ func GetProductionHasCostProductsHandler(w http.ResponseWriter, r *http.Request)
} }
if argeDB := db.GetArgeBaggiDB(); argeDB != nil && len(list) > 0 { if argeDB := db.GetArgeBaggiDB(); argeDB != nil && len(list) > 0 {
workOrders := make([]string, 0, len(list)) lookups := make([]queries.ArgeBaggiDepotEntryLookup, 0, len(list))
for i := range list { for i := range list {
workOrders = append(workOrders, list[i].UrtSiparisNo) lookups = append(lookups, queries.ArgeBaggiDepotEntryLookup{
WorkOrder: list[i].UrtSiparisNo,
ModelCode: list[i].UrunKodu,
})
} }
argeCtx, cancelArge := context.WithTimeout(r.Context(), 15*time.Second) argeCtx, cancelArge := context.WithTimeout(r.Context(), 15*time.Second)
totalsByWorkOrder, argeErr := queries.GetArgeBaggiDepotEntryTotals(argeCtx, argeDB, workOrders) totalsByWorkOrderModel, argeErr := queries.GetArgeBaggiDepotEntryTotals(argeCtx, argeDB, lookups)
cancelArge() cancelArge()
if argeErr != nil { if argeErr != nil {
log.Printf("[ProductionHasCost] ArgeBAGGI enrichment error: %v", argeErr) log.Printf("[ProductionHasCost] ArgeBAGGI enrichment error: %v", argeErr)
} else { } else {
for i := range list { for i := range list {
totals := totalsByWorkOrder[strings.TrimSpace(list[i].UrtSiparisNo)] totals := totalsByWorkOrderModel[queries.ArgeBaggiDepotEntryKey(list[i].UrtSiparisNo, list[i].UrunKodu)]
list[i].CeketDepoGiris = totals.Ceket list[i].CeketDepoGiris = totals.Ceket
list[i].PantolonDepoGiris = totals.Pantolon list[i].PantolonDepoGiris = totals.Pantolon
list[i].YelekDepoGiris = totals.Yelek list[i].YelekDepoGiris = totals.Yelek