diff --git a/svc/queries/productstockquery_by_attributes.go b/svc/queries/productstockquery_by_attributes.go index 25a0ac9..f4aeeaa 100644 --- a/svc/queries/productstockquery_by_attributes.go +++ b/svc/queries/productstockquery_by_attributes.go @@ -5,13 +5,63 @@ package queries const GetProductStockAttributeOptionsQuery = ` DECLARE @Kategori NVARCHAR(100) = NULLIF(LTRIM(RTRIM(@p1)), ''); DECLARE @UrunAnaGrubu NVARCHAR(100) = NULLIF(LTRIM(RTRIM(@p2)), ''); -DECLARE @UrunAltGrubu NVARCHAR(100) = NULLIF(LTRIM(RTRIM(@p3)), ''); -DECLARE @Renk NVARCHAR(100) = NULLIF(LTRIM(RTRIM(@p4)), ''); -DECLARE @Renk2 NVARCHAR(100) = NULLIF(LTRIM(RTRIM(@p5)), ''); -DECLARE @UrunIcerigi NVARCHAR(100) = NULLIF(LTRIM(RTRIM(@p6)), ''); -DECLARE @Fit NVARCHAR(100) = NULLIF(LTRIM(RTRIM(@p7)), ''); -DECLARE @Drop NVARCHAR(100) = NULLIF(LTRIM(RTRIM(@p8)), ''); -DECLARE @Beden NVARCHAR(100) = NULLIF(LTRIM(RTRIM(@p9)), ''); +DECLARE @UrunAltGrubuList NVARCHAR(MAX) = NULLIF(LTRIM(RTRIM(@p3)), ''); +DECLARE @RenkList NVARCHAR(MAX) = NULLIF(LTRIM(RTRIM(@p4)), ''); +DECLARE @Renk2List NVARCHAR(MAX) = NULLIF(LTRIM(RTRIM(@p5)), ''); +DECLARE @UrunIcerigiList NVARCHAR(MAX) = NULLIF(LTRIM(RTRIM(@p6)), ''); +DECLARE @FitList NVARCHAR(MAX) = NULLIF(LTRIM(RTRIM(@p7)), ''); +DECLARE @DropList NVARCHAR(MAX) = NULLIF(LTRIM(RTRIM(@p8)), ''); +DECLARE @BedenList NVARCHAR(MAX) = NULLIF(LTRIM(RTRIM(@p9)), ''); + +DECLARE @SelUrunAltGrubu TABLE (Value NVARCHAR(100) PRIMARY KEY); +DECLARE @SelRenk TABLE (Value NVARCHAR(100) PRIMARY KEY); +DECLARE @SelRenk2 TABLE (Value NVARCHAR(100) PRIMARY KEY); +DECLARE @SelUrunIcerigi TABLE (Value NVARCHAR(100) PRIMARY KEY); +DECLARE @SelFit TABLE (Value NVARCHAR(100) PRIMARY KEY); +DECLARE @SelDrop TABLE (Value NVARCHAR(100) PRIMARY KEY); +DECLARE @SelBeden TABLE (Value NVARCHAR(100) PRIMARY KEY); + +IF @UrunAltGrubuList IS NOT NULL + INSERT INTO @SelUrunAltGrubu(Value) + SELECT DISTINCT LTRIM(RTRIM(value)) + FROM STRING_SPLIT(@UrunAltGrubuList, NCHAR(31)) + WHERE LTRIM(RTRIM(value)) <> ''; + +IF @RenkList IS NOT NULL + INSERT INTO @SelRenk(Value) + SELECT DISTINCT LTRIM(RTRIM(value)) + FROM STRING_SPLIT(@RenkList, NCHAR(31)) + WHERE LTRIM(RTRIM(value)) <> ''; + +IF @Renk2List IS NOT NULL + INSERT INTO @SelRenk2(Value) + SELECT DISTINCT LTRIM(RTRIM(value)) + FROM STRING_SPLIT(@Renk2List, NCHAR(31)) + WHERE LTRIM(RTRIM(value)) <> ''; + +IF @UrunIcerigiList IS NOT NULL + INSERT INTO @SelUrunIcerigi(Value) + SELECT DISTINCT LTRIM(RTRIM(value)) + FROM STRING_SPLIT(@UrunIcerigiList, NCHAR(31)) + WHERE LTRIM(RTRIM(value)) <> ''; + +IF @FitList IS NOT NULL + INSERT INTO @SelFit(Value) + SELECT DISTINCT LTRIM(RTRIM(value)) + FROM STRING_SPLIT(@FitList, NCHAR(31)) + WHERE LTRIM(RTRIM(value)) <> ''; + +IF @DropList IS NOT NULL + INSERT INTO @SelDrop(Value) + SELECT DISTINCT LTRIM(RTRIM(value)) + FROM STRING_SPLIT(@DropList, NCHAR(31)) + WHERE LTRIM(RTRIM(value)) <> ''; + +IF @BedenList IS NOT NULL + INSERT INTO @SelBeden(Value) + SELECT DISTINCT LTRIM(RTRIM(value)) + FROM STRING_SPLIT(@BedenList, NCHAR(31)) + WHERE LTRIM(RTRIM(value)) <> ''; CREATE TABLE #AttrBase ( @@ -39,10 +89,10 @@ BEGIN WHERE LEN(ProductCode) = 13 AND (@Kategori IS NULL OR ProductAtt44Desc = @Kategori) AND (@UrunAnaGrubu IS NULL OR ProductAtt01Desc = @UrunAnaGrubu) - AND (@UrunAltGrubu IS NULL OR ProductAtt02Desc = @UrunAltGrubu) - AND (@UrunIcerigi IS NULL OR ProductAtt41Desc = @UrunIcerigi) - AND (@Fit IS NULL OR ProductAtt38Desc = @Fit) - AND (@Drop IS NULL OR ProductAtt11Desc = @Drop); + AND (NOT EXISTS (SELECT 1 FROM @SelUrunAltGrubu) OR EXISTS (SELECT 1 FROM @SelUrunAltGrubu S WHERE S.Value = ProductAtt02Desc)) + AND (NOT EXISTS (SELECT 1 FROM @SelUrunIcerigi) OR EXISTS (SELECT 1 FROM @SelUrunIcerigi S WHERE S.Value = ProductAtt41Desc)) + AND (NOT EXISTS (SELECT 1 FROM @SelFit) OR EXISTS (SELECT 1 FROM @SelFit S WHERE S.Value = ProductAtt38Desc)) + AND (NOT EXISTS (SELECT 1 FROM @SelDrop) OR EXISTS (SELECT 1 FROM @SelDrop S WHERE S.Value = ProductAtt11Desc)); END ELSE BEGIN @@ -59,10 +109,10 @@ BEGIN WHERE LEN(ProductCode) = 13 AND (@Kategori IS NULL OR ProductAtt44Desc = @Kategori) AND (@UrunAnaGrubu IS NULL OR ProductAtt01Desc = @UrunAnaGrubu) - AND (@UrunAltGrubu IS NULL OR ProductAtt02Desc = @UrunAltGrubu) - AND (@UrunIcerigi IS NULL OR ProductAtt41Desc = @UrunIcerigi) - AND (@Fit IS NULL OR ProductAtt38Desc = @Fit) - AND (@Drop IS NULL OR ProductAtt11Desc = @Drop); + AND (NOT EXISTS (SELECT 1 FROM @SelUrunAltGrubu) OR EXISTS (SELECT 1 FROM @SelUrunAltGrubu S WHERE S.Value = ProductAtt02Desc)) + AND (NOT EXISTS (SELECT 1 FROM @SelUrunIcerigi) OR EXISTS (SELECT 1 FROM @SelUrunIcerigi S WHERE S.Value = ProductAtt41Desc)) + AND (NOT EXISTS (SELECT 1 FROM @SelFit) OR EXISTS (SELECT 1 FROM @SelFit S WHERE S.Value = ProductAtt38Desc)) + AND (NOT EXISTS (SELECT 1 FROM @SelDrop) OR EXISTS (SELECT 1 FROM @SelDrop S WHERE S.Value = ProductAtt11Desc)); END; IF @Kategori IS NULL OR @UrunAnaGrubu IS NULL @@ -184,12 +234,12 @@ FROM ( WHERE (CASE WHEN A.RenkAciklama <> '' THEN A.RenkAciklama ELSE A.Renk END) <> '' AND (@Kategori IS NULL OR AB.Kategori = @Kategori) AND (@UrunAnaGrubu IS NULL OR AB.UrunAnaGrubu = @UrunAnaGrubu) - AND (@UrunAltGrubu IS NULL OR AB.UrunAltGrubu = @UrunAltGrubu) - AND (@UrunIcerigi IS NULL OR AB.UrunIcerigi = @UrunIcerigi) - AND (@Fit IS NULL OR AB.Fit = @Fit) - AND (@Drop IS NULL OR AB.DropVal = @Drop) - AND (@Renk2 IS NULL OR A.Renk2 = @Renk2) - AND (@Beden IS NULL OR A.Beden = @Beden) + AND (NOT EXISTS (SELECT 1 FROM @SelUrunAltGrubu) OR EXISTS (SELECT 1 FROM @SelUrunAltGrubu S WHERE S.Value = AB.UrunAltGrubu)) + AND (NOT EXISTS (SELECT 1 FROM @SelUrunIcerigi) OR EXISTS (SELECT 1 FROM @SelUrunIcerigi S WHERE S.Value = AB.UrunIcerigi)) + AND (NOT EXISTS (SELECT 1 FROM @SelFit) OR EXISTS (SELECT 1 FROM @SelFit S WHERE S.Value = AB.Fit)) + AND (NOT EXISTS (SELECT 1 FROM @SelDrop) OR EXISTS (SELECT 1 FROM @SelDrop S WHERE S.Value = AB.DropVal)) + AND (NOT EXISTS (SELECT 1 FROM @SelRenk2) OR EXISTS (SELECT 1 FROM @SelRenk2 S WHERE S.Value = A.Renk2)) + AND (NOT EXISTS (SELECT 1 FROM @SelBeden) OR EXISTS (SELECT 1 FROM @SelBeden S WHERE S.Value = A.Beden)) ) X UNION ALL SELECT 'renk2', X.FieldValue @@ -200,12 +250,12 @@ FROM ( WHERE A.Renk2 <> '' AND (@Kategori IS NULL OR AB.Kategori = @Kategori) AND (@UrunAnaGrubu IS NULL OR AB.UrunAnaGrubu = @UrunAnaGrubu) - AND (@UrunAltGrubu IS NULL OR AB.UrunAltGrubu = @UrunAltGrubu) - AND (@UrunIcerigi IS NULL OR AB.UrunIcerigi = @UrunIcerigi) - AND (@Fit IS NULL OR AB.Fit = @Fit) - AND (@Drop IS NULL OR AB.DropVal = @Drop) - AND (@Renk IS NULL OR (CASE WHEN A.RenkAciklama <> '' THEN A.RenkAciklama ELSE A.Renk END) = @Renk) - AND (@Beden IS NULL OR A.Beden = @Beden) + AND (NOT EXISTS (SELECT 1 FROM @SelUrunAltGrubu) OR EXISTS (SELECT 1 FROM @SelUrunAltGrubu S WHERE S.Value = AB.UrunAltGrubu)) + AND (NOT EXISTS (SELECT 1 FROM @SelUrunIcerigi) OR EXISTS (SELECT 1 FROM @SelUrunIcerigi S WHERE S.Value = AB.UrunIcerigi)) + AND (NOT EXISTS (SELECT 1 FROM @SelFit) OR EXISTS (SELECT 1 FROM @SelFit S WHERE S.Value = AB.Fit)) + AND (NOT EXISTS (SELECT 1 FROM @SelDrop) OR EXISTS (SELECT 1 FROM @SelDrop S WHERE S.Value = AB.DropVal)) + AND (NOT EXISTS (SELECT 1 FROM @SelRenk) OR EXISTS (SELECT 1 FROM @SelRenk S WHERE S.Value = (CASE WHEN A.RenkAciklama <> '' THEN A.RenkAciklama ELSE A.Renk END))) + AND (NOT EXISTS (SELECT 1 FROM @SelBeden) OR EXISTS (SELECT 1 FROM @SelBeden S WHERE S.Value = A.Beden)) ) X UNION ALL SELECT 'urun_icerigi', X.FieldValue @@ -215,6 +265,7 @@ FROM ( WHERE AB.UrunIcerigi <> '' AND (@Kategori IS NULL OR AB.Kategori = @Kategori) AND (@UrunAnaGrubu IS NULL OR AB.UrunAnaGrubu = @UrunAnaGrubu) + AND (NOT EXISTS (SELECT 1 FROM @SelUrunAltGrubu) OR EXISTS (SELECT 1 FROM @SelUrunAltGrubu S WHERE S.Value = AB.UrunAltGrubu)) ) X UNION ALL SELECT 'fit', X.FieldValue @@ -224,6 +275,8 @@ FROM ( WHERE AB.Fit <> '' AND (@Kategori IS NULL OR AB.Kategori = @Kategori) AND (@UrunAnaGrubu IS NULL OR AB.UrunAnaGrubu = @UrunAnaGrubu) + AND (NOT EXISTS (SELECT 1 FROM @SelUrunAltGrubu) OR EXISTS (SELECT 1 FROM @SelUrunAltGrubu S WHERE S.Value = AB.UrunAltGrubu)) + AND (NOT EXISTS (SELECT 1 FROM @SelUrunIcerigi) OR EXISTS (SELECT 1 FROM @SelUrunIcerigi S WHERE S.Value = AB.UrunIcerigi)) ) X UNION ALL SELECT 'drop', X.FieldValue @@ -233,6 +286,9 @@ FROM ( WHERE AB.DropVal <> '' AND (@Kategori IS NULL OR AB.Kategori = @Kategori) AND (@UrunAnaGrubu IS NULL OR AB.UrunAnaGrubu = @UrunAnaGrubu) + AND (NOT EXISTS (SELECT 1 FROM @SelUrunAltGrubu) OR EXISTS (SELECT 1 FROM @SelUrunAltGrubu S WHERE S.Value = AB.UrunAltGrubu)) + AND (NOT EXISTS (SELECT 1 FROM @SelUrunIcerigi) OR EXISTS (SELECT 1 FROM @SelUrunIcerigi S WHERE S.Value = AB.UrunIcerigi)) + AND (NOT EXISTS (SELECT 1 FROM @SelFit) OR EXISTS (SELECT 1 FROM @SelFit S WHERE S.Value = AB.Fit)) ) X UNION ALL SELECT 'beden', X.FieldValue @@ -243,12 +299,12 @@ FROM ( WHERE A.Beden <> '' AND (@Kategori IS NULL OR AB.Kategori = @Kategori) AND (@UrunAnaGrubu IS NULL OR AB.UrunAnaGrubu = @UrunAnaGrubu) - AND (@UrunAltGrubu IS NULL OR AB.UrunAltGrubu = @UrunAltGrubu) - AND (@UrunIcerigi IS NULL OR AB.UrunIcerigi = @UrunIcerigi) - AND (@Fit IS NULL OR AB.Fit = @Fit) - AND (@Drop IS NULL OR AB.DropVal = @Drop) - AND (@Renk IS NULL OR (CASE WHEN A.RenkAciklama <> '' THEN A.RenkAciklama ELSE A.Renk END) = @Renk) - AND (@Renk2 IS NULL OR A.Renk2 = @Renk2) + AND (NOT EXISTS (SELECT 1 FROM @SelUrunAltGrubu) OR EXISTS (SELECT 1 FROM @SelUrunAltGrubu S WHERE S.Value = AB.UrunAltGrubu)) + AND (NOT EXISTS (SELECT 1 FROM @SelUrunIcerigi) OR EXISTS (SELECT 1 FROM @SelUrunIcerigi S WHERE S.Value = AB.UrunIcerigi)) + AND (NOT EXISTS (SELECT 1 FROM @SelFit) OR EXISTS (SELECT 1 FROM @SelFit S WHERE S.Value = AB.Fit)) + AND (NOT EXISTS (SELECT 1 FROM @SelDrop) OR EXISTS (SELECT 1 FROM @SelDrop S WHERE S.Value = AB.DropVal)) + AND (NOT EXISTS (SELECT 1 FROM @SelRenk) OR EXISTS (SELECT 1 FROM @SelRenk S WHERE S.Value = (CASE WHEN A.RenkAciklama <> '' THEN A.RenkAciklama ELSE A.Renk END))) + AND (NOT EXISTS (SELECT 1 FROM @SelRenk2) OR EXISTS (SELECT 1 FROM @SelRenk2 S WHERE S.Value = A.Renk2)) ) X OPTION (RECOMPILE); ` @@ -258,13 +314,63 @@ OPTION (RECOMPILE); const GetProductStockQueryByAttributes = ` DECLARE @Kategori NVARCHAR(100) = NULLIF(LTRIM(RTRIM(@p1)), ''); DECLARE @UrunAnaGrubu NVARCHAR(100) = NULLIF(LTRIM(RTRIM(@p2)), ''); -DECLARE @UrunAltGrubu NVARCHAR(100) = NULLIF(LTRIM(RTRIM(@p3)), ''); -DECLARE @Renk NVARCHAR(100) = NULLIF(LTRIM(RTRIM(@p4)), ''); -DECLARE @Renk2 NVARCHAR(100) = NULLIF(LTRIM(RTRIM(@p5)), ''); -DECLARE @UrunIcerigi NVARCHAR(100) = NULLIF(LTRIM(RTRIM(@p6)), ''); -DECLARE @Fit NVARCHAR(100) = NULLIF(LTRIM(RTRIM(@p7)), ''); -DECLARE @Drop NVARCHAR(100) = NULLIF(LTRIM(RTRIM(@p8)), ''); -DECLARE @Beden NVARCHAR(100) = NULLIF(LTRIM(RTRIM(@p9)), ''); +DECLARE @UrunAltGrubuList NVARCHAR(MAX) = NULLIF(LTRIM(RTRIM(@p3)), ''); +DECLARE @RenkList NVARCHAR(MAX) = NULLIF(LTRIM(RTRIM(@p4)), ''); +DECLARE @Renk2List NVARCHAR(MAX) = NULLIF(LTRIM(RTRIM(@p5)), ''); +DECLARE @UrunIcerigiList NVARCHAR(MAX) = NULLIF(LTRIM(RTRIM(@p6)), ''); +DECLARE @FitList NVARCHAR(MAX) = NULLIF(LTRIM(RTRIM(@p7)), ''); +DECLARE @DropList NVARCHAR(MAX) = NULLIF(LTRIM(RTRIM(@p8)), ''); +DECLARE @BedenList NVARCHAR(MAX) = NULLIF(LTRIM(RTRIM(@p9)), ''); + +DECLARE @SelUrunAltGrubu TABLE (Value NVARCHAR(100) PRIMARY KEY); +DECLARE @SelRenk TABLE (Value NVARCHAR(100) PRIMARY KEY); +DECLARE @SelRenk2 TABLE (Value NVARCHAR(100) PRIMARY KEY); +DECLARE @SelUrunIcerigi TABLE (Value NVARCHAR(100) PRIMARY KEY); +DECLARE @SelFit TABLE (Value NVARCHAR(100) PRIMARY KEY); +DECLARE @SelDrop TABLE (Value NVARCHAR(100) PRIMARY KEY); +DECLARE @SelBeden TABLE (Value NVARCHAR(100) PRIMARY KEY); + +IF @UrunAltGrubuList IS NOT NULL + INSERT INTO @SelUrunAltGrubu(Value) + SELECT DISTINCT LTRIM(RTRIM(value)) + FROM STRING_SPLIT(@UrunAltGrubuList, NCHAR(31)) + WHERE LTRIM(RTRIM(value)) <> ''; + +IF @RenkList IS NOT NULL + INSERT INTO @SelRenk(Value) + SELECT DISTINCT LTRIM(RTRIM(value)) + FROM STRING_SPLIT(@RenkList, NCHAR(31)) + WHERE LTRIM(RTRIM(value)) <> ''; + +IF @Renk2List IS NOT NULL + INSERT INTO @SelRenk2(Value) + SELECT DISTINCT LTRIM(RTRIM(value)) + FROM STRING_SPLIT(@Renk2List, NCHAR(31)) + WHERE LTRIM(RTRIM(value)) <> ''; + +IF @UrunIcerigiList IS NOT NULL + INSERT INTO @SelUrunIcerigi(Value) + SELECT DISTINCT LTRIM(RTRIM(value)) + FROM STRING_SPLIT(@UrunIcerigiList, NCHAR(31)) + WHERE LTRIM(RTRIM(value)) <> ''; + +IF @FitList IS NOT NULL + INSERT INTO @SelFit(Value) + SELECT DISTINCT LTRIM(RTRIM(value)) + FROM STRING_SPLIT(@FitList, NCHAR(31)) + WHERE LTRIM(RTRIM(value)) <> ''; + +IF @DropList IS NOT NULL + INSERT INTO @SelDrop(Value) + SELECT DISTINCT LTRIM(RTRIM(value)) + FROM STRING_SPLIT(@DropList, NCHAR(31)) + WHERE LTRIM(RTRIM(value)) <> ''; + +IF @BedenList IS NOT NULL + INSERT INTO @SelBeden(Value) + SELECT DISTINCT LTRIM(RTRIM(value)) + FROM STRING_SPLIT(@BedenList, NCHAR(31)) + WHERE LTRIM(RTRIM(value)) <> ''; CREATE TABLE #AttrFiltered ( @@ -376,10 +482,10 @@ BEGIN WHERE LEN(C.ProductCode) = 13 AND (@Kategori IS NULL OR C.ProductAtt44Desc = @Kategori) AND (@UrunAnaGrubu IS NULL OR C.ProductAtt01Desc = @UrunAnaGrubu) - AND (@UrunAltGrubu IS NULL OR C.ProductAtt02Desc = @UrunAltGrubu) - AND (@UrunIcerigi IS NULL OR C.ProductAtt41Desc = @UrunIcerigi) - AND (@Fit IS NULL OR C.ProductAtt38Desc = @Fit) - AND (@Drop IS NULL OR C.ProductAtt11Desc = @Drop); + AND (NOT EXISTS (SELECT 1 FROM @SelUrunAltGrubu) OR EXISTS (SELECT 1 FROM @SelUrunAltGrubu S WHERE S.Value = C.ProductAtt02Desc)) + AND (NOT EXISTS (SELECT 1 FROM @SelUrunIcerigi) OR EXISTS (SELECT 1 FROM @SelUrunIcerigi S WHERE S.Value = C.ProductAtt41Desc)) + AND (NOT EXISTS (SELECT 1 FROM @SelFit) OR EXISTS (SELECT 1 FROM @SelFit S WHERE S.Value = C.ProductAtt38Desc)) + AND (NOT EXISTS (SELECT 1 FROM @SelDrop) OR EXISTS (SELECT 1 FROM @SelDrop S WHERE S.Value = C.ProductAtt11Desc)); END ELSE BEGIN @@ -455,10 +561,10 @@ BEGIN WHERE LEN(ProductCode) = 13 AND (@Kategori IS NULL OR ProductAtt44Desc = @Kategori) AND (@UrunAnaGrubu IS NULL OR ProductAtt01Desc = @UrunAnaGrubu) - AND (@UrunAltGrubu IS NULL OR ProductAtt02Desc = @UrunAltGrubu) - AND (@UrunIcerigi IS NULL OR ProductAtt41Desc = @UrunIcerigi) - AND (@Fit IS NULL OR ProductAtt38Desc = @Fit) - AND (@Drop IS NULL OR ProductAtt11Desc = @Drop); + AND (NOT EXISTS (SELECT 1 FROM @SelUrunAltGrubu) OR EXISTS (SELECT 1 FROM @SelUrunAltGrubu S WHERE S.Value = ProductAtt02Desc)) + AND (NOT EXISTS (SELECT 1 FROM @SelUrunIcerigi) OR EXISTS (SELECT 1 FROM @SelUrunIcerigi S WHERE S.Value = ProductAtt41Desc)) + AND (NOT EXISTS (SELECT 1 FROM @SelFit) OR EXISTS (SELECT 1 FROM @SelFit S WHERE S.Value = ProductAtt38Desc)) + AND (NOT EXISTS (SELECT 1 FROM @SelDrop) OR EXISTS (SELECT 1 FROM @SelDrop S WHERE S.Value = ProductAtt11Desc)); END; CREATE CLUSTERED INDEX IX_AttrFiltered_ProductCode ON #AttrFiltered(ProductCode); @@ -598,17 +704,17 @@ Grouped AS A.ItemDim2Code FROM Avail A INNER JOIN #AttrFiltered AF ON AF.ProductCode = A.ItemCode - WHERE (@Renk IS NULL OR (CASE WHEN A.RenkAciklama <> '' THEN A.RenkAciklama ELSE A.ColorCode END) = @Renk) - AND (@Renk2 IS NULL OR A.ItemDim2Code = @Renk2) + WHERE (NOT EXISTS (SELECT 1 FROM @SelRenk) OR EXISTS (SELECT 1 FROM @SelRenk S WHERE S.Value = (CASE WHEN A.RenkAciklama <> '' THEN A.RenkAciklama ELSE A.ColorCode END))) + AND (NOT EXISTS (SELECT 1 FROM @SelRenk2) OR EXISTS (SELECT 1 FROM @SelRenk2 S WHERE S.Value = A.ItemDim2Code)) AND ( - @Beden IS NULL + NOT EXISTS (SELECT 1 FROM @SelBeden) OR EXISTS ( SELECT 1 FROM Avail AB WHERE AB.ItemCode = A.ItemCode AND AB.ColorCode = A.ColorCode AND ISNULL(AB.ItemDim2Code, '') = ISNULL(A.ItemDim2Code, '') - AND AB.ItemDim1Code = @Beden + AND EXISTS (SELECT 1 FROM @SelBeden SB WHERE SB.Value = AB.ItemDim1Code) ) ) GROUP BY A.ItemCode, A.ColorCode, A.ItemDim2Code diff --git a/svc/routes/product_images.go b/svc/routes/product_images.go index 61d3f77..b4f366e 100644 --- a/svc/routes/product_images.go +++ b/svc/routes/product_images.go @@ -209,6 +209,11 @@ WHERE typ='img' } query += ` ORDER BY + CASE + WHEN COALESCE(file_name,'') ~* 'gallery[-_ ]*1' THEN 0 + WHEN COALESCE(file_name,'') ~* '\(1\)(\.[A-Za-z0-9]+)?$' THEN 0 + ELSE 1 + END, COALESCE(sort_order,999999), zlins_dttm DESC, id DESC` diff --git a/svc/routes/product_stock_query_by_attributes.go b/svc/routes/product_stock_query_by_attributes.go index 42cc8eb..50f13be 100644 --- a/svc/routes/product_stock_query_by_attributes.go +++ b/svc/routes/product_stock_query_by_attributes.go @@ -7,23 +7,39 @@ import ( "encoding/json" "log" "net/http" + "net/url" "strings" "time" ) -func readStockAttrFilters(r *http.Request) (kategori, urunAnaGrubu, urunAltGrubu, renk, renk2, urunIcerigi, fit, drop, beden string) { +const filterValueSeparator = "\x1f" + +type stockAttrFilters struct { + kategori string + urunAnaGrubu string + urunAltGrubu []string + renk []string + renk2 []string + urunIcerigi []string + fit []string + drop []string + beden []string +} + +func readStockAttrFilters(r *http.Request) stockAttrFilters { q := r.URL.Query() - kategori = strings.TrimSpace(firstNonEmpty(q.Get("kategori"), q.Get("att44"))) - urunAnaGrubu = strings.TrimSpace(firstNonEmpty(q.Get("urun_ana_grubu"), q.Get("att01"))) - urunAltGrubu = strings.TrimSpace(firstNonEmpty(q.Get("urun_alt_grubu"), q.Get("att02"))) - renk = strings.TrimSpace(q.Get("renk")) - renk2 = strings.TrimSpace(firstNonEmpty(q.Get("renk2"), q.Get("yaka"))) - urunIcerigi = strings.TrimSpace(firstNonEmpty(q.Get("urun_icerigi"), q.Get("att41"))) - fit = strings.TrimSpace(firstNonEmpty(q.Get("fit"), q.Get("att38"))) - drop = strings.TrimSpace(firstNonEmpty(q.Get("drop"), q.Get("att11"))) - beden = strings.TrimSpace(q.Get("beden")) - return + return stockAttrFilters{ + kategori: readSingleFilter(q, "kategori", "att44"), + urunAnaGrubu: readSingleFilter(q, "urun_ana_grubu", "att01"), + urunAltGrubu: readMultiFilter(q, "urun_alt_grubu", "att02"), + renk: readMultiFilter(q, "renk"), + renk2: readMultiFilter(q, "renk2", "yaka"), + urunIcerigi: readMultiFilter(q, "urun_icerigi", "att41"), + fit: readMultiFilter(q, "fit", "att38"), + drop: readMultiFilter(q, "drop", "att11"), + beden: readMultiFilter(q, "beden"), + } } func firstNonEmpty(vals ...string) string { @@ -35,10 +51,66 @@ func firstNonEmpty(vals ...string) string { return "" } +func readSingleFilter(q url.Values, keys ...string) string { + for _, k := range keys { + for _, raw := range q[k] { + if v := strings.TrimSpace(raw); v != "" { + return v + } + } + } + return "" +} + +func splitFilterToken(raw string) []string { + raw = strings.TrimSpace(raw) + if raw == "" { + return nil + } + r := strings.NewReplacer( + filterValueSeparator, ",", + ";", ",", + ) + normalized := r.Replace(raw) + parts := strings.Split(normalized, ",") + out := make([]string, 0, len(parts)) + for _, p := range parts { + v := strings.TrimSpace(p) + if v != "" { + out = append(out, v) + } + } + return out +} + +func readMultiFilter(q url.Values, keys ...string) []string { + seen := make(map[string]struct{}, 8) + out := make([]string, 0, 8) + for _, k := range keys { + for _, raw := range q[k] { + for _, token := range splitFilterToken(raw) { + if _, ok := seen[token]; ok { + continue + } + seen[token] = struct{}{} + out = append(out, token) + } + } + } + return out +} + +func joinFilterValues(values []string) string { + if len(values) == 0 { + return "" + } + return strings.Join(values, filterValueSeparator) +} + // GetProductStockAttributeOptionsHandler // GET /api/product-stock-attribute-options func GetProductStockAttributeOptionsHandler(w http.ResponseWriter, r *http.Request) { - kategori, urunAnaGrubu, urunAltGrubu, renk, renk2, urunIcerigi, fit, drop, beden := readStockAttrFilters(r) + f := readStockAttrFilters(r) ctx, cancel := context.WithTimeout(context.Background(), 120*time.Second) defer cancel() @@ -46,15 +118,15 @@ func GetProductStockAttributeOptionsHandler(w http.ResponseWriter, r *http.Reque rows, err := db.MssqlDB.QueryContext( ctx, queries.GetProductStockAttributeOptionsQuery, - kategori, - urunAnaGrubu, - urunAltGrubu, - renk, - renk2, - urunIcerigi, - fit, - drop, - beden, + f.kategori, + f.urunAnaGrubu, + joinFilterValues(f.urunAltGrubu), + joinFilterValues(f.renk), + joinFilterValues(f.renk2), + joinFilterValues(f.urunIcerigi), + joinFilterValues(f.fit), + joinFilterValues(f.drop), + joinFilterValues(f.beden), ) if err != nil { log.Printf("[PRODUCT-STOCK-ATTR-OPTIONS] SQL hatasi: %v", err) @@ -100,9 +172,9 @@ func GetProductStockAttributeOptionsHandler(w http.ResponseWriter, r *http.Reque // GetProductStockQueryByAttributesHandler // GET /api/product-stock-query-by-attributes func GetProductStockQueryByAttributesHandler(w http.ResponseWriter, r *http.Request) { - kategori, urunAnaGrubu, urunAltGrubu, renk, renk2, urunIcerigi, fit, drop, beden := readStockAttrFilters(r) + f := readStockAttrFilters(r) - if kategori == "" || urunAnaGrubu == "" { + if f.kategori == "" || f.urunAnaGrubu == "" { http.Error(w, "Kategori ve Urun Ana Grubu secimi zorunludur", http.StatusBadRequest) return } @@ -112,21 +184,21 @@ func GetProductStockQueryByAttributesHandler(w http.ResponseWriter, r *http.Requ defer cancel() log.Printf( "[PRODUCT-STOCK-BY-ATTRS] request kategori=%q urun_ana_grubu=%q urun_alt_grubu=%q renk=%q renk2=%q urun_icerigi=%q fit=%q drop=%q beden=%q", - kategori, urunAnaGrubu, urunAltGrubu, renk, renk2, urunIcerigi, fit, drop, beden, + f.kategori, f.urunAnaGrubu, strings.Join(f.urunAltGrubu, ","), strings.Join(f.renk, ","), strings.Join(f.renk2, ","), strings.Join(f.urunIcerigi, ","), strings.Join(f.fit, ","), strings.Join(f.drop, ","), strings.Join(f.beden, ","), ) rows, err := db.MssqlDB.QueryContext( ctx, queries.GetProductStockQueryByAttributes, - kategori, - urunAnaGrubu, - urunAltGrubu, - renk, - renk2, - urunIcerigi, - fit, - drop, - beden, + f.kategori, + f.urunAnaGrubu, + joinFilterValues(f.urunAltGrubu), + joinFilterValues(f.renk), + joinFilterValues(f.renk2), + joinFilterValues(f.urunIcerigi), + joinFilterValues(f.fit), + joinFilterValues(f.drop), + joinFilterValues(f.beden), ) if err != nil { log.Printf("[PRODUCT-STOCK-BY-ATTRS] SQL hatasi: %v", err) diff --git a/ui/src/pages/ProductStockByAttributes.vue b/ui/src/pages/ProductStockByAttributes.vue index d24e264..c7cab18 100644 --- a/ui/src/pages/ProductStockByAttributes.vue +++ b/ui/src/pages/ProductStockByAttributes.vue @@ -15,17 +15,30 @@ v-model="filters[def.key]" :options="filteredOptionLists[def.key] || []" :label="def.label" + :multiple="isMultiFilter(def.key)" + :use-chips="isMultiFilter(def.key)" filled dense clearable use-input + use-selected input-debounce="250" :disable="isFilterDisabled(def.key)" :loading="loadingFilterOptions" @update:model-value="onFilterValueChange(def.key)" @filter="(val, update) => filterOptions(def.key, val, update)" @keyup.enter="fetchStockByAttributes" - /> + > + +
@@ -389,21 +402,16 @@ const filterDefs = [ { key: 'drop', label: 'Drop' }, { key: 'beden', label: 'Beden' } ] +const singleSelectFilterKeys = new Set(['kategori', 'urun_ana_grubu']) +const multiSelectFilterKeys = new Set( + filterDefs.map((def) => def.key).filter((key) => !singleSelectFilterKeys.has(key)) +) +const filterValueSeparator = '\u001f' const loadingFilterOptions = ref(false) const loadingStock = ref(false) const errorMessage = ref('') -const filters = ref({ - kategori: '', - urun_ana_grubu: '', - urun_alt_grubu: '', - renk: '', - renk2: '', - urun_icerigi: '', - fit: '', - drop: '', - beden: '' -}) +const filters = ref(createEmptyFilters()) const optionLists = ref({}) const filteredOptionLists = ref({}) const filterOptionsCache = ref({}) @@ -442,8 +450,8 @@ const activeSchema = ref(storeSchemaByKey.tak) const activeGrpKey = ref('tak') const openState = ref({}) const canQuery = computed(() => - String(filters.value?.kategori || '').trim() !== '' && - String(filters.value?.urun_ana_grubu || '').trim() !== '' + normalizeFilterScalar(filters.value?.kategori) !== '' && + normalizeFilterScalar(filters.value?.urun_ana_grubu) !== '' ) const sizeLabels = computed(() => activeSchema.value?.values || []) @@ -654,6 +662,8 @@ function resolveProductImageUrl(item) { function extractImageOrder(fileName, fallbackIndex) { const name = String(fileName || '').trim() + const mg = name.match(/gallery[-_\s]?(\d+)/i) + if (mg) return Number(mg[1] || 999999) const m = name.match(/\((\d+)\)(?=\.[a-z0-9]+$)/i) if (m) return Number(m[1] || 999999) const m2 = name.match(/[-_ ](\d+)(?=\.[a-z0-9]+$)/i) @@ -759,8 +769,9 @@ async function ensureProductImage(code, color, secondColor = '', dim1Id = '', di } } const rawList = Array.isArray(productImageListByCode.value[listKey]) ? productImageListByCode.value[listKey] : [] - const primaryItem = rawList[0] || null - const secondaryItem = rawList.length > 1 ? rawList[rawList.length - 1] : null + const sortedList = sortImagesForDisplay(rawList) + const primaryItem = sortedList[0] || null + const secondaryItem = sortedList.length > 1 ? sortedList[sortedList.length - 1] : null const primaryResolved = resolveProductImageUrl(primaryItem) let preferredCardUrl = primaryItem ? await resolveProductImageUrlForCarousel(primaryItem) : '' @@ -992,14 +1003,51 @@ const level1Groups = computed(() => { .sort(sortByTotalQtyDesc) }) -function normalizeText(v) { - return String(v || '').trim() +function createEmptyFilters() { + return { + kategori: '', + urun_ana_grubu: '', + urun_alt_grubu: [], + renk: [], + renk2: [], + urun_icerigi: [], + fit: [], + drop: [], + beden: [] + } } -function buildFilterParams() { +function isMultiFilter(key) { + return multiSelectFilterKeys.has(key) +} + +function normalizeFilterScalar(v) { + return String(v ?? '').trim() +} + +function normalizeFilterList(v) { + const src = Array.isArray(v) ? v : (normalizeFilterScalar(v) ? [v] : []) + const out = [] + const seen = new Set() + for (const item of src) { + const val = normalizeFilterScalar(item) + if (!val || seen.has(val)) continue + seen.add(val) + out.push(val) + } + return out +} + +function buildFilterParams(excludeKey = '') { const out = {} for (const def of filterDefs) { - const val = normalizeText(filters.value?.[def.key]) + if (excludeKey && def.key === excludeKey) continue + if (isMultiFilter(def.key)) { + const vals = normalizeFilterList(filters.value?.[def.key]) + if (vals.length) out[def.key] = vals.join(filterValueSeparator) + continue + } + const val = normalizeFilterScalar(filters.value?.[def.key]) if (val) out[def.key] = val } return out @@ -1013,7 +1061,7 @@ function buildFilterCacheKey(params) { function isFilterDisabled(key) { if (key === 'kategori') return false if (key === 'urun_ana_grubu') { - return normalizeText(filters.value.kategori) === '' + return normalizeFilterScalar(filters.value.kategori) === '' } return !canQuery.value } @@ -1021,33 +1069,34 @@ function isFilterDisabled(key) { function onFilterValueChange(changedKey) { if (changedKey === 'kategori') { filters.value.urun_ana_grubu = '' - filters.value.urun_alt_grubu = '' - filters.value.renk = '' - filters.value.renk2 = '' - filters.value.urun_icerigi = '' - filters.value.fit = '' - filters.value.drop = '' - filters.value.beden = '' + filters.value.urun_alt_grubu = [] + filters.value.renk = [] + filters.value.renk2 = [] + filters.value.urun_icerigi = [] + filters.value.fit = [] + filters.value.drop = [] + filters.value.beden = [] } else if (changedKey === 'urun_ana_grubu') { - filters.value.urun_alt_grubu = '' - filters.value.renk = '' - filters.value.renk2 = '' - filters.value.urun_icerigi = '' - filters.value.fit = '' - filters.value.drop = '' - filters.value.beden = '' + filters.value.urun_alt_grubu = [] + filters.value.renk = [] + filters.value.renk2 = [] + filters.value.urun_icerigi = [] + filters.value.fit = [] + filters.value.drop = [] + filters.value.beden = [] } else if (changedKey === 'renk') { - filters.value.renk2 = '' - filters.value.beden = '' + filters.value.renk2 = [] + filters.value.beden = [] } else if (changedKey === 'renk2') { - filters.value.beden = '' + filters.value.beden = [] } if (filterOptionsDebounceTimer) { clearTimeout(filterOptionsDebounceTimer) } + const excludeKey = isMultiFilter(changedKey) ? changedKey : '' filterOptionsDebounceTimer = setTimeout(() => { - void loadFilterOptions() + void loadFilterOptions(false, excludeKey) }, FILTER_OPTIONS_DEBOUNCE_MS) } @@ -1069,8 +1118,21 @@ function filterOptions(field, val, update) { }) } -async function loadFilterOptions(force = false) { - const params = buildFilterParams() +function selectAllFilterOptions(key) { + if (!isMultiFilter(key) || isFilterDisabled(key)) return + const list = Array.isArray(optionLists.value?.[key]) ? optionLists.value[key] : [] + filters.value[key] = [...list] + onFilterValueChange(key) +} + +function clearAllFilterOptions(key) { + if (!isMultiFilter(key) || isFilterDisabled(key)) return + filters.value[key] = [] + onFilterValueChange(key) +} + +async function loadFilterOptions(force = false, excludeKey = '') { + const params = buildFilterParams(excludeKey) const cacheKey = buildFilterCacheKey(params) const now = Date.now() if (!force) { @@ -1102,9 +1164,14 @@ async function loadFilterOptions(force = false) { next[def.key] = list nextFiltered[def.key] = [...list] - const selected = normalizeText(filters.value?.[def.key]) - if (selected && !list.includes(selected)) { - filters.value[def.key] = '' + if (isMultiFilter(def.key)) { + const selectedList = normalizeFilterList(filters.value?.[def.key]) + filters.value[def.key] = selectedList.filter((v) => list.includes(v)) + } else { + const selected = normalizeFilterScalar(filters.value?.[def.key]) + if (selected && !list.includes(selected)) { + filters.value[def.key] = '' + } } } @@ -1359,17 +1426,7 @@ function onFullscreenSlideChange() { } function resetForm() { - filters.value = { - kategori: '', - urun_ana_grubu: '', - urun_alt_grubu: '', - renk: '', - renk2: '', - urun_icerigi: '', - fit: '', - drop: '', - beden: '' - } + filters.value = createEmptyFilters() rawRows.value = [] errorMessage.value = '' openState.value = {}