package queries import ( "database/sql" "fmt" "log" "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(l.ItemDim2Code,'') AS OldDim2, ISNULL(l.LineDescription,'') AS OldDesc, CAST('' AS NVARCHAR(60)) AS NewItemCode, CAST('' AS NVARCHAR(30)) AS NewColor, CAST('' AS NVARCHAR(30)) AS NewDim2, CAST('' AS NVARCHAR(250)) AS NewDesc, 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)*5+2) paramPos := 1 for _, line := range chunk { values = append(values, fmt.Sprintf("(@p%d,@p%d,@p%d,@p%d,@p%d)", paramPos, paramPos+1, paramPos+2, paramPos+3, paramPos+4)) args = append(args, strings.TrimSpace(line.OrderLineID), line.NewItemCode, line.NewColor, line.NewDim2, line.NewDesc, ) paramPos += 5 } orderHeaderParam := paramPos usernameParam := paramPos + 1 args = append(args, orderHeaderID, username) query := fmt.Sprintf(` SET NOCOUNT ON; WITH src (OrderLineID, NewItemCode, NewColor, NewDim2, NewDesc) AS ( SELECT * FROM (VALUES %s) AS v (OrderLineID, NewItemCode, NewColor, NewDim2, NewDesc) ) UPDATE l SET l.ItemCode = s.NewItemCode, l.ColorCode = s.NewColor, l.ItemDim2Code = s.NewDim2, l.LineDescription = COALESCE(NULLIF(s.NewDesc,''), l.LineDescription), 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 { 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 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 if err := tx.QueryRow(query, args...).Scan(&chunkAffected); err != nil { return affected, err } affected += chunkAffected log.Printf("[UpsertItemAttributesTx] chunk=%d-%d chunkAffected=%d cumulative=%d", i, end, chunkAffected, affected) } 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 }