package queries import ( "database/sql" "fmt" "log" "sort" "strconv" "strings" "time" "bssapp-backend/models" ) // ======================================================== // 📌 GetOrderProductionItems — OrderHeaderID için U ürünleri // ======================================================== func GetOrderProductionItems(mssql *sql.DB, orderHeaderID string) (*sql.Rows, error) { return mssql.Query(` SELECT CAST(l.OrderHeaderID AS NVARCHAR(50)) AS OrderHeaderID, CAST(l.OrderLineID AS NVARCHAR(50)) AS OrderLineID, l.ItemTypeCode AS ItemTypeCode, ISNULL(l.ItemDim1Code,'') AS OldDim1, ISNULL(l.ItemDim3Code,'') AS OldDim3, ISNULL(l.ItemCode,'') AS OldItemCode, ISNULL(l.ColorCode,'') AS OldColor, ISNULL(( SELECT TOP 1 LTRIM(RTRIM(cd.ColorDescription)) FROM dbo.cdColorDesc cd WITH (NOLOCK) WHERE cd.ColorCode = l.ColorCode AND cd.LangCode = N'TR' ), '') AS OldColorDescription, ISNULL(l.ItemDim2Code,'') AS OldDim2, ISNULL(l.LineDescription,'') AS OldDesc, CAST(ISNULL(l.Qty1, 0) AS FLOAT) AS OldQty, CAST('' AS NVARCHAR(60)) AS NewItemCode, CAST('' AS NVARCHAR(30)) AS NewColor, CAST('' AS NVARCHAR(30)) AS NewDim2, CAST('' AS NVARCHAR(250)) AS NewDesc, CONVERT(NVARCHAR(10), l.DeliveryDate, 126) AS OldDueDate, CONVERT(NVARCHAR(10), l.DeliveryDate, 126) AS NewDueDate, CAST(0 AS bit) AS IsVariantMissing FROM dbo.trOrderLine l WHERE l.OrderHeaderID = @p1 AND ISNULL(l.ItemCode,'') LIKE 'U%' ORDER BY l.SortOrder, l.OrderLineID `, orderHeaderID) } // ======================================================== // 📌 InsertMissingProductionVariants — eksik prItemVariant ekler // ======================================================== func InsertMissingProductionVariants(mssql *sql.DB, orderHeaderID string, username string) (int64, error) { query := ` ;WITH Missing AS ( SELECT DISTINCT l.ItemTypeCode, l.ItemCode, l.ColorCode, l.ItemDim1Code, l.ItemDim2Code, l.ItemDim3Code FROM dbo.trOrderLine l LEFT JOIN dbo.prItemVariant pv ON pv.ItemTypeCode = l.ItemTypeCode AND ISNULL(LTRIM(RTRIM(pv.ItemCode)),'') = ISNULL(LTRIM(RTRIM(l.ItemCode)),'') AND ISNULL(LTRIM(RTRIM(pv.ColorCode)),'') = ISNULL(LTRIM(RTRIM(l.ColorCode)),'') AND ISNULL(LTRIM(RTRIM(pv.ItemDim1Code)),'') = ISNULL(LTRIM(RTRIM(l.ItemDim1Code)),'') AND ISNULL(LTRIM(RTRIM(pv.ItemDim2Code)),'') = ISNULL(LTRIM(RTRIM(l.ItemDim2Code)),'') AND ISNULL(LTRIM(RTRIM(pv.ItemDim3Code)),'') = ISNULL(LTRIM(RTRIM(l.ItemDim3Code)),'') WHERE l.OrderHeaderID = @p1 AND ISNULL(l.ItemCode,'') LIKE 'U%' AND pv.ItemCode IS NULL ) INSERT INTO dbo.prItemVariant ( ItemTypeCode, ItemCode, ColorCode, ItemDim1Code, ItemDim2Code, ItemDim3Code, IsSalesOrderClosed, IsPurchaseOrderClosed, IsLocked, IsBlocked, CreatedUserName, CreatedDate, LastUpdatedUserName, LastUpdatedDate, RowGuid, UseInternet, IsStoreOrderClosed ) SELECT m.ItemTypeCode, m.ItemCode, m.ColorCode, m.ItemDim1Code, m.ItemDim2Code, m.ItemDim3Code, 0, 0, 0, 0, @p2, GETDATE(), @p2, GETDATE(), NEWID(), 0, 0 FROM Missing m; ` res, err := mssql.Exec(query, orderHeaderID, username) if err != nil { return 0, err } return res.RowsAffected() } // ======================================================== // OrderProductionUpdate - variant kontrolu ve guncelleme // ======================================================== func GetOrderLineDims(mssql *sql.DB, orderHeaderID string, orderLineID string) (int16, string, string, string, error) { var itemTypeCode int16 var dim1 string var dim2 string var dim3 string err := mssql.QueryRow(` SELECT ItemTypeCode, ISNULL(ItemDim1Code,'') AS ItemDim1Code, ISNULL(ItemDim2Code,'') AS ItemDim2Code, ISNULL(ItemDim3Code,'') AS ItemDim3Code FROM dbo.trOrderLine WHERE OrderHeaderID = @p1 AND OrderLineID = @p2 `, orderHeaderID, orderLineID).Scan(&itemTypeCode, &dim1, &dim2, &dim3) return itemTypeCode, dim1, dim2, dim3, err } type OrderLineDims struct { ItemTypeCode int16 ItemDim1Code string ItemDim2Code string ItemDim3Code string } func GetOrderLineDimsMap(mssql *sql.DB, orderHeaderID string) (map[string]OrderLineDims, error) { rows, err := mssql.Query(` SELECT CAST(OrderLineID AS NVARCHAR(50)) AS OrderLineID, ItemTypeCode, ISNULL(ItemDim1Code,'') AS ItemDim1Code, ISNULL(ItemDim2Code,'') AS ItemDim2Code, ISNULL(ItemDim3Code,'') AS ItemDim3Code FROM dbo.trOrderLine WITH(NOLOCK) WHERE OrderHeaderID = @p1 `, orderHeaderID) if err != nil { return nil, err } defer rows.Close() out := make(map[string]OrderLineDims, 128) for rows.Next() { var lineID string var d OrderLineDims if err := rows.Scan(&lineID, &d.ItemTypeCode, &d.ItemDim1Code, &d.ItemDim2Code, &d.ItemDim3Code); err != nil { return nil, err } out[strings.TrimSpace(lineID)] = d } if err := rows.Err(); err != nil { return nil, err } return out, nil } func VariantExists(mssql *sql.DB, itemTypeCode int16, itemCode string, colorCode string, dim1 string, dim2 string, dim3 string) (bool, error) { var exists int err := mssql.QueryRow(` SELECT TOP 1 1 FROM dbo.prItemVariant WHERE ItemTypeCode = @p1 AND ItemCode = @p2 AND ( ColorCode = @p3 OR (@p3 = '' AND (ColorCode IS NULL OR ColorCode = '')) ) AND ( ItemDim1Code = @p4 OR (@p4 = '' AND (ItemDim1Code IS NULL OR ItemDim1Code = '')) ) AND ( ItemDim2Code = @p5 OR (@p5 = '' AND (ItemDim2Code IS NULL OR ItemDim2Code = '')) ) AND ( ItemDim3Code = @p6 OR (@p6 = '' AND (ItemDim3Code IS NULL OR ItemDim3Code = '')) ) `, itemTypeCode, itemCode, colorCode, dim1, dim2, dim3).Scan(&exists) if err == sql.ErrNoRows { return false, nil } if err != nil { return false, err } return true, nil } func InsertMissingVariantsTx( tx *sql.Tx, missing []models.OrderProductionMissingVariant, username string, cdItemByCode map[string]models.OrderProductionCdItemDraft, ) (int64, error) { start := time.Now() if len(missing) == 0 { log.Printf("[InsertMissingVariantsTx] missing=0 inserted=0 duration_ms=0") return 0, nil } var inserted int64 ensuredItems := make(map[string]struct{}, len(missing)) uniqueVariants := make([]models.OrderProductionMissingVariant, 0, len(missing)) seenVariants := make(map[string]struct{}, len(missing)) for _, v := range missing { variantKey := strconv.FormatInt(int64(v.ItemTypeCode), 10) + "|" + strings.ToUpper(strings.TrimSpace(v.ItemCode)) + "|" + strings.ToUpper(strings.TrimSpace(v.ColorCode)) + "|" + strings.ToUpper(strings.TrimSpace(v.ItemDim1Code)) + "|" + strings.ToUpper(strings.TrimSpace(v.ItemDim2Code)) + "|" + strings.ToUpper(strings.TrimSpace(v.ItemDim3Code)) if _, ok := seenVariants[variantKey]; ok { continue } seenVariants[variantKey] = struct{}{} uniqueVariants = append(uniqueVariants, v) itemKey := strconv.FormatInt(int64(v.ItemTypeCode), 10) + "|" + v.ItemCode if _, ok := ensuredItems[itemKey]; !ok { draft, hasDraft := cdItemByCode[itemKey] if !hasDraft { draft, hasDraft = cdItemByCode[NormalizeCdItemMapKey(v.ItemTypeCode, v.ItemCode)] } var draftPtr *models.OrderProductionCdItemDraft if hasDraft { tmp := draft draftPtr = &tmp } if err := ensureCdItemTx(tx, v.ItemTypeCode, v.ItemCode, username, draftPtr); err != nil { return inserted, err } ensuredItems[itemKey] = struct{}{} } } if len(uniqueVariants) == 0 { return 0, nil } args := make([]any, 0, len(uniqueVariants)*6+1) valueRows := make([]string, 0, len(uniqueVariants)) paramPos := 1 for _, v := range uniqueVariants { valueRows = append(valueRows, fmt.Sprintf("(@p%d,@p%d,@p%d,@p%d,@p%d,@p%d)", paramPos, paramPos+1, paramPos+2, paramPos+3, paramPos+4, paramPos+5)) args = append(args, v.ItemTypeCode, v.ItemCode, v.ColorCode, v.ItemDim1Code, v.ItemDim2Code, v.ItemDim3Code) paramPos += 6 } usernameParam := paramPos args = append(args, username) query := fmt.Sprintf(` SET NOCOUNT ON; ;WITH Missing(ItemTypeCode, ItemCode, ColorCode, ItemDim1Code, ItemDim2Code, ItemDim3Code) AS ( SELECT * FROM (VALUES %s) AS v(ItemTypeCode, ItemCode, ColorCode, ItemDim1Code, ItemDim2Code, ItemDim3Code) ) INSERT INTO dbo.prItemVariant ( ItemTypeCode, ItemCode, ColorCode, ItemDim1Code, ItemDim2Code, ItemDim3Code, IsSalesOrderClosed, IsPurchaseOrderClosed, IsLocked, IsBlocked, CreatedUserName, CreatedDate, LastUpdatedUserName, LastUpdatedDate, RowGuid, UseInternet, IsStoreOrderClosed ) SELECT m.ItemTypeCode, m.ItemCode, m.ColorCode, m.ItemDim1Code, m.ItemDim2Code, m.ItemDim3Code, 0, 0, 0, 0, @p%d, GETDATE(), @p%d, GETDATE(), NEWID(), 0, 0 FROM Missing m LEFT JOIN dbo.prItemVariant pv ON pv.ItemTypeCode = m.ItemTypeCode AND pv.ItemCode = m.ItemCode AND ( pv.ColorCode = m.ColorCode OR (m.ColorCode = '' AND (pv.ColorCode IS NULL OR pv.ColorCode = '')) ) AND ( pv.ItemDim1Code = m.ItemDim1Code OR (m.ItemDim1Code = '' AND (pv.ItemDim1Code IS NULL OR pv.ItemDim1Code = '')) ) AND ( pv.ItemDim2Code = m.ItemDim2Code OR (m.ItemDim2Code = '' AND (pv.ItemDim2Code IS NULL OR pv.ItemDim2Code = '')) ) AND ( pv.ItemDim3Code = m.ItemDim3Code OR (m.ItemDim3Code = '' AND (pv.ItemDim3Code IS NULL OR pv.ItemDim3Code = '')) ) WHERE pv.ItemCode IS NULL; `, strings.Join(valueRows, ","), usernameParam, usernameParam) res, err := tx.Exec(query, args...) if err != nil { return inserted, err } if rows, rowsErr := res.RowsAffected(); rowsErr == nil { inserted += rows } log.Printf("[InsertMissingVariantsTx] missing=%d unique=%d ensuredItems=%d inserted=%d duration_ms=%d", len(missing), len(uniqueVariants), len(ensuredItems), inserted, time.Since(start).Milliseconds()) return inserted, nil } func NormalizeCdItemMapKey(itemTypeCode int16, itemCode string) string { return strconv.FormatInt(int64(itemTypeCode), 10) + "|" + strings.ToUpper(strings.TrimSpace(itemCode)) } func ensureCdItemTx( tx *sql.Tx, itemTypeCode int16, itemCode string, username string, draft *models.OrderProductionCdItemDraft, ) error { _, err := tx.Exec(` IF NOT EXISTS ( SELECT 1 FROM dbo.cdItem WHERE ItemTypeCode = @p1 AND ItemCode = @p2 ) BEGIN ;WITH Template AS ( SELECT TOP 1 ItemDimTypeCode, ProductTypeCode, ProductHierarchyID, UnitOfMeasureCode1, UnitOfMeasureCode2, UnitConvertRate, UnitConvertRateNotFixed, UseInternet, UsePOS, UseStore, EnablePartnerCompanies, UseManufacturing, UseSerialNumber, GenerateOpticalDataMatrixCode, ByWeight, SupplyPeriod, GuaranteePeriod, ShelfLife, OrderLeadTime, ItemAccountGrCode, ItemTaxGrCode, ItemPaymentPlanGrCode, ItemDiscountGrCode, ItemVendorGrCode, PromotionGroupCode, PromotionGroupCode2, ProductCollectionGrCode, StorePriceLevelCode, PerceptionOfFashionCode, CommercialRoleCode, StoreCapacityLevelCode, CustomsTariffNumberCode, IsFixedExpense, BOMEntityCode, CompanyCode, IsBlocked, IsLocked, LockedDate, IsSalesOrderClosed, IsPurchaseOrderClosed, UseRoll, UseBatch, MaxCreditCardInstallmentCount, GenerateSerialNumber, IsSubsequentDeliveryForR, IsSubsequentDeliveryForRI, IGACommissionGroup, UniFreeCommissionGroup, CustomsProductGroupCode, IsUTSDeclaratedItem, IsStoreOrderClosed FROM dbo.cdItem WITH (UPDLOCK, HOLDLOCK) WHERE ItemTypeCode = @p1 AND ItemCode LIKE 'U%' ORDER BY CreatedDate DESC ) INSERT INTO dbo.cdItem ( ItemTypeCode, ItemCode, ItemDimTypeCode, ProductTypeCode, ProductHierarchyID, UnitOfMeasureCode1, UnitOfMeasureCode2, UnitConvertRate, UnitConvertRateNotFixed, UseInternet, UsePOS, UseStore, EnablePartnerCompanies, UseManufacturing, UseSerialNumber, GenerateOpticalDataMatrixCode, ByWeight, SupplyPeriod, GuaranteePeriod, ShelfLife, OrderLeadTime, ItemAccountGrCode, ItemTaxGrCode, ItemPaymentPlanGrCode, ItemDiscountGrCode, ItemVendorGrCode, PromotionGroupCode, PromotionGroupCode2, ProductCollectionGrCode, StorePriceLevelCode, PerceptionOfFashionCode, CommercialRoleCode, StoreCapacityLevelCode, CustomsTariffNumberCode, IsFixedExpense, BOMEntityCode, CompanyCode, IsBlocked, IsLocked, LockedDate, IsSalesOrderClosed, IsPurchaseOrderClosed, CreatedUserName, CreatedDate, LastUpdatedUserName, LastUpdatedDate, RowGuid, UseRoll, UseBatch, MaxCreditCardInstallmentCount, GenerateSerialNumber, IsSubsequentDeliveryForR, IsSubsequentDeliveryForRI, IGACommissionGroup, UniFreeCommissionGroup, CustomsProductGroupCode, IsUTSDeclaratedItem, IsStoreOrderClosed ) SELECT @p1, @p2, t.ItemDimTypeCode, t.ProductTypeCode, t.ProductHierarchyID, t.UnitOfMeasureCode1, t.UnitOfMeasureCode2, t.UnitConvertRate, t.UnitConvertRateNotFixed, t.UseInternet, t.UsePOS, t.UseStore, t.EnablePartnerCompanies, t.UseManufacturing, t.UseSerialNumber, t.GenerateOpticalDataMatrixCode, t.ByWeight, t.SupplyPeriod, t.GuaranteePeriod, t.ShelfLife, t.OrderLeadTime, t.ItemAccountGrCode, t.ItemTaxGrCode, t.ItemPaymentPlanGrCode, t.ItemDiscountGrCode, t.ItemVendorGrCode, t.PromotionGroupCode, t.PromotionGroupCode2, t.ProductCollectionGrCode, t.StorePriceLevelCode, t.PerceptionOfFashionCode, t.CommercialRoleCode, t.StoreCapacityLevelCode, t.CustomsTariffNumberCode, t.IsFixedExpense, t.BOMEntityCode, t.CompanyCode, t.IsBlocked, t.IsLocked, t.LockedDate, t.IsSalesOrderClosed, t.IsPurchaseOrderClosed, @p3, GETDATE(), @p3, GETDATE(), NEWID(), t.UseRoll, t.UseBatch, t.MaxCreditCardInstallmentCount, t.GenerateSerialNumber, t.IsSubsequentDeliveryForR, t.IsSubsequentDeliveryForRI, t.IGACommissionGroup, t.UniFreeCommissionGroup, t.CustomsProductGroupCode, t.IsUTSDeclaratedItem, t.IsStoreOrderClosed FROM Template t; IF @@ROWCOUNT = 0 BEGIN INSERT INTO dbo.cdItem ( ItemTypeCode, ItemCode, ItemDimTypeCode, ProductTypeCode, ProductHierarchyID, UnitOfMeasureCode1, UnitOfMeasureCode2, UnitConvertRate, UnitConvertRateNotFixed, UseInternet, UsePOS, UseStore, EnablePartnerCompanies, UseManufacturing, UseSerialNumber, GenerateOpticalDataMatrixCode, ByWeight, SupplyPeriod, GuaranteePeriod, ShelfLife, OrderLeadTime, ItemAccountGrCode, ItemTaxGrCode, ItemPaymentPlanGrCode, ItemDiscountGrCode, ItemVendorGrCode, PromotionGroupCode, PromotionGroupCode2, ProductCollectionGrCode, StorePriceLevelCode, PerceptionOfFashionCode, CommercialRoleCode, StoreCapacityLevelCode, CustomsTariffNumberCode, IsFixedExpense, BOMEntityCode, CompanyCode, IsBlocked, IsLocked, LockedDate, IsSalesOrderClosed, IsPurchaseOrderClosed, CreatedUserName, CreatedDate, LastUpdatedUserName, LastUpdatedDate, RowGuid, UseRoll, UseBatch, MaxCreditCardInstallmentCount, GenerateSerialNumber, IsSubsequentDeliveryForR, IsSubsequentDeliveryForRI, IGACommissionGroup, UniFreeCommissionGroup, CustomsProductGroupCode, IsUTSDeclaratedItem, IsStoreOrderClosed ) VALUES ( @p1, @p2, 2, 1, 2, 'AD', '', 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, '', '%10', '', '', '', '', '', '0', '0', '0', '0', '', '', 0, '', '1', 0, 0, '1900-01-01', 0, 0, @p3, GETDATE(), @p3, GETDATE(), NEWID(), 0, 0, 12, 0, 0, 0, '', '', '0', 0, 0 ); END END `, itemTypeCode, itemCode, username) if err != nil { return err } if draft == nil { return nil } _, err = tx.Exec(` UPDATE dbo.cdItem SET ItemDimTypeCode = COALESCE(@p3, ItemDimTypeCode), ProductTypeCode = COALESCE(@p4, ProductTypeCode), ProductHierarchyID = COALESCE(@p5, ProductHierarchyID), UnitOfMeasureCode1 = COALESCE(NULLIF(@p6,''), UnitOfMeasureCode1), ItemAccountGrCode = COALESCE(NULLIF(@p7,''), ItemAccountGrCode), ItemTaxGrCode = CASE WHEN NULLIF(@p8,'') IS NULL THEN ItemTaxGrCode WHEN EXISTS ( SELECT 1 FROM dbo.cdItemTaxGr g WITH(NOLOCK) WHERE LTRIM(RTRIM(g.ItemTaxGrCode)) = LTRIM(RTRIM(@p8)) ) THEN @p8 ELSE ItemTaxGrCode END, ItemPaymentPlanGrCode = COALESCE(NULLIF(@p9,''), ItemPaymentPlanGrCode), ItemDiscountGrCode = COALESCE(NULLIF(@p10,''), ItemDiscountGrCode), ItemVendorGrCode = COALESCE(NULLIF(@p11,''), ItemVendorGrCode), PromotionGroupCode = COALESCE(NULLIF(@p12,''), PromotionGroupCode), ProductCollectionGrCode = COALESCE(NULLIF(@p13,''), ProductCollectionGrCode), StorePriceLevelCode = COALESCE(NULLIF(@p14,''), StorePriceLevelCode), PerceptionOfFashionCode = COALESCE(NULLIF(@p15,''), PerceptionOfFashionCode), CommercialRoleCode = COALESCE(NULLIF(@p16,''), CommercialRoleCode), StoreCapacityLevelCode = COALESCE(NULLIF(@p17,''), StoreCapacityLevelCode), CustomsTariffNumberCode = COALESCE(NULLIF(@p18,''), CustomsTariffNumberCode), CompanyCode = COALESCE(NULLIF(@p19,''), CompanyCode), LastUpdatedUserName = @p20, LastUpdatedDate = GETDATE() WHERE ItemTypeCode = @p1 AND ItemCode = @p2; `, itemTypeCode, itemCode, draft.ItemDimTypeCode, draft.ProductTypeCode, draft.ProductHierarchyID, draft.UnitOfMeasureCode1, draft.ItemAccountGrCode, draft.ItemTaxGrCode, draft.ItemPaymentPlanGrCode, draft.ItemDiscountGrCode, draft.ItemVendorGrCode, draft.PromotionGroupCode, draft.ProductCollectionGrCode, draft.StorePriceLevelCode, draft.PerceptionOfFashionCode, draft.CommercialRoleCode, draft.StoreCapacityLevelCode, draft.CustomsTariffNumberCode, draft.CompanyCode, username, ) return err } func UpdateOrderLinesTx(tx *sql.Tx, orderHeaderID string, lines []models.OrderProductionUpdateLine, username string) (int64, error) { if len(lines) == 0 { return 0, nil } const chunkSize = 300 var updated int64 for i := 0; i < len(lines); i += chunkSize { end := i + chunkSize if end > len(lines) { end = len(lines) } chunk := lines[i:end] values := make([]string, 0, len(chunk)) args := make([]any, 0, len(chunk)*8+2) paramPos := 1 for _, line := range chunk { var itemDim1 any if line.ItemDim1Code != nil { itemDim1 = strings.TrimSpace(*line.ItemDim1Code) } values = append(values, fmt.Sprintf("(@p%d,@p%d,@p%d,@p%d,@p%d,@p%d,@p%d,@p%d)", paramPos, paramPos+1, paramPos+2, paramPos+3, paramPos+4, paramPos+5, paramPos+6, paramPos+7)) args = append(args, strings.TrimSpace(line.OrderLineID), line.NewItemCode, line.NewColor, itemDim1, line.NewDim2, line.NewDesc, line.OldDueDate, line.NewDueDate, ) paramPos += 8 } orderHeaderParam := paramPos usernameParam := paramPos + 1 args = append(args, orderHeaderID, username) query := fmt.Sprintf(` SET NOCOUNT ON; ;WITH src (OrderLineID, NewItemCode, NewColor, ItemDim1Code, NewDim2, NewDesc, OldDueDate, NewDueDate) AS ( SELECT * FROM (VALUES %s) AS v (OrderLineID, NewItemCode, NewColor, ItemDim1Code, NewDim2, NewDesc, OldDueDate, NewDueDate) ) UPDATE l SET l.ItemCode = s.NewItemCode, l.ColorCode = s.NewColor, l.ItemDim1Code = COALESCE(s.ItemDim1Code, l.ItemDim1Code), l.ItemDim2Code = s.NewDim2, l.LineDescription = COALESCE(NULLIF(s.NewDesc,''), l.LineDescription), l.DeliveryDate = CASE WHEN ISDATE(s.NewDueDate) = 1 THEN CAST(s.NewDueDate AS DATETIME) ELSE l.DeliveryDate END, l.LastUpdatedUserName = @p%d, l.LastUpdatedDate = GETDATE() FROM dbo.trOrderLine l JOIN src s ON CAST(l.OrderLineID AS NVARCHAR(50)) = s.OrderLineID WHERE l.OrderHeaderID = @p%d; `, strings.Join(values, ","), usernameParam, orderHeaderParam) chunkStart := time.Now() res, execErr := tx.Exec(query, args...) if execErr != nil { log.Printf("[UpdateOrderLinesTx] ERROR orderHeaderID=%s chunk=%d-%d err=%v", orderHeaderID, i, end, execErr) return updated, fmt.Errorf("update lines chunk failed chunkStart=%d chunkEnd=%d duration_ms=%d: %w", i, end, time.Since(chunkStart).Milliseconds(), execErr) } log.Printf("[UpdateOrderLinesTx] orderHeaderID=%s chunk=%d-%d duration_ms=%d", orderHeaderID, i, end, time.Since(chunkStart).Milliseconds()) if rows, rowsErr := res.RowsAffected(); rowsErr == nil { updated += rows } } return updated, nil } func UpdateOrderHeaderAverageDueDateTx(tx *sql.Tx, orderHeaderID string, averageDueDate *string, username string) error { if averageDueDate == nil { return nil } dueDate := strings.TrimSpace(*averageDueDate) if dueDate != "" { if _, err := time.Parse("2006-01-02", dueDate); err != nil { return fmt.Errorf("invalid header average due date %q: %w", dueDate, err) } } _, err := tx.Exec(` UPDATE dbo.trOrderHeader SET AverageDueDate = CASE WHEN @p1 = '' THEN NULL ELSE CAST(@p1 AS DATETIME) END, LastUpdatedUserName = @p2, LastUpdatedDate = GETDATE() WHERE OrderHeaderID = @p3; `, dueDate, username, orderHeaderID) return err } type sqlQueryRower interface { QueryRow(query string, args ...any) *sql.Row } type plannedProductionBarcode struct { Barcode string BarcodeTypeCode string ItemTypeCode int16 ItemCode string ColorCode string ItemDim1Code string ItemDim2Code string ItemDim3Code string } func barcodeTypeExists(q sqlQueryRower, barcodeTypeCode string) (bool, error) { var exists int err := q.QueryRow(` SELECT TOP 1 1 FROM dbo.cdBarcodeType WHERE BarcodeTypeCode = @p1 `, strings.TrimSpace(barcodeTypeCode)).Scan(&exists) if err == sql.ErrNoRows { return false, nil } if err != nil { return false, err } return true, nil } func barcodeExists(q sqlQueryRower, barcode string) (bool, error) { var exists int err := q.QueryRow(` SELECT TOP 1 1 FROM dbo.prItemBarcode WITH (UPDLOCK, HOLDLOCK) WHERE Barcode = @p1 `, strings.TrimSpace(barcode)).Scan(&exists) if err == sql.ErrNoRows { return false, nil } if err != nil { return false, err } return true, nil } func existingVariantBarcode(q sqlQueryRower, barcodeTypeCode string, itemTypeCode int16, itemCode string, colorCode string, dim1 string, dim2 string, dim3 string) (string, bool, error) { var barcode string err := q.QueryRow(` SELECT TOP 1 LTRIM(RTRIM(ISNULL(Barcode, ''))) FROM dbo.prItemBarcode WITH (UPDLOCK, HOLDLOCK) WHERE BarcodeTypeCode = @p1 AND ItemTypeCode = @p2 AND ISNULL(LTRIM(RTRIM(ItemCode)), '') = @p3 AND ISNULL(LTRIM(RTRIM(ColorCode)), '') = @p4 AND ISNULL(LTRIM(RTRIM(ItemDim1Code)), '') = @p5 AND ISNULL(LTRIM(RTRIM(ItemDim2Code)), '') = @p6 AND ISNULL(LTRIM(RTRIM(ItemDim3Code)), '') = @p7 AND ISNULL(LTRIM(RTRIM(UnitOfMeasureCode)), '') = 'AD' ORDER BY TRY_CONVERT(BIGINT, NULLIF(LTRIM(RTRIM(Barcode)), '')) DESC, Barcode DESC `, strings.TrimSpace(barcodeTypeCode), itemTypeCode, strings.TrimSpace(itemCode), strings.TrimSpace(colorCode), strings.TrimSpace(dim1), strings.TrimSpace(dim2), strings.TrimSpace(dim3)).Scan(&barcode) if err == sql.ErrNoRows { return "", false, nil } if err != nil { return "", false, err } return strings.TrimSpace(barcode), true, nil } func maxNumericBarcode(q sqlQueryRower) (int64, error) { var maxBarcode int64 err := q.QueryRow(` SELECT ISNULL(MAX(TRY_CONVERT(BIGINT, NULLIF(LTRIM(RTRIM(Barcode)), ''))), 0) FROM dbo.prItemBarcode WITH (UPDLOCK, HOLDLOCK) `).Scan(&maxBarcode) return maxBarcode, err } func ValidateProductionBarcodePlan(q sqlQueryRower, variants []models.OrderProductionMissingVariant, barcodeTypeCode string) ([]models.OrderProductionBarcodeValidation, error) { typeCode := strings.ToUpper(strings.TrimSpace(barcodeTypeCode)) if len(variants) == 0 { return nil, nil } validations := make([]models.OrderProductionBarcodeValidation, 0) typeExists, err := barcodeTypeExists(q, typeCode) if err != nil { return nil, err } if !typeExists { validations = append(validations, models.OrderProductionBarcodeValidation{ Code: "invalid_barcode_type", Message: fmt.Sprintf("Barkod tipi bulunamadi: %s", typeCode), BarcodeTypeCode: typeCode, }) return validations, nil } sorted := append([]models.OrderProductionMissingVariant(nil), variants...) sort.Slice(sorted, func(i, j int) bool { left := sorted[i] right := sorted[j] leftKey := fmt.Sprintf("%05d|%s|%s|%s|%s|%s", left.ItemTypeCode, left.ItemCode, left.ColorCode, left.ItemDim1Code, left.ItemDim2Code, left.ItemDim3Code) rightKey := fmt.Sprintf("%05d|%s|%s|%s|%s|%s", right.ItemTypeCode, right.ItemCode, right.ColorCode, right.ItemDim1Code, right.ItemDim2Code, right.ItemDim3Code) return leftKey < rightKey }) maxBarcode, err := maxNumericBarcode(q) if err != nil { return nil, err } nextOffset := int64(0) planned := make(map[string]struct{}, len(sorted)) for _, variant := range sorted { existingBarcode, exists, err := existingVariantBarcode(q, typeCode, variant.ItemTypeCode, variant.ItemCode, variant.ColorCode, variant.ItemDim1Code, variant.ItemDim2Code, variant.ItemDim3Code) if err != nil { return nil, err } if exists && existingBarcode != "" { continue } nextOffset++ barcode := strconv.FormatInt(maxBarcode+nextOffset, 10) if _, duplicated := planned[barcode]; duplicated { validations = append(validations, models.OrderProductionBarcodeValidation{ Code: "barcode_duplicate_in_plan", Message: fmt.Sprintf("Planlanan barkod ayni istekte birden fazla kez olusuyor: %s", barcode), Barcode: barcode, BarcodeTypeCode: typeCode, ItemTypeCode: variant.ItemTypeCode, ItemCode: strings.TrimSpace(variant.ItemCode), ColorCode: strings.TrimSpace(variant.ColorCode), ItemDim1Code: strings.TrimSpace(variant.ItemDim1Code), ItemDim2Code: strings.TrimSpace(variant.ItemDim2Code), ItemDim3Code: strings.TrimSpace(variant.ItemDim3Code), }) continue } planned[barcode] = struct{}{} inUse, err := barcodeExists(q, barcode) if err != nil { return nil, err } if inUse { validations = append(validations, models.OrderProductionBarcodeValidation{ Code: "barcode_in_use", Message: fmt.Sprintf("Barkod daha once kullanilmis: %s (%s / %s / %s / %s)", barcode, strings.TrimSpace(variant.ItemCode), strings.TrimSpace(variant.ColorCode), strings.TrimSpace(variant.ItemDim1Code), strings.TrimSpace(variant.ItemDim2Code)), Barcode: barcode, BarcodeTypeCode: typeCode, ItemTypeCode: variant.ItemTypeCode, ItemCode: strings.TrimSpace(variant.ItemCode), ColorCode: strings.TrimSpace(variant.ColorCode), ItemDim1Code: strings.TrimSpace(variant.ItemDim1Code), ItemDim2Code: strings.TrimSpace(variant.ItemDim2Code), ItemDim3Code: strings.TrimSpace(variant.ItemDim3Code), }) } } return validations, nil } func InsertItemBarcodesTx(tx *sql.Tx, orderHeaderID string, lines []models.OrderProductionUpdateLine, username string) (int64, error) { start := time.Now() if len(lines) == 0 { log.Printf("[InsertItemBarcodesTx] lines=0 inserted=0 duration_ms=0") return 0, nil } lineIDs := make([]string, 0, len(lines)) seen := make(map[string]struct{}, len(lines)) for _, line := range lines { lineID := strings.TrimSpace(line.OrderLineID) if lineID == "" { continue } if _, ok := seen[lineID]; ok { continue } seen[lineID] = struct{}{} lineIDs = append(lineIDs, lineID) } if len(lineIDs) == 0 { log.Printf("[InsertItemBarcodesTx] lines=%d uniqueLineIDs=0 inserted=0 duration_ms=%d", len(lines), time.Since(start).Milliseconds()) return 0, nil } const chunkSize = 900 var inserted int64 for i := 0; i < len(lineIDs); i += chunkSize { end := i + chunkSize if end > len(lineIDs) { end = len(lineIDs) } chunk := lineIDs[i:end] values := make([]string, 0, len(chunk)) args := make([]any, 0, len(chunk)+2) paramPos := 1 for _, lineID := range chunk { values = append(values, fmt.Sprintf("(@p%d)", paramPos)) args = append(args, lineID) paramPos++ } orderHeaderParam := paramPos usernameParam := paramPos + 1 args = append(args, orderHeaderID, username) query := fmt.Sprintf(` ;WITH srcLine (OrderLineID) AS ( SELECT * FROM (VALUES %s) AS v (OrderLineID) ), src AS ( SELECT DISTINCT l.ItemTypeCode, UPPER(LTRIM(RTRIM(ISNULL(l.ItemCode, '')))) AS ItemCode, UPPER(LTRIM(RTRIM(ISNULL(l.ColorCode, '')))) AS ColorCode, UPPER(LTRIM(RTRIM(ISNULL(l.ItemDim1Code, '')))) AS ItemDim1Code, UPPER(LTRIM(RTRIM(ISNULL(l.ItemDim2Code, '')))) AS ItemDim2Code, CAST('' AS NVARCHAR(50)) AS ItemDim3Code FROM dbo.trOrderLine l WITH (UPDLOCK, HOLDLOCK) JOIN srcLine s ON CAST(l.OrderLineID AS NVARCHAR(50)) = s.OrderLineID WHERE l.OrderHeaderID = @p%d AND NULLIF(LTRIM(RTRIM(ISNULL(l.ItemCode, ''))), '') IS NOT NULL ), missing AS ( SELECT s.ItemTypeCode, s.ItemCode, s.ColorCode, s.ItemDim1Code, s.ItemDim2Code, s.ItemDim3Code, ROW_NUMBER() OVER ( ORDER BY s.ItemCode, s.ColorCode, s.ItemDim1Code, s.ItemDim2Code, s.ItemDim3Code ) AS RowNo FROM src s LEFT JOIN dbo.prItemBarcode b WITH (UPDLOCK, HOLDLOCK) ON b.BarcodeTypeCode = 'BAGGI3' AND b.UnitOfMeasureCode = 'AD' AND b.ItemTypeCode = s.ItemTypeCode AND UPPER(LTRIM(RTRIM(ISNULL(b.ItemCode, '')))) = s.ItemCode AND UPPER(LTRIM(RTRIM(ISNULL(b.ColorCode, '')))) = s.ColorCode AND UPPER(LTRIM(RTRIM(ISNULL(b.ItemDim1Code, '')))) = s.ItemDim1Code AND UPPER(LTRIM(RTRIM(ISNULL(b.ItemDim2Code, '')))) = s.ItemDim2Code AND UPPER(LTRIM(RTRIM(ISNULL(b.ItemDim3Code, '')))) = s.ItemDim3Code WHERE b.Barcode IS NULL ) INSERT INTO dbo.prItemBarcode ( Barcode, BarcodeTypeCode, ItemTypeCode, ItemCode, ColorCode, ItemDim1Code, ItemDim2Code, ItemDim3Code, UnitOfMeasureCode, Qty, CreatedUserName, CreatedDate, LastUpdatedUserName, LastUpdatedDate, RowGuid ) SELECT CAST(seed.MaxBarcode + m.RowNo AS NVARCHAR(50)) AS Barcode, 'BAGGI3', m.ItemTypeCode, m.ItemCode, m.ColorCode, m.ItemDim1Code, m.ItemDim2Code, m.ItemDim3Code, 'AD', 1, @p%d, GETDATE(), @p%d, GETDATE(), NEWID() FROM missing m CROSS JOIN ( SELECT ISNULL(MAX(TRY_CONVERT(BIGINT, NULLIF(LTRIM(RTRIM(Barcode)), ''))), 0) AS MaxBarcode FROM dbo.prItemBarcode WITH (UPDLOCK, HOLDLOCK) WHERE TRY_CONVERT(BIGINT, NULLIF(LTRIM(RTRIM(Barcode)), '')) IS NOT NULL ) seed; SELECT @@ROWCOUNT AS Inserted; `, strings.Join(values, ","), orderHeaderParam, usernameParam, usernameParam) chunkStart := time.Now() var chunkInserted int64 if err := tx.QueryRow(query, args...).Scan(&chunkInserted); err != nil { log.Printf("[InsertItemBarcodesTx] ERROR orderHeaderID=%s chunk=%d-%d err=%v", orderHeaderID, i, end, err) return inserted, fmt.Errorf("upsert item barcodes chunk failed chunkStart=%d chunkEnd=%d duration_ms=%d: %w", i, end, time.Since(chunkStart).Milliseconds(), err) } inserted += chunkInserted log.Printf("[InsertItemBarcodesTx] orderHeaderID=%s chunk=%d-%d chunkInserted=%d cumulative=%d duration_ms=%d", orderHeaderID, i, end, chunkInserted, inserted, time.Since(chunkStart).Milliseconds()) } log.Printf("[InsertItemBarcodesTx] orderHeaderID=%s lines=%d uniqueLineIDs=%d inserted=%d duration_ms=%d", orderHeaderID, len(lines), len(lineIDs), inserted, time.Since(start).Milliseconds()) return inserted, nil } func UpsertItemAttributesTx(tx *sql.Tx, attrs []models.OrderProductionItemAttributeRow, username string) (int64, error) { start := time.Now() if len(attrs) == 0 { log.Printf("[UpsertItemAttributesTx] attrs=0 affected=0 duration_ms=0") return 0, nil } // SQL Server parameter limiti (2100) nedeniyle batch'li set-based upsert kullanilir. const chunkSize = 400 // 400 * 4 param + 1 username = 1601 var affected int64 for i := 0; i < len(attrs); i += chunkSize { end := i + chunkSize if end > len(attrs) { end = len(attrs) } chunk := attrs[i:end] values := make([]string, 0, len(chunk)) args := make([]any, 0, len(chunk)*4+1) paramPos := 1 for _, a := range chunk { values = append(values, fmt.Sprintf("(@p%d,@p%d,@p%d,@p%d)", paramPos, paramPos+1, paramPos+2, paramPos+3)) args = append(args, a.ItemTypeCode, a.ItemCode, a.AttributeTypeCode, a.AttributeCode) paramPos += 4 } usernameParam := paramPos args = append(args, username) query := fmt.Sprintf(` SET NOCOUNT ON; DECLARE @updated INT = 0; DECLARE @inserted INT = 0; ;WITH src (ItemTypeCode, ItemCode, AttributeTypeCode, AttributeCode) AS ( SELECT * FROM (VALUES %s) AS v (ItemTypeCode, ItemCode, AttributeTypeCode, AttributeCode) ) UPDATE tgt SET tgt.AttributeCode = src.AttributeCode, tgt.LastUpdatedUserName = @p%d, tgt.LastUpdatedDate = GETDATE() FROM dbo.prItemAttribute tgt JOIN src ON src.ItemTypeCode = tgt.ItemTypeCode AND src.ItemCode = tgt.ItemCode AND src.AttributeTypeCode = tgt.AttributeTypeCode; SET @updated = @@ROWCOUNT; ;WITH src (ItemTypeCode, ItemCode, AttributeTypeCode, AttributeCode) AS ( SELECT * FROM (VALUES %s) AS v (ItemTypeCode, ItemCode, AttributeTypeCode, AttributeCode) ) INSERT INTO dbo.prItemAttribute ( ItemTypeCode, ItemCode, AttributeTypeCode, AttributeCode, CreatedUserName, CreatedDate, LastUpdatedUserName, LastUpdatedDate, RowGuid ) SELECT src.ItemTypeCode, src.ItemCode, src.AttributeTypeCode, src.AttributeCode, @p%d, GETDATE(), @p%d, GETDATE(), NEWID() FROM src LEFT JOIN dbo.prItemAttribute tgt ON src.ItemTypeCode = tgt.ItemTypeCode AND src.ItemCode = tgt.ItemCode AND src.AttributeTypeCode = tgt.AttributeTypeCode WHERE tgt.ItemCode IS NULL; SET @inserted = @@ROWCOUNT; SELECT (@updated + @inserted) AS Affected; `, strings.Join(values, ","), usernameParam, strings.Join(values, ","), usernameParam, usernameParam) var chunkAffected int64 chunkStart := time.Now() if err := tx.QueryRow(query, args...).Scan(&chunkAffected); err != nil { log.Printf("[UpsertItemAttributesTx] ERROR chunk=%d-%d err=%v", i, end, err) return affected, fmt.Errorf("upsert item attributes chunk failed chunkStart=%d chunkEnd=%d duration_ms=%d: %w", i, end, time.Since(chunkStart).Milliseconds(), err) } affected += chunkAffected log.Printf("[UpsertItemAttributesTx] chunk=%d-%d chunkAffected=%d cumulative=%d duration_ms=%d", i, end, chunkAffected, affected, time.Since(chunkStart).Milliseconds()) } log.Printf("[UpsertItemAttributesTx] attrs=%d affected=%d duration_ms=%d", len(attrs), affected, time.Since(start).Milliseconds()) return affected, nil } func GetOrderProductionLookupOptions(mssql *sql.DB) (models.OrderProductionCdItemLookups, error) { out := models.OrderProductionCdItemLookups{} queryPairs := []struct { Name string Query string Target *[]models.OrderProductionLookupOption }{ {"ItemDimTypeCodes", `SELECT CAST(t.ItemDimTypeCode AS NVARCHAR(50)) AS Code, ISNULL(d.ItemDimTypeDescription, CAST(t.ItemDimTypeCode AS NVARCHAR(50))) AS [Description] FROM dbo.bsItemDimType t WITH(NOLOCK) LEFT JOIN dbo.bsItemDimTypeDesc d WITH(NOLOCK) ON d.ItemDimTypeCode = t.ItemDimTypeCode AND d.LangCode = 'TR' WHERE ISNULL(t.IsBlocked, 0) = 0 ORDER BY t.ItemDimTypeCode`, &out.ItemDimTypeCodes}, {"ProductTypeCodes", `SELECT DISTINCT CAST(ProductTypeCode AS NVARCHAR(50)) AS Code, CAST(ProductTypeCode AS NVARCHAR(50)) AS [Description] FROM dbo.cdItem WITH(NOLOCK) WHERE ProductTypeCode IS NOT NULL ORDER BY Code`, &out.ProductTypeCodes}, {"ProductHierarchyIDs", `SELECT CAST(h.ProductHierarchyID AS NVARCHAR(50)) AS Code, LTRIM(RTRIM( CONCAT( CAST(ISNULL(h.ProductHierarchyLevelCode01, 0) AS NVARCHAR(50)), CASE WHEN ISNULL(d.ProductHierarchyLevelDescription, '') <> '' THEN CONCAT(' - ', d.ProductHierarchyLevelDescription) ELSE '' END ) )) AS [Description] FROM dbo.dfProductHierarchy h WITH(NOLOCK) LEFT JOIN dbo.cdProductHierarchyLevelDesc d WITH(NOLOCK) ON d.ProductHierarchyLevelCode = h.ProductHierarchyLevelCode01 AND d.LangCode = 'TR' ORDER BY h.ProductHierarchyID`, &out.ProductHierarchyIDs}, {"UnitOfMeasureCode1List", `SELECT DISTINCT CAST(UnitOfMeasureCode1 AS NVARCHAR(50)) AS Code, CAST(UnitOfMeasureCode1 AS NVARCHAR(200)) AS [Description] FROM dbo.cdItem WITH(NOLOCK) WHERE NULLIF(LTRIM(RTRIM(CAST(UnitOfMeasureCode1 AS NVARCHAR(200)))), '') IS NOT NULL ORDER BY Code`, &out.UnitOfMeasureCode1List}, {"ItemAccountGrCodes", `SELECT DISTINCT CAST(ItemAccountGrCode AS NVARCHAR(50)) AS Code, CAST(ItemAccountGrCode AS NVARCHAR(200)) AS [Description] FROM dbo.cdItem WITH(NOLOCK) WHERE NULLIF(LTRIM(RTRIM(CAST(ItemAccountGrCode AS NVARCHAR(200)))), '') IS NOT NULL ORDER BY Code`, &out.ItemAccountGrCodes}, {"ItemTaxGrCodes", `SELECT DISTINCT CAST(ItemTaxGrCode AS NVARCHAR(50)) AS Code, CAST(ItemTaxGrCode AS NVARCHAR(200)) AS [Description] FROM dbo.cdItem WITH(NOLOCK) WHERE NULLIF(LTRIM(RTRIM(CAST(ItemTaxGrCode AS NVARCHAR(200)))), '') IS NOT NULL ORDER BY Code`, &out.ItemTaxGrCodes}, {"ItemPaymentPlanGrCodes", `SELECT DISTINCT CAST(ItemPaymentPlanGrCode AS NVARCHAR(50)) AS Code, CAST(ItemPaymentPlanGrCode AS NVARCHAR(200)) AS [Description] FROM dbo.cdItem WITH(NOLOCK) WHERE NULLIF(LTRIM(RTRIM(CAST(ItemPaymentPlanGrCode AS NVARCHAR(200)))), '') IS NOT NULL ORDER BY Code`, &out.ItemPaymentPlanGrCodes}, {"ItemDiscountGrCodes", `SELECT DISTINCT CAST(ItemDiscountGrCode AS NVARCHAR(50)) AS Code, CAST(ItemDiscountGrCode AS NVARCHAR(200)) AS [Description] FROM dbo.cdItem WITH(NOLOCK) WHERE NULLIF(LTRIM(RTRIM(CAST(ItemDiscountGrCode AS NVARCHAR(200)))), '') IS NOT NULL ORDER BY Code`, &out.ItemDiscountGrCodes}, {"ItemVendorGrCodes", `SELECT DISTINCT CAST(ItemVendorGrCode AS NVARCHAR(50)) AS Code, CAST(ItemVendorGrCode AS NVARCHAR(200)) AS [Description] FROM dbo.cdItem WITH(NOLOCK) WHERE NULLIF(LTRIM(RTRIM(CAST(ItemVendorGrCode AS NVARCHAR(200)))), '') IS NOT NULL ORDER BY Code`, &out.ItemVendorGrCodes}, {"PromotionGroupCodes", `SELECT DISTINCT CAST(PromotionGroupCode AS NVARCHAR(50)) AS Code, CAST(PromotionGroupCode AS NVARCHAR(200)) AS [Description] FROM dbo.cdItem WITH(NOLOCK) WHERE NULLIF(LTRIM(RTRIM(CAST(PromotionGroupCode AS NVARCHAR(200)))), '') IS NOT NULL ORDER BY Code`, &out.PromotionGroupCodes}, {"ProductCollectionGrCodes", `SELECT DISTINCT CAST(ProductCollectionGrCode AS NVARCHAR(50)) AS Code, CAST(ProductCollectionGrCode AS NVARCHAR(200)) AS [Description] FROM dbo.cdItem WITH(NOLOCK) WHERE NULLIF(LTRIM(RTRIM(CAST(ProductCollectionGrCode AS NVARCHAR(200)))), '') IS NOT NULL ORDER BY Code`, &out.ProductCollectionGrCodes}, {"StorePriceLevelCodes", `SELECT DISTINCT CAST(StorePriceLevelCode AS NVARCHAR(50)) AS Code, CAST(StorePriceLevelCode AS NVARCHAR(200)) AS [Description] FROM dbo.cdItem WITH(NOLOCK) WHERE NULLIF(LTRIM(RTRIM(CAST(StorePriceLevelCode AS NVARCHAR(200)))), '') IS NOT NULL ORDER BY Code`, &out.StorePriceLevelCodes}, {"PerceptionOfFashionCodes", `SELECT DISTINCT CAST(PerceptionOfFashionCode AS NVARCHAR(50)) AS Code, CAST(PerceptionOfFashionCode AS NVARCHAR(200)) AS [Description] FROM dbo.cdItem WITH(NOLOCK) WHERE NULLIF(LTRIM(RTRIM(CAST(PerceptionOfFashionCode AS NVARCHAR(200)))), '') IS NOT NULL ORDER BY Code`, &out.PerceptionOfFashionCodes}, {"CommercialRoleCodes", `SELECT DISTINCT CAST(CommercialRoleCode AS NVARCHAR(50)) AS Code, CAST(CommercialRoleCode AS NVARCHAR(200)) AS [Description] FROM dbo.cdItem WITH(NOLOCK) WHERE NULLIF(LTRIM(RTRIM(CAST(CommercialRoleCode AS NVARCHAR(200)))), '') IS NOT NULL ORDER BY Code`, &out.CommercialRoleCodes}, {"StoreCapacityLevelCodes", `SELECT DISTINCT CAST(StoreCapacityLevelCode AS NVARCHAR(50)) AS Code, CAST(StoreCapacityLevelCode AS NVARCHAR(200)) AS [Description] FROM dbo.cdItem WITH(NOLOCK) WHERE NULLIF(LTRIM(RTRIM(CAST(StoreCapacityLevelCode AS NVARCHAR(200)))), '') IS NOT NULL ORDER BY Code`, &out.StoreCapacityLevelCodes}, {"CustomsTariffNumbers", `SELECT DISTINCT CAST(CustomsTariffNumberCode AS NVARCHAR(50)) AS Code, CAST(CustomsTariffNumberCode AS NVARCHAR(200)) AS [Description] FROM dbo.cdItem WITH(NOLOCK) WHERE NULLIF(LTRIM(RTRIM(CAST(CustomsTariffNumberCode AS NVARCHAR(200)))), '') IS NOT NULL ORDER BY Code`, &out.CustomsTariffNumbers}, {"CompanyCodes", `SELECT DISTINCT CAST(CompanyCode AS NVARCHAR(50)) AS Code, CAST(CompanyCode AS NVARCHAR(200)) AS [Description] FROM dbo.cdItem WITH(NOLOCK) WHERE NULLIF(LTRIM(RTRIM(CAST(CompanyCode AS NVARCHAR(200)))), '') IS NOT NULL ORDER BY Code`, &out.CompanyCodes}, } for _, pair := range queryPairs { start := time.Now() log.Printf("[GetOrderProductionLookupOptions] executing [%s]", pair.Name) rows, err := mssql.Query(pair.Query) if err != nil { return out, fmt.Errorf("lookup query failed [%s]: %w", pair.Name, err) } list := make([]models.OrderProductionLookupOption, 0, 64) for rows.Next() { var item models.OrderProductionLookupOption if err := rows.Scan(&item.Code, &item.Description); err != nil { rows.Close() return out, fmt.Errorf("lookup scan failed [%s]: %w", pair.Name, err) } item.Code = strings.TrimSpace(item.Code) item.Description = strings.TrimSpace(item.Description) list = append(list, item) } if err := rows.Err(); err != nil { rows.Close() return out, fmt.Errorf("lookup rows failed [%s]: %w", pair.Name, err) } rows.Close() log.Printf("[GetOrderProductionLookupOptions] ok [%s] count=%d duration=%s", pair.Name, len(list), time.Since(start)) *pair.Target = list } return out, nil }