package queries import ( "bssapp-backend/db" "bssapp-backend/models" "context" "database/sql" "strings" "time" ) func GetProductPricingList(ctx context.Context) ([]models.ProductPricing, error) { const query = ` WITH base_products AS ( SELECT LTRIM(RTRIM(ProductCode)) AS ProductCode, COALESCE(LTRIM(RTRIM(ProductAtt45Desc)), '') AS AskiliYan, COALESCE(LTRIM(RTRIM(ProductAtt44Desc)), '') AS Kategori, COALESCE(LTRIM(RTRIM(ProductAtt42Desc)), '') AS UrunIlkGrubu, COALESCE(LTRIM(RTRIM(ProductAtt01Desc)), '') AS UrunAnaGrubu, COALESCE(LTRIM(RTRIM(ProductAtt02Desc)), '') AS UrunAltGrubu, COALESCE(LTRIM(RTRIM(ProductAtt41Desc)), '') AS Icerik, COALESCE(LTRIM(RTRIM(ProductAtt29Desc)), '') AS Karisim, COALESCE(LTRIM(RTRIM(ProductAtt10Desc)), '') AS Marka FROM ProductFilterWithDescription('TR') WHERE ProductAtt42 IN ('SERI', 'AKSESUAR') AND IsBlocked = 0 AND LEN(LTRIM(RTRIM(ProductCode))) = 13 ), latest_base_price AS ( SELECT LTRIM(RTRIM(b.ItemCode)) AS ItemCode, CAST(b.Price AS DECIMAL(18, 2)) AS CostPrice, CONVERT(VARCHAR(10), b.PriceDate, 23) AS LastPricingDate, ROW_NUMBER() OVER ( PARTITION BY LTRIM(RTRIM(b.ItemCode)) ORDER BY b.PriceDate DESC, b.LastUpdatedDate DESC ) AS rn FROM prItemBasePrice b WHERE b.ItemTypeCode = 1 AND b.BasePriceCode = 1 AND LTRIM(RTRIM(b.CurrencyCode)) = 'USD' AND EXISTS ( SELECT 1 FROM base_products bp WHERE bp.ProductCode = LTRIM(RTRIM(b.ItemCode)) ) ), stock_entry_dates AS ( SELECT LTRIM(RTRIM(s.ItemCode)) AS ItemCode, CONVERT(VARCHAR(10), MAX(s.OperationDate), 23) AS StockEntryDate FROM trStock s WITH(NOLOCK) WHERE s.ItemTypeCode = 1 AND LEN(LTRIM(RTRIM(s.ItemCode))) = 13 AND s.In_Qty1 > 0 AND LTRIM(RTRIM(s.WarehouseCode)) IN ( '1-0-14','1-0-10','1-0-8','1-2-5','1-2-4','1-0-12','100','1-0-28', '1-0-24','1-2-6','1-1-14','1-0-2','1-0-52','1-1-2','1-0-21','1-1-3', '1-0-33','101','1-014','1-0-49','1-0-36' ) AND EXISTS ( SELECT 1 FROM base_products bp WHERE bp.ProductCode = LTRIM(RTRIM(s.ItemCode)) ) GROUP BY LTRIM(RTRIM(s.ItemCode)) ), stock_base AS ( SELECT LTRIM(RTRIM(s.ItemCode)) AS ItemCode, SUM(s.In_Qty1 - s.Out_Qty1) AS InventoryQty1 FROM trStock s WITH(NOLOCK) WHERE s.ItemTypeCode = 1 AND LEN(LTRIM(RTRIM(s.ItemCode))) = 13 AND EXISTS ( SELECT 1 FROM base_products bp WHERE bp.ProductCode = LTRIM(RTRIM(s.ItemCode)) ) GROUP BY LTRIM(RTRIM(s.ItemCode)) ), pick_base AS ( SELECT LTRIM(RTRIM(p.ItemCode)) AS ItemCode, SUM(p.Qty1) AS PickingQty1 FROM PickingStates p WHERE p.ItemTypeCode = 1 AND LEN(LTRIM(RTRIM(p.ItemCode))) = 13 AND EXISTS ( SELECT 1 FROM base_products bp WHERE bp.ProductCode = LTRIM(RTRIM(p.ItemCode)) ) GROUP BY LTRIM(RTRIM(p.ItemCode)) ), reserve_base AS ( SELECT LTRIM(RTRIM(r.ItemCode)) AS ItemCode, SUM(r.Qty1) AS ReserveQty1 FROM ReserveStates r WHERE r.ItemTypeCode = 1 AND LEN(LTRIM(RTRIM(r.ItemCode))) = 13 AND EXISTS ( SELECT 1 FROM base_products bp WHERE bp.ProductCode = LTRIM(RTRIM(r.ItemCode)) ) GROUP BY LTRIM(RTRIM(r.ItemCode)) ), disp_base AS ( SELECT LTRIM(RTRIM(d.ItemCode)) AS ItemCode, SUM(d.Qty1) AS DispOrderQty1 FROM DispOrderStates d WHERE d.ItemTypeCode = 1 AND LEN(LTRIM(RTRIM(d.ItemCode))) = 13 AND EXISTS ( SELECT 1 FROM base_products bp WHERE bp.ProductCode = LTRIM(RTRIM(d.ItemCode)) ) GROUP BY LTRIM(RTRIM(d.ItemCode)) ), stock_totals AS ( SELECT bp.ProductCode AS ItemCode, CAST(ROUND( ISNULL(sb.InventoryQty1, 0) - ISNULL(pb.PickingQty1, 0) - ISNULL(rb.ReserveQty1, 0) - ISNULL(db.DispOrderQty1, 0) , 2) AS DECIMAL(18, 2)) AS StockQty FROM base_products bp LEFT JOIN stock_base sb ON sb.ItemCode = bp.ProductCode LEFT JOIN pick_base pb ON pb.ItemCode = bp.ProductCode LEFT JOIN reserve_base rb ON rb.ItemCode = bp.ProductCode LEFT JOIN disp_base db ON db.ItemCode = bp.ProductCode ) SELECT bp.ProductCode AS ProductCode, COALESCE(lp.CostPrice, 0) AS CostPrice, COALESCE(st.StockQty, 0) AS StockQty, COALESCE(se.StockEntryDate, '') AS StockEntryDate, COALESCE(lp.LastPricingDate, '') AS LastPricingDate, bp.AskiliYan, bp.Kategori, bp.UrunIlkGrubu, bp.UrunAnaGrubu, bp.UrunAltGrubu, bp.Icerik, bp.Karisim, bp.Marka FROM base_products bp LEFT JOIN latest_base_price lp ON lp.ItemCode = bp.ProductCode AND lp.rn = 1 LEFT JOIN stock_entry_dates se ON se.ItemCode = bp.ProductCode LEFT JOIN stock_totals st ON st.ItemCode = bp.ProductCode ORDER BY bp.ProductCode; ` var ( rows *sql.Rows rowsErr error ) for attempt := 1; attempt <= 3; attempt++ { var err error rows, err = db.MssqlDB.QueryContext(ctx, query) if err == nil { rowsErr = nil break } rowsErr = err if ctx.Err() != nil || !isTransientMSSQLNetworkError(err) || attempt == 3 { break } wait := time.Duration(attempt*300) * time.Millisecond select { case <-ctx.Done(): break case <-time.After(wait): } } if rowsErr != nil { return nil, rowsErr } defer rows.Close() var out []models.ProductPricing for rows.Next() { var item models.ProductPricing if err := rows.Scan( &item.ProductCode, &item.CostPrice, &item.StockQty, &item.StockEntryDate, &item.LastPricingDate, &item.AskiliYan, &item.Kategori, &item.UrunIlkGrubu, &item.UrunAnaGrubu, &item.UrunAltGrubu, &item.Icerik, &item.Karisim, &item.Marka, ); err != nil { return nil, err } out = append(out, item) } return out, nil } func isTransientMSSQLNetworkError(err error) bool { if err == nil { return false } e := strings.ToLower(err.Error()) return strings.Contains(e, "i/o timeout") || strings.Contains(e, "timeout") || strings.Contains(e, "wsarecv") || strings.Contains(e, "connection attempt failed") || strings.Contains(e, "no connection could be made") || strings.Contains(e, "broken pipe") || strings.Contains(e, "connection reset") }