diff --git a/svc/queries/production_product_costing.go b/svc/queries/production_product_costing.go index d540119..3bfb5b5 100644 --- a/svc/queries/production_product_costing.go +++ b/svc/queries/production_product_costing.go @@ -2029,6 +2029,31 @@ ORDER BY return mssqlDB.QueryRowContext(ctx, sqlText, sKodu, costDate, colorCode, itemDim1Code), nil } +// Best-effort: resolve TR item description for an item code. Used for warnings export readability. +func GetItemDescriptionTRByItemCode(ctx context.Context, mssqlDB *sql.DB, itemCode string) (string, error) { + itemCode = strings.TrimSpace(itemCode) + if itemCode == "" { + return "", nil + } + sqlText := ` +SELECT TOP 1 ISNULL(D.ItemDescription, '') AS ItemDescription +FROM cdItem CI +INNER JOIN cdItemDesc D + ON D.ItemTypeCode = CI.ItemTypeCode + AND D.ItemCode = CI.ItemCode + AND D.LangCode = 'TR' +WHERE LTRIM(RTRIM(CI.ItemCode)) = @p1 +` + var desc string + if err := mssqlDB.QueryRowContext(ctx, sqlText, itemCode).Scan(&desc); err != nil { + if err == sql.ErrNoRows { + return "", nil + } + return "", err + } + return strings.TrimSpace(desc), nil +} + // Bulk version of GetProductionHasCostLatestPurchasePriceForItem. // Uses OPENJSON to avoid 1-query-per-item fan-out. // For each requested rowKey, picks the latest purchase invoice before costDate, diff --git a/svc/routes/production_product_costing.go b/svc/routes/production_product_costing.go index 329c1a7..b8446b2 100644 --- a/svc/routes/production_product_costing.go +++ b/svc/routes/production_product_costing.go @@ -2362,6 +2362,43 @@ VALUES ( avgUSDByKey[key] = avgUSD } + // Fill missing descriptions from MSSQL (best-effort, small set). + { + miss := make([]string, 0, len(codes)) + for _, c := range codes { + if strings.TrimSpace(descByCode[c]) == "" { + miss = append(miss, c) + } + } + if len(miss) > 0 { + type res struct{ code, desc string } + jobs := make(chan string, len(miss)) + out := make(chan res, len(miss)) + worker := func() { + for code := range jobs { + stepCtx, cancel := context.WithTimeout(bg, 2*time.Second) + d, _ := queries.GetItemDescriptionTRByItemCode(stepCtx, mssqlLocal, code) + cancel() + out <- res{code: code, desc: d} + } + } + workers := 8 + for i := 0; i < workers; i++ { + go worker() + } + for _, c := range miss { + jobs <- c + } + close(jobs) + for i := 0; i < len(miss); i++ { + r := <-out + if strings.TrimSpace(r.desc) != "" { + descByCode[r.code] = r.desc + } + } + } + } + writeCtx, cancelWrite := context.WithTimeout(bg, 12*time.Second) err = queries.ReplaceProductionCostingLast10Warnings( writeCtx,