From 2b40983cee9e6502731b58f289bc49eb173bf59a Mon Sep 17 00:00:00 2001 From: M_Kececi Date: Tue, 31 Mar 2026 13:07:00 +0300 Subject: [PATCH] Merge remote-tracking branch 'origin/master' --- ui/src/pages/OrderEntry.vue | 66 ++++++++++++++++++++++++-------- ui/src/stores/orderentryStore.js | 66 +++++++++++++++++++++++++++++--- 2 files changed, 111 insertions(+), 21 deletions(-) diff --git a/ui/src/pages/OrderEntry.vue b/ui/src/pages/OrderEntry.vue index fa3b68f..ff50ffc 100644 --- a/ui/src/pages/OrderEntry.vue +++ b/ui/src/pages/OrderEntry.vue @@ -1098,6 +1098,7 @@ const form = reactive({ kategori: '', askiliyan: '', yetiskinGarson: '', + yasPayloadMap: {}, seri: '', bedenLabels: [], bedenler: [], @@ -1256,6 +1257,7 @@ async function resetEditor(force = false) { drop: '', askiliyan: '', yetiskinGarson: '', + yasPayloadMap: {}, adet: 0, fiyat: 0, @@ -1371,17 +1373,29 @@ const selectedRow = computed(() => { const groupOpen = reactive({}) function normalizeYetiskinGarsonToken (row) { - const raw = String( - row?.yetiskinGarson || - row?.YETISKIN_GARSON || - row?.YetiskinGarson || - row?.kategori || - row?.Kategori || - '' - ).toUpperCase() + const raw = [ + row?.yetiskinGarson, + row?.YETISKIN_GARSON, + row?.YetiskinGarson, + row?.askiliyan, + row?.AskiliYan, + row?.kategori, + row?.Kategori + ] + .map(v => String(v || '').trim()) + .filter(Boolean) + .join(' ') - if (raw.includes('GARSON')) return 'GARSON' - if (raw.includes('YETISKIN') || raw.includes('YETİSKİN')) return 'YETISKIN' + const normalized = raw + .toUpperCase() + .normalize('NFD') + .replace(/[\u0300-\u036f]/g, '') + .replace(/[^A-Z0-9/ ]+/g, ' ') + .replace(/\s+/g, ' ') + .trim() + + if (normalized.includes('GARSON')) return 'GARSON' + if (normalized.includes('YETISKIN')) return 'YETISKIN' return 'GENEL' } @@ -1428,10 +1442,7 @@ const groupedRows = computed(() => { return order.map(bucketKey => { const grp = buckets[bucketKey] const schema = schemaMap?.[grp.grpKey] - const schemaTitle = String(schema?.title || grp.grpKey || '').trim() - const displayName = schemaTitle - ? `${grp.yg} ${grp.name} (${schemaTitle})` - : `${grp.yg} ${grp.name}` + const displayName = `${grp.yg} ${grp.name}`.trim() return { ...grp, @@ -2349,6 +2360,7 @@ async function hydrateEditorFromRow(row, opts = {}) { drop: row.drop || row.Drop || modelMeta?.Drop || '', askiliyan: rowAskili, yetiskinGarson: rowYetiskinGarson, + yasPayloadMap: { ...(row.yasPayloadMap || {}) }, kategori: rowKategori, aciklama: row.aciklama, fiyat: Number(row.fiyat || 0), @@ -2790,6 +2802,7 @@ async function onModelChange(modelCode) { kategori: d.Kategori || '', askiliyan: d.AskiliYan || '', yetiskinGarson: d.YETISKIN_GARSON || d.YetiskinGarson || d.AskiliYan || '', + yasPayloadMap: {}, aciklama: keep.aciklama, fiyat: keep.fiyat, adet: keep.adet, @@ -3096,12 +3109,34 @@ async function loadOrderInventory(merge = false) { console.log(`📦 MSSQL stok verisi geldi: ${data.length}`) console.table(data) + const pickPreferredYasPayloadLabel = (currentRaw, nextRaw) => { + const cur = String(currentRaw || '').trim().toUpperCase() + const nxt = String(nextRaw || '').trim().toUpperCase() + if (!nxt) return cur + if (!cur) return nxt + const curYas = /YAS$|YAŞ$/.test(cur) + const nxtYas = /YAS$|YAŞ$/.test(nxt) + if (!curYas && nxtYas) return nxt + return cur + } + // 1️⃣ Normalize (gelen büyük harfli) const invMap = {} + const invYasPayloadMap = {} for (const x of data) { - const beden = normalizeBedenLabel(String(x.Beden || '').trim()) + const rawBeden = String(x.Beden || '').trim() + const beden = normalizeBedenLabel(rawBeden) const stokDeger = Number(x.KullanilabilirAdet ?? 0) invMap[beden] = stokDeger + + const rawUpper = rawBeden.toUpperCase() + if (/^(\d+)\s*(Y|YAS|YAŞ)$/.test(rawUpper)) { + const canonical = normalizeBedenLabel(rawUpper) + invYasPayloadMap[canonical] = pickPreferredYasPayloadLabel( + invYasPayloadMap[canonical], + rawUpper + ) + } } // 2️⃣ Form bedenlerine göre map oluştur @@ -3125,6 +3160,7 @@ async function loadOrderInventory(merge = false) { beden, stok })) + form.yasPayloadMap = { ...(form.yasPayloadMap || {}), ...invYasPayloadMap } console.log('✅ Stok haritası güncellendi:', stockMap.value) } catch (err) { diff --git a/ui/src/stores/orderentryStore.js b/ui/src/stores/orderentryStore.js index 999a380..d69ca90 100644 --- a/ui/src/stores/orderentryStore.js +++ b/ui/src/stores/orderentryStore.js @@ -2521,6 +2521,7 @@ export const useOrderEntryStore = defineStore('orderentry', { ? '' : String(raw.ItemDim1Code).trim() const beden = bedenRaw === '' ? ' ' : normalizeBedenLabel(bedenRaw) + const bedenRawUpper = safeTrimUpperJs(bedenRaw) const qty = Number(raw.Qty1 || raw.Qty || 0) @@ -2562,6 +2563,7 @@ export const useOrderEntryStore = defineStore('orderentry', { __tmpMap: {}, // beden → qty lineIdMap: {}, // beden → OrderLineID + yasPayloadMap: {}, adet: 0, tutar: 0, @@ -2586,6 +2588,14 @@ export const useOrderEntryStore = defineStore('orderentry', { entry.lineIdMap[beden] = String(rawLineId) } + if (bedenRawUpper && /^(\d+)\s*(Y|YAS|YAŞ)$/.test(bedenRawUpper)) { + const canonical = normalizeBedenLabel(bedenRawUpper) + entry.yasPayloadMap[canonical] = pickPreferredYasPayloadLabel( + entry.yasPayloadMap[canonical], + bedenRawUpper + ) + } + if (qty > 0) { entry.__tmpMap[beden] = (entry.__tmpMap[beden] || 0) + qty entry.adet += qty @@ -2644,6 +2654,16 @@ export const useOrderEntryStore = defineStore('orderentry', { row.bedenMap[grpKey][' '] = Number(row.adet || 0) } + if (grpKey === 'yas') { + row.yasPayloadMap = row.yasPayloadMap || {} + for (const b of Object.keys(cleanedMap || {})) { + const s = String(b || '').trim() + if (/^\d+$/.test(s) && !row.yasPayloadMap[s]) { + row.yasPayloadMap[s] = `${s}Y` + } + } + } + delete row.__tmpMap out.push(row) } @@ -2695,6 +2715,7 @@ export const useOrderEntryStore = defineStore('orderentry', { const cached = sizeCache.value[cacheKey] bedenStock.value = [...cached.stockArray] stockMap.value = { ...cached.stockMap } + form.yasPayloadMap = { ...(cached.yasPayloadMap || {}) } console.log(`♻️ loadProductSizes CACHE → ${grpKey}`) return } @@ -2719,12 +2740,25 @@ export const useOrderEntryStore = defineStore('orderentry', { 📦 STOK MAP (' ' KORUNUR) ======================================================= */ const apiStockMap = {} + const apiYasPayloadMap = {} for (const x of data) { - const key = - x.item_dim1_code === null || x.item_dim1_code === '' + const rawDim1 = + x.item_dim1_code == null ? ' ' - : normalizeBedenLabel(String(x.item_dim1_code)) + : String(x.item_dim1_code) + const key = rawDim1 === ' ' + ? ' ' + : normalizeBedenLabel(rawDim1) apiStockMap[key] = Number(x.kullanilabilir_envanter ?? 0) + + const rawUpper = safeTrimUpperJs(rawDim1) + if (grpKey === 'yas' && /^(\d+)\s*(Y|YAS|YAŞ)$/.test(rawUpper)) { + const canonical = normalizeBedenLabel(rawUpper) + apiYasPayloadMap[canonical] = pickPreferredYasPayloadLabel( + apiYasPayloadMap[canonical], + rawUpper + ) + } } const finalStockMap = {} @@ -2740,6 +2774,7 @@ export const useOrderEntryStore = defineStore('orderentry', { bedenStock.value = Object.entries(stockMap.value).map( ([beden, stok]) => ({ beden, stok }) ) + form.yasPayloadMap = { ...(form.yasPayloadMap || {}), ...apiYasPayloadMap } /* ======================================================= 💾 CACHE @@ -2747,7 +2782,8 @@ export const useOrderEntryStore = defineStore('orderentry', { sizeCache.value[cacheKey] = { labels: [...form.bedenLabels], stockArray: [...bedenStock.value], - stockMap: { ...stockMap.value } + stockMap: { ...stockMap.value }, + yasPayloadMap: { ...(form.yasPayloadMap || {}) } } console.log(`✅ loadProductSizes FINAL v4.2 → ${grpKey}`) @@ -3334,10 +3370,16 @@ export const useOrderEntryStore = defineStore('orderentry', { } // UI'de yas grubu 2/4/6... gösterilir; payload'a 2Y/4Y/6... yazılır. - const toPayloadBeden = (grpKey, v) => { + const toPayloadBeden = (row, grpKey, v) => { const base = normBeden(v) if (!base) return '' if (grpKey === 'yas' && /^\d+$/.test(base)) { + const map = + row?.yasPayloadMap && typeof row.yasPayloadMap === 'object' + ? row.yasPayloadMap + : {} + const mapped = safeStr(map[base]).toUpperCase() + if (mapped) return mapped return `${base}Y` } return base @@ -3591,7 +3633,7 @@ export const useOrderEntryStore = defineStore('orderentry', { // ✅ UI/combokey için kanonik beden (yas'ta 2/4/6...) const bedenCanonical = normBeden(bedenRaw) // ✅ payload beden: yas grubunda 2Y/4Y/6..., diğerlerinde normal - const bedenPayload = toPayloadBeden(grpKey, bedenRaw) + const bedenPayload = toPayloadBeden(row, grpKey, bedenRaw) // ✅ combokey beden: boşsa '_' ile stabil kalsın const bedenKey = bedenCanonical || '_' @@ -3746,6 +3788,17 @@ function parseNumericSizeJs(v) { return Number.isNaN(n) ? null : n } +function pickPreferredYasPayloadLabel(currentRaw, nextRaw) { + const cur = safeTrimUpperJs(currentRaw) + const nxt = safeTrimUpperJs(nextRaw) + if (!nxt) return cur + if (!cur) return nxt + const curYas = /YAS$|YAŞ$/.test(cur) + const nxtYas = /YAS$|YAŞ$/.test(nxt) + if (!curYas && nxtYas) return nxt + return cur +} + export function normalizeBedenLabel(v) { let s = (v == null ? '' : String(v)).trim() if (s === '') return ' ' @@ -4059,6 +4112,7 @@ export function toSummaryRowFromForm(form) { urunAltGrubu: form.urunAltGrubu || '', kategori: form.kategori || '', yetiskinGarson: form.yetiskinGarson || form.askiliyan || '', + yasPayloadMap: { ...(form.yasPayloadMap || {}) }, aciklama: form.aciklama || '', fiyat: Number(form.fiyat || 0),