ui: add B2B olmayan stok (orphans) page
This commit is contained in:
@@ -1168,19 +1168,22 @@ func productSeriesResolvePGVariant(ctx context.Context, pg *sql.DB, productCode,
|
|||||||
dim3ID = sql.NullInt64{Int64: id, Valid: true}
|
dim3ID = sql.NullInt64{Int64: id, Valid: true}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only treat variants as ready if they exist in authoritative item-dim combos.
|
// Only treat variants as ready if they exist in authoritative item-dim combos (mmitem_dim).
|
||||||
// This prevents writing series assignments for stock variants that don't exist on the PG side.
|
// This prevents writing series assignments for stock variants that don't exist on the PG side.
|
||||||
dim3Key := int64(0)
|
dim3Key := int64(0)
|
||||||
if dim3ID.Valid {
|
if dim3ID.Valid && dim3ID.Int64 > 1000 {
|
||||||
dim3Key = dim3ID.Int64
|
dim3Key = dim3ID.Int64
|
||||||
}
|
}
|
||||||
var exists int
|
var exists int
|
||||||
if err := pg.QueryRowContext(ctx, `
|
if err := pg.QueryRowContext(ctx, `
|
||||||
SELECT 1
|
SELECT 1
|
||||||
FROM mk_mmitem_dim_combo
|
FROM mmitem_dim
|
||||||
WHERE product_code=$1 AND dim1=$2 AND dim3_key=$3
|
WHERE mmitem_id=$1
|
||||||
|
AND is_active=TRUE
|
||||||
|
AND val1=$2
|
||||||
|
AND COALESCE(CASE WHEN val3 IS NOT NULL AND val3 > 1000 THEN val3 ELSE 0 END, 0) = $3
|
||||||
LIMIT 1
|
LIMIT 1
|
||||||
`, strings.TrimSpace(productCode), dim1ID, dim3Key).Scan(&exists); err != nil {
|
`, mmitemID, dim1ID, dim3Key).Scan(&exists); err != nil {
|
||||||
if err == sql.ErrNoRows {
|
if err == sql.ErrNoRows {
|
||||||
return 0, 0, sql.NullInt64{}, false, nil
|
return 0, 0, sql.NullInt64{}, false, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -318,28 +318,34 @@ WHERE dim_column=$1 AND token = ANY($2)
|
|||||||
return out, rows.Err()
|
return out, rows.Err()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load all known (product_code, dim1, dim3_key) combos for products in this response.
|
// Load authoritative combos from mmitem_dim (mmitem_id + val1(color) + val3(dim3 if any)).
|
||||||
loadProductDimCombos := func(ctx context.Context, pg *sql.DB, productCodes []string) (map[string]struct{}, error) {
|
// We do NOT rely on mk_mmitem_dim_combo here because that cache may be empty/stale.
|
||||||
|
loadProductDimCombos := func(ctx context.Context, pg *sql.DB, mmitemIDs []int64) (map[string]struct{}, error) {
|
||||||
out := map[string]struct{}{}
|
out := map[string]struct{}{}
|
||||||
if len(productCodes) == 0 {
|
if len(mmitemIDs) == 0 {
|
||||||
return out, nil
|
return out, nil
|
||||||
}
|
}
|
||||||
rows, err := pg.QueryContext(ctx, `
|
rows, err := pg.QueryContext(ctx, `
|
||||||
SELECT product_code, dim1, dim3_key
|
SELECT
|
||||||
FROM mk_mmitem_dim_combo
|
mmitem_id,
|
||||||
WHERE product_code = ANY($1)
|
val1 AS dim1,
|
||||||
`, pq.Array(productCodes))
|
CASE WHEN val3 IS NOT NULL AND val3 > 1000 THEN val3 ELSE 0 END AS dim3_key
|
||||||
|
FROM mmitem_dim
|
||||||
|
WHERE mmitem_id = ANY($1)
|
||||||
|
AND is_active = TRUE
|
||||||
|
AND val1 IS NOT NULL
|
||||||
|
GROUP BY mmitem_id, val1, CASE WHEN val3 IS NOT NULL AND val3 > 1000 THEN val3 ELSE 0 END
|
||||||
|
`, pq.Array(mmitemIDs))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return out, err
|
return out, err
|
||||||
}
|
}
|
||||||
defer rows.Close()
|
defer rows.Close()
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
var code string
|
var mmitemID, dim1, dim3Key int64
|
||||||
var dim1, dim3Key int64
|
if err := rows.Scan(&mmitemID, &dim1, &dim3Key); err != nil {
|
||||||
if err := rows.Scan(&code, &dim1, &dim3Key); err != nil {
|
|
||||||
return out, err
|
return out, err
|
||||||
}
|
}
|
||||||
key := fmt.Sprintf("%s|%d|%d", strings.TrimSpace(code), dim1, dim3Key)
|
key := fmt.Sprintf("%d|%d|%d", mmitemID, dim1, dim3Key)
|
||||||
out[key] = struct{}{}
|
out[key] = struct{}{}
|
||||||
}
|
}
|
||||||
return out, rows.Err()
|
return out, rows.Err()
|
||||||
@@ -349,7 +355,13 @@ WHERE product_code = ANY($1)
|
|||||||
mmitemByCode, _ := loadMmitemIDs(ctx, pg, codes)
|
mmitemByCode, _ := loadMmitemIDs(ctx, pg, codes)
|
||||||
dim1ByToken, _ := loadDimTokenIDsStrict(ctx, pg, "dimval1", setToSortedSlice(colorSet))
|
dim1ByToken, _ := loadDimTokenIDsStrict(ctx, pg, "dimval1", setToSortedSlice(colorSet))
|
||||||
dim3ByToken, _ := loadDimTokenIDsStrict(ctx, pg, "dimval3", setToSortedSlice(dim3Set))
|
dim3ByToken, _ := loadDimTokenIDsStrict(ctx, pg, "dimval3", setToSortedSlice(dim3Set))
|
||||||
combos, _ := loadProductDimCombos(ctx, pg, codes)
|
mmitemIDs := make([]int64, 0, len(mmitemByCode))
|
||||||
|
for _, c := range codes {
|
||||||
|
if id := mmitemByCode[c]; id > 0 {
|
||||||
|
mmitemIDs = append(mmitemIDs, id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
combos, _ := loadProductDimCombos(ctx, pg, mmitemIDs)
|
||||||
existing, _ := loadProductSeriesAssignments(ctx, pg, codes)
|
existing, _ := loadProductSeriesAssignments(ctx, pg, codes)
|
||||||
|
|
||||||
// Per-request cache for per-mmitem dimval3 inference to avoid repeated dfblob scans.
|
// Per-request cache for per-mmitem dimval3 inference to avoid repeated dfblob scans.
|
||||||
@@ -430,7 +442,7 @@ LIMIT 1
|
|||||||
dim3Key = row.Dim3ID
|
dim3Key = row.Dim3ID
|
||||||
}
|
}
|
||||||
if row.MappingReady {
|
if row.MappingReady {
|
||||||
_, ok := combos[fmt.Sprintf("%s|%d|%d", strings.TrimSpace(row.ProductCode), row.Dim1ID, dim3Key)]
|
_, ok := combos[fmt.Sprintf("%d|%d|%d", row.MmitemID, row.Dim1ID, dim3Key)]
|
||||||
row.MappingReady = ok
|
row.MappingReady = ok
|
||||||
}
|
}
|
||||||
if !row.MappingReady {
|
if !row.MappingReady {
|
||||||
@@ -609,27 +621,32 @@ WHERE dim_column=$1 AND token = ANY($2)
|
|||||||
return out, rows.Err()
|
return out, rows.Err()
|
||||||
}
|
}
|
||||||
|
|
||||||
loadProductDimCombos := func(ctx context.Context, pg *sql.DB, productCodes []string) (map[string]struct{}, error) {
|
loadProductDimCombos := func(ctx context.Context, pg *sql.DB, mmitemIDs []int64) (map[string]struct{}, error) {
|
||||||
out := map[string]struct{}{}
|
out := map[string]struct{}{}
|
||||||
if len(productCodes) == 0 {
|
if len(mmitemIDs) == 0 {
|
||||||
return out, nil
|
return out, nil
|
||||||
}
|
}
|
||||||
rows, err := pg.QueryContext(ctx, `
|
rows, err := pg.QueryContext(ctx, `
|
||||||
SELECT product_code, dim1, dim3_key
|
SELECT
|
||||||
FROM mk_mmitem_dim_combo
|
mmitem_id,
|
||||||
WHERE product_code = ANY($1)
|
val1 AS dim1,
|
||||||
`, pq.Array(productCodes))
|
CASE WHEN val3 IS NOT NULL AND val3 > 1000 THEN val3 ELSE 0 END AS dim3_key
|
||||||
|
FROM mmitem_dim
|
||||||
|
WHERE mmitem_id = ANY($1)
|
||||||
|
AND is_active = TRUE
|
||||||
|
AND val1 IS NOT NULL
|
||||||
|
GROUP BY mmitem_id, val1, CASE WHEN val3 IS NOT NULL AND val3 > 1000 THEN val3 ELSE 0 END
|
||||||
|
`, pq.Array(mmitemIDs))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return out, err
|
return out, err
|
||||||
}
|
}
|
||||||
defer rows.Close()
|
defer rows.Close()
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
var code string
|
var mmitemID, dim1, dim3Key int64
|
||||||
var dim1, dim3Key int64
|
if err := rows.Scan(&mmitemID, &dim1, &dim3Key); err != nil {
|
||||||
if err := rows.Scan(&code, &dim1, &dim3Key); err != nil {
|
|
||||||
return out, err
|
return out, err
|
||||||
}
|
}
|
||||||
key := fmt.Sprintf("%s|%d|%d", strings.TrimSpace(code), dim1, dim3Key)
|
key := fmt.Sprintf("%d|%d|%d", mmitemID, dim1, dim3Key)
|
||||||
out[key] = struct{}{}
|
out[key] = struct{}{}
|
||||||
}
|
}
|
||||||
return out, rows.Err()
|
return out, rows.Err()
|
||||||
@@ -639,7 +656,13 @@ WHERE product_code = ANY($1)
|
|||||||
mmitemByCode, _ := loadMmitemIDs(ctx, pg, codes)
|
mmitemByCode, _ := loadMmitemIDs(ctx, pg, codes)
|
||||||
dim1ByToken, _ := loadDimTokenIDsStrict(ctx, pg, "dimval1", setToSortedSlice(colorSet))
|
dim1ByToken, _ := loadDimTokenIDsStrict(ctx, pg, "dimval1", setToSortedSlice(colorSet))
|
||||||
dim3ByToken, _ := loadDimTokenIDsStrict(ctx, pg, "dimval3", setToSortedSlice(dim3Set))
|
dim3ByToken, _ := loadDimTokenIDsStrict(ctx, pg, "dimval3", setToSortedSlice(dim3Set))
|
||||||
combos, _ := loadProductDimCombos(ctx, pg, codes)
|
mmitemIDs := make([]int64, 0, len(mmitemByCode))
|
||||||
|
for _, c := range codes {
|
||||||
|
if id := mmitemByCode[c]; id > 0 {
|
||||||
|
mmitemIDs = append(mmitemIDs, id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
combos, _ := loadProductDimCombos(ctx, pg, mmitemIDs)
|
||||||
|
|
||||||
// Per-request cache for per-mmitem dimval3 inference (dfblob scan).
|
// Per-request cache for per-mmitem dimval3 inference (dfblob scan).
|
||||||
inferCache := map[string]int64{}
|
inferCache := map[string]int64{}
|
||||||
@@ -720,8 +743,7 @@ LIMIT 1
|
|||||||
if row.Dim3Code != "" {
|
if row.Dim3Code != "" {
|
||||||
dim3Key = row.Dim3ID
|
dim3Key = row.Dim3ID
|
||||||
}
|
}
|
||||||
comboKey := fmt.Sprintf("%s|%d|%d", strings.TrimSpace(row.ProductCode), row.Dim1ID, dim3Key)
|
_, comboOK := combos[fmt.Sprintf("%d|%d|%d", row.MmitemID, row.Dim1ID, dim3Key)]
|
||||||
_, comboOK := combos[comboKey]
|
|
||||||
|
|
||||||
row.MappingReady = false
|
row.MappingReady = false
|
||||||
switch {
|
switch {
|
||||||
@@ -732,7 +754,7 @@ LIMIT 1
|
|||||||
case row.Dim3Code != "" && row.Dim3ID <= 0:
|
case row.Dim3Code != "" && row.Dim3ID <= 0:
|
||||||
row.MappingWarning = "B2B'de dim3 token eslesmesi yok (mk_dim_token_map: dimval3)"
|
row.MappingWarning = "B2B'de dim3 token eslesmesi yok (mk_dim_token_map: dimval3)"
|
||||||
case !comboOK:
|
case !comboOK:
|
||||||
row.MappingWarning = "B2B'de varyant kombosu yok (mk_mmitem_dim_combo)"
|
row.MappingWarning = "B2B'de varyant kombosu yok (mmitem_dim)"
|
||||||
default:
|
default:
|
||||||
// Not an orphan; skip.
|
// Not an orphan; skip.
|
||||||
if baseReady && comboOK {
|
if baseReady && comboOK {
|
||||||
|
|||||||
Reference in New Issue
Block a user