Merge remote-tracking branch 'origin/master'

This commit is contained in:
2026-02-16 15:53:00 +03:00
parent f8b07a6aea
commit 5124ad78af
6 changed files with 104 additions and 63 deletions

View File

@@ -48,7 +48,7 @@ export const BEDEN_SCHEMA = [
{ key: 'pan', title: 'PANTOLON', values: ['38','40','42','44','46','48','50','52','54','56','58','60','62','64','66','68'] },
{ key: 'gom', title: 'GOMLEK', values: ['XS','S','M','L','XL','2XL','3XL','4XL','5XL','6XL','7XL'] },
{ key: 'tak', title: 'TAKIM ELBISE', values: ['44','46','48','50','52','54','56','58','60','62','64','66','68','70','72','74'] },
{ key: 'aksbir', title: 'AKSESUAR', values: [' ', '44', 'STD', '110CM', '115CM', '120CM', '125CM', '130CM', '135CM'] }
{ key: 'aksbir', title: 'AKSESUAR', values: [' ', '44', 'STD', '110', '115', '120', '125', '130', '135'] }
]
export const schemaByKey = BEDEN_SCHEMA.reduce((m, g) => {
@@ -1826,7 +1826,7 @@ export const useOrderEntryStore = defineStore('orderentry', {
for (const [k, v] of Object.entries(newMap || {})) {
const beden = (k == null || String(k).trim() === '')
? ' '
: normalizeBeden(String(k))
: normalizeBedenLabel(String(k))
merged[beden] = Number(merged[beden] || 0) + Number(v || 0)
}
@@ -2244,7 +2244,7 @@ export const useOrderEntryStore = defineStore('orderentry', {
raw.ItemDim1Code == null
? ''
: String(raw.ItemDim1Code).trim()
const beden = bedenRaw === '' ? ' ' : normalizeBeden(bedenRaw)
const beden = bedenRaw === '' ? ' ' : normalizeBedenLabel(bedenRaw)
const qty = Number(raw.Qty1 || raw.Qty || 0)
@@ -3276,85 +3276,128 @@ export const useOrderEntryStore = defineStore('orderentry', {
/* ===========================================================
🔹 BEDEN LABEL NORMALİZASYONU (exported helper)
Size Label Normalization (frontend helper)
=========================================================== */
function safeTrimUpperJs(v) {
return (v == null ? '' : String(v)).trim().toUpperCase()
}
function normalizeTextForMatch(v) {
return safeTrimUpperJs(v)
.normalize('NFD')
.replace(/[\u0300-\u036f]/g, '')
}
function parseNumericSizeJs(v) {
const s = safeTrimUpperJs(v)
if (s === '' || !/^\d+$/.test(s)) return null
const n = Number.parseInt(s, 10)
return Number.isNaN(n) ? null : n
}
export function normalizeBedenLabel(v) {
if (v === null || v === undefined) return ' '
let s = String(v).trim()
let s = (v == null ? '' : String(v)).trim()
if (s === '') return ' '
// 44R, 50L vb. son ekleri at
s = s.replace(/(^\d+)\s*[A-Z]?$/i, '$1')
s = s.toUpperCase()
// harfli bedenlerin normalizasyonu
const map = {
'XS': 'XS', 'S': 'S', 'M': 'M', 'L': 'L', 'XL': 'XL',
'XXL': '2XL', '2XL': '2XL', '3XL': '3XL', '4XL': '4XL',
'5XL': '5XL', '6XL': '6XL', '7XL': '7XL', 'STD': 'STD'
// Backend parity: normalize common "standard size" aliases.
switch (s) {
case 'STD':
case 'STANDART':
case 'STANDARD':
case 'ONE SIZE':
case 'ONESIZE':
return 'STD'
}
if (map[s]) return map[s]
// tamamen sayıysa string olarak döndür
if (/^\d+$/.test(s)) return s
// Backend parity: only values ending with CM are converted to numeric part.
if (s.endsWith('CM')) {
const num = s.slice(0, -2).trim()
if (num !== '') return num
}
switch (s) {
case 'XS':
case 'S':
case 'M':
case 'L':
case 'XL':
case '2XL':
case '3XL':
case '4XL':
case '5XL':
case '6XL':
case '7XL':
return s
}
// virgüllü değer geldiyse ilkini al
if (s.includes(',')) return s.split(',')[0].trim()
return s
}
/* ===========================================================
🔹 BEDEN GRUBU ALGILAMA HELPER’I
-----------------------------------------------------------
Gelen beden listesini, ürün grubu/kategori bilgisine göre
doğru grup anahtarına dönüştürür (ayk, yas, pan, gom, tak, aksbir).
-----------------------------------------------------------
=========================================================== */
Size Group Detection
- Core logic aligned with backend detectBedenGroupGo
- Keeps frontend aksbir bucket for accessory lines
=========================================================== */
export function detectBedenGroup(bedenList, urunAnaGrubu = '', urunKategori = '') {
const list = Array.isArray(bedenList) && bedenList.length > 0
? bedenList.map(v => (v || '').toString().trim().toUpperCase())
: [' ']
const list = Array.isArray(bedenList) ? bedenList : []
const ana = normalizeTextForMatch(urunAnaGrubu)
const alt = normalizeTextForMatch(urunKategori)
const ana = (urunAnaGrubu || '')
.toUpperCase()
.trim()
.replace(/\(.*?\)/g, '')
.replace(/[^A-ZÇĞİÃŞÜ0-9\s]/g, '')
.replace(/\s+/g, ' ')
const kat = (urunKategori || '').toUpperCase().trim()
// 🔸 Aksesuar ise "aksbir"
const aksesuarGruplari = [
'AKSESUAR','KRAVAT','PAPYON','KEMER','CORAP','ÇORAP',
'FULAR','MENDIL','MENDİL','KASKOL','ASKI',
'YAKA','KOL DUGMESI','KOL DÜĞMESİ'
// Frontend compatibility: accessory-only products should stay in aksbir.
const accessoryGroups = [
'AKSESUAR', 'KRAVAT', 'PAPYON', 'KEMER', 'CORAP',
'FULAR', 'MENDIL', 'KASKOL', 'ASKI', 'YAKA', 'KOL DUGMESI'
]
const giyimGruplari = ['GÖMLEK','CEKET','PANTOLON','MONT','YELEK','TAKIM','TSHIRT','TİŞÃRT']
// 🔸 Pantolon özel durumu
const clothingGroups = ['GOMLEK', 'CEKET', 'PANTOLON', 'MONT', 'YELEK', 'TAKIM', 'TSHIRT']
if (
aksesuarGruplari.some(g => ana.includes(g) || kat.includes(g)) &&
!giyimGruplari.some(g => ana.includes(g))
) return 'aksbir'
if (ana.includes('PANTOLON') && kat.includes('YETİŞKİN')) return 'pan'
// 🔸 Tamamen numerik (örneğin 39-44 arası) → ayakkabı
const allNumeric = list.every(v => /^\d+$/.test(v))
if (allNumeric) {
const nums = list.map(v => parseInt(v, 10)).filter(Boolean)
const diffs = nums.slice(1).map((v, i) => v - nums[i])
if (diffs.every(d => d === 1) && nums[0] >= 35 && nums[0] <= 46) return 'ayk'
accessoryGroups.some(g => ana.includes(g) || alt.includes(g)) &&
!clothingGroups.some(g => ana.includes(g))
) {
return 'aksbir'
}
// 🔸 Yaş grubu (çocuk/garson)
if (kat.includes('GARSON') || kat.includes('ÇOCUK')) return 'yas'
if (ana.includes('AYAKKABI') || alt.includes('AYAKKABI')) {
return 'ayk'
}
// 🔸 Harfli beden varsa doğrudan "gom" (gömlek, üst giyim)
const harfliBedenler = ['XS','S','M','L','XL','XXL','2XL','3XL','4XL','5XL','6XL','7XL']
if (list.some(b => harfliBedenler.includes(b))) return 'gom'
let hasYasNumeric = false
let hasAykNumeric = false
let hasPanNumeric = false
for (const raw of list) {
const b = safeTrimUpperJs(raw)
switch (b) {
case 'XS':
case 'S':
case 'M':
case 'L':
case 'XL':
case '2XL':
case '3XL':
case '4XL':
case '5XL':
case '6XL':
case '7XL':
return 'gom'
}
const n = parseNumericSizeJs(b)
if (n == null) continue
if (n >= 2 && n <= 14) hasYasNumeric = true
if (n >= 39 && n <= 45) hasAykNumeric = true
if (n >= 38 && n <= 68) hasPanNumeric = true
}
if (hasAykNumeric) return 'ayk'
if (ana.includes('PANTOLON')) return 'pan'
if (hasPanNumeric) return 'pan'
if (alt.includes('COCUK') || alt.includes('GARSON')) return 'yas'
if (hasYasNumeric) return 'yas'
// 🔸 Varsayılan: takım elbise
return 'tak'
}
@@ -3372,7 +3415,7 @@ export function toSummaryRowFromForm(form) {
const lbl =
rawLbl == null || String(rawLbl).trim() === ''
? ' '
: normalizeBeden(String(rawLbl))
: normalizeBedenLabel(String(rawLbl))
const val = Number(values[i] || 0)
if (val > 0) {