Merge remote-tracking branch 'origin/master'
This commit is contained in:
@@ -37,6 +37,78 @@ func normalizeDimParam(v string) string {
|
||||
return s
|
||||
}
|
||||
|
||||
func uniqueNonEmpty(items ...string) []string {
|
||||
out := make([]string, 0, len(items))
|
||||
seen := make(map[string]struct{}, len(items))
|
||||
for _, it := range items {
|
||||
v := normalizeDimParam(it)
|
||||
if v == "" {
|
||||
continue
|
||||
}
|
||||
if _, ok := seen[v]; ok {
|
||||
continue
|
||||
}
|
||||
seen[v] = struct{}{}
|
||||
out = append(out, v)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func buildNameLikePatterns(token string) []string {
|
||||
t := strings.ToUpper(strings.TrimSpace(token))
|
||||
if t == "" {
|
||||
return nil
|
||||
}
|
||||
return []string{
|
||||
"% " + t + " %",
|
||||
"%-" + t + "-%",
|
||||
"%-" + t + "_%",
|
||||
"%_" + t + "_%",
|
||||
"%(" + t + ")%",
|
||||
t + " %",
|
||||
}
|
||||
}
|
||||
|
||||
func resolveDimvalFromFileNameToken(pg *sql.DB, column, token string) string {
|
||||
patterns := buildNameLikePatterns(token)
|
||||
if len(patterns) == 0 {
|
||||
return ""
|
||||
}
|
||||
query := fmt.Sprintf(`
|
||||
SELECT x.dimv
|
||||
FROM (
|
||||
SELECT COALESCE(%s::text, '') AS dimv, COUNT(*) AS cnt
|
||||
FROM dfblob
|
||||
WHERE src_table='mmitem'
|
||||
AND typ='img'
|
||||
AND COALESCE(%s::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(%s::text, '')
|
||||
) x
|
||||
ORDER BY x.cnt DESC, x.dimv
|
||||
LIMIT 1
|
||||
`, column, column, column)
|
||||
var v string
|
||||
if err := pg.QueryRow(query,
|
||||
patterns[0],
|
||||
patterns[1],
|
||||
patterns[2],
|
||||
patterns[3],
|
||||
patterns[4],
|
||||
patterns[5],
|
||||
).Scan(&v); err != nil {
|
||||
return ""
|
||||
}
|
||||
return normalizeDimParam(v)
|
||||
}
|
||||
|
||||
func extractImageUUID(storagePath, fileName string) string {
|
||||
if m := uuidPattern.FindString(storagePath); m != "" {
|
||||
return strings.ToLower(m)
|
||||
@@ -112,20 +184,8 @@ LIMIT 1
|
||||
return
|
||||
}
|
||||
|
||||
// Rule:
|
||||
// dim1!=0 && dim3!=0 => dimval1=dim1 AND dimval3=dim3
|
||||
// dim1!=0 && dim3==0 => dimval1=dim1
|
||||
// dim1==0 && dim3==0 => generic photos
|
||||
dim1Filter := normalizeDimParam(dim1ID)
|
||||
if dim1Filter == "" {
|
||||
dim1Filter = normalizeDimParam(dim1)
|
||||
}
|
||||
dim3Filter := normalizeDimParam(dim3ID)
|
||||
if dim3Filter == "" {
|
||||
dim3Filter = normalizeDimParam(dim3)
|
||||
}
|
||||
|
||||
query := `
|
||||
runQuery := func(dim1Filter, dim3Filter string) ([]ProductImageItem, error) {
|
||||
query := `
|
||||
SELECT
|
||||
id,
|
||||
COALESCE(file_name,'') AS file_name,
|
||||
@@ -135,26 +195,110 @@ FROM dfblob
|
||||
WHERE typ='img'
|
||||
AND src_table='mmitem'
|
||||
AND src_id=$1`
|
||||
args := []interface{}{mmItemID}
|
||||
argPos := 2
|
||||
if dim1Filter != "" {
|
||||
query += fmt.Sprintf(" AND COALESCE(dimval1::text,'') = $%d", argPos)
|
||||
args = append(args, dim1Filter)
|
||||
argPos++
|
||||
if dim3Filter != "" {
|
||||
query += fmt.Sprintf(" AND COALESCE(dimval3::text,'') = $%d", argPos)
|
||||
args = append(args, dim3Filter)
|
||||
args := []interface{}{mmItemID}
|
||||
argPos := 2
|
||||
if dim1Filter != "" {
|
||||
query += fmt.Sprintf(" AND COALESCE(dimval1::text,'') = $%d", argPos)
|
||||
args = append(args, dim1Filter)
|
||||
argPos++
|
||||
if dim3Filter != "" {
|
||||
query += fmt.Sprintf(" AND COALESCE(dimval3::text,'') = $%d", argPos)
|
||||
args = append(args, dim3Filter)
|
||||
argPos++
|
||||
}
|
||||
}
|
||||
}
|
||||
query += `
|
||||
query += `
|
||||
ORDER BY
|
||||
COALESCE(sort_order,999999),
|
||||
zlins_dttm DESC,
|
||||
id DESC`
|
||||
|
||||
rows, err := pg.Query(query, args...)
|
||||
if err != nil {
|
||||
rows, err := pg.Query(query, args...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
items := make([]ProductImageItem, 0, 16)
|
||||
for rows.Next() {
|
||||
var it ProductImageItem
|
||||
if err := rows.Scan(&it.ID, &it.FileName, &it.FileSize, &it.Storage); err != nil {
|
||||
continue
|
||||
}
|
||||
it.ContentURL = fmt.Sprintf("/api/product-images/%d/content", it.ID)
|
||||
if u := extractImageUUID(it.Storage, it.FileName); u != "" {
|
||||
it.UUID = u
|
||||
it.ThumbURL = "/uploads/image/t300/" + u + ".jpg"
|
||||
it.FullURL = "/uploads/image/" + u + ".jpg"
|
||||
}
|
||||
items = append(items, it)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
// Rule:
|
||||
// dim1!=0 && dim3!=0 => dimval1=dim1 AND dimval3=dim3
|
||||
// dim1!=0 && dim3==0 => dimval1=dim1
|
||||
// dim1==0 && dim3==0 => generic photos
|
||||
//
|
||||
// Frontend'den yanlis dim id gelebildigi icin:
|
||||
// 1) once *_id ile deneriz
|
||||
// 2) sonuc yoksa kod degeriyle fallback deneriz.
|
||||
resolvedDim1ID := normalizeDimParam(dim1ID)
|
||||
if resolvedDim1ID == "" && normalizeDimParam(dim1) != "" {
|
||||
resolvedDim1ID = resolveDimvalFromFileNameToken(pg, "dimval1", dim1)
|
||||
}
|
||||
resolvedDim3ID := normalizeDimParam(dim3ID)
|
||||
if resolvedDim3ID == "" && normalizeDimParam(dim3) != "" {
|
||||
resolvedDim3ID = resolveDimvalFromFileNameToken(pg, "dimval3", dim3)
|
||||
}
|
||||
|
||||
dim1Candidates := uniqueNonEmpty(resolvedDim1ID, dim1ID, dim1)
|
||||
if len(dim1Candidates) == 0 {
|
||||
dim1Candidates = []string{""}
|
||||
}
|
||||
dim3Candidates := uniqueNonEmpty(resolvedDim3ID, dim3ID, dim3)
|
||||
|
||||
items := make([]ProductImageItem, 0, 16)
|
||||
selectedDim1 := ""
|
||||
selectedDim3 := ""
|
||||
var queryErr error
|
||||
|
||||
for _, d1 := range dim1Candidates {
|
||||
localDim3Candidates := []string{""}
|
||||
if d1 != "" {
|
||||
if len(dim3Candidates) > 0 {
|
||||
localDim3Candidates = append([]string{}, dim3Candidates...)
|
||||
localDim3Candidates = append(localDim3Candidates, "")
|
||||
}
|
||||
}
|
||||
|
||||
for _, d3 := range localDim3Candidates {
|
||||
var runErr error
|
||||
items, runErr = runQuery(d1, d3)
|
||||
if runErr != nil {
|
||||
queryErr = runErr
|
||||
continue
|
||||
}
|
||||
if len(items) > 0 {
|
||||
selectedDim1 = d1
|
||||
selectedDim3 = d3
|
||||
break
|
||||
}
|
||||
if selectedDim1 == "" && selectedDim3 == "" {
|
||||
selectedDim1 = d1
|
||||
selectedDim3 = d3
|
||||
}
|
||||
}
|
||||
if len(items) > 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if queryErr != nil && len(items) == 0 {
|
||||
slog.Error("product_images.list.query_failed",
|
||||
"req_id", reqID,
|
||||
"code", code,
|
||||
@@ -162,35 +306,23 @@ ORDER BY
|
||||
"dim1_id", dim1ID,
|
||||
"dim3", dim3,
|
||||
"dim3_id", dim3ID,
|
||||
"err", err.Error(),
|
||||
"err", queryErr.Error(),
|
||||
)
|
||||
http.Error(w, "Gorsel sorgu hatasi: "+err.Error(), http.StatusInternalServerError)
|
||||
http.Error(w, "Gorsel sorgu hatasi: "+queryErr.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
items := make([]ProductImageItem, 0, 16)
|
||||
for rows.Next() {
|
||||
var it ProductImageItem
|
||||
if err := rows.Scan(&it.ID, &it.FileName, &it.FileSize, &it.Storage); err != nil {
|
||||
continue
|
||||
}
|
||||
it.ContentURL = fmt.Sprintf("/api/product-images/%d/content", it.ID)
|
||||
if u := extractImageUUID(it.Storage, it.FileName); u != "" {
|
||||
it.UUID = u
|
||||
it.ThumbURL = "/uploads/image/t300/" + u + ".jpg"
|
||||
it.FullURL = "/uploads/image/" + u + ".jpg"
|
||||
}
|
||||
items = append(items, it)
|
||||
}
|
||||
|
||||
slog.Info("product_images.list.ok",
|
||||
"req_id", reqID,
|
||||
"code", code,
|
||||
"dim1", dim1,
|
||||
"dim1_id", dim1ID,
|
||||
"resolved_dim1_id", resolvedDim1ID,
|
||||
"dim3", dim3,
|
||||
"dim3_id", dim3ID,
|
||||
"resolved_dim3_id", resolvedDim3ID,
|
||||
"selected_dim1", selectedDim1,
|
||||
"selected_dim3", selectedDim3,
|
||||
"count", len(items),
|
||||
)
|
||||
|
||||
|
||||
@@ -486,7 +486,15 @@ function resolvePhotoDim3(item, secondColorDisplay = '') {
|
||||
}
|
||||
|
||||
function resolvePhotoDim1ID(item) {
|
||||
const candidates = [item?.ItemDim1Code, item?.itemDim1Code, item?.ITEMDIM1CODE, item?.Beden]
|
||||
const candidates = [
|
||||
item?.PhotoDim1ID,
|
||||
item?.photoDim1ID,
|
||||
item?.Dim1ID,
|
||||
item?.dim1ID,
|
||||
item?.ColorID,
|
||||
item?.colorID,
|
||||
item?.RenkID
|
||||
]
|
||||
for (const value of candidates) {
|
||||
const s = String(value || '').trim()
|
||||
if (/^\d+$/.test(s)) return s
|
||||
@@ -495,7 +503,15 @@ function resolvePhotoDim1ID(item) {
|
||||
}
|
||||
|
||||
function resolvePhotoDim3ID(item) {
|
||||
const candidates = [item?.ItemDim3Code, item?.itemDim3Code, item?.ITEMDIM3CODE, item?.Renk2]
|
||||
const candidates = [
|
||||
item?.PhotoDim3ID,
|
||||
item?.photoDim3ID,
|
||||
item?.Dim3ID,
|
||||
item?.dim3ID,
|
||||
item?.SecondColorID,
|
||||
item?.secondColorID,
|
||||
item?.Renk2ID
|
||||
]
|
||||
for (const value of candidates) {
|
||||
const s = String(value || '').trim()
|
||||
if (/^\d+$/.test(s)) return s
|
||||
|
||||
@@ -479,7 +479,15 @@ function resolvePhotoDim3(item, secondColorDisplay = '') {
|
||||
}
|
||||
|
||||
function resolvePhotoDim1ID(item) {
|
||||
const candidates = [item?.ItemDim1Code, item?.itemDim1Code, item?.ITEMDIM1CODE, item?.Beden]
|
||||
const candidates = [
|
||||
item?.PhotoDim1ID,
|
||||
item?.photoDim1ID,
|
||||
item?.Dim1ID,
|
||||
item?.dim1ID,
|
||||
item?.ColorID,
|
||||
item?.colorID,
|
||||
item?.RenkID
|
||||
]
|
||||
for (const value of candidates) {
|
||||
const s = String(value || '').trim()
|
||||
if (/^\d+$/.test(s)) return s
|
||||
@@ -488,7 +496,15 @@ function resolvePhotoDim1ID(item) {
|
||||
}
|
||||
|
||||
function resolvePhotoDim3ID(item) {
|
||||
const candidates = [item?.ItemDim3Code, item?.itemDim3Code, item?.ITEMDIM3CODE, item?.Renk2]
|
||||
const candidates = [
|
||||
item?.PhotoDim3ID,
|
||||
item?.photoDim3ID,
|
||||
item?.Dim3ID,
|
||||
item?.dim3ID,
|
||||
item?.SecondColorID,
|
||||
item?.secondColorID,
|
||||
item?.Renk2ID
|
||||
]
|
||||
for (const value of candidates) {
|
||||
const s = String(value || '').trim()
|
||||
if (/^\d+$/.test(s)) return s
|
||||
|
||||
Reference in New Issue
Block a user