From 96ede5593689f06574235e3b4f6adacbb7db9054 Mon Sep 17 00:00:00 2001 From: M_Kececi Date: Tue, 24 Mar 2026 15:38:26 +0300 Subject: [PATCH] Merge remote-tracking branch 'origin/master' --- svc/routes/order_pdf.go | 10 ++++++ ui/src/pages/OrderEntry.vue | 14 +++++++- ui/src/stores/orderentryStore.js | 56 ++++++++++++++++++++++++-------- 3 files changed, 66 insertions(+), 14 deletions(-) diff --git a/svc/routes/order_pdf.go b/svc/routes/order_pdf.go index 0f0395b..ecce0a5 100644 --- a/svc/routes/order_pdf.go +++ b/svc/routes/order_pdf.go @@ -336,6 +336,16 @@ func detectBedenGroupGo(bedenList []string, ana, alt string) string { ana = normalizeTextForMatchGo(ana) alt = normalizeTextForMatchGo(alt) + isYetiskin := strings.Contains(alt, "YETISKIN") || strings.Contains(alt, "YETISKIN/GARSON") + isGomlekKlasikOrAtayaka := strings.Contains(ana, "GOMLEK KLASIK") || + strings.Contains(ana, "GOMLEK ATA YAKA") || + strings.Contains(ana, "GOMLEK ATAYAKA") + // Özel kural: + // Kategorisi YETISKIN ve ana grubu GOMLEK KLASIK/ATA YAKA olanlar "gom" grubunda raporlanır. + if isYetiskin && isGomlekKlasikOrAtayaka { + return catGom + } + // Beden seti çocuk yaş formatındaysa metadata beklemeden "yas" aç. yasNums := map[string]bool{"2": true, "4": true, "6": true, "8": true, "10": true, "12": true, "14": true} if len(bedenList) > 0 { diff --git a/ui/src/pages/OrderEntry.vue b/ui/src/pages/OrderEntry.vue index a5ec451..6791a5f 100644 --- a/ui/src/pages/OrderEntry.vue +++ b/ui/src/pages/OrderEntry.vue @@ -2689,7 +2689,7 @@ async function onModelChange(modelCode) { } if (!bedenGrpKey) { - const anaN = String(form.urunAnaGrubu || '') + const anaNRaw = String(form.urunAnaGrubu || '') .normalize('NFD') .replace(/[\u0300-\u036f]/g, '') .toLowerCase() @@ -2704,6 +2704,10 @@ async function onModelChange(modelCode) { .replace(/[\u0300-\u036f]/g, '') .toLowerCase() .trim() + const anaN = + (katN.includes('yetiskin') && anaNRaw.includes('gomlek klasik')) + ? anaNRaw.replace('gomlek klasik', 'gomlek ata yaka') + : anaNRaw const hasGarsonMeta = anaN.includes('garson') || @@ -2862,6 +2866,10 @@ const onSaveOrUpdateRow = async () => { recalcVat: typeof recalcVat === 'function' ? recalcVat : null, resetEditor: typeof resetEditor === 'function' ? resetEditor : null, + loadProductSizes: async () => { + await orderStore.loadProductSizes(form, true, $q, productCache) + await loadOrderInventory(true) + }, // gerekiyorsa pass edebilirsin (store tarafında zaten optional) stockMap, @@ -2910,6 +2918,10 @@ const onSaveAndNextColor = async () => { form, recalcVat: typeof recalcVat === 'function' ? recalcVat : null, resetEditor: () => {}, + loadProductSizes: async () => { + await orderStore.loadProductSizes(form, true, $q, productCache) + await loadOrderInventory(true) + }, stockMap, $q }) diff --git a/ui/src/stores/orderentryStore.js b/ui/src/stores/orderentryStore.js index 70bf7e3..6da0839 100644 --- a/ui/src/stores/orderentryStore.js +++ b/ui/src/stores/orderentryStore.js @@ -1685,18 +1685,32 @@ export const useOrderEntryStore = defineStore('orderentry', { const overLimit = [] for (let i = 0; i < bedenLabels.length; i++) { - const lbl = String(bedenLabels[i] ?? '').trim() - const stok = Number(stockMapLocal?.[lbl] ?? 0) + const rawLbl = String(bedenLabels[i] ?? '') + const lbl = rawLbl.trim() === '' ? ' ' : rawLbl + const hasExactKey = Object.prototype.hasOwnProperty.call(stockMapLocal || {}, lbl) + const hasTrimKey = Object.prototype.hasOwnProperty.call(stockMapLocal || {}, rawLbl.trim()) + const stokRaw = hasExactKey + ? stockMapLocal?.[lbl] + : hasTrimKey + ? stockMapLocal?.[rawLbl.trim()] + : undefined + const stok = Number(stokRaw ?? 0) const girilen = Number(bedenValues?.[i] ?? 0) - if (stok > 0 && girilen > stok) { - overLimit.push({ beden: lbl, stok, girilen }) + // Stok 0 veya stok kaydı yokken giriş yapılırsa da uyarı ver. + if (girilen > 0 && girilen > stok) { + overLimit.push({ + beden: lbl, + stok, + girilen, + stokKaydiVar: hasExactKey || hasTrimKey + }) } } if (overLimit.length && $q) { const msg = overLimit - .map(x => `• ${x.beden}: ${x.girilen} (Stok: ${x.stok})`) + .map(x => `• ${x.beden}: ${x.girilen} (Stok: ${x.stokKaydiVar ? x.stok : 'kayıt yok'})`) .join('
') const stokOK = await new Promise(resolve => { @@ -3617,6 +3631,21 @@ export function detectBedenGroup(bedenList, urunAnaGrubu = '', urunKategori = '' ? bedenList.map(v => (v || '').toString().trim().toUpperCase()) : [' '] + const rawAna = normalizeTextForMatch(urunAnaGrubu || '') + const rawKat = normalizeTextForMatch(urunKategori || '') + const rawYetiskinGarson = normalizeTextForMatch(yetiskinGarson || '') + const isYetiskin = rawKat.includes('YETISKIN') + const isGomlekKlasikOrAtayaka = + rawAna.includes('GOMLEK KLASIK') || + rawAna.includes('GOMLEK ATA YAKA') || + rawAna.includes('GOMLEK ATAYAKA') + + // Özel kural: + // Kategorisi YETISKIN ve ana grubu GOMLEK KLASIK/ATA YAKA olanlar her zaman "gom" grubundadır. + if (isYetiskin && isGomlekKlasikOrAtayaka) { + return 'gom' + } + // Beden seti çocuk yaş formatındaysa metadata beklemeden "yas" aç. // Örn: 2,4,6,8,10,12,14 veya 2Y,4Y,6Y... const yasNums = new Set(['2', '4', '6', '8', '10', '12', '14']) @@ -3626,18 +3655,19 @@ export function detectBedenGroup(bedenList, urunAnaGrubu = '', urunKategori = '' return 'yas' } - const rawAna = normalizeTextForMatch(urunAnaGrubu || '') - const rawKat = normalizeTextForMatch(urunKategori || '') - const rawYetiskinGarson = normalizeTextForMatch(yetiskinGarson || '') + const isYetiskinGomlekKlasik = isYetiskin && rawAna.includes('GOMLEK KLASIK') + const mappedRawAna = isYetiskinGomlekKlasik + ? rawAna.replace('GOMLEK KLASIK', 'GOMLEK ATA YAKA') + : rawAna // Ozel kural: // YETISKIN/GARSON = GARSON ve URUN ANA GRUBU "GOMLEK ATA YAKA" veya "GOMLEK KLASIK" ise // sonuc "yas" olmalidir. const isGarsonGomlekAnaGrubu = - rawAna.includes('GOMLEK ATAYAKA') || - rawAna.includes('GOMLEK ATA YAKA') || - rawAna.includes('GOMLEK KLASIK') - const hasGarsonSignal = rawAna.includes('GARSON') || rawKat.includes('GARSON') || rawYetiskinGarson.includes('GARSON') + mappedRawAna.includes('GOMLEK ATAYAKA') || + mappedRawAna.includes('GOMLEK ATA YAKA') || + mappedRawAna.includes('GOMLEK KLASIK') + const hasGarsonSignal = mappedRawAna.includes('GARSON') || rawKat.includes('GARSON') || rawYetiskinGarson.includes('GARSON') if (isGarsonGomlekAnaGrubu && (rawKat.includes('GARSON') || rawYetiskinGarson.includes('GARSON'))) { return 'yas' } @@ -3650,7 +3680,7 @@ export function detectBedenGroup(bedenList, urunAnaGrubu = '', urunKategori = '' const harfliBedenler = ['XS','S','M','L','XL','2XL','3XL','4XL','5XL','6XL','7XL'] if (list.some(b => harfliBedenler.includes(b))) return 'gom' - const ana = normalizeTextForMatch(urunAnaGrubu || '') + const ana = mappedRawAna .trim() .replace(/\(.*?\)/g, '') .replace(/[^A-Z0-9\s]/g, '')