Merge remote-tracking branch 'origin/master'

This commit is contained in:
M_Kececi
2026-03-04 13:20:58 +03:00
parent 4dc0415546
commit 96d782e474
17 changed files with 1946 additions and 565 deletions

View File

@@ -2,6 +2,67 @@
import { defineStore } from 'pinia'
import api from 'src/services/api'
function normalizeTextForMatch (v) {
return String(v || '')
.trim()
.toUpperCase()
.normalize('NFD')
.replace(/[\u0300-\u036f]/g, '')
}
// Production ekranlari icin beden grup tespiti helper'i.
// Ozel kural:
// YETISKIN/GARSON = GARSON ve URUN ANA GRUBU "GOMLEK ATA YAKA" veya "GOMLEK KLASIK" ise => yas
export function detectProductionBedenGroup (bedenList, urunAnaGrubu = '', urunKategori = '', yetiskinGarson = '') {
const list = Array.isArray(bedenList) ? bedenList : []
const hasLetterSizes = list
.map(v => String(v || '').trim().toUpperCase())
.some(v => ['XS', 'S', 'M', 'L', 'XL', '2XL', '3XL', '4XL', '5XL', '6XL', '7XL'].includes(v))
const ana = normalizeTextForMatch(urunAnaGrubu)
const kat = normalizeTextForMatch(urunKategori)
const yg = normalizeTextForMatch(yetiskinGarson)
if ((kat.includes('GARSON') || yg.includes('GARSON')) &&
(ana.includes('GOMLEK ATAYAKA') || ana.includes('GOMLEK KLASIK'))) {
return 'yas'
}
if (hasLetterSizes) return 'gom'
if ((ana.includes('AYAKKABI') || kat.includes('AYAKKABI')) && (kat.includes('GARSON') || yg.includes('GARSON'))) return 'ayk_garson'
if (kat.includes('GARSON') || yg.includes('GARSON') || ana.includes('GARSON')) return 'yas'
if (ana.includes('PANTOLON') && kat.includes('YETISKIN')) return 'pan'
if (ana.includes('AKSESUAR')) return 'aksbir'
return 'tak'
}
function extractApiErrorMessage (err, fallback) {
const data = err?.response?.data
if (typeof data === 'string' && data.trim()) return data
if (data && typeof data === 'object') {
const msg = String(data.message || '').trim()
const step = String(data.step || '').trim()
const detail = String(data.detail || '').trim()
const parts = [msg]
if (step) parts.push(`step=${step}`)
if (detail) parts.push(detail)
const merged = parts.filter(Boolean).join(' | ')
if (merged) return merged
}
return err?.message || fallback
}
function logApiError (action, err, payload = null) {
const status = err?.response?.status
const data = err?.response?.data
console.error(`[OrderProductionItemStore] ${action} failed`, {
status,
payload,
data,
message: err?.message
})
}
export const useOrderProductionItemStore = defineStore('orderproductionitems', {
state: () => ({
items: [],
@@ -118,7 +179,8 @@ export const useOrderProductionItemStore = defineStore('orderproductionitems', {
)
return res?.data || { missingCount: 0, missing: [] }
} catch (err) {
this.error = err?.response?.data || err?.message || 'Kontrol basarisiz'
logApiError('validateUpdates', err, { orderHeaderID, lineCount: lines?.length || 0 })
this.error = extractApiErrorMessage(err, 'Kontrol basarisiz')
throw err
} finally {
this.saving = false
@@ -137,7 +199,8 @@ export const useOrderProductionItemStore = defineStore('orderproductionitems', {
)
return res?.data || { updated: 0, inserted: 0 }
} catch (err) {
this.error = err?.response?.data || err?.message || 'Guncelleme basarisiz'
logApiError('applyUpdates', err, { orderHeaderID, lineCount: lines?.length || 0, insertMissing })
this.error = extractApiErrorMessage(err, 'Guncelleme basarisiz')
throw err
} finally {
this.saving = false

View File

@@ -3438,17 +3438,28 @@ export function normalizeBeden(v) {
- Core logic aligned with backend detectBedenGroupGo
- Keeps frontend aksbir bucket for accessory lines
=========================================================== */
export function detectBedenGroup(bedenList, urunAnaGrubu = '', urunKategori = '') {
export function detectBedenGroup(bedenList, urunAnaGrubu = '', urunKategori = '', yetiskinGarson = '') {
const list = Array.isArray(bedenList) && bedenList.length > 0
? bedenList.map(v => (v || '').toString().trim().toUpperCase())
: [' ']
const rawAna = (urunAnaGrubu || '').toString().toUpperCase()
const rawKat = (urunKategori || '').toString().toUpperCase()
const hasGarson = rawAna.includes('GARSON') || rawKat.includes('GARSON') ||
rawAna.includes('GARSON') || rawKat.includes('GARSON')
const hasAyakkabi = rawAna.includes('AYAKKABI') || rawKat.includes('AYAKKABI') ||
rawAna.includes('AYAKKABI') || rawKat.includes('AYAKKABI')
const rawAna = normalizeTextForMatch(urunAnaGrubu || '')
const rawKat = normalizeTextForMatch(urunKategori || '')
const rawYetiskinGarson = normalizeTextForMatch(yetiskinGarson || '')
// Ozel kural:
// YETISKIN/GARSON = GARSON ve URUN ANA GRUBU "GOMLEK ATA YAKA" veya "GOMLEK KLASIK" ise
// sonuc "yas" olmalidir.
const isGarsonGomlekAnaGrubu =
rawAna.includes('GOMLEK ATA YAKA') ||
rawAna.includes('GOMLEK KLASIK')
const hasGarsonSignal = rawAna.includes('GARSON') || rawKat.includes('GARSON') || rawYetiskinGarson.includes('GARSON')
if (isGarsonGomlekAnaGrubu && (rawKat.includes('GARSON') || rawYetiskinGarson.includes('GARSON'))) {
return 'yas'
}
const hasGarson = hasGarsonSignal
const hasAyakkabi = rawAna.includes('AYAKKABI') || rawKat.includes('AYAKKABI')
if (hasGarson && hasAyakkabi) return 'ayk_garson'
if (hasGarson) return 'yas'
@@ -3457,28 +3468,27 @@ 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 = (urunAnaGrubu || '')
.toUpperCase()
const ana = normalizeTextForMatch(urunAnaGrubu || '')
.trim()
.replace(/\(.*?\)/g, '')
.replace(/[^A-ZÇĞİÖŞÜ0-9\s]/g, '')
.replace(/[^A-Z0-9\s]/g, '')
.replace(/\s+/g, ' ')
const kat = (urunKategori || '').toUpperCase().trim()
const kat = normalizeTextForMatch(urunKategori || '').trim()
// 🔸 Aksesuar ise "aksbir"
const aksesuarGruplari = [
'AKSESUAR','KRAVAT','PAPYON','KEMER','CORAP','ÇORAP',
'FULAR','MENDIL','MENDİL','KASKOL','ASKI',
'YAKA','KOL DUGMESI','KOL DÜĞMESİ'
'AKSESUAR','KRAVAT','PAPYON','KEMER','CORAP',
'FULAR','MENDIL','KASKOL','ASKI',
'YAKA','KOL DUGMESI'
]
const giyimGruplari = ['GÖMLEK','CEKET','PANTOLON','MONT','YELEK','TAKIM','TSHIRT','TİŞÖRT']
const giyimGruplari = ['GOMLEK','CEKET','PANTOLON','MONT','YELEK','TAKIM','TSHIRT','TISORT']
// 🔸 Pantolon özel durumu
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'
if (ana.includes('PANTOLON') && kat.includes('YETISKIN')) return 'pan'
// 🔸 Tamamen numerik (örneğin 39-44 arası) → ayakkabı
const allNumeric = list.every(v => /^\d+$/.test(v))
if (allNumeric) {
@@ -3488,7 +3498,7 @@ export function detectBedenGroup(bedenList, urunAnaGrubu = '', urunKategori = ''
}
// 🔸 Yaş grubu (çocuk/garson)
if (kat.includes('GARSON') || kat.includes('ÇOCUK')) return 'yas'
if (kat.includes('GARSON') || kat.includes('COCUK')) return 'yas'
// 🔸 Varsayılan: takım elbise
return 'tak'