diff --git a/svc/queries/productstockquery.go b/svc/queries/productstockquery.go index 282f873..8127d78 100644 --- a/svc/queries/productstockquery.go +++ b/svc/queries/productstockquery.go @@ -98,6 +98,7 @@ SELECT C.ColorDescription AS Renk_Aciklamasi, S.ItemDim1Code AS Beden, + S.ItemDim3Code AS Renk2, S.ItemDim2Code AS Yaka, ROUND( diff --git a/svc/queries/productstockquery_by_attributes.go b/svc/queries/productstockquery_by_attributes.go index ce304f3..25a0ac9 100644 --- a/svc/queries/productstockquery_by_attributes.go +++ b/svc/queries/productstockquery_by_attributes.go @@ -622,6 +622,7 @@ SELECT A.ColorCode AS Renk_Kodu, A.RenkAciklama AS Renk_Aciklamasi, A.ItemDim1Code AS Beden, + A.ItemDim3Code AS Renk2, A.ItemDim2Code AS Yaka, A.Kullanilabilir AS Kullanilabilir_Envanter, AF.ProductAtt01Desc AS URUN_ANA_GRUBU, diff --git a/ui/src/pages/ProductStockByAttributes.vue b/ui/src/pages/ProductStockByAttributes.vue index 0633e41..a63f9e4 100644 --- a/ui/src/pages/ProductStockByAttributes.vue +++ b/ui/src/pages/ProductStockByAttributes.vue @@ -469,16 +469,40 @@ function buildImageKey(code, color, secondColor = '') { return `${String(code || '').trim().toUpperCase()}::${String(color || '').trim().toUpperCase()}::${String(secondColor || '').trim().toUpperCase()}` } -function imageNameMatches(fileName, color, secondColor) { - const text = String(fileName || '').toUpperCase() - if (!text) return false - const tokens = text.replace(/[^A-Z0-9_]+/g, ' ').trim().split(/\s+/).filter(Boolean) - if (!tokens.length) return false - const colorTrim = String(color || '').trim().toUpperCase() +function normalizeSecondColorValue(value) { + const s = String(value || '').trim().toUpperCase() + if (!s) return '' + if (/^\d{3}(?:_\d+)?$/.test(s)) return s + return '' +} + +function extractSecondColor(item) { + return ( + normalizeSecondColorValue(item?.Renk2) || + normalizeSecondColorValue(item?.ItemDim3Code) || + normalizeSecondColorValue(item?.Yaka) || + '' + ) +} + +function buildDim3Candidates(secondColor) { const secondTrim = String(secondColor || '').trim().toUpperCase() - if (colorTrim && !tokens.includes(colorTrim)) return false - if (secondTrim && !tokens.includes(secondTrim)) return false - return true + if (!secondTrim) return [''] + const set = new Set([secondTrim]) + if (/^\d{3}$/.test(secondTrim)) set.add(`${secondTrim}_1`) + return Array.from(set) +} + +async function fetchProductImageList(codeTrim, colorTrim, secondTrim) { + const dim3Candidates = buildDim3Candidates(secondTrim) + for (const dim3Candidate of dim3Candidates) { + const params = { code: codeTrim, dim1: colorTrim } + if (dim3Candidate) params.dim3 = dim3Candidate + const res = await api.get('/product-images', { params }) + const list = Array.isArray(res?.data) ? res.data : [] + if (list.length) return list + } + return [] } function normalizeUploadsPath(storagePath) { @@ -595,9 +619,7 @@ async function ensureProductImage(code, color, secondColor = '') { await new Promise((resolve) => imageListWaitQueue.push(resolve)) } imageListActiveRequests++ - const params = { code: codeTrim, dim1: colorTrim, dim3: secondTrim } - const res = await api.get('/product-images', { params }) - productImageListByCode.value[listKey] = Array.isArray(res?.data) ? res.data : [] + productImageListByCode.value[listKey] = await fetchProductImageList(codeTrim, colorTrim, secondTrim) } catch (err) { productImageListByCode.value[listKey] = [] const status = Number(err?.response?.status || 0) @@ -620,14 +642,7 @@ async function ensureProductImage(code, color, secondColor = '') { } } const list = productImageListByCode.value[listKey] || [] - - let first = null - if (colorTrim || secondTrim) { - first = list.find((item) => - imageNameMatches(String(item?.file_name || item?.FileName || ''), colorTrim, secondTrim) - ) || null - } - if (!first) first = list[0] || null + const first = list[0] || null const resolved = resolveProductImageUrl(first) @@ -704,7 +719,7 @@ function buildLevel3Rows(grp3) { for (const item of grp3.items || []) { const model = String(item.Urun_Kodu || '').trim() const renk = String(item.Renk_Kodu || '').trim() - const renk2 = String(item.Yaka || '').trim() + const renk2 = extractSecondColor(item) const urunAnaGrubu = String(item.URUN_ANA_GRUBU || '').trim() const urunAltGrubu = String(item.URUN_ALT_GRUBU || '').trim() const aciklama = String(item.Madde_Aciklamasi || '').trim() @@ -752,7 +767,7 @@ const level1Groups = computed(() => { const productDesc = String(item.Madde_Aciklamasi || '').trim() const colorCode = String(item.Renk_Kodu || '').trim() const colorDesc = String(item.Renk_Aciklamasi || '').trim() - const secondColor = String(item.Yaka || '').trim() + const secondColor = extractSecondColor(item) const depoKodu = String(item.Depo_Kodu || '').trim() const depoAdi = String(item.Depo_Adi || '').trim() const urunAnaGrubu = String(item.URUN_ANA_GRUBU || '').trim() @@ -1064,9 +1079,7 @@ async function openProductCard(grp1, grp2) { let list = Array.isArray(productImageListByCode.value[listKey]) ? productImageListByCode.value[listKey] : [] if (!list.length && codeTrim) { try { - const params = { code: codeTrim, dim1: colorTrim, dim3: secondTrim } - const res = await api.get('/product-images', { params }) - list = Array.isArray(res?.data) ? res.data : [] + list = await fetchProductImageList(codeTrim, colorTrim, secondTrim) productImageListByCode.value[listKey] = list } catch (err) { console.warn('[ProductStockByAttributes] product card image list refetch failed', { diff --git a/ui/src/pages/ProductStockQuery.vue b/ui/src/pages/ProductStockQuery.vue index 2382d0e..edc1325 100644 --- a/ui/src/pages/ProductStockQuery.vue +++ b/ui/src/pages/ProductStockQuery.vue @@ -462,16 +462,40 @@ function buildImageKey(code, color, secondColor = '') { return `${String(code || '').trim().toUpperCase()}::${String(color || '').trim().toUpperCase()}::${String(secondColor || '').trim().toUpperCase()}` } -function imageNameMatches(fileName, color, secondColor) { - const text = String(fileName || '').toUpperCase() - if (!text) return false - const tokens = text.replace(/[^A-Z0-9_]+/g, ' ').trim().split(/\s+/).filter(Boolean) - if (!tokens.length) return false - const colorTrim = String(color || '').trim().toUpperCase() +function normalizeSecondColorValue(value) { + const s = String(value || '').trim().toUpperCase() + if (!s) return '' + if (/^\d{3}(?:_\d+)?$/.test(s)) return s + return '' +} + +function extractSecondColor(item) { + return ( + normalizeSecondColorValue(item?.Renk2) || + normalizeSecondColorValue(item?.ItemDim3Code) || + normalizeSecondColorValue(item?.Yaka) || + '' + ) +} + +function buildDim3Candidates(secondColor) { const secondTrim = String(secondColor || '').trim().toUpperCase() - if (colorTrim && !tokens.includes(colorTrim)) return false - if (secondTrim && !tokens.includes(secondTrim)) return false - return true + if (!secondTrim) return [''] + const set = new Set([secondTrim]) + if (/^\d{3}$/.test(secondTrim)) set.add(`${secondTrim}_1`) + return Array.from(set) +} + +async function fetchProductImageList(codeTrim, colorTrim, secondTrim) { + const dim3Candidates = buildDim3Candidates(secondTrim) + for (const dim3Candidate of dim3Candidates) { + const params = { code: codeTrim, dim1: colorTrim } + if (dim3Candidate) params.dim3 = dim3Candidate + const res = await api.get('/product-images', { params }) + const list = Array.isArray(res?.data) ? res.data : [] + if (list.length) return list + } + return [] } function normalizeUploadsPath(storagePath) { @@ -574,9 +598,7 @@ async function ensureProductImage(code, color, secondColor = '') { await new Promise((resolve) => imageListWaitQueue.push(resolve)) } imageListActiveRequests++ - const params = { code: codeTrim, dim1: colorTrim, dim3: secondTrim } - const res = await api.get('/product-images', { params }) - productImageListByCode.value[listKey] = Array.isArray(res?.data) ? res.data : [] + productImageListByCode.value[listKey] = await fetchProductImageList(codeTrim, colorTrim, secondTrim) } catch (err) { productImageListByCode.value[listKey] = [] const status = Number(err?.response?.status || 0) @@ -598,13 +620,7 @@ async function ensureProductImage(code, color, secondColor = '') { } const list = productImageListByCode.value[listKey] || [] - let first = null - if (colorTrim || secondTrim) { - first = list.find((item) => - imageNameMatches(String(item?.file_name || item?.FileName || ''), colorTrim, secondTrim) - ) || null - } - if (!first) first = list[0] || null + const first = list[0] || null const resolved = resolveProductImageUrl(first) productImageCache.value[key] = resolved.contentUrl || resolved.publicUrl || '' @@ -680,7 +696,7 @@ function buildLevel3Rows(grp3) { for (const item of grp3.items || []) { const model = String(item.Urun_Kodu || '').trim() const renk = String(item.Renk_Kodu || '').trim() - const renk2 = String(item.Yaka || '').trim() + const renk2 = extractSecondColor(item) const urunAnaGrubu = String(item.URUN_ANA_GRUBU || '').trim() const urunAltGrubu = String(item.URUN_ALT_GRUBU || '').trim() const aciklama = String(item.Madde_Aciklamasi || '').trim() @@ -728,7 +744,7 @@ const level1Groups = computed(() => { const productDesc = String(item.Madde_Aciklamasi || '').trim() const colorCode = String(item.Renk_Kodu || '').trim() const colorDesc = String(item.Renk_Aciklamasi || '').trim() - const secondColor = String(item.Yaka || '').trim() + const secondColor = extractSecondColor(item) const depoKodu = String(item.Depo_Kodu || '').trim() const depoAdi = String(item.Depo_Adi || '').trim() const kategori = String(item.YETISKIN_GARSON || '').trim() @@ -931,9 +947,7 @@ async function openProductCard(grp1, grp2) { let list = Array.isArray(productImageListByCode.value[listKey]) ? productImageListByCode.value[listKey] : [] if (!list.length && codeTrim) { try { - const params = { code: codeTrim, dim1: colorTrim, dim3: secondTrim } - const res = await api.get('/product-images', { params }) - list = Array.isArray(res?.data) ? res.data : [] + list = await fetchProductImageList(codeTrim, colorTrim, secondTrim) productImageListByCode.value[listKey] = list } catch (err) { console.warn('[ProductStockQuery] product card image list refetch failed', {