Merge remote-tracking branch 'origin/master'

This commit is contained in:
M_Kececi
2026-06-23 17:17:44 +03:00
parent e980d6c2d5
commit 0f9b7549ec
2 changed files with 234 additions and 12 deletions

View File

@@ -297,12 +297,76 @@ func GetProductSeriesMappingsHandler(pg *sql.DB) http.HandlerFunc {
dim3ByToken, _ := loadDimTokenIDs(ctx, pg, "dimval3", setToSortedSlice(dim3Set))
existing, _ := loadProductSeriesAssignments(ctx, pg, codes)
// Per-request cache for per-mmitem dimval3 inference to avoid repeated dfblob scans.
inferCache := map[string]int64{}
inferDim3ForMmitem := func(mmitemID int64, token string) int64 {
mmitemID = int64(mmitemID)
tok := strings.ToUpper(normalizeDimParam(token))
if mmitemID <= 0 || tok == "" {
return 0
}
key := fmt.Sprintf("%d|%s", mmitemID, tok)
if v, ok := inferCache[key]; ok {
return v
}
// Use the same pattern approach as resolveDimvalFromFileNameToken, but scoped to src_id.
patterns := buildNameLikePatterns(tok)
if len(patterns) == 0 {
inferCache[key] = 0
return 0
}
var dimv string
err := pg.QueryRowContext(ctx, `
SELECT x.dimv
FROM (
SELECT COALESCE(dimval3::text, '') AS dimv, COUNT(*) AS cnt
FROM dfblob
WHERE src_table='mmitem'
AND typ='img'
AND src_id=$7
AND COALESCE(dimval3::text, '') <> ''
AND (
UPPER(COALESCE(file_name,'')) LIKE $1 OR
UPPER(COALESCE(file_name,'')) LIKE $2 OR
UPPER(COALESCE(file_name,'')) LIKE $3 OR
UPPER(COALESCE(file_name,'')) LIKE $4 OR
UPPER(COALESCE(file_name,'')) LIKE $5 OR
UPPER(COALESCE(file_name,'')) LIKE $6
)
GROUP BY COALESCE(dimval3::text, '')
) x
ORDER BY x.cnt DESC, x.dimv
LIMIT 1
`, patterns[0], patterns[1], patterns[2], patterns[3], patterns[4], patterns[5], mmitemID).Scan(&dimv)
if err != nil {
inferCache[key] = 0
return 0
}
dimv = strings.TrimSpace(dimv)
if dimv == "" || dimv == "0" {
inferCache[key] = 0
return 0
}
id, err := strconv.ParseInt(dimv, 10, 64)
if err != nil || id <= 0 {
inferCache[key] = 0
return 0
}
inferCache[key] = id
return id
}
out := make([]productSeriesMappingRow, 0, len(grouped))
for _, row := range grouped {
row.MmitemID = mmitemByCode[row.ProductCode]
row.Dim1ID = dim1ByToken[row.ColorCode]
if row.Dim3Code != "" {
row.Dim3ID = dim3ByToken[row.Dim3Code]
// dimval3 tokens can be ambiguous globally; prefer per-mmitem inference.
if inferred := inferDim3ForMmitem(row.MmitemID, row.Dim3Code); inferred > 0 {
row.Dim3ID = inferred
} else {
row.Dim3ID = dim3ByToken[row.Dim3Code]
}
}
row.MappingReady = row.MmitemID > 0 && row.Dim1ID > 0 && (row.Dim3Code == "" || row.Dim3ID > 0)
if !row.MappingReady {
@@ -515,7 +579,45 @@ WHERE dim_column=$1 AND token = ANY($2)
}
out[strings.TrimSpace(token)] = id
}
return out, rows.Err()
if err := rows.Err(); err != nil {
return out, err
}
// Best-effort fallback: infer missing token->dim_id from dfblob file_name patterns.
// NOTE: For dimval3, the same token can map to different dim ids per product in this
// installation, so we do NOT infer/persist globally here. Per-product inference is
// handled in the row loop (using mmitem_id) to avoid wrong matches.
for _, rawTok := range tokens {
tok := strings.ToUpper(normalizeDimParam(rawTok))
if tok == "" {
continue
}
if _, ok := out[tok]; ok {
continue
}
if column == "dimval3" {
// avoid global inference for dimval3
continue
}
v := resolveDimvalFromFileNameToken(pg, column, tok)
if v == "" {
continue
}
id, err := strconv.ParseInt(v, 10, 64)
if err != nil || id <= 0 {
continue
}
// Persist for future requests (best-effort).
_, _ = pg.ExecContext(ctx, `
INSERT INTO mk_dim_token_map (dim_column, token, dim_id, updated_at)
VALUES ($1,$2,$3,now())
ON CONFLICT (dim_column, token)
DO UPDATE SET dim_id = EXCLUDED.dim_id, updated_at = EXCLUDED.updated_at
`, column, tok, id)
out[tok] = id
}
return out, nil
}
func loadProductSeriesAssignments(ctx context.Context, pg *sql.DB, codes []string) (map[string][]int64, error) {