Merge remote-tracking branch 'origin/master'
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
package queries
|
||||
|
||||
// GetProductVariantDimsForPricing:
|
||||
// Pull variant dimension combos from Nebim stock tables (same source as product-stock-query UI).
|
||||
// Pull variant dimension combos from Nebim's variant master table.
|
||||
// We intentionally keep it small: only the keys we need to write dim-aware prices into PG sdprc.
|
||||
//
|
||||
// Note: Column semantics depend on your Nebim setup. We treat ItemDim1Code/ItemDim3Code as the
|
||||
@@ -10,16 +10,16 @@ const GetProductVariantDimsForPricing = `
|
||||
DECLARE @ProductCode NVARCHAR(50) = @p1;
|
||||
|
||||
SELECT DISTINCT
|
||||
LTRIM(RTRIM(ISNULL(S.ColorCode,''))) AS ColorCode,
|
||||
LTRIM(RTRIM(ISNULL(S.ItemDim1Code,''))) AS ItemDim1Code,
|
||||
LTRIM(RTRIM(ISNULL(S.ItemDim3Code,''))) AS ItemDim3Code
|
||||
FROM trStock S WITH(NOLOCK)
|
||||
WHERE S.ItemTypeCode = 1
|
||||
AND S.ItemCode = @ProductCode
|
||||
AND LEN(S.ItemCode) = 13
|
||||
LTRIM(RTRIM(ISNULL(V.ColorCode,''))) AS ColorCode,
|
||||
LTRIM(RTRIM(ISNULL(V.ItemDim1Code,''))) AS ItemDim1Code,
|
||||
LTRIM(RTRIM(ISNULL(V.ItemDim3Code,''))) AS ItemDim3Code
|
||||
FROM prItemVariant V WITH(NOLOCK)
|
||||
WHERE V.ItemTypeCode = 1
|
||||
AND V.ItemCode = @ProductCode
|
||||
AND LEN(V.ItemCode) = 13
|
||||
AND LEN(@ProductCode) = 13
|
||||
ORDER BY
|
||||
LTRIM(RTRIM(ISNULL(S.ColorCode,''))),
|
||||
LTRIM(RTRIM(ISNULL(S.ItemDim1Code,''))),
|
||||
LTRIM(RTRIM(ISNULL(S.ItemDim3Code,'')));
|
||||
LTRIM(RTRIM(ISNULL(V.ColorCode,''))),
|
||||
LTRIM(RTRIM(ISNULL(V.ItemDim1Code,''))),
|
||||
LTRIM(RTRIM(ISNULL(V.ItemDim3Code,'')));
|
||||
`
|
||||
|
||||
@@ -16,6 +16,45 @@ DECLARE @Codes NVARCHAR(MAX) = @p1;
|
||||
CROSS APPLY D.XmlData.nodes('/i') AS X(C)
|
||||
WHERE LTRIM(RTRIM(X.C.value('.', 'NVARCHAR(50)'))) <> ''
|
||||
),
|
||||
VARIANT_MASTER AS (
|
||||
SELECT
|
||||
V.ItemCode,
|
||||
LTRIM(RTRIM(ISNULL(V.ColorCode,''))) AS ColorCode,
|
||||
LTRIM(RTRIM(ISNULL(V.ItemDim3Code,''))) AS ItemDim3Code,
|
||||
MAX(LTRIM(RTRIM(ISNULL(V.ItemDim1Code,'')))) AS ItemDim1Code
|
||||
FROM prItemVariant V WITH(NOLOCK)
|
||||
JOIN INP ON INP.ItemCode = V.ItemCode
|
||||
WHERE V.ItemTypeCode = 1
|
||||
AND LEN(V.ItemCode) = 13
|
||||
GROUP BY
|
||||
V.ItemCode, V.ColorCode, V.ItemDim3Code
|
||||
),
|
||||
VARIANT_STOCK AS (
|
||||
SELECT
|
||||
S.ItemCode,
|
||||
LTRIM(RTRIM(ISNULL(S.ColorCode,''))) AS ColorCode,
|
||||
LTRIM(RTRIM(ISNULL(S.ItemDim3Code,''))) AS ItemDim3Code,
|
||||
MAX(LTRIM(RTRIM(ISNULL(S.ItemDim1Code,'')))) AS ItemDim1Code
|
||||
FROM trStock S WITH(NOLOCK)
|
||||
JOIN INP ON INP.ItemCode = S.ItemCode
|
||||
WHERE S.ItemTypeCode = 1
|
||||
AND LEN(S.ItemCode) = 13
|
||||
GROUP BY
|
||||
S.ItemCode, S.ColorCode, S.ItemDim3Code
|
||||
),
|
||||
VARIANT AS (
|
||||
SELECT
|
||||
X.ItemCode,
|
||||
X.ColorCode,
|
||||
X.ItemDim3Code,
|
||||
MAX(X.ItemDim1Code) AS ItemDim1Code
|
||||
FROM (
|
||||
SELECT ItemCode, ColorCode, ItemDim3Code, ItemDim1Code FROM VARIANT_MASTER
|
||||
UNION ALL
|
||||
SELECT ItemCode, ColorCode, ItemDim3Code, ItemDim1Code FROM VARIANT_STOCK
|
||||
) X
|
||||
GROUP BY X.ItemCode, X.ColorCode, X.ItemDim3Code
|
||||
),
|
||||
STOCK AS (
|
||||
SELECT
|
||||
S.ItemCode,
|
||||
@@ -73,27 +112,25 @@ DISP AS (
|
||||
D.ItemCode, D.ColorCode, D.ItemDim3Code
|
||||
)
|
||||
SELECT
|
||||
S.ItemCode AS ItemCode,
|
||||
S.ColorCode AS ColorCode,
|
||||
S.ItemDim1Code AS ItemDim1Code,
|
||||
S.ItemDim3Code AS ItemDim3Code,
|
||||
V.ItemCode AS ItemCode,
|
||||
V.ColorCode AS ColorCode,
|
||||
V.ItemDim1Code AS ItemDim1Code,
|
||||
V.ItemDim3Code AS ItemDim3Code,
|
||||
CAST(ROUND(
|
||||
S.InventoryQty1
|
||||
ISNULL(S.InventoryQty1,0)
|
||||
- ISNULL(PK.PickingQty1,0)
|
||||
- ISNULL(RS.ReserveQty1,0)
|
||||
- ISNULL(DP.DispOrderQty1,0),
|
||||
2
|
||||
) AS FLOAT) AS StockQty
|
||||
FROM STOCK S
|
||||
FROM VARIANT V
|
||||
LEFT JOIN STOCK S
|
||||
ON S.ItemCode=V.ItemCode AND S.ColorCode=V.ColorCode AND S.ItemDim3Code=V.ItemDim3Code
|
||||
LEFT JOIN PICK PK
|
||||
ON PK.ItemCode=S.ItemCode AND PK.ColorCode=S.ColorCode AND PK.ItemDim3Code=S.ItemDim3Code
|
||||
ON PK.ItemCode=V.ItemCode AND PK.ColorCode=V.ColorCode AND PK.ItemDim3Code=V.ItemDim3Code
|
||||
LEFT JOIN RESERVE RS
|
||||
ON RS.ItemCode=S.ItemCode AND RS.ColorCode=S.ColorCode AND RS.ItemDim3Code=S.ItemDim3Code
|
||||
ON RS.ItemCode=V.ItemCode AND RS.ColorCode=V.ColorCode AND RS.ItemDim3Code=V.ItemDim3Code
|
||||
LEFT JOIN DISP DP
|
||||
ON DP.ItemCode=S.ItemCode AND DP.ColorCode=S.ColorCode AND DP.ItemDim3Code=S.ItemDim3Code
|
||||
WHERE (S.InventoryQty1
|
||||
- ISNULL(PK.PickingQty1,0)
|
||||
- ISNULL(RS.ReserveQty1,0)
|
||||
- ISNULL(DP.DispOrderQty1,0)) <> 0
|
||||
ORDER BY S.ItemCode, S.ColorCode, S.ItemDim3Code;
|
||||
ON DP.ItemCode=V.ItemCode AND DP.ColorCode=V.ColorCode AND DP.ItemDim3Code=V.ItemDim3Code
|
||||
ORDER BY V.ItemCode, V.ColorCode, V.ItemDim3Code;
|
||||
`
|
||||
|
||||
@@ -53,9 +53,7 @@ CREATE TABLE IF NOT EXISTS mk_order_price_list_first_group_mail (
|
||||
urun_ilk_grubu TEXT NOT NULL,
|
||||
mail_id UUID NOT NULL,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
PRIMARY KEY (urun_ilk_grubu, mail_id),
|
||||
CONSTRAINT fk_order_price_list_first_group_mail_mail
|
||||
FOREIGN KEY (mail_id) REFERENCES mk_mail(id) ON DELETE CASCADE
|
||||
PRIMARY KEY (urun_ilk_grubu, mail_id)
|
||||
)
|
||||
`,
|
||||
`CREATE INDEX IF NOT EXISTS ix_order_price_list_first_group_mail_group ON mk_order_price_list_first_group_mail (urun_ilk_grubu)`,
|
||||
@@ -79,7 +77,7 @@ func GetCostingFirstGroupMailMappingLookupsHandler(pg *sql.DB) http.HandlerFunc
|
||||
return
|
||||
}
|
||||
if err := ensureFirstGroupMailMappingTables(pg); err != nil {
|
||||
http.Error(w, "mapping table bootstrap error", http.StatusInternalServerError)
|
||||
http.Error(w, "mapping table bootstrap error: "+err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -156,7 +154,7 @@ func GetCostingFirstGroupMailMappingsHandler(pg *sql.DB) http.HandlerFunc {
|
||||
return
|
||||
}
|
||||
if err := ensureFirstGroupMailMappingTables(pg); err != nil {
|
||||
http.Error(w, "mapping table bootstrap error", http.StatusInternalServerError)
|
||||
http.Error(w, "mapping table bootstrap error: "+err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -279,7 +277,7 @@ func GetPricingFirstGroupMailMappingsHandler(pg *sql.DB) http.HandlerFunc {
|
||||
return
|
||||
}
|
||||
if err := ensureFirstGroupMailMappingTables(pg); err != nil {
|
||||
http.Error(w, "mapping table bootstrap error", http.StatusInternalServerError)
|
||||
http.Error(w, "mapping table bootstrap error: "+err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -531,7 +529,7 @@ func getFirstGroupMailMappingsByQuery(pg *sql.DB, mappingQuery string) http.Hand
|
||||
return
|
||||
}
|
||||
if err := ensureFirstGroupMailMappingTables(pg); err != nil {
|
||||
http.Error(w, "mapping table bootstrap error", http.StatusInternalServerError)
|
||||
http.Error(w, "mapping table bootstrap error: "+err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -619,16 +619,13 @@ DO UPDATE SET dim_id = EXCLUDED.dim_id, updated_at = EXCLUDED.updated_at
|
||||
if c.Dim1 <= 0 {
|
||||
continue
|
||||
}
|
||||
v2 := int64(0)
|
||||
var v2any any = nil
|
||||
if c.Dim3.Valid && c.Dim3.Int64 > 0 {
|
||||
v2 = c.Dim3.Int64
|
||||
v2any = v2
|
||||
}
|
||||
// If we managed to resolve an "ItemDim3Code" id too, store it in val3 and mark mmdim_id=3.
|
||||
// Active key: val1=color, val3=itemdim3. val2 is size and is not part of price/campaign key.
|
||||
v3 := int64(0)
|
||||
if extraVal3 != nil {
|
||||
if vv, ok := extraVal3[fmt.Sprintf("%d|%d", c.Dim1, v2)]; ok && vv > 0 {
|
||||
if c.Dim3.Valid && c.Dim3.Int64 > 0 {
|
||||
v3 = c.Dim3.Int64
|
||||
} else if extraVal3 != nil {
|
||||
if vv, ok := extraVal3[fmt.Sprintf("%d|0", c.Dim1)]; ok && vv > 0 {
|
||||
v3 = vv
|
||||
}
|
||||
}
|
||||
@@ -1071,18 +1068,38 @@ VALUES (
|
||||
_ = upsertDimCombosCache(code, dims) // best-effort cache fill
|
||||
}
|
||||
|
||||
// 2) Last resort: MSSQL stock tokens, then seed mmitem_dim. Do not use
|
||||
// mk_mmitem_dim_combo as a write source; stale cache rows can create wrong keys.
|
||||
if len(dims) == 0 {
|
||||
d, err := loadDimsFromMssqlStock(code)
|
||||
if err != nil {
|
||||
logger.Error("save:pg:dims:mssql:error", "product_code", code, "err", err)
|
||||
} else {
|
||||
dims = d
|
||||
_ = upsertDimCombosCache(code, dims)
|
||||
// If PG doesn't have mmitem_dim rows for this product yet, try to seed them.
|
||||
ensureMMItemDimRows(mmItemID, dims, nil)
|
||||
// 2) Merge MSSQL variant master combos. PG may be partially populated; missing
|
||||
// colors/dim3 combos still need to be seeded before sdprc/zbggcampaign writes.
|
||||
if d, err := loadDimsFromMssqlStock(code); err != nil {
|
||||
logger.Error("save:pg:dims:mssql:error", "product_code", code, "err", err)
|
||||
} else if len(d) > 0 {
|
||||
seenDims := make(map[string]struct{}, len(dims)+len(d))
|
||||
merged := make([]dimCombo, 0, len(dims)+len(d))
|
||||
dim3Value := func(v sql.NullInt64) int64 {
|
||||
if v.Valid {
|
||||
return v.Int64
|
||||
}
|
||||
return 0
|
||||
}
|
||||
for _, c := range dims {
|
||||
k := fmt.Sprintf("%d|%d", c.Dim1, dim3Value(c.Dim3))
|
||||
if _, ok := seenDims[k]; ok {
|
||||
continue
|
||||
}
|
||||
seenDims[k] = struct{}{}
|
||||
merged = append(merged, c)
|
||||
}
|
||||
for _, c := range d {
|
||||
k := fmt.Sprintf("%d|%d", c.Dim1, dim3Value(c.Dim3))
|
||||
if _, ok := seenDims[k]; ok {
|
||||
continue
|
||||
}
|
||||
seenDims[k] = struct{}{}
|
||||
merged = append(merged, c)
|
||||
}
|
||||
dims = merged
|
||||
_ = upsertDimCombosCache(code, dims)
|
||||
ensureMMItemDimRows(mmItemID, d, nil)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -420,6 +421,18 @@ type wholesaleVariantRow struct {
|
||||
CampaignLast string `json:"campaign_last_dttm"`
|
||||
}
|
||||
|
||||
func buildNebimVariantDisplayCode(colorCode string, dim3Code string) string {
|
||||
colorCode = strings.TrimSpace(colorCode)
|
||||
dim3Code = strings.TrimSpace(dim3Code)
|
||||
if colorCode != "" && dim3Code != "" {
|
||||
return colorCode + "-" + dim3Code
|
||||
}
|
||||
if colorCode != "" {
|
||||
return colorCode
|
||||
}
|
||||
return dim3Code
|
||||
}
|
||||
|
||||
type wholesaleCampaignHistoryRow struct {
|
||||
ID int64 `json:"id"`
|
||||
CampaignID *int64 `json:"campaign_id"`
|
||||
@@ -736,6 +749,7 @@ DO UPDATE SET dim_id = EXCLUDED.dim_id, updated_at = EXCLUDED.updated_at
|
||||
ItemID int64
|
||||
Dim1 int64
|
||||
Dim3Key int64
|
||||
HasMSSQL bool
|
||||
}
|
||||
|
||||
// Build base variant keys from PG's authoritative table (mmitem_dim).
|
||||
@@ -805,7 +819,8 @@ WHERE mmitem_id = ANY($1::bigint[])
|
||||
rows.Close()
|
||||
}
|
||||
|
||||
// Resolve dim ids -> tokens for a readable VariantCode.
|
||||
// Resolve dim ids -> tokens for a fallback readable VariantCode.
|
||||
// MSSQL/Nebim tokens override this below; PG ids are only storage keys.
|
||||
idToToken := map[int64]string{}
|
||||
if len(dimIDs) > 0 {
|
||||
// uniq
|
||||
@@ -900,23 +915,23 @@ ORDER BY dim_id, updated_at DESC;
|
||||
key := fmt.Sprintf("%d|%d|%d", itemID, d1, d3k)
|
||||
prev, ok := tmpMap[key]
|
||||
if !ok {
|
||||
// If PG does not have mmitem_dim rows for this item yet, seed it from MSSQL and include it.
|
||||
if !hasMMItemDim[itemID] {
|
||||
var v2 any = nil
|
||||
if d3k > 0 {
|
||||
v2 = d3k
|
||||
}
|
||||
v3 := int64(0)
|
||||
if id, ok := resolveDimID("dimval1", dim3Code); ok {
|
||||
v3 = id
|
||||
}
|
||||
mmdimID := int64(2)
|
||||
var v3any any = nil
|
||||
if v3 > 0 {
|
||||
mmdimID = 3
|
||||
v3any = v3
|
||||
}
|
||||
_, _ = pg.ExecContext(ctx, `
|
||||
// Seed missing MSSQL combos even when the product already has some mmitem_dim rows.
|
||||
// PG remains the storage key source, but MSSQL may reveal new/missing color or dim3 combos.
|
||||
var v2 any = nil
|
||||
if sizeID, ok := resolveDimID("dimval1", dim1Code); ok && sizeID > 0 {
|
||||
v2 = sizeID
|
||||
}
|
||||
v3 := int64(0)
|
||||
if id, ok := resolveDimID("dimval1", dim3Code); ok {
|
||||
v3 = id
|
||||
}
|
||||
mmdimID := int64(2)
|
||||
var v3any any = nil
|
||||
if v3 > 0 {
|
||||
mmdimID = 3
|
||||
v3any = v3
|
||||
}
|
||||
_, _ = pg.ExecContext(ctx, `
|
||||
INSERT INTO mmitem_dim (mmitem_id, mmdim_id, val1, val2, val3, is_active, qty)
|
||||
SELECT $1, $2, $3, $4, $5, TRUE, 0
|
||||
WHERE NOT EXISTS (
|
||||
@@ -930,26 +945,25 @@ WHERE NOT EXISTS (
|
||||
LIMIT 1
|
||||
);
|
||||
`, itemID, mmdimID, d1, v2, v3any)
|
||||
hasMMItemDim[itemID] = true
|
||||
hasMMItemDim[itemID] = true
|
||||
|
||||
code := strings.TrimSpace(itemToCode[itemID])
|
||||
if code != "" {
|
||||
tmpMap[key] = tmpRow{
|
||||
ProductCode: code,
|
||||
VariantCode: "",
|
||||
StockQty: 0,
|
||||
ItemID: itemID,
|
||||
Dim1: d1,
|
||||
Dim3Key: d3k,
|
||||
}
|
||||
// Keep dim token cache for VariantCode formatting.
|
||||
dimIDs = append(dimIDs, d1)
|
||||
if d3k > 0 {
|
||||
dimIDs = append(dimIDs, d3k)
|
||||
}
|
||||
prev = tmpMap[key]
|
||||
ok = true
|
||||
code := strings.TrimSpace(itemToCode[itemID])
|
||||
if code != "" {
|
||||
tmpMap[key] = tmpRow{
|
||||
ProductCode: code,
|
||||
VariantCode: "",
|
||||
StockQty: 0,
|
||||
ItemID: itemID,
|
||||
Dim1: d1,
|
||||
Dim3Key: d3k,
|
||||
}
|
||||
// Keep dim token cache for VariantCode formatting.
|
||||
dimIDs = append(dimIDs, d1)
|
||||
if d3k > 0 {
|
||||
dimIDs = append(dimIDs, d3k)
|
||||
}
|
||||
prev = tmpMap[key]
|
||||
ok = true
|
||||
}
|
||||
if !ok {
|
||||
continue
|
||||
@@ -960,6 +974,8 @@ WHERE NOT EXISTS (
|
||||
q = qty.Float64
|
||||
}
|
||||
prev.StockQty += q
|
||||
prev.VariantCode = buildNebimVariantDisplayCode(colorCode, dim3Code)
|
||||
prev.HasMSSQL = true
|
||||
tmpMap[key] = prev
|
||||
_ = colorCode // display-only
|
||||
}
|
||||
@@ -968,6 +984,15 @@ WHERE NOT EXISTS (
|
||||
for _, v := range tmpMap {
|
||||
tmp = append(tmp, v)
|
||||
}
|
||||
sort.SliceStable(tmp, func(i, j int) bool {
|
||||
if tmp[i].ProductCode != tmp[j].ProductCode {
|
||||
return tmp[i].ProductCode < tmp[j].ProductCode
|
||||
}
|
||||
if tmp[i].HasMSSQL != tmp[j].HasMSSQL {
|
||||
return tmp[i].HasMSSQL
|
||||
}
|
||||
return strings.TrimSpace(tmp[i].VariantCode) < strings.TrimSpace(tmp[j].VariantCode)
|
||||
})
|
||||
|
||||
// Bulk load campaign assignment for each (mmitem_id, dim1, dim3_key)
|
||||
type keyRec struct {
|
||||
|
||||
Reference in New Issue
Block a user