From 539ca4b5873d0db7992ebf5dca59fa3b1b0ef363 Mon Sep 17 00:00:00 2001 From: M_Kececi Date: Fri, 19 Jun 2026 14:46:32 +0300 Subject: [PATCH] Merge remote-tracking branch 'origin/master' --- svc/routes/product_pricing_save.go | 25 +++++++++++++++++++++++++ svc/routes/wholesale_campaigns.go | 12 ++++++++++++ ui/src/pages/OrderPriceList.vue | 11 +++++++++++ ui/src/pages/ProductPricing.vue | 9 +++++++++ ui/src/pages/WholesaleCampaigns.vue | 9 +++++++++ 5 files changed, 66 insertions(+) diff --git a/svc/routes/product_pricing_save.go b/svc/routes/product_pricing_save.go index ba9ead1..4c9ec24 100644 --- a/svc/routes/product_pricing_save.go +++ b/svc/routes/product_pricing_save.go @@ -384,6 +384,25 @@ WHERE is_active = TRUE Dim3 sql.NullInt64 } + hasDim3Combo := func(dims []dimCombo) bool { + for _, d := range dims { + if d.Dim3.Valid && d.Dim3.Int64 > 0 { + return true + } + } + return false + } + + filterDim3Combos := func(dims []dimCombo) []dimCombo { + out := make([]dimCombo, 0, len(dims)) + for _, d := range dims { + if d.Dim3.Valid && d.Dim3.Int64 > 0 { + out = append(out, d) + } + } + return out + } + type sdprcWriteRow struct { Currency string `json:"currency"` SdprcGrpID int `json:"sdprcgrp_id"` @@ -578,6 +597,9 @@ DO UPDATE SET dim_id = EXCLUDED.dim_id, updated_at = EXCLUDED.updated_at d3 = sql.NullInt64{Int64: id, Valid: true} resolvedDim3++ } + if strings.TrimSpace(dim3Code) != "" && !d3.Valid { + continue + } key := fmt.Sprintf("%d|%d", d1, func() int64 { if d3.Valid { return d3.Int64 @@ -1071,6 +1093,9 @@ VALUES ( if d, err := loadDimsFromMssqlStock(code); err != nil { logger.Error("save:pg:dims:mssql:error", "product_code", code, "err", err) } else if len(d) > 0 { + if hasDim3Combo(d) { + dims = filterDim3Combos(dims) + } seenDims := make(map[string]struct{}, len(dims)+len(d)) merged := make([]dimCombo, 0, len(dims)+len(d)) dim3Value := func(v sql.NullInt64) int64 { diff --git a/svc/routes/wholesale_campaigns.go b/svc/routes/wholesale_campaigns.go index f6cce74..0014042 100644 --- a/svc/routes/wholesale_campaigns.go +++ b/svc/routes/wholesale_campaigns.go @@ -1039,6 +1039,7 @@ DO UPDATE SET dim_id = EXCLUDED.dim_id, updated_at = EXCLUDED.updated_at msVariants := make([]msVariantRow, 0, 1024) colorTokensByItem := make(map[int64][]string, len(itemIDs)) dim3TokensByItem := make(map[int64][]string, len(itemIDs)) + itemHasMssqlDim3 := make(map[int64]bool, len(itemIDs)) for msRows.Next() { var itemCode, colorCode, dim1Code, dim3Code string var qty sql.NullFloat64 @@ -1064,6 +1065,9 @@ DO UPDATE SET dim_id = EXCLUDED.dim_id, updated_at = EXCLUDED.updated_at }) addToken(colorTokensByItem, itemID, colorCode) addToken(dim3TokensByItem, itemID, dim3Code) + if strings.TrimSpace(dim3Code) != "" { + itemHasMssqlDim3[itemID] = true + } } if err := msRows.Err(); err != nil { msRows.Close() @@ -1074,6 +1078,11 @@ DO UPDATE SET dim_id = EXCLUDED.dim_id, updated_at = EXCLUDED.updated_at inferredDim1 := buildInferredMap("dimval1", colorTokensByItem, itemDim1Candidates) inferredDim3 := buildInferredMap("dimval3", dim3TokensByItem, itemDim3Candidates) + for key, row := range tmpMap { + if itemHasMssqlDim3[row.ItemID] && row.Dim3Key == 0 { + delete(tmpMap, key) + } + } resolveProductDimID := func(itemID int64, column string, token string, inferred map[string]int64) (int64, bool) { token = strings.ToUpper(normalizeDimParam(token)) if token == "" { @@ -1113,6 +1122,9 @@ DO UPDATE SET dim_id = EXCLUDED.dim_id, updated_at = EXCLUDED.updated_at if id, ok := resolveProductDimID(itemID, "dimval3", dim3Code, inferredDim3); ok { d3k = id } + if strings.TrimSpace(dim3Code) != "" && d3k <= 0 { + continue + } key := fmt.Sprintf("%d|%d|%d", itemID, d1, d3k) prev, ok := tmpMap[key] if !ok { diff --git a/ui/src/pages/OrderPriceList.vue b/ui/src/pages/OrderPriceList.vue index 1e2200f..70c291e 100644 --- a/ui/src/pages/OrderPriceList.vue +++ b/ui/src/pages/OrderPriceList.vue @@ -104,6 +104,13 @@ :disable="pageBusy" @click="leftDetailsExpanded = !leftDetailsExpanded" /> +
@@ -641,6 +648,7 @@ const columnFilters = ref({}) const columnFilterSearch = ref({}) const selectedPriceOptions = ref(['usd5', 'try5']) const leftDetailsExpanded = ref(true) +const showInStockOnly = ref(false) const rows = ref([]) const loading = ref(false) @@ -1262,6 +1270,9 @@ const filteredRows = computed(() => { const variantSet = selectedVariantCodeSet.value const localFilters = columnFilters.value || {} let list = rows.value || [] + if (showInStockOnly.value) { + list = list.filter((row) => Number(row?.stockQty ?? 0) > 0) + } if (campaignSet.size > 0) { list = list.filter((row) => campaignSet.has(toText(row?.campaignLabel))) } diff --git a/ui/src/pages/ProductPricing.vue b/ui/src/pages/ProductPricing.vue index b725253..f84ee23 100644 --- a/ui/src/pages/ProductPricing.vue +++ b/ui/src/pages/ProductPricing.vue @@ -106,6 +106,13 @@ +
@@ -1245,6 +1252,7 @@ const selectedCurrencies = ref(['USD', 'EUR', 'TRY']) const exportAllLoading = ref(false) const showSelectedOnly = ref(false) const leftDetailsExpanded = ref(true) +const showInStockOnly = ref(false) const calcLoadingMap = ref({}) const bulkCalcLoading = ref(false) const saving = ref(false) @@ -1528,6 +1536,7 @@ function rowSelectionKey (row) { const filteredRows = computed(() => { return rows.value.filter((row) => { if (showSelectedOnly.value && !selectedMap.value[rowSelectionKey(row)]) return false + if (showInStockOnly.value && Number(row?.stockQty ?? 0) <= 0) return false for (const { field } of multiFilterColumns) { // Server-backed filters already reload full dataset (all pages) from backend. // Keep only non-server multi filters (e.g. brandGroupSelection) as local page filter. diff --git a/ui/src/pages/WholesaleCampaigns.vue b/ui/src/pages/WholesaleCampaigns.vue index 568457a..760a5ee 100644 --- a/ui/src/pages/WholesaleCampaigns.vue +++ b/ui/src/pages/WholesaleCampaigns.vue @@ -106,6 +106,13 @@ +
x.value)) const exportAllLoading = ref(false) const showSelectedOnly = ref(false) const leftDetailsExpanded = ref(true) +const showInStockOnly = ref(false) // Keep the old calc state around (not used on this screen) to avoid touching shared helpers. const calcLoadingMap = ref({}) @@ -1602,6 +1610,7 @@ function rowSelectionKey (row) { const filteredRows = computed(() => { return rows.value.filter((row) => { if (showSelectedOnly.value && !selectedMap.value[rowSelectionKey(row)]) return false + if (showInStockOnly.value && Number(row?.stockQty ?? 0) <= 0) return false for (const { field } of multiFilterColumns) { // Server-backed filters already reload full dataset (all pages) from backend. // Keep only non-server multi filters (e.g. brandGroupSelection) as local page filter.