From a2a756870d20273df514fd3f016e61b8ea834ff7 Mon Sep 17 00:00:00 2001 From: MEHMETKECECI Date: Sat, 14 Feb 2026 19:57:41 +0300 Subject: [PATCH] Merge remote-tracking branch 'origin/master' --- ui/src/services/api.js | 43 +- ui/src/stores/downloadstHeadStore.js | 20 +- ui/src/stores/downloadstpdfStore.js | 26 +- ui/src/stores/orderentryStore.js | 900 +++++++++++++-------------- 4 files changed, 501 insertions(+), 488 deletions(-) diff --git a/ui/src/services/api.js b/ui/src/services/api.js index 8c6bb3b..61a92a5 100644 --- a/ui/src/services/api.js +++ b/ui/src/services/api.js @@ -37,6 +37,17 @@ let isLoggingOut = false api.interceptors.response.use( r => r, async (error) => { + const status = error?.response?.status + const hasBlob = typeof Blob !== 'undefined' && error?.response?.data instanceof Blob + + if ((status >= 500 || hasBlob) && error) { + const method = String(error?.config?.method || 'GET').toUpperCase() + const url = error?.config?.url || '' + const detail = await extractApiErrorDetail(error) + error.parsedMessage = detail + console.error(`❌ API ${status || '-'} ${method} ${url}: ${detail}`) + } + if (error?.response?.status === 401 && !isLoggingOut) { isLoggingOut = true try { @@ -98,23 +109,31 @@ async function parseBlobErrorMessage(data) { return '' } +export async function extractApiErrorDetail(err) { + let detail = + err?.parsedMessage || + err?.response?.data?.detail || + err?.response?.data?.message || + err?.response?.data?.error || + '' + + if (!detail) { + detail = await parseBlobErrorMessage(err?.response?.data) + } + + if (!detail) { + detail = err?.message || 'Request failed' + } + + return detail +} + export const download = async (u, p = {}, c = {}) => { try { const r = await api.get(u, { params: p, responseType: 'blob', ...c }) return r.data } catch (err) { - let detail = - err?.response?.data?.detail || - err?.response?.data?.message || - '' - - if (!detail) { - detail = await parseBlobErrorMessage(err?.response?.data) - } - - if (!detail) { - detail = err?.message || 'Download failed' - } + const detail = await extractApiErrorDetail(err) const wrapped = new Error(detail) wrapped.status = err?.response?.status diff --git a/ui/src/stores/downloadstHeadStore.js b/ui/src/stores/downloadstHeadStore.js index ad60b1f..7d6b1c9 100644 --- a/ui/src/stores/downloadstHeadStore.js +++ b/ui/src/stores/downloadstHeadStore.js @@ -1,10 +1,10 @@ -// src/stores/downloadstHeadStore.js +// src/stores/downloadstHeadStore.js import { defineStore } from 'pinia' -import { download } from 'src/services/api' +import { download, extractApiErrorDetail } from 'src/services/api' export const useDownloadstHeadStore = defineStore('downloadstHead', { actions: { - // 📄 Statement Header PDF indir / aç + // 📄 Statement Header PDF indir / aç async handlestHeadDownload ( accountCode, startDate, @@ -12,7 +12,7 @@ export const useDownloadstHeadStore = defineStore('downloadstHead', { parislemler ) { try { - // ✅ Params (axios paramsSerializer array=repeat destekliyor) + // ✅ Params (axios paramsSerializer array=repeat destekliyor) const params = { accountcode: accountCode, startdate: startDate, @@ -25,7 +25,7 @@ export const useDownloadstHeadStore = defineStore('downloadstHead', { ) } - // 🔥 API CALL (TOKEN + BLOB + ERROR HANDLING OTOMATİK) + // 🔥 API CALL (TOKEN + BLOB + ERROR HANDLING OTOMATİK) const blob = await download( '/exportstamentheaderreport-pdf', params @@ -34,15 +34,17 @@ export const useDownloadstHeadStore = defineStore('downloadstHead', { const pdfUrl = window.URL.createObjectURL(blob) window.open(pdfUrl, '_blank') - return { ok: true, message: '📄 PDF hazırlandı' } + return { ok: true, message: '📄 PDF hazırlandı' } } catch (err) { - console.error('❌ PDF açma hatası:', err) + const detail = await extractApiErrorDetail(err) + const status = err?.status || err?.response?.status || '-' + console.error(`❌ PDF açma hatası [${status}] /exportstamentheaderreport-pdf: ${detail}`) return { ok: false, message: - err?.message || - '❌ PDF açma hatası' + detail || + 'PDF açma hatası' } } } diff --git a/ui/src/stores/downloadstpdfStore.js b/ui/src/stores/downloadstpdfStore.js index d857edd..e6b860f 100644 --- a/ui/src/stores/downloadstpdfStore.js +++ b/ui/src/stores/downloadstpdfStore.js @@ -1,15 +1,15 @@ -// src/stores/downloadstpdfStore.js +// src/stores/downloadstpdfStore.js import { defineStore } from 'pinia' -import { download } from 'src/services/api' +import { download, extractApiErrorDetail } from 'src/services/api' export const useDownloadstpdfStore = defineStore('downloadstpdf', { actions: { /* ========================================================== - 📄 PDF İNDİR / AÇ + 📄 PDF İNDİR / AÇ ========================================================== */ async downloadPDF(accountCode, startDate, endDate, parislemler = []) { try { - // 🔹 Query params + // 🔹 Query params const params = { accountcode: accountCode, startdate: startDate, @@ -22,28 +22,30 @@ export const useDownloadstpdfStore = defineStore('downloadstpdf', { ) } - // 🔥 MERKEZİ API — BLOB + // 🔥 MERKEZİ API — BLOB const blob = await download('/export-pdf', params) - // 🔹 Blob → URL + // 🔹 Blob → URL const pdfUrl = window.URL.createObjectURL( new Blob([blob], { type: 'application/pdf' }) ) - // 🔹 Yeni sekmede aç + // 🔹 Yeni sekmede aç window.open(pdfUrl, '_blank') - console.log('✅ PDF yeni sekmede açıldı') - return { ok: true, message: '📄 PDF hazırlandı' } + console.log('✅ PDF yeni sekmede açıldı') + return { ok: true, message: '📄 PDF hazırlandı' } } catch (err) { - console.error('❌ PDF açma hatası:', err) + const detail = await extractApiErrorDetail(err) + const status = err?.status || err?.response?.status || '-' + console.error(`❌ PDF açma hatası [${status}] /export-pdf: ${detail}`) return { ok: false, message: - err?.message || - '❌ PDF alınamadı' + detail || + 'PDF alınamadı' } } } diff --git a/ui/src/stores/orderentryStore.js b/ui/src/stores/orderentryStore.js index 8bf190f..c036056 100644 --- a/ui/src/stores/orderentryStore.js +++ b/ui/src/stores/orderentryStore.js @@ -1,25 +1,25 @@ -/* =========================================================== - 📦 orderentryStore.js (v3.4 CLEAN — AUTH + LOCAL PERSIST + AUTO RESUME) +/* =========================================================== + 📦 orderentryStore.js (v3.4 CLEAN — AUTH + LOCAL PERSIST + AUTO RESUME) =========================================================== */ import { defineStore } from 'pinia' -import api from 'src/services/api' +import api, { extractApiErrorDetail } from 'src/services/api' import dayjs from 'src/boot/dayjs' -import { ref, toRaw, nextTick } from 'vue' // ✅ düzeltildi +import { ref, toRaw, nextTick } from 'vue' // ✅ düzeltildi import { useAuthStore } from 'src/stores/authStore' // =========================================================== -// 🔹 Shared Reactive Referanslar (Global, Reaktif Nesneler) +// 🔹 Shared Reactive Referanslar (Global, Reaktif Nesneler) // =========================================================== /* =========================================================== - 🔹 BEDEN ŞEMALARI — STORE SOURCE OF TRUTH + 🔹 BEDEN ŞEMALARI — STORE SOURCE OF TRUTH =========================================================== */ -// ⬆️ orderentryStore.js EN ÜSTÜNE +// ⬆️ orderentryStore.js EN ÜSTÜNE // =========================================================== -// 🔑 COMBO KEY CONTRACT (Frontend ↔ Backend) — v1 +// 🔑 COMBO KEY CONTRACT (Frontend ↔ Backend) — v1 // - trim + UPPER -// - dim1 boşsa " " -// - dim2 boşsa "" +// - dim1 boÅŸsa " " +// - dim2 boÅŸsa "" // =========================================================== const BEDEN_EMPTY = '_' @@ -33,7 +33,7 @@ export function buildComboKey(row, beden) { const bdn = normUpper(beden) const bedenFinal = bdn === '' ? BEDEN_EMPTY : bdn - // 🔒 KANONİK SIRA + // 🔒 KANONİK SIRA return `${model}||${renk}||${renk2}||${bedenFinal}` } @@ -44,10 +44,10 @@ export function buildComboKey(row, beden) { export const BEDEN_SCHEMA = [ { key: 'ayk', title: 'AYAKKABI', values: ['39','40','41','42','43','44','45'] }, - { key: 'yas', title: 'YAŞ', values: ['2','4','6','8','10','12','14'] }, + { key: 'yas', title: 'YAS', values: ['2','4','6','8','10','12','14'] }, { key: 'pan', title: 'PANTOLON', values: ['38','40','42','44','46','48','50','52','54','56','58','60','62','64','66','68'] }, - { key: 'gom', title: 'GÖMLEK', values: ['XS','S','M','L','XL','2XL','3XL','4XL','5XL','6XL','7XL'] }, - { key: 'tak', title: 'TAKIM ELBİSE', values: ['44','46','48','50','52','54','56','58','60','62','64','66','68','70','72','74'] }, + { 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'] } ] @@ -61,10 +61,10 @@ export const stockMap = ref({}) export const bedenStock = ref([]) export const sizeCache = ref({}) // =========================================================== -// 🔹 Shared Reactive Referanslar (Global, Reaktif Nesneler) +// 🔹 Shared Reactive Referanslar (Global, Reaktif Nesneler) // =========================================================== // ======================== -// 🧰 GLOBAL DATE NORMALIZER +// 🧰 GLOBAL DATE NORMALIZER // ======================== function newGuid() { @@ -73,7 +73,7 @@ function newGuid() { -// 🔑 Her beden satırı için deterministik clientKey üretimi +// 🔑 Her beden satırı için deterministik clientKey üretimi function makeLineClientKey(row, grpKey, beden) { const base = row.clientRowKey || @@ -89,7 +89,7 @@ function makeLineClientKey(row, grpKey, beden) { // =========================================================== -// 🧩 Pinia Store — ORDER ENTRY STORE (REV 2025-11-03.2) +// 🧩 Pinia Store — ORDER ENTRY STORE (REV 2025-11-03.2) // =========================================================== export const useOrderEntryStore = defineStore('orderentry', { state: () => ({ @@ -145,12 +145,12 @@ export const useOrderEntryStore = defineStore('orderentry', { getters: { getDraftKey() { - // NEW taslak → GLOBAL ama tekil + // NEW taslak → GLOBAL ama tekil return 'bss_orderentry_new_draft' }, getEditKey() { - // EDIT → OrderHeaderID’ye bağlı + // EDIT → OrderHeaderID’ye baÄŸlı const id = this.header?.OrderHeaderID return id ? `bss_orderentry_edit:${id}` : null } @@ -201,7 +201,7 @@ export const useOrderEntryStore = defineStore('orderentry', { , /* =========================================================== - 🧩 initSchemaMap — BEDEN ŞEMA İNİT + 🧩 initSchemaMap — BEDEN ŞEMA İNİT - TEK SOURCE OF TRUTH: BEDEN_SCHEMA =========================================================== */ initSchemaMap() { @@ -222,7 +222,7 @@ export const useOrderEntryStore = defineStore('orderentry', { this.schemaMap = map console.log( - '🧩 schemaMap INIT edildi:', + '🧩 schemaMap INIT edildi:', Object.keys(this.schemaMap) ) }, @@ -244,32 +244,32 @@ export const useOrderEntryStore = defineStore('orderentry', { 0 ) - // Header sadece GÖSTERİM / BACKEND için + // Header sadece GÖSTERİM / BACKEND için if (this.header) { this.header.TotalAmount = Number(total.toFixed(2)) } return total } catch (err) { - console.error('❌ updateHeaderTotals hata:', err) + console.error('❌ updateHeaderTotals hata:', err) return 0 } } , /* =========================================================== - 🚨 showInvalidVariantDialog — FINAL + 🚨 showInvalidVariantDialog — FINAL ----------------------------------------------------------- - ✔ prItemVariant olmayan satırları listeler - ✔ Satıra tıkla → scroll + highlight - ✔ Kaydı BLOKLAYAN tek UI noktası + ✔ prItemVariant olmayan satırları listeler + ✔ Satıra tıkla → scroll + highlight + ✔ Kaydı BLOKLAYAN tek UI noktası =========================================================== */ async showInvalidVariantDialog($q, invalidList = []) { if (!Array.isArray(invalidList) || invalidList.length === 0) return return new Promise(resolve => { const dlg = $q.dialog({ - title: '🚨 Tanımsız Ürün Kombinasyonları', + title: '🚨 Tanımsız Ürün Kombinasyonları', message: `
${invalidList.map((v, i) => ` @@ -288,12 +288,12 @@ export const useOrderEntryStore = defineStore('orderentry', { #${i + 1} | Item: ${v.itemCode}
- Beden: ${v.dim1 || '(boş)'} | + Beden: ${v.dim1 || '(boÅŸ)'} | Renk: ${v.colorCode || '-'} | Qty: ${v.qty1}
- Sebep: ${v.reason || 'Tanımsız ürün kombinasyonu'} + Sebep: ${v.reason || 'Tanımsız ürün kombinasyonu'}
`).join('')} @@ -301,7 +301,7 @@ export const useOrderEntryStore = defineStore('orderentry', { `, html: true, ok: { - label: 'Düzelt', + label: 'Düzelt', color: 'negative' }, cancel: false, @@ -310,7 +310,7 @@ export const useOrderEntryStore = defineStore('orderentry', { .onOk(() => resolve()) .onDismiss(() => resolve()) - // Quasar v2 chain API'de onShown yok; dialog DOM'u render olduktan sonra bağla. + // Quasar v2 chain API'de onShown yok; dialog DOM'u render olduktan sonra baÄŸla. setTimeout(() => { if (!dlg) return const nodes = document.querySelectorAll('.invalid-row') @@ -325,42 +325,42 @@ export const useOrderEntryStore = defineStore('orderentry', { } , /* =========================================================== - 🎯 scrollToInvalidRow — FINAL + 🎯 scrollToInvalidRow — FINAL ----------------------------------------------------------- - ✔ ClientKey bazlı scroll - ✔ Hem summaryRows hem orders destekli - ✔ Highlight otomatik kalkar + ✔ ClientKey bazlı scroll + ✔ Hem summaryRows hem orders destekli + ✔ Highlight otomatik kalkar =========================================================== */ scrollToInvalidRow(clientKey) { if (!clientKey) return - // 1️⃣ Store içindeki satırı bul + // 1️⃣ Store içindeki satırı bul const idx = this.summaryRows?.findIndex( r => r.clientKey === clientKey ) if (idx === -1) { - console.warn('❌ Satır bulunamadı:', clientKey) + console.warn('❌ Satır bulunamadı:', clientKey) return } - // 2️⃣ DOM node + // 2️⃣ DOM node const el = document.querySelector( `[data-clientkey="${clientKey}"]` ) if (!el) { - console.warn('❌ DOM satırı bulunamadı:', clientKey) + console.warn('❌ DOM satırı bulunamadı:', clientKey) return } - // 3️⃣ Scroll + // 3️⃣ Scroll el.scrollIntoView({ behavior: 'smooth', block: 'center' }) - // 4️⃣ Highlight + // 4️⃣ Highlight el.classList.add('invalid-highlight') setTimeout(() => { @@ -375,10 +375,10 @@ export const useOrderEntryStore = defineStore('orderentry', { const res = await api.get(`/orders/check/${orderHeaderID}`) - // Backend “true/false” döner varsayımı + // Backend “true/false” döner varsayımı return res?.data?.exists === true } catch (err) { - console.warn("⚠ checkHeaderExists hata:", err) + console.warn("âš  checkHeaderExists hata:", err) return false } } @@ -391,8 +391,10 @@ export const useOrderEntryStore = defineStore('orderentry', { }) return resp.data } catch (err) { - console.error("❌ fetchOrderPdf hata:", err) - throw err + const detail = await extractApiErrorDetail(err) + const status = err?.status || err?.response?.status || '-' + console.error(`❌ fetchOrderPdf hata [${status}] order=${orderId}: ${detail}`) + throw new Error(detail) } } , @@ -401,7 +403,7 @@ export const useOrderEntryStore = defineStore('orderentry', { try { const orderId = id || this.header?.OrderHeaderID if (!orderId) { - console.error('❌ PDF ID bulunamadı') + console.error('❌ PDF ID bulunamadı') return } @@ -416,22 +418,10 @@ export const useOrderEntryStore = defineStore('orderentry', { setTimeout(() => URL.revokeObjectURL(url), 60_000) } catch (err) { - console.error('❌ PDF açma hatası:', err) - let detail = - err?.response?.data?.detail || - err?.response?.data?.message || - err?.message || - 'PDF açılamadı' - - // responseType=blob olduğunda backend metni Blob içine gelir. - const blob = err?.response?.data - if (blob instanceof Blob) { - try { - const text = (await blob.text())?.trim() - if (text) detail = text - } catch (_) {} - } - + const detail = await extractApiErrorDetail(err) + const orderId = id || this.header?.OrderHeaderID || '-' + const status = err?.status || err?.response?.status || '-' + console.error(`❌ PDF açma hatası [${status}] order=${orderId}: ${detail}`) throw new Error(detail) } } @@ -452,14 +442,14 @@ export const useOrderEntryStore = defineStore('orderentry', { }, /* =========================================================== - 🧩 initFromRoute (v5.6 — groupedRows TOUCH YOK) + 🧩 initFromRoute (v5.6 — groupedRows TOUCH YOK) ----------------------------------------------------------- - - Route ID ve bss_last_txn arasında en dolu snapshot'ı seçer + - Route ID ve bss_last_txn arasında en dolu snapshot'ı seçer - header + orders + summaryRows restore edilir - groupedRows hydrate edilmez / resetlenmez / dokunulmaz - - Route ID farklıysa router.replace ile URL düzeltilir + - Route ID farklıysa router.replace ile URL düzeltilir =========================================================== */ - async initFromRoute(orderId, router = null) { // ✅ NEW MODE → SADECE global draft + async initFromRoute(orderId, router = null) { // ✅ NEW MODE → SADECE global draft if (this.mode === 'new') { const raw = localStorage.getItem(this.getDraftKey) if (raw) { @@ -468,11 +458,11 @@ export const useOrderEntryStore = defineStore('orderentry', { this.header = payload.header || {} this.orders = payload.orders || [] this.summaryRows = payload.summaryRows || this.orders - console.log('♻️ NEW draft restore edildi (global)') + console.log('♻️ NEW draft restore edildi (global)') return } catch {} } - console.log('⚪ NEW draft yok, boş başlatılıyor') + console.log('⚪ NEW draft yok, boÅŸ baÅŸlatılıyor') return } if (!this.schemaMap || !Object.keys(this.schemaMap).length) { @@ -480,7 +470,7 @@ export const useOrderEntryStore = defineStore('orderentry', { } try { - console.log('🧩 [initFromRoute] orderId:', orderId) + console.log('🧩 [initFromRoute] orderId:', orderId) const lastTxn = localStorage.getItem('bss_last_txn') || null @@ -510,18 +500,18 @@ export const useOrderEntryStore = defineStore('orderentry', { if (hasData(fromRoute)) { chosenId = orderId chosenPayload = fromRoute - console.log('✅ [initFromRoute] Route ID snapshot seçildi:', chosenId) + console.log('✅ [initFromRoute] Route ID snapshot seçildi:', chosenId) } else if (hasData(fromLast)) { chosenId = lastTxn chosenPayload = fromLast - console.log('✅ [initFromRoute] lastTxn snapshot seçildi:', chosenId) + console.log('✅ [initFromRoute] lastTxn snapshot seçildi:', chosenId) } /* ------------------------------------------------------- - 🚫 SNAPSHOT YOK → BOŞ BAŞLA + 🚫 SNAPSHOT YOK → BOŞ BAŞLA -------------------------------------------------------- */ if (!chosenId || !chosenPayload) { - console.log('⚪ [initFromRoute] Snapshot yok, boş başlatılıyor') + console.log('⚪ [initFromRoute] Snapshot yok, boÅŸ baÅŸlatılıyor') this.header = { ...(this.header || {}), @@ -531,12 +521,12 @@ export const useOrderEntryStore = defineStore('orderentry', { this.orders = [] this.summaryRows = [] - // ❗ groupedRows'a DOKUNMA + // ❗ groupedRows'a DOKUNMA return } /* ------------------------------------------------------- - ✅ SNAPSHOT RESTORE (SAFE CLONE) + ✅ SNAPSHOT RESTORE (SAFE CLONE) -------------------------------------------------------- */ this.header = { ...(chosenPayload.header || {}), @@ -554,22 +544,22 @@ export const useOrderEntryStore = defineStore('orderentry', { this.orders = orders this.summaryRows = summaryRows - // ❗ groupedRows hydrate edilmez, resetlenmez + // ❗ groupedRows hydrate edilmez, resetlenmez /* ------------------------------------------------------- - 🔁 lastTxn SENKRON + 🔁 lastTxn SENKRON -------------------------------------------------------- */ try { localStorage.setItem('bss_last_txn', chosenId) } catch (e) { - console.warn('⚠️ bss_last_txn yazılamadı:', e) + console.warn('⚠️ bss_last_txn yazılamadı:', e) } /* ------------------------------------------------------- - 🔁 ROUTE DÜZELTME (GEREKİRSE) + 🔁 ROUTE DÜZELTME (GEREKİRSE) -------------------------------------------------------- */ if (router && orderId && orderId !== chosenId) { - console.log('🔁 [initFromRoute] Route ID düzeltiliyor →', chosenId) + console.log('🔁 [initFromRoute] Route ID düzeltiliyor →', chosenId) await router.replace({ name: 'order-entry', params: { orderHeaderID: chosenId } @@ -577,19 +567,19 @@ export const useOrderEntryStore = defineStore('orderentry', { } console.log( - '✅ [initFromRoute] Restore tamam. Satır sayısı:', + '✅ [initFromRoute] Restore tamam. Satır sayısı:', this.summaryRows.length ) } catch (err) { - console.error('❌ [initFromRoute] hata:', err) + console.error('❌ [initFromRoute] hata:', err) } } , /* =========================================================== - 🆕 startNewOrder (v8.3 — FINAL & STABLE) + 🆕 startNewOrder (v8.3 — FINAL & STABLE) =========================================================== */ async startNewOrder({ $q }) { @@ -607,7 +597,7 @@ export const useOrderEntryStore = defineStore('orderentry', { orderNumber = res.data.OrderNumber } } catch { - console.info('ℹ️ Backend order number yok, LOCAL kullanıldı') + console.info('ℹ️ Backend order number yok, LOCAL kullanıldı') } this.mode = 'new' @@ -627,10 +617,10 @@ export const useOrderEntryStore = defineStore('orderentry', { this.orders = [] this.summaryRows = [] - // ✅ fingerprint bazlı sistem için reset + // ✅ fingerprint bazlı sistem için reset this._lastSavedFingerprint = null - // ✅ NEW draft hemen yazılır + // ✅ NEW draft hemen yazılır this.persistLocalStorage?.() return this.header @@ -657,7 +647,7 @@ export const useOrderEntryStore = defineStore('orderentry', { const ex = map.get(key) ex.Qty1 = (Number(ex.Qty1) || 0) + (Number(ln.Qty1) || 0) - // OrderLineID boşsa doldur (editte önemli) + // OrderLineID boÅŸsa doldur (editte önemli) if (!ex.OrderLineID && ln.OrderLineID) ex.OrderLineID = ln.OrderLineID } return Array.from(map.values()) @@ -666,7 +656,7 @@ export const useOrderEntryStore = defineStore('orderentry', { , /* =========================================================== - 🧹 Core reset helper — sadece state'i sıfırlar + 🧹 Core reset helper — sadece state'i sıfırlar =========================================================== */ resetCoreState() { this.orders = [] @@ -676,14 +666,14 @@ export const useOrderEntryStore = defineStore('orderentry', { this.editingKey = null this.currentOrderId = null },resetForNewOrder() { - // mevcut her şeyi temizle + // mevcut her ÅŸeyi temizle this.header = { OrderHeaderID: this.header?.OrderHeaderID || null, OrderDate: new Date().toISOString().slice(0,10), CurrAccCode: null, DocCurrencyCode: 'TRY', PriceCurrencyCode: 'TRY', - // ihtiyaç duyduğun diğer default header alanları + // ihtiyaç duyduÄŸun diÄŸer default header alanları } this.orders = [] @@ -695,7 +685,7 @@ export const useOrderEntryStore = defineStore('orderentry', { } , resetForEdit() { - // EDIT modda grid temizlenmez — sadece UI state resetlenir + // EDIT modda grid temizlenmez — sadece UI state resetlenir this.editingKey = null this.groupedRows = [] this.mode = 'edit' @@ -704,9 +694,9 @@ export const useOrderEntryStore = defineStore('orderentry', { ,markAsSaved() { try { this._lastSavedFingerprint = this._persistFingerprint() - console.log('✅ markAsSaved → fingerprint senkron') + console.log('✅ markAsSaved → fingerprint senkron') } catch (e) { - console.warn('⚠️ markAsSaved hata:', e) + console.warn('⚠️ markAsSaved hata:', e) } } ,clearLocalSnapshot() { @@ -714,12 +704,12 @@ export const useOrderEntryStore = defineStore('orderentry', { const id = this.header?.OrderHeaderID if (!id) return localStorage.removeItem(`bss_orderentry_data:${id}`) - console.log('🧹 Local snapshot temizlendi:', id) + console.log('🧹 Local snapshot temizlendi:', id) } catch (e) { - console.warn('⚠️ clearLocalSnapshot hata:', e) + console.warn('⚠️ clearLocalSnapshot hata:', e) } },/* =========================================================== - 🧹 HARD CLEAN — ALL ORDERENTRY SNAPSHOTS + 🧹 HARD CLEAN — ALL ORDERENTRY SNAPSHOTS =========================================================== */ clearAllOrderSnapshots () { Object.keys(localStorage) @@ -728,7 +718,7 @@ export const useOrderEntryStore = defineStore('orderentry', { k.startsWith('bss_orderentry_edit:') ) .forEach(k => { - console.log('🧹 snapshot silindi:', k) + console.log('🧹 snapshot silindi:', k) localStorage.removeItem(k) }) @@ -740,18 +730,18 @@ export const useOrderEntryStore = defineStore('orderentry', { , /* =========================================================== - 🧹 Store Hard Reset — Submit Sonrası Temizlik (FIXED) - - Grid, header, toplamlar, local state'ler sıfırlanır - - persistKey / lastSnapshotKey NULL yapılmaz (config sabit kalır) - - localStorage txn/snapshot temizliği güvenli yapılır + 🧹 Store Hard Reset — Submit Sonrası Temizlik (FIXED) + - Grid, header, toplamlar, local state'ler sıfırlanır + - persistKey / lastSnapshotKey NULL yapılmaz (config sabit kalır) + - localStorage txn/snapshot temizliÄŸi güvenli yapılır =========================================================== */ hardResetAfterSubmit() { try { - // 🔑 mevcut id’yi yakala (local temizliği için) + // 🔑 mevcut id’yi yakala (local temizliÄŸi için) const id = this.header?.OrderHeaderID || null /* ------------------------------------------------------- - 1) Grid ve satırlar + 1) Grid ve satırlar -------------------------------------------------------- */ this.orders = [] this.summaryRows = [] @@ -771,12 +761,12 @@ export const useOrderEntryStore = defineStore('orderentry', { /* ------------------------------------------------------- 4) Snapshot / transaction meta - ⚠️ persistKey / lastSnapshotKey store config → NULL YAPMA + ⚠️ persistKey / lastSnapshotKey store config → NULL YAPMA -------------------------------------------------------- */ this.activeTransactionId = null this.submitted = false - // fingerprint / debounce meta varsa sıfırla + // fingerprint / debounce meta varsa sıfırla this._lastSavedFingerprint = null this._lastPersistFingerprint = null if (this._persistTimeout) { @@ -785,7 +775,7 @@ export const useOrderEntryStore = defineStore('orderentry', { } /* ------------------------------------------------------- - 5) LocalStorage temizlik (opsiyonel ama submit sonrası doğru) + 5) LocalStorage temizlik (opsiyonel ama submit sonrası doÄŸru) -------------------------------------------------------- */ try { if (id) { @@ -795,32 +785,32 @@ export const useOrderEntryStore = defineStore('orderentry', { localStorage.removeItem('bss_last_txn') localStorage.removeItem('bss_active_new_header') } catch (e) { - console.warn('⚠️ hardResetAfterSubmit localStorage temizliği hata:', e) + console.warn('⚠️ hardResetAfterSubmit localStorage temizliÄŸi hata:', e) } - console.log('🧹 Store resetlendi (submit sonrası).') + console.log('🧹 Store resetlendi (submit sonrası).') } catch (err) { - console.error('❌ hardResetAfterSubmit hata:', err) + console.error('❌ hardResetAfterSubmit hata:', err) } } , /* =========================================================== - ✏️ openExistingForEdit (v12 — FINAL & CLEAN) + ✏️ openExistingForEdit (v12 — FINAL & CLEAN) ----------------------------------------------------------- - ✔ Backend authoritative (orderlist açılışı local'i dikkate almaz) - ✔ mode=new → backend çağrısı YOK - ✔ normalizeOrderLines → grpKey + bedenMap garanti - ✔ isClosed varsa → view, yoksa → edit - ✔ Form sync opsiyonel - ✔ İlk açılışta snapshot yazılır (edit boyunca persist ile güncellenir) + ✔ Backend authoritative (orderlist açılışı local'i dikkate almaz) + ✔ mode=new → backend çaÄŸrısı YOK + ✔ normalizeOrderLines → grpKey + bedenMap garanti + ✔ isClosed varsa → view, yoksa → edit + ✔ Form sync opsiyonel + ✔ İlk açılışta snapshot yazılır (edit boyunca persist ile güncellenir) =========================================================== */ async openExistingForEdit( orderId, { $q = null, form = null, productCache = null } = {} ) { - // 🔑 schemaMap garanti + // 🔑 schemaMap garanti if (!this.schemaMap || !Object.keys(this.schemaMap).length) { this.initSchemaMap?.() } @@ -828,25 +818,25 @@ export const useOrderEntryStore = defineStore('orderentry', { if (!orderId) return false /* ======================================================= - 🟦 NEW MODE — ASLA backend çağrısı yok + 🟦 NEW MODE — ASLA backend çaÄŸrısı yok ======================================================= */ if (this.mode === 'new') { - console.log('⚪ openExistingForEdit skip (mode=new)') + console.log('⚪ openExistingForEdit skip (mode=new)') return false } - // productCache hem ref hem reactive olabilir → güvenli oku + // productCache hem ref hem reactive olabilir → güvenli oku const pc = productCache?.value ? productCache.value : (productCache && typeof productCache === 'object' ? productCache : {}) try { - // geçici varsayım (sonra isClosed durumuna göre set edilecek) + // geçici varsayım (sonra isClosed durumuna göre set edilecek) this.setMode?.('edit') /* ======================================================= - 🔹 BACKEND — authoritative load + 🔹 BACKEND — authoritative load ======================================================= */ const res = await api.get(`/order/get/${orderId}`) const backend = res?.data @@ -856,8 +846,8 @@ export const useOrderEntryStore = defineStore('orderentry', { } /* ======================================================= - 🔹 HEADER — SADECE BACKEND - (orderlist açılışında local merge YOK) + 🔹 HEADER — SADECE BACKEND + (orderlist açılışında local merge YOK) ======================================================= */ this.header = { ...backend.header, @@ -865,11 +855,11 @@ export const useOrderEntryStore = defineStore('orderentry', { } /* ======================================================= - 🔹 NORMALIZE LINES (TEK KAYNAK) - normalizeOrderLines şu alanları üretmeli: - ✔ row.grpKey - ✔ row.bedenMap[grpKey] - ✔ row.isClosed (boolean) + 🔹 NORMALIZE LINES (TEK KAYNAK) + normalizeOrderLines ÅŸu alanları üretmeli: + ✔ row.grpKey + ✔ row.bedenMap[grpKey] + ✔ row.isClosed (boolean) ======================================================= */ const normalized = this.normalizeOrderLines( backend.lines || [], @@ -881,31 +871,31 @@ export const useOrderEntryStore = defineStore('orderentry', { this.summaryRows = [...this.orders] /* ======================================================= - 🔹 MODE KARARI (BACKEND SATIRLARI ÜZERİNDEN) - - herhangi bir isClosed=true → view - - değilse → edit + 🔹 MODE KARARI (BACKEND SATIRLARI ÜZERİNDEN) + - herhangi bir isClosed=true → view + - deÄŸilse → edit ======================================================= */ const hasClosedLine = (this.summaryRows || []).some(r => r?.isClosed === true) this.setMode?.(hasClosedLine ? 'view' : 'edit') /* ======================================================= - 🔹 FORM SYNC (opsiyonel) + 🔹 FORM SYNC (opsiyonel) ======================================================= */ if (form) { Object.assign(form, this.header) } /* ======================================================= - 🔹 LOCAL SNAPSHOT (edit boyunca tutulacak temel) - - Açılışta snapshot yaz - - Sonraki değişikliklerde zaten persistLocalStorage çağrıları var + 🔹 LOCAL SNAPSHOT (edit boyunca tutulacak temel) + - Açılışta snapshot yaz + - Sonraki deÄŸiÅŸikliklerde zaten persistLocalStorage çaÄŸrıları var ======================================================= */ this.persistLocalStorage?.() try { localStorage.setItem('bss_last_txn', String(orderId)) } catch {} - console.log('✅ openExistingForEdit OK:', { + console.log('✅ openExistingForEdit OK:', { id: orderId, rows: this.summaryRows.length, mode: this.mode, @@ -914,13 +904,13 @@ export const useOrderEntryStore = defineStore('orderentry', { return true } catch (err) { - console.error('❌ openExistingForEdit hata:', err) + console.error('❌ openExistingForEdit hata:', err) - // new değilse uyar + // new deÄŸilse uyar if (this.mode !== 'new') { $q?.notify?.({ type: 'negative', - message: 'Sipariş yüklenemedi' + message: 'SipariÅŸ yüklenemedi' }) } @@ -930,12 +920,12 @@ export const useOrderEntryStore = defineStore('orderentry', { , /* =========================================================== - ♻️ hydrateFromLocalStorage (v5.5 — FIXED & CLEAN) + ♻️ hydrateFromLocalStorage (v5.5 — FIXED & CLEAN) ----------------------------------------------------------- - Tek assign (double overwrite YOK) - groupedRows hydrate edilmez - mode ASLA set edilmez - - header + rows güvenli restore + - header + rows güvenli restore =========================================================== */ async hydrateFromLocalStorage(orderId, log = false) {if (this.mode === 'new') { return this.hydrateFromLocalStorageIfExists() @@ -946,15 +936,15 @@ export const useOrderEntryStore = defineStore('orderentry', { const payload = JSON.parse(localStorage.getItem(key) || 'null') if (!payload) { - log && console.log('ℹ️ hydrate → snapshot yok:', orderId) + log && console.log('ℹ️ hydrate → snapshot yok:', orderId) return null } - // 🔑 source bilgisi (mode set edilmez) + // 🔑 source bilgisi (mode set edilmez) this.source = payload.source || 'local' /* ------------------------------------------------------- - MSSQL tarih helper’ları + MSSQL tarih helper’ları -------------------------------------------------------- */ const safeDateTime = v => { if (!v) return null @@ -1004,11 +994,11 @@ export const useOrderEntryStore = defineStore('orderentry', { ? payload.summaryRows : orders - // ❌ groupedRows hydrate edilmez (computed olmalı) + // ❌ groupedRows hydrate edilmez (computed olmalı) this.groupedRows = [] /* ------------------------------------------------------- - SNAPSHOT ÖZET + SNAPSHOT ÖZET -------------------------------------------------------- */ const output = { type : payload.submitted === true ? 'submitted' : 'draft', @@ -1021,11 +1011,11 @@ export const useOrderEntryStore = defineStore('orderentry', { payload.header?.IsSubmitted === true } - log && console.log('♻️ hydrate sonuc (FIXED):', output) + log && console.log('♻️ hydrate sonuc (FIXED):', output) return output } catch (err) { - console.warn('⚠️ hydrateFromLocalStorage hata:', err) + console.warn('⚠️ hydrateFromLocalStorage hata:', err) return null } } @@ -1037,11 +1027,11 @@ export const useOrderEntryStore = defineStore('orderentry', { let raw = null if (this.mode === 'new') { - raw = localStorage.getItem(this.getDraftKey) // ✅ + raw = localStorage.getItem(this.getDraftKey) // ✅ } if (this.mode === 'edit') { - const key = this.getEditKey // ✅ + const key = this.getEditKey // ✅ if (key) raw = localStorage.getItem(key) } @@ -1053,7 +1043,7 @@ export const useOrderEntryStore = defineStore('orderentry', { this.orders = payload.orders || [] this.summaryRows = payload.summaryRows || this.orders - console.log('♻️ hydrate OK:', this.mode) + console.log('♻️ hydrate OK:', this.mode) return true } catch (err) { @@ -1065,8 +1055,8 @@ export const useOrderEntryStore = defineStore('orderentry', { , /* =========================================================== - 🔀 mergeOrders (local + backend) - normalizeISO → kaldırıldı + 🔀 mergeOrders (local + backend) + normalizeISO → kaldırıldı safe MSSQL helpers eklendi =========================================================== */ mergeOrders(local, backend, preferLocal = true) { @@ -1097,12 +1087,12 @@ export const useOrderEntryStore = defineStore('orderentry', { const map = new Map() - // Backend satırları + // Backend satırları for (const b of (backend?.lines || backend?.orders || [])) { map.set(getKey(b), { ...b, _src: 'backend' }) } - // Local satırları merge et + // Local satırları merge et for (const l of (local?.orders || [])) { const k = getKey(l) if (map.has(k)) { @@ -1115,10 +1105,10 @@ export const useOrderEntryStore = defineStore('orderentry', { } const mergedOrders = Array.from(map.values()) - console.log(`🧩 mergeOrders → ${mergedOrders.length} satır birleşti (ID:${header.OrderHeaderID})`) + console.log(`🧩 mergeOrders → ${mergedOrders.length} satır birleÅŸti (ID:${header.OrderHeaderID})`) // ==================================================== - // 🕒 HEADER TARİHLERİNİ MSSQL FORMATINA NORMALİZE ET + // 🕒 HEADER TARİHLERİNİ MSSQL FORMATINA NORMALİZE ET // ==================================================== const safeDateTime = v => { if (!v) return null @@ -1151,14 +1141,14 @@ export const useOrderEntryStore = defineStore('orderentry', { , markRowSource(row) { - if (row._src === 'local-only') return '🟠 Offline' - if (row._src === 'local') return '🔵 Local' - return '⚪ Backend' + if (row._src === 'local-only') return '🟠 Offline' + if (row._src === 'local') return '🔵 Local' + return '⚪ Backend' } , /* =========================================================== - 🔄 mergeAndPersistBackendOrder (edit mode) + 🔄 mergeAndPersistBackendOrder (edit mode) =========================================================== */ mergeAndPersistBackendOrder(orderId, backendPayload) { const key = `bss_orderentry_data:${orderId}` @@ -1173,7 +1163,7 @@ export const useOrderEntryStore = defineStore('orderentry', { updatedAt: new Date().toISOString() })) - console.log(`💾 mergeAndPersistBackendOrder → ${orderId} localStorage’a yazıldı`) + console.log(`💾 mergeAndPersistBackendOrder → ${orderId} localStorage’a yazıldı`) } , @@ -1190,19 +1180,19 @@ export const useOrderEntryStore = defineStore('orderentry', { } /* =============================== - 🟢 NEW MODE — GLOBAL TEK TASLAK + 🟢 NEW MODE — GLOBAL TEK TASLAK =============================== */ if (this.mode === 'new') { localStorage.setItem(this.getDraftKey, JSON.stringify(payload)) - // 🔒 sadece aktif new header bilgisi + // 🔒 sadece aktif new header bilgisi this.setActiveNewHeader?.(this.header?.OrderHeaderID) return } /* =============================== - 🔵 EDIT MODE — ID BAZLI + 🔵 EDIT MODE — ID BAZLI =============================== */ if (this.mode === 'edit') { const key = this.getEditKey @@ -1221,26 +1211,26 @@ export const useOrderEntryStore = defineStore('orderentry', { clearEditSnapshotIfExists() { if (this.mode !== 'edit') return - const key = this.getEditKey // ✅ + const key = this.getEditKey // ✅ if (!key) return localStorage.removeItem(key) - console.log('🧹 EDIT snapshot silindi:', key) + console.log('🧹 EDIT snapshot silindi:', key) } ,/* =========================================================== - 🧠 _persistFingerprint — kritik state’leri tek stringe indirger - - X3: orders+header yetmez → mode, summaryRows, id/no, map’ler dahil + 🧠 _persistFingerprint — kritik state’leri tek stringe indirger + - X3: orders+header yetmez → mode, summaryRows, id/no, map’ler dahil =========================================================== */ _persistFingerprint() { - // 🔹 orders: çok büyürse pahalı olabilir ama snapshot tutarlılığı için önemli + // 🔹 orders: çok büyürse pahalı olabilir ama snapshot tutarlılığı için önemli // (istersen burada sadece length + rowKey listesi gibi optimize ederiz) const ordersSnap = JSON.stringify(this.orders || []) - // 🔹 header: sadece kritik alanları al (tam header yerine daha stabil) + // 🔹 header: sadece kritik alanları al (tam header yerine daha stabil) const h = this.header || {} const headerSnap = JSON.stringify({ OrderHeaderID: h.OrderHeaderID || '', @@ -1250,14 +1240,14 @@ export const useOrderEntryStore = defineStore('orderentry', { ExchangeRate: h.ExchangeRate ?? null }) - // 🔹 summaryRows: hash yerine şimdilik “length + rowKey listesi” (hafif + etkili) + // 🔹 summaryRows: hash yerine ÅŸimdilik “length + rowKey listesi” (hafif + etkili) const sr = Array.isArray(this.summaryRows) ? this.summaryRows : [] const summaryMeta = JSON.stringify({ len: sr.length, keys: sr.map(r => this.getRowKey?.(r) || r?.key || r?.id || '').filter(Boolean) }) - // 🔹 comboLineIds / lineIdMap gibi kritik map’ler + // 🔹 comboLineIds / lineIdMap gibi kritik map’ler // (sende hangisi varsa onu otomatik topluyoruz) const mapSnap = JSON.stringify({ lineIdMap: this.lineIdMap || null, @@ -1266,15 +1256,15 @@ export const useOrderEntryStore = defineStore('orderentry', { comboLineIdSet: this.comboLineIdSet ? Array.from(this.comboLineIdSet) : null }) - // 🔹 mode + // 🔹 mode const modeSnap = String(this.mode || 'new') - // ✅ Tek fingerprint + // ✅ Tek fingerprint return `${modeSnap}|${headerSnap}|${summaryMeta}|${mapSnap}|${ordersSnap}` } , /* =========================================================== - 🕒 _safePersistDebounced — snapshot değişmediği sürece yazmaz (X3) + 🕒 _safePersistDebounced — snapshot deÄŸiÅŸmediÄŸi sürece yazmaz (X3) - fingerprint: mode + header(id/no) + summaryRows meta + lineIdMap/combo + orders =========================================================== */ _safePersistDebounced(delay = 1200) { @@ -1282,7 +1272,7 @@ export const useOrderEntryStore = defineStore('orderentry', { this._persistTimeout = setTimeout(() => { try { - // ✅ Persist guard’ları (varsa) + // ✅ Persist guard’ları (varsa) if (this.preventPersist) return if (this._uiBusy) return @@ -1295,9 +1285,9 @@ export const useOrderEntryStore = defineStore('orderentry', { this._lastPersistFingerprint = fp this.persistLocalStorage() - console.log(`🕒 Otomatik LocalStorage senkron (${this.orders?.length || 0} satır).`) + console.log(`🕒 Otomatik LocalStorage senkron (${this.orders?.length || 0} satır).`) } catch (err) { - console.warn('⚠️ Debounce persist hata:', err) + console.warn('⚠️ Debounce persist hata:', err) } }, delay) } @@ -1305,7 +1295,7 @@ export const useOrderEntryStore = defineStore('orderentry', { , /* =========================================================== - 💰 fetchMinPrice — model/pb için min fiyat + 💰 fetchMinPrice — model/pb için min fiyat =========================================================== */ async fetchMinPrice(model, currency, $q) { try { @@ -1313,17 +1303,17 @@ export const useOrderEntryStore = defineStore('orderentry', { params: { model, currency } }) const data = res?.data || {} - console.log('💰 [store.fetchMinPrice] yanıt:', data) + console.log('💰 [store.fetchMinPrice] yanıt:', data) return { price: Number(data.price || 0), rateToTRY: Number(data.rateToTRY || 1), priceTRY: Number(data.priceTRY || 0) } } catch (err) { - console.error('❌ [store.fetchMinPrice] Min fiyat alınamadı:', err) + console.error('❌ [store.fetchMinPrice] Min fiyat alınamadı:', err) $q?.notify?.({ type: 'warning', - message: 'Min. fiyat bilgisi alınamadı, kontrol atlandı ⚠️', + message: 'Min. fiyat bilgisi alınamadı, kontrol atlandı ⚠️', position: 'top-right' }) return { price: 0, rateToTRY: 1, priceTRY: 0 } @@ -1333,13 +1323,13 @@ export const useOrderEntryStore = defineStore('orderentry', { applyCurrencyToLines(newPB) { if (!newPB) return - // 🔹 Header + // 🔹 Header if (this.header) { this.header.DocCurrencyCode = newPB this.header.PriceCurrencyCode = newPB } - // 🔹 Lines + // 🔹 Lines if (Array.isArray(this.orders)) { this.orders = this.orders.map(r => ({ ...r, @@ -1349,7 +1339,7 @@ export const useOrderEntryStore = defineStore('orderentry', { })) } - // 🔹 Summary + // 🔹 Summary if (Array.isArray(this.summaryRows)) { this.summaryRows = this.summaryRows.map(r => ({ ...r, @@ -1359,14 +1349,14 @@ export const useOrderEntryStore = defineStore('orderentry', { })) } - // ❗ totalAmount SET ETME - // ✔️ TEK MERKEZ + // ❗ totalAmount SET ETME + // ✔️ TEK MERKEZ this.updateHeaderTotals?.() } , /* =========================================================== - 💠 HEADER SET & CURRENCY PROPAGATION + 💠 HEADER SET & CURRENCY PROPAGATION =========================================================== */ setHeaderFields(fields, opts = {}) { const { @@ -1374,13 +1364,13 @@ export const useOrderEntryStore = defineStore('orderentry', { immediatePersist = false } = opts - // 1️⃣ HEADER + // 1️⃣ HEADER this.header = { ...(this.header || {}), ...fields } - // 2️⃣ SATIRLARA GERÇEKTEN YAY + // 2️⃣ SATIRLARA GERÇEKTEN YAY if (applyCurrencyToLines && Array.isArray(this.summaryRows)) { this.summaryRows = this.summaryRows.map(r => ({ ...r, @@ -1390,11 +1380,11 @@ export const useOrderEntryStore = defineStore('orderentry', { })) } - // 3️⃣ STORE ORDERS REFERANSI + // 3️⃣ STORE ORDERS REFERANSI this.orders = [...this.summaryRows] - // 4️⃣ PERSIST + // 4️⃣ PERSIST if (immediatePersist) { this.persistLocalStorage('header-change') } @@ -1418,12 +1408,12 @@ export const useOrderEntryStore = defineStore('orderentry', { cnt++ } - console.log(`💱 ${cnt} satırda PB güncellendi → Doc:${doc} Price:${prc} Rate:${rate}`) + console.log(`💱 ${cnt} satırda PB güncellendi → Doc:${doc} Price:${prc} Rate:${rate}`) } ,/* =========================================================== - 📸 saveSnapshot — küçük debug snapshot + 📸 saveSnapshot — küçük debug snapshot =========================================================== */ saveSnapshot(tag = 'snapshot') { try { @@ -1441,26 +1431,26 @@ export const useOrderEntryStore = defineStore('orderentry', { } localStorage.setItem(key, JSON.stringify(snap)) - console.log(`📸 Snapshot kaydedildi [${key}]`) + console.log(`📸 Snapshot kaydedildi [${key}]`) } catch (err) { - console.warn('⚠️ saveSnapshot hata:', err) + console.warn('⚠️ saveSnapshot hata:', err) } } , /* =========================================================== - ♻️ loadFromStorage — eski generic persist için + ♻️ loadFromStorage — eski generic persist için =========================================================== */ loadFromStorage(force = false) { try { const raw = localStorage.getItem(this.getPersistKey) if (!raw) { - console.info('ℹ️ LocalStorage boş, grid başlatılmadı.') + console.info('ℹ️ LocalStorage boÅŸ, grid baÅŸlatılmadı.') return false } if (!force && this.mode === 'edit') { - console.info('⚠️ Edit modda local restore atlandı (force=false).') + console.info('⚠️ Edit modda local restore atlandı (force=false).') return false } @@ -1471,21 +1461,21 @@ export const useOrderEntryStore = defineStore('orderentry', { this.currentOrderId = data.currentOrderId || null this.selectedCustomer = data.selectedCustomer || null - // 🔧 Temiz ID + // 🔧 Temiz ID this.header.OrderHeaderID = data.header?.OrderHeaderID || null this.mode = data.mode || 'new' this.lastSavedAt = data.savedAt || null - console.log(`♻️ Storage yüklendi • txn:${this.header.OrderHeaderID} (${this.orders.length} satır)`) + console.log(`♻️ Storage yüklendi • txn:${this.header.OrderHeaderID} (${this.orders.length} satır)`) - // Header PB -> satırlara + // Header PB -> satırlara this.applyHeaderCurrencyToOrders() this._safePersistDebounced(200) return data } catch (err) { - console.warn('⚠️ localStorage okuma hatası:', err) + console.warn('⚠️ localStorage okuma hatası:', err) return false } } @@ -1494,23 +1484,23 @@ export const useOrderEntryStore = defineStore('orderentry', { clearStorage() { try { localStorage.removeItem(this.getPersistKey) - console.log(`🗑️ LocalStorage temizlendi [${this.getPersistKey}]`) + console.log(`🗑️ LocalStorage temizlendi [${this.getPersistKey}]`) } catch (err) { - console.warn('⚠️ clearStorage hatası:', err) + console.warn('⚠️ clearStorage hatası:', err) } } , clearNewDraft() { - localStorage.removeItem(this.getDraftKey) // ✅ + localStorage.removeItem(this.getDraftKey) // ✅ localStorage.removeItem('bss_last_txn') - console.log('🧹 NEW taslak temizlendi') + console.log('🧹 NEW taslak temizlendi') } , // =========================================================== -// 🔹 isSameCombo — STORE LEVEL (TEK KAYNAK) -// - model ZORUNLU eşleşir -// - renk / renk2 boşsa → joker +// 🔹 isSameCombo — STORE LEVEL (TEK KAYNAK) +// - model ZORUNLU eÅŸleÅŸir +// - renk / renk2 boÅŸsa → joker // =========================================================== isSameCombo(a, b) { if (!a || !b) return false @@ -1531,11 +1521,11 @@ export const useOrderEntryStore = defineStore('orderentry', { // =========================================================== -// 🔹 saveOrUpdateRowUnified (v6.6 — COMBO SAFE + FIXED STOCK+PRICE + UI) +// 🔹 saveOrUpdateRowUnified (v6.6 — COMBO SAFE + FIXED STOCK+PRICE + UI) // - v6.5 korunur (stok+min fiyat + this.loadProductSizes) -// - ✅ NEW MODE: dupIdx artık _deleteSignal satırlarını BAŞTAN hariç tutar -// - EDIT MODE: sameCombo → update, combo değişti → delete + insert (korundu) -// - lineIdMap koruması korunur +// - ✅ NEW MODE: dupIdx artık _deleteSignal satırlarını BAŞTAN hariç tutar +// - EDIT MODE: sameCombo → update, combo deÄŸiÅŸti → delete + insert (korundu) +// - lineIdMap koruması korunur // =========================================================== async saveOrUpdateRowUnified({ form, @@ -1546,7 +1536,7 @@ export const useOrderEntryStore = defineStore('orderentry', { $q = null }) { try { - console.log('🔥 saveOrUpdateRowUnified v6.6', { + console.log('🔥 saveOrUpdateRowUnified v6.6', { model: form?.model, mode: this.mode, editingKey: this.editingKey @@ -1562,10 +1552,10 @@ export const useOrderEntryStore = defineStore('orderentry', { : [] /* ======================================================= - 1️⃣ ZORUNLU KONTROLLER + 1️⃣ ZORUNLU KONTROLLER ======================================================= */ if (!form?.model) { - $q?.notify?.({ type: 'warning', message: 'Model seçiniz' }) + $q?.notify?.({ type: 'warning', message: 'Model seçiniz' }) return false } @@ -1574,28 +1564,28 @@ export const useOrderEntryStore = defineStore('orderentry', { } /* ======================================================= - 2️⃣ STOK KONTROLÜ (FIXED) - - stok guard’dan önce this.loadProductSizes(form,true,$q) + 2️⃣ STOK KONTROLÜ (FIXED) + - stok guard’dan önce this.loadProductSizes(form,true,$q) - opsiyonel callback loadProductSizes(true) - - tek dialog + doğru await + - tek dialog + doÄŸru await ======================================================= */ - // ✅ store fonksiyonu + // ✅ store fonksiyonu try { if (typeof this.loadProductSizes === 'function') { await this.loadProductSizes(form, true, $q) } } catch (err) { - console.warn('⚠ this.loadProductSizes hata:', err) + console.warn('âš  this.loadProductSizes hata:', err) } - // ✅ dışarıdan callback geldiyse + // ✅ dışarıdan callback geldiyse try { if (typeof loadProductSizes === 'function') { await loadProductSizes(true) } } catch (err) { - console.warn('⚠ loadProductSizes hata:', err) + console.warn('âš  loadProductSizes hata:', err) } const stockMapLocal = stockMap?.value || stockMap || {} @@ -1615,16 +1605,16 @@ export const useOrderEntryStore = defineStore('orderentry', { if (overLimit.length && $q) { const msg = overLimit - .map(x => `• ${x.beden}: ${x.girilen} (Stok: ${x.stok})`) + .map(x => `• ${x.beden}: ${x.girilen} (Stok: ${x.stok})`) .join('
') const stokOK = await new Promise(resolve => { $q.dialog({ - title: 'Stok Uyarısı', - message: `Bazı bedenlerde stoktan fazla giriş yaptınız:

${msg}`, + title: 'Stok Uyarısı', + message: `Bazı bedenlerde stoktan fazla giriş yaptınız:

${msg}`, html: true, ok: { label: 'Devam', color: 'primary' }, - cancel: { label: 'İptal', color: 'negative' } + cancel: { label: 'İptal', color: 'negative' } }) .onOk(() => resolve(true)) .onCancel(() => resolve(false)) @@ -1635,7 +1625,7 @@ export const useOrderEntryStore = defineStore('orderentry', { } /* ======================================================= - 3️⃣ FİYAT (MIN) KONTROLÜ (FIXED) + 3️⃣ FİYAT (MIN) KONTROLÜ (FIXED) ======================================================= */ let fiyatOK = true try { @@ -1653,13 +1643,13 @@ export const useOrderEntryStore = defineStore('orderentry', { if (minFiyat > 0 && girilen > 0 && girilen < minFiyat && $q) { fiyatOK = await new Promise(resolve => { $q.dialog({ - title: 'Fiyat Uyarısı', + title: 'Fiyat Uyarısı', message: `Min. Fiyat: ${minFiyat} ${form.pb}
` + - `Girdiğiniz: ${girilen} ${form.pb}`, + `GirdiÄŸiniz: ${girilen} ${form.pb}`, html: true, ok: { label: 'Devam', color: 'primary' }, - cancel: { label: 'İptal', color: 'negative' } + cancel: { label: 'İptal', color: 'negative' } }) .onOk(() => resolve(true)) .onCancel(() => resolve(false)) @@ -1667,12 +1657,12 @@ export const useOrderEntryStore = defineStore('orderentry', { }) } } catch (err) { - console.warn('⚠ Min fiyat hata:', err) + console.warn('âš  Min fiyat hata:', err) } if (!fiyatOK) return false /* ======================================================= - 4️⃣ TOPLAM HESABI + 4️⃣ TOPLAM HESABI ======================================================= */ const adet = (form.bedenler || []).reduce((a, b) => a + Number(b || 0), 0) form.adet = adet @@ -1681,7 +1671,7 @@ export const useOrderEntryStore = defineStore('orderentry', { const newRow = toSummaryRowFromForm(form) /* ======================================================= - 5️⃣ EDIT MODE (editingKey ZORUNLU) + 5️⃣ EDIT MODE (editingKey ZORUNLU) ======================================================= */ if (this.editingKey) { const idx = rows.findIndex(r => getKey(r) === this.editingKey) @@ -1694,13 +1684,13 @@ export const useOrderEntryStore = defineStore('orderentry', { const prev = rows[idx] if (this.isRowLocked?.(prev)) { - $q?.notify?.({ type: 'warning', message: 'Satır kapalı' }) + $q?.notify?.({ type: 'warning', message: 'Satır kapalı' }) this.editingKey = null resetEditor?.(true) return false } - // ✅ kritik: store-level + // ✅ kritik: store-level const sameCombo = this.isSameCombo(prev, newRow) const preservedLineIdMap = @@ -1710,7 +1700,7 @@ export const useOrderEntryStore = defineStore('orderentry', { ? { ...newRow.lineIdMap } : {} - /* ===== SAME COMBO → UPDATE ===== */ + /* ===== SAME COMBO → UPDATE ===== */ if (sameCombo) { rows[idx] = { ...prev, @@ -1730,11 +1720,11 @@ export const useOrderEntryStore = defineStore('orderentry', { resetEditor?.(true) recalcVat?.() - $q?.notify?.({ type: 'positive', message: 'Satır güncellendi' }) + $q?.notify?.({ type: 'positive', message: 'Satır güncellendi' }) return true } - /* ===== COMBO CHANGED → DELETE + INSERT ===== */ + /* ===== COMBO CHANGED → DELETE + INSERT ===== */ const grpKey = prev?.grpKey || Object.keys(prev?.bedenMap || {})[0] || @@ -1790,22 +1780,22 @@ export const useOrderEntryStore = defineStore('orderentry', { resetEditor?.(true) recalcVat?.() - $q?.notify?.({ type: 'positive', message: 'Kombinasyon değişti' }) + $q?.notify?.({ type: 'positive', message: 'Kombinasyon deÄŸiÅŸti' }) return true } /* ======================================================= - 6️⃣ NEW MODE (MERGE / INSERT) — COMBO SAFE - - aynı combo → bedenMap merge (satır sayısı artmaz) - - farklı combo → yeni satır - - ✅ FIX: _deleteSignal satırlarını dup aramasında hariç tut + 6️⃣ NEW MODE (MERGE / INSERT) — COMBO SAFE + - aynı combo → bedenMap merge (satır sayısı artmaz) + - farklı combo → yeni satır + - ✅ FIX: _deleteSignal satırlarını dup aramasında hariç tut ======================================================= */ const dupIdx = rows.findIndex(r => !r?._deleteSignal && this.isSameCombo(r, newRow) ) - // helper: bedenMap çıkar (gruplu ya da düz) + // helper: bedenMap çıkar (gruplu ya da düz) const extractMap = (row) => { const grpKey = row?.grpKey || @@ -1823,15 +1813,15 @@ export const useOrderEntryStore = defineStore('orderentry', { if (dupIdx !== -1) { const prev = rows[dupIdx] - // delete satırına merge yapma (ek güvenlik) + // delete satırına merge yapma (ek güvenlik) if (prev?._deleteSignal !== true) { const { grpKey: prevGrp, map: prevMap } = extractMap(prev) const { grpKey: newGrp, map: newMap } = extractMap(newRow) - // hangi grpKey kullanılacak? + // hangi grpKey kullanılacak? const grpKey = newRow?.grpKey || prevGrp || newGrp || 'GENEL' - // MERGE: bedenleri topluyoruz (override değil) + // MERGE: bedenleri topluyoruz (override deÄŸil) const merged = { ...(prevMap || {}) } for (const [k, v] of Object.entries(newMap || {})) { const beden = (k == null || String(k).trim() === '') @@ -1873,12 +1863,12 @@ export const useOrderEntryStore = defineStore('orderentry', { resetEditor?.(true) recalcVat?.() - $q?.notify?.({ type: 'positive', message: 'Aynı kombinasyon bulundu, bedenler birleştirildi' }) + $q?.notify?.({ type: 'positive', message: 'Aynı kombinasyon bulundu, bedenler birleÅŸtirildi' }) return true } } - // dup yoksa (veya dup delete satırıydı) → yeni satır + // dup yoksa (veya dup delete satırıydı) → yeni satır rows.push({ ...newRow, id: newRow.id || crypto.randomUUID(), @@ -1894,12 +1884,12 @@ export const useOrderEntryStore = defineStore('orderentry', { resetEditor?.(true) recalcVat?.() - $q?.notify?.({ type: 'positive', message: 'Yeni satır eklendi' }) + $q?.notify?.({ type: 'positive', message: 'Yeni satır eklendi' }) return true } catch (err) { - console.error('❌ saveOrUpdateRowUnified:', err) - $q?.notify?.({ type: 'negative', message: 'Satır kaydı başarısız' }) + console.error('❌ saveOrUpdateRowUnified:', err) + $q?.notify?.({ type: 'negative', message: 'Satır kaydı baÅŸarısız' }) return false } } @@ -1910,24 +1900,24 @@ export const useOrderEntryStore = defineStore('orderentry', { , /* =========================================================== - 🔄 setTransaction — yeni transaction ID set et + 🔄 setTransaction — yeni transaction ID set et =========================================================== */ setTransaction(id, autoResume = true) { if (!id) return - // 🔧 temiz ID + // 🔧 temiz ID this.header.OrderHeaderID = id localStorage.setItem('bss_last_txn', id) - console.log('🔄 Transaction değiştirildi:', id) + console.log('🔄 Transaction deÄŸiÅŸtirildi:', id) if (autoResume) { const hasData = Array.isArray(this.orders) && this.orders.length > 0 if (!hasData) { const ok = this.hydrateFromLocalStorage(id,true) - if (ok) console.info('📦 Local kayıt geri yüklendi (boş grid için).') + if (ok) console.info('📦 Local kayıt geri yüklendi (boÅŸ grid için).') } else { - console.log('🚫 Grid dolu, auto-resume atlandı (mevcut satırlar korundu).') + console.log('🚫 Grid dolu, auto-resume atlandı (mevcut satırlar korundu).') } } } @@ -1935,7 +1925,7 @@ export const useOrderEntryStore = defineStore('orderentry', { /* =========================================================== - 🧹 clearTransaction — sadece NEW MODE taslaklarını temizler + 🧹 clearTransaction — sadece NEW MODE taslaklarını temizler =========================================================== */ clearTransaction() { try { @@ -1952,22 +1942,22 @@ export const useOrderEntryStore = defineStore('orderentry', { localStorage.removeItem('bss_last_txn') - console.log('🧹 Transaction temizlendi') + console.log('🧹 Transaction temizlendi') } catch (err) { - console.warn('⚠️ clearTransaction hata:', err) + console.warn('⚠️ clearTransaction hata:', err) } } , // ======================================================= - // 🔒 KİLİT KONTROLÜ — Sadece EDIT modunda, backend satırı + // 🔒 KİLİT KONTROLÜ — Sadece EDIT modunda, backend satırı // ======================================================= isRowLocked(row) { if (!row) return false // Sadece edit modunda, - // ve backend'den gelen gerçek OrderLineID varsa, - // ve IsClosed=1 ise satır kilitli + // ve backend'den gelen gerçek OrderLineID varsa, + // ve IsClosed=1 ise satır kilitli return ( this.mode === 'edit' && !!row.OrderLineID && @@ -2000,10 +1990,10 @@ export const useOrderEntryStore = defineStore('orderentry', { aciklama: row.aciklama || old.aciklama, updatedAt: dayjs().toISOString() } - console.log(`⚠️ Aynı kombinasyon bulundu, satır güncellendi: ${row.model} ${row.renk || ''} ${row.renk2 || ''}`) + console.log(`⚠️ Aynı kombinasyon bulundu, satır güncellendi: ${row.model} ${row.renk || ''} ${row.renk2 || ''}`) } else { this.orders.push(toRaw(row)) - console.log(`➕ Yeni kombinasyon eklendi: ${row.model} ${row.renk || ''} ${row.renk2 || ''}`) + console.log(`➕ Yeni kombinasyon eklendi: ${row.model} ${row.renk || ''} ${row.renk2 || ''}`) } this.persistLocalStorage() @@ -2019,7 +2009,7 @@ export const useOrderEntryStore = defineStore('orderentry', { } this.persistLocalStorage() this.saveSnapshot('after-update') - console.log(`✏️ Satır güncellendi (store): #${index}`) + console.log(`✏️ Satır güncellendi (store): #${index}`) }, @@ -2033,27 +2023,27 @@ export const useOrderEntryStore = defineStore('orderentry', { this.persistLocalStorage() this.saveSnapshot('after-remove') - console.log(`🗑️ Satır silindi: ${removed[0]?.model || '(model yok)'}`) + console.log(`🗑️ Satır silindi: ${removed[0]?.model || '(model yok)'}`) }, removeSelectedRow(row, $q = null) { if (!row) return - // 1) Kilitli satır silinemez + // 1) Kilitli satır silinemez if (this.isRowLocked(row)) { $q?.notify?.({ type: 'warning', - message: '🔒 Bu satır (IsClosed=1) kapatılmış. Silinemez.' + message: '🔒 Bu satır (IsClosed=1) kapatılmış. Silinemez.' }) return false } - // 2) Kullanıcıya onay sor + // 2) Kullanıcıya onay sor return new Promise(resolve => { $q?.dialog({ - title: 'Satır Sil', + title: 'Satır Sil', message: `${row.model} / ${row.renk} / ${row.renk2} kombinasyonu silinsin mi?`, ok: { label: 'Evet', color: 'negative' }, - cancel: { label: 'Vazgeç' } + cancel: { label: 'Vazgeç' } }) .onOk(() => { this.removeRowInternal(row) @@ -2066,9 +2056,9 @@ export const useOrderEntryStore = defineStore('orderentry', { removeRowInternal(row) { if (!row) return false - // 1️⃣ Kilit kontrolü + // 1️⃣ Kilit kontrolü if (this.isRowLocked(row)) { - console.warn('🔒 Kilitli satır silinemez.') + console.warn('🔒 Kilitli satır silinemez.') return false } @@ -2083,27 +2073,27 @@ export const useOrderEntryStore = defineStore('orderentry', { const idx = this.summaryRows.findIndex(r => getKey(r) === rowKey) if (idx === -1) return false - console.log('🗑️ X2 removeRowInternal →', row) + console.log('🗑️ X2 removeRowInternal →', row) - // 🔐 UI BUSY + // 🔐 UI BUSY this._uiBusy = true this.preventPersist = true try { - // 2️⃣ UI’dan kaldır + // 2️⃣ UI’dan kaldır this.summaryRows.splice(idx, 1) - // orders = UI satırları (temiz kopya) + // orders = UI satırları (temiz kopya) this.orders = [...this.summaryRows] - // 3️⃣ EDIT MODE → DELETE SİNYALİ + // 3️⃣ EDIT MODE → DELETE SİNYALİ if (this.mode === 'edit') { const grpKey = row.grpKey || Object.keys(row.bedenMap || {})[0] || 'tak' - // ✅ lineIdMap referansı (varsa) + // ✅ lineIdMap referansı (varsa) const lineIdMap = (row.lineIdMap && typeof row.lineIdMap === 'object') ? { ...row.lineIdMap } @@ -2111,7 +2101,7 @@ export const useOrderEntryStore = defineStore('orderentry', { const emptyMap = {} - // Öncelik: bedenMap[grpKey] → lineIdMap → fallback + // Öncelik: bedenMap[grpKey] → lineIdMap → fallback if (row.bedenMap && row.bedenMap[grpKey]) { for (const beden of Object.keys(row.bedenMap[grpKey] || {})) { emptyMap[beden] = 0 @@ -2127,21 +2117,21 @@ export const useOrderEntryStore = defineStore('orderentry', { const deleteSignalRow = { ...row, - // 🔴 UI KEY + // 🔴 UI KEY id: `DEL::${row.id || row.OrderLineID || crypto.randomUUID()}`, - // 🔴 BACKEND DELETE SIGNAL + // 🔴 BACKEND DELETE SIGNAL adet: 0, Qty1: 0, tutar: 0, - // 🔴 CRITICAL: duplicate guard'a girmesin + // 🔴 CRITICAL: duplicate guard'a girmesin ComboKey: '', - // 🔴 legacy tekil alan (varsa kalsın) + // 🔴 legacy tekil alan (varsa kalsın) OrderLineID: row.OrderLineID || null, - // ✅ CRITICAL + // ✅ CRITICAL grpKey, bedenMap: { [grpKey]: emptyMap }, lineIdMap, @@ -2150,21 +2140,21 @@ export const useOrderEntryStore = defineStore('orderentry', { _deleteSignal: true } - console.log('📡 DELETE sinyali üretildi:', deleteSignalRow) + console.log('📡 DELETE sinyali üretildi:', deleteSignalRow) this.orders.push(deleteSignalRow) } - // 4️⃣ Totals (persist YOK) + // 4️⃣ Totals (persist YOK) this.updateHeaderTotals?.() } finally { - // 🔓 GUARD KAPAT + // 🔓 GUARD KAPAT this.preventPersist = false this._uiBusy = false } - // 5️⃣ TEK VE KONTROLLÜ persist + // 5️⃣ TEK VE KONTROLLÜ persist this.persistLocalStorage() return true @@ -2174,12 +2164,12 @@ export const useOrderEntryStore = defineStore('orderentry', { /* =========================================================== - 📦 normalizeOrderLines (v9 — lineIdMap FIXED + AKSBİR SAFE) + 📦 normalizeOrderLines (v9 — lineIdMap FIXED + AKSBİR SAFE) ----------------------------------------------------------- - ✔ grpKey SADECE burada set edilir - ✔ detectBedenGroup SADECE store’da kullanılır - ✔ aksbir → ' ' bedeni = GERÇEK adet - ✔ backend satırlarında BEDEN → OrderLineID map’i üretilir + ✔ grpKey SADECE burada set edilir + ✔ detectBedenGroup SADECE store’da kullanılır + ✔ aksbir → ' ' bedeni = GERÇEK adet + ✔ backend satırlarında BEDEN → OrderLineID map’i üretilir =========================================================== */ normalizeOrderLines(lines, pbFallback = 'USD') { if (!Array.isArray(lines)) return [] @@ -2198,17 +2188,17 @@ export const useOrderEntryStore = defineStore('orderentry', { raw.IsClosed?.Bool === true /* ======================================================= - 1️⃣ UI / SNAPSHOT KAYNAKLI SATIR + 1️⃣ UI / SNAPSHOT KAYNAKLI SATIR ------------------------------------------------------- - ✔ ComboKey YOK - ✔ Sadece model / renk / renk2 bazında gruplanır + ✔ ComboKey YOK + ✔ Sadece model / renk / renk2 bazında gruplanır ======================================================= */ if (raw.bedenMap && Object.keys(raw.bedenMap).length) { const model = (raw.model || raw.ItemCode || '').trim() const renk = (raw.renk || raw.ColorCode || '').trim() const renk2 = (raw.renk2 || raw.ItemDim2Code || '').trim() - // ❗ BEDEN YOK → bu SADECE üst seviye grup anahtarı + // ❗ BEDEN YOK → bu SADECE üst seviye grup anahtarı const modelKey = `${model}||${renk}||${renk2}` const grpKey = raw.grpKey || 'tak' @@ -2235,17 +2225,17 @@ export const useOrderEntryStore = defineStore('orderentry', { /* ======================================================= - 2️⃣ BACKEND / LEGACY SATIR (FIXED) + 2️⃣ BACKEND / LEGACY SATIR (FIXED) ------------------------------------------------------- - ✔ ComboKey YOK - ✔ Sadece model / renk / renk2 bazlı gruplanır - ✔ BEDEN sadece bedenMap + lineIdMap için kullanılır + ✔ ComboKey YOK + ✔ Sadece model / renk / renk2 bazlı gruplanır + ✔ BEDEN sadece bedenMap + lineIdMap için kullanılır ======================================================= */ const model = (raw.Model || raw.ItemCode || '').trim() const renk = (raw.ColorCode || '').trim() const renk2 = (raw.ItemDim2Code || '').trim() - // ❗ BEDEN HARİÇ — üst seviye grup anahtarı + // ❗ BEDEN HARİÇ — üst seviye grup anahtarı const modelKey = `${model}||${renk}||${renk2}` merged[modelKey] ??= [] @@ -2275,8 +2265,8 @@ export const useOrderEntryStore = defineStore('orderentry', { fiyat: Number(raw.Price || 0), pb: raw.DocCurrencyCode || pbFallback, - __tmpMap: {}, // beden → qty - lineIdMap: {}, // beden → OrderLineID + __tmpMap: {}, // beden → qty + lineIdMap: {}, // beden → OrderLineID adet: 0, tutar: 0, @@ -2289,7 +2279,7 @@ export const useOrderEntryStore = defineStore('orderentry', { } /* ------------------------------------------------------- - 🔑 BEDEN → OrderLineID (DETERMINISTIC & SAFE) + 🔑 BEDEN → OrderLineID (DETERMINISTIC & SAFE) -------------------------------------------------------- */ const rawLineId = raw.OrderLineID || @@ -2309,7 +2299,7 @@ export const useOrderEntryStore = defineStore('orderentry', { } /* ======================================================= - 3️⃣ FINAL — grpKey KESİN + AKSBİR FIX + 3️⃣ FINAL — grpKey KESİN + AKSBİR FIX ======================================================= */ const out = [] @@ -2322,7 +2312,7 @@ export const useOrderEntryStore = defineStore('orderentry', { const bedenList = Object.keys(row.__tmpMap) - // 🔒 TEK VE KESİN KARAR + // 🔒 TEK VE KESİN KARAR const grpKey = detectBedenGroup( bedenList, row.urunAnaGrubu, @@ -2350,9 +2340,9 @@ export const useOrderEntryStore = defineStore('orderentry', { row.tutar = Number((row.adet * Number(row.fiyat || 0)).toFixed(2)) /* =================================================== - 🔒 AKSBİR — BOŞLUK BEDEN GERÇEK ADETİ ALIR - ❗ STD’ye dönme YOK - ❗ 0 yazma YOK + 🔒 AKSBİR — BOŞLUK BEDEN GERÇEK ADETİ ALIR + ❗ STD’ye dönme YOK + ❗ 0 yazma YOK =================================================== */ if (grpKey === 'aksbir') { row.bedenMap[grpKey] ??= {} @@ -2365,7 +2355,7 @@ export const useOrderEntryStore = defineStore('orderentry', { } console.log( - `📦 normalizeOrderLines (v9 + lineIdMap) → ${out.length} satır` + `📦 normalizeOrderLines (v9 + lineIdMap) → ${out.length} satır` ) return out @@ -2375,12 +2365,12 @@ export const useOrderEntryStore = defineStore('orderentry', { /** * =========================================================== - * loadProductSizes — FINAL v4.2 (EDITOR SAFE) + * loadProductSizes — FINAL v4.2 (EDITOR SAFE) * ----------------------------------------------------------- - * ✔ grpKey SADECE form.grpKey - * ✔ schemaMap TEK OTORİTE - * ✔ edit modda BEDEN LABEL DOKUNULMAZ - * ✔ ' ' (boş beden) korunur + * ✔ grpKey SADECE form.grpKey + * ✔ schemaMap TEK OTORİTE + * ✔ edit modda BEDEN LABEL DOKUNULMAZ + * ✔ ' ' (boÅŸ beden) korunur * =========================================================== */ async loadProductSizes(form, forceRefresh = false, $q = null) { @@ -2395,7 +2385,7 @@ export const useOrderEntryStore = defineStore('orderentry', { try { const grpKey = form.grpKey if (!grpKey) { - console.warn('⛔ loadProductSizes iptal → grpKey yok') + console.warn('â›” loadProductSizes iptal → grpKey yok') return } @@ -2404,18 +2394,18 @@ export const useOrderEntryStore = defineStore('orderentry', { const cacheKey = `${form.model}_${colorKey}_${color2Key}_${grpKey}` /* ======================================================= - ♻️ CACHE (LABEL DOKUNMADAN) + ♻️ CACHE (LABEL DOKUNMADAN) ======================================================= */ if (!forceRefresh && sizeCache.value?.[cacheKey]) { const cached = sizeCache.value[cacheKey] bedenStock.value = [...cached.stockArray] stockMap.value = { ...cached.stockMap } - console.log(`♻️ loadProductSizes CACHE → ${grpKey}`) + console.log(`♻️ loadProductSizes CACHE → ${grpKey}`) return } /* ======================================================= - 📡 API + 📡 API ======================================================= */ const params = { code: form.model } if (form.renk) params.color = form.renk @@ -2431,7 +2421,7 @@ export const useOrderEntryStore = defineStore('orderentry', { } /* ======================================================= - 📦 STOK MAP (' ' KORUNUR) + 📦 STOK MAP (' ' KORUNUR) ======================================================= */ const apiStockMap = {} for (const x of data) { @@ -2453,7 +2443,7 @@ export const useOrderEntryStore = defineStore('orderentry', { ) /* ======================================================= - 💾 CACHE + 💾 CACHE ======================================================= */ sizeCache.value[cacheKey] = { labels: [...form.bedenLabels], @@ -2461,14 +2451,14 @@ export const useOrderEntryStore = defineStore('orderentry', { stockMap: { ...stockMap.value } } - console.log(`✅ loadProductSizes FINAL v4.2 → ${grpKey}`) + console.log(`✅ loadProductSizes FINAL v4.2 → ${grpKey}`) } catch (err) { - console.error('❌ loadProductSizes hata:', err) - $q?.notify?.({ type: 'negative', message: 'Beden / stok alınamadı' }) + console.error('❌ loadProductSizes hata:', err) + $q?.notify?.({ type: 'negative', message: 'Beden / stok alınamadı' }) } finally { store._uiBusy = prevBusy store.preventPersist = prevPrevent - console.log('🧩 Editor beden hydrate', { + console.log('🧩 Editor beden hydrate', { grpKey: form.grpKey, labels: form.bedenLabels, values: form.bedenler @@ -2483,24 +2473,24 @@ export const useOrderEntryStore = defineStore('orderentry', { , // ======================================================= -// 🔸 TOPLAM HESAPLAMA (store içi) — X3 SAFE +// 🔸 TOPLAM HESAPLAMA (store içi) — X3 SAFE // ------------------------------------------------------- -// ✔ f.adet / f.tutar hesaplanır -// ✔ store.totalAmount ASLA set edilmez -// ✔ gerçek toplam → header.TotalAmount +// ✔ f.adet / f.tutar hesaplanır +// ✔ store.totalAmount ASLA set edilmez +// ✔ gerçek toplam → header.TotalAmount // ======================================================= updateTotals(f) { - // 1️⃣ Satır adet + // 1️⃣ Satır adet f.adet = (f.bedenler || []).reduce( (a, b) => a + Number(b || 0), 0 ) - // 2️⃣ Satır tutar + // 2️⃣ Satır tutar const fiyat = Number(f.fiyat) || 0 f.tutar = Number((f.adet * fiyat).toFixed(2)) - // 3️⃣ Header toplam (tek gerçek state) + // 3️⃣ Header toplam (tek gerçek state) if (this.header) { const total = (this.summaryRows || []).reduce( (sum, r) => sum + Number(r?.tutar || 0), @@ -2515,39 +2505,39 @@ export const useOrderEntryStore = defineStore('orderentry', { , // ======================================================= - // 🔸 GRUP ANAHTARI TESPİTİ + // 🔸 GRUP ANAHTARI TESPİTİ // ======================================================= activeGroupKeyForRow(row) { const g = (row?.urunAnaGrubu || '').toUpperCase() if (g.includes('TAKIM')) return 'tak' if (g.includes('PANTOLON')) return 'pan' - if (g.includes('GÖMLEK')) return 'gom' + if (g.includes('GOMLEK')) return 'gom' if (g.includes('AYAKKABI')) return 'ayk' - if (g.includes('YAŞ')) return 'yas' + if (g.includes('YAS')) return 'yas' return 'tak' }, /* ======================================================= - 🔹 MODE YÖNETİMİ — new / edit arası geçiş + 🔹 MODE YÖNETİMİ — new / edit arası geçiÅŸ ======================================================= */ setMode(mode) { if (!['new', 'edit', 'view'].includes(mode)) { - console.warn('⚠️ Geçersiz mode:', mode) + console.warn('⚠️ Geçersiz mode:', mode) return } this.mode = mode - console.log(`🧭 Order mode set edildi → ${mode}`) + console.log(`🧭 Order mode set edildi → ${mode}`) } , /* =========================================================== - 🟦 submitAllReal (v12.1c — FINAL / CLEAN + PRE-VALIDATE) + 🟦 submitAllReal (v12.1c — FINAL / CLEAN + PRE-VALIDATE) ----------------------------------------------------------- - ✔ NEW → INSERT, EDIT → UPDATE (tek karar noktası) - ✔ Controlled submit → route guard SUSAR - ✔ Snapshot temizliği route öncesi - ✔ Kaydet → edit replace → backend reload - ✔ Listeye giderken guard popup 1 kez bypass - ✔ ✅ PRE-VALIDATE → prItemVariant olmayan kombinasyonlar kaydı DURDURUR + ✔ NEW → INSERT, EDIT → UPDATE (tek karar noktası) + ✔ Controlled submit → route guard SUSAR + ✔ Snapshot temizliÄŸi route öncesi + ✔ Kaydet → edit replace → backend reload + ✔ Listeye giderken guard popup 1 kez bypass + ✔ ✅ PRE-VALIDATE → prItemVariant olmayan kombinasyonlar kaydı DURDURUR =========================================================== */ async submitAllReal($q, router, form, summaryRows, productCache) { let serverOrderId = null @@ -2556,17 +2546,17 @@ export const useOrderEntryStore = defineStore('orderentry', { try { this.loading = true - // 🔒 Kontrollü submit → route leave guard susar + // 🔒 Kontrollü submit → route leave guard susar this.isControlledSubmit = true const isNew = this.mode === 'new' const { header, lines } = this.buildFinalOrderJson() // ======================================================= - // 🧾 DEBUG — FRONTEND → BACKEND GİDEN PAYLOAD + // 🧾 DEBUG — FRONTEND → BACKEND GİDEN PAYLOAD // ======================================================= console.groupCollapsed( - `%c📤 ORDER PAYLOAD (${this.mode})`, + `%c📤 ORDER PAYLOAD (${this.mode})`, 'color:#c9a873;font-weight:bold' ) @@ -2589,21 +2579,21 @@ export const useOrderEntryStore = defineStore('orderentry', { console.groupEnd() // ======================================================= - // 🧾 DEBUG (opsiyonel helper) + // 🧾 DEBUG (opsiyonel helper) // ======================================================= this.debugOrderPayload?.(header, lines, 'PRE-VALIDATE') // ======================================================= - // 🧩 DUMMY CURRENCY PAYLOAD (model genişletmeden) - // - trOrderLineCurrency için gerekli alanları satıra basar - // - örnek satırdaki gibi: PriceVI/AmountVI = KDV dahil, Price/Amount = KDV hariç + // 🧩 DUMMY CURRENCY PAYLOAD (model geniÅŸletmeden) + // - trOrderLineCurrency için gerekli alanları satıra basar + // - örnek satırdaki gibi: PriceVI/AmountVI = KDV dahil, Price/Amount = KDV hariç // ======================================================= const r2 = (n) => Number((Number(n) || 0).toFixed(2)) const r4 = (n) => Number((Number(n) || 0).toFixed(4)) for (const ln of lines) { const qty = Number(ln?.Qty1 || 0) - const unitBase = Number(ln?.Price || 0) // KDV hariç birim + const unitBase = Number(ln?.Price || 0) // KDV hariç birim const vatRate = Number(ln?.VatRate || 0) const exRate = Number(ln?.PriceExchangeRate || header?.ExchangeRate || 1) || 1 @@ -2614,7 +2604,7 @@ export const useOrderEntryStore = defineStore('orderentry', { const docCurrency = String(ln?.DocCurrencyCode || header?.DocCurrencyCode || 'TRY').trim() || 'TRY' - // Backend model alanları + // Backend model alanları ln.RelationCurrencyCode = docCurrency ln.DocPrice = unitWithVat ln.DocAmount = net @@ -2628,7 +2618,7 @@ export const useOrderEntryStore = defineStore('orderentry', { ln.VatDeducation = 0 ln.NetAmount = net - // SQL kolonu isimleriyle dummy alias (decoder ignore etse de payload'da görünür) + // SQL kolonu isimleriyle dummy alias (decoder ignore etse de payload'da görünür) ln.CurrencyCode = docCurrency ln.ExchangeRate = exRate ln.PriceVI = unitWithVat @@ -2640,25 +2630,25 @@ export const useOrderEntryStore = defineStore('orderentry', { } // ======================================================= - // 🧪 PRE-VALIDATE — prItemVariant ön kontrol - // - invalid varsa CREATE/UPDATE ÇALIŞMAZ + // 🧪 PRE-VALIDATE — prItemVariant ön kontrol + // - invalid varsa CREATE/UPDATE ÇALIŞMAZ // ======================================================= const v = await api.post('/order/validate', { header, lines }) const invalid = v?.data?.invalid || [] if (invalid.length > 0) { await this.showInvalidVariantDialog?.($q, invalid) - return // ❌ create / update ÇALIŞMAZ + return // ❌ create / update ÇALIŞMAZ } - console.log('📤 submitAllReal payload', { + console.log('📤 submitAllReal payload', { mode: this.mode, lines: lines.length, deletes: lines.filter(l => l._deleteSignal).length }) /* ======================================================= - 🚀 API CALL — TEK NOKTA + 🚀 API CALL — TEK NOKTA ======================================================= */ const resp = await api.post( isNew ? '/order/create' : '/order/update', @@ -2679,11 +2669,11 @@ export const useOrderEntryStore = defineStore('orderentry', { header?.OrderNumber if (!serverOrderId) { - throw new Error('OrderHeaderID backend’den dönmedi') + throw new Error('OrderHeaderID backend’den dönmedi') } /* ======================================================= - 🔁 MODE SWITCH → EDIT + 🔁 MODE SWITCH → EDIT ======================================================= */ this.setMode('edit') @@ -2695,25 +2685,25 @@ export const useOrderEntryStore = defineStore('orderentry', { } /* ======================================================= - 🧹 KRİTİK: Snapshot + Dirty temizliği - ❗ ROUTE değişmeden ÖNCE + 🧹 KRİTİK: Snapshot + Dirty temizliÄŸi + ❗ ROUTE deÄŸiÅŸmeden ÖNCE ======================================================= */ this.updateHeaderTotals?.() this.markAsSaved?.() /* ======================================================= - 🧹 KRİTİK: NEW → EDIT geçişinde TÜM SNAPSHOT TEMİZLENİR + 🧹 KRİTİK: NEW → EDIT geçiÅŸinde TÜM SNAPSHOT TEMİZLENİR ======================================================= */ this.clearAllOrderSnapshots() $q.notify({ type: 'positive', - message: `Sipariş kaydedildi: ${serverOrderNo || ''}`.trim() + message: `SipariÅŸ kaydedildi: ${serverOrderNo || ''}`.trim() }) /* ======================================================= - 🔀 ROUTE REPLACE (EDIT MODE) - - aynı sayfa → param değişti + 🔀 ROUTE REPLACE (EDIT MODE) + - aynı sayfa → param deÄŸiÅŸti - guard 1 kez bypass ======================================================= */ this.allowRouteLeaveOnce = true @@ -2725,7 +2715,7 @@ export const useOrderEntryStore = defineStore('orderentry', { }) /* ======================================================= - 🔄 BACKEND RELOAD (TEK GERÇEK KAYNAK) + 🔄 BACKEND RELOAD (TEK GERÇEK KAYNAK) ======================================================= */ await this.openExistingForEdit(serverOrderId, { $q, @@ -2735,21 +2725,21 @@ export const useOrderEntryStore = defineStore('orderentry', { }) /* ======================================================= - ❓ USER NEXT STEP + ❓ USER NEXT STEP ======================================================= */ const choice = await new Promise(resolve => { $q.dialog({ - title: 'Sipariş Kaydedildi', + title: 'SipariÅŸ Kaydedildi', options: { type: 'radio', model: 'continue', items: [ - { label: '✏️ Düzenlemeye Devam', value: 'continue' }, - { label: '🖨 Yazdır', value: 'print' }, - { label: '📋 Listeye Dön', value: 'list' } + { label: '✏️ Düzenlemeye Devam', value: 'continue' }, + { label: '🖨 Yazdır', value: 'print' }, + { label: '📋 Listeye Dön', value: 'list' } ] }, - ok: { label: 'Seç' }, + ok: { label: 'Seç' }, cancel: { label: 'Kapat' } }) .onOk(v => resolve(v)) @@ -2757,7 +2747,7 @@ export const useOrderEntryStore = defineStore('orderentry', { }) /* ======================================================= - 🧭 USER ROUTING + 🧭 USER ROUTING ======================================================= */ if (choice === 'print') { const id = this.header?.OrderHeaderID || serverOrderId @@ -2765,12 +2755,12 @@ export const useOrderEntryStore = defineStore('orderentry', { try { await this.downloadOrderPdf(id) } catch (pdfErr) { - console.error('⚠️ PDF açılamadı, kayıt başarılı:', pdfErr) + console.error('⚠️ PDF açılamadı, kayıt baÅŸarılı:', pdfErr) $q.notify({ type: 'warning', message: pdfErr?.message || - 'Sipariş kaydedildi fakat PDF açılamadı.' + 'SipariÅŸ kaydedildi fakat PDF açılamadı.' }) } } @@ -2783,10 +2773,10 @@ export const useOrderEntryStore = defineStore('orderentry', { return } - // continue → sayfada kal (hiçbir şey yapma) + // continue → sayfada kal (hiçbir ÅŸey yapma) } catch (err) { - console.error('❌ submitAllReal:', err) + console.error('❌ submitAllReal:', err) $q.notify({ type: 'negative', @@ -2794,11 +2784,11 @@ export const useOrderEntryStore = defineStore('orderentry', { err?.response?.data?.detail || err?.response?.data?.message || err?.message || - 'Kayıt sırasında hata' + 'Kayıt sırasında hata' }) } finally { - // 🔓 Guard’lar normale dönsün + // 🔓 Guard’lar normale dönsün this.isControlledSubmit = false this.loading = false } @@ -2807,28 +2797,28 @@ export const useOrderEntryStore = defineStore('orderentry', { , /* ======================================================= - 🧪 SUBMIT ALL TEST + 🧪 SUBMIT ALL TEST ======================================================= */ async submitAllTest($q = null) { try { const { header, lines } = this.buildFinalOrderJson() - console.log('🧾 TEST HEADER', Object.keys(header).length, 'alan') + console.log('🧾 TEST HEADER', Object.keys(header).length, 'alan') console.log(JSON.stringify(header, null, 2)) - console.log('🧾 TEST LINES', lines.length, 'satır') + console.log('🧾 TEST LINES', lines.length, 'satır') console.log(JSON.stringify(lines, null, 2)) $q?.notify?.({ type: 'info', - message: `Header (${Object.keys(header).length}) + Lines (${lines.length}) gösterildi`, + message: `Header (${Object.keys(header).length}) + Lines (${lines.length}) gösterildi`, position: 'top' }) } catch (err) { - console.error('❌ submitAllTest hata:', err) + console.error('❌ submitAllTest hata:', err) $q?.notify?.({ type: 'negative', - message: 'Gösterimde hata oluştu ❌', + message: 'Gösterimde hata oluÅŸtu ❌', position: 'top' }) } @@ -2836,15 +2826,15 @@ export const useOrderEntryStore = defineStore('orderentry', { /* ======================================================= - 🧹 KAYIT SONRASI TEMİZLİK + 🧹 KAYIT SONRASI TEMİZLİK ======================================================= */ afterSubmit(opts = { keepLocalStorage: true, backendPayload: null, - resetMode: true // 🔑 yeni + resetMode: true // 🔑 yeni }) { try { - console.log('🧹 afterSubmit başlatıldı', opts) + console.log('🧹 afterSubmit baÅŸlatıldı', opts) if (opts?.backendPayload?.header?.OrderHeaderID) { this.mergeAndPersistBackendOrder( @@ -2865,14 +2855,14 @@ export const useOrderEntryStore = defineStore('orderentry', { this.editingKey = null this.currentOrderId = null - // 🔐 MODE RESET OPSİYONEL + // 🔐 MODE RESET OPSİYONEL if (opts.resetMode === true) { this.mode = 'new' } - console.log('✅ afterSubmit tamamlandı.') + console.log('✅ afterSubmit tamamlandı.') } catch (err) { - console.error('❌ afterSubmit hata:', err) + console.error('❌ afterSubmit hata:', err) } } @@ -2880,14 +2870,14 @@ export const useOrderEntryStore = defineStore('orderentry', { /* =========================================================== - 🟦 BUILD FINAL ORDER JSON — SAFE v26.1 (FINAL) + 🟦 BUILD FINAL ORDER JSON — SAFE v26.1 (FINAL) ----------------------------------------------------------- - ✔ ComboKey TEK OTORİTE → buildComboKey (bedenKey ile) - ✔ UI/Map placeholder: '_' (bedenKey) - ✔ DB/payload: '' (bedenPayload) → "_" ASLA GİTMEZ - ✔ payload içinde aynı ComboKey TEK satır - ✔ backend duplicate guard %100 uyumlu (ComboKey stabil) - ✔ Final assert: payload’da "_" yakalanırsa patlatır + ✔ ComboKey TEK OTORİTE → buildComboKey (bedenKey ile) + ✔ UI/Map placeholder: '_' (bedenKey) + ✔ DB/payload: '' (bedenPayload) → "_" ASLA GİTMEZ + ✔ payload içinde aynı ComboKey TEK satır + ✔ backend duplicate guard %100 uyumlu (ComboKey stabil) + ✔ Final assert: payload’da "_" yakalanırsa patlatır =========================================================== */ buildFinalOrderJson () { const auth = useAuthStore() @@ -2904,7 +2894,7 @@ export const useOrderEntryStore = defineStore('orderentry', { const formatTimeOnly = v => dayjs(v).format('HH:mm:ss') const formatDateTime = v => (v ? dayjs(v).format('YYYY-MM-DD HH:mm:ss') : null) - // ✅ Payload beden normalize: "_" / "-" / "" => '' + // ✅ Payload beden normalize: "_" / "-" / "" => '' const normBeden = (v) => { const s = safeStr(v) if (s === '' || s === '_' || s === '-') return '' // payload empty @@ -2959,16 +2949,16 @@ export const useOrderEntryStore = defineStore('orderentry', { } /* ======================================================= - LINES — COMBOKEY AGGREGATE (TEK MAP) + LINES — COMBOKEY AGGREGATE (TEK MAP) ======================================================= */ const lines = [] - const lineByCombo = new Map() // 🔒 KEY = ComboKey + const lineByCombo = new Map() // 🔒 KEY = ComboKey const pushOrMerge = (row, ctx) => { const { grpKey, - bedenKey, // ✅ sadece ComboKey / Map için ('_' olabilir) - bedenPayload, // ✅ DB için ('' / 'S' / 'M' ...) + bedenKey, // ✅ sadece ComboKey / Map için ('_' olabilir) + bedenPayload, // ✅ DB için ('' / 'S' / 'M' ...) qty, orderLineId, isDeleteSignal @@ -2976,7 +2966,7 @@ export const useOrderEntryStore = defineStore('orderentry', { if (qty <= 0 && !isDeleteSignal) return - // ComboKey stabil kalsın diye bedenKey kullan + // ComboKey stabil kalsın diye bedenKey kullan const comboKey = buildComboKey(row, bedenKey) const makeLine = () => ({ @@ -2990,7 +2980,7 @@ export const useOrderEntryStore = defineStore('orderentry', { ItemCode: safeStr(row.model), ColorCode: safeStr(row.renk), - // ✅ PAYLOAD: "_" ASLA YOK + // ✅ PAYLOAD: "_" ASLA YOK ItemDim1Code: bedenPayload, ItemDim2Code: safeStr(row.renk2), @@ -3101,7 +3091,7 @@ export const useOrderEntryStore = defineStore('orderentry', { const hasAnyBeden = map && typeof map === 'object' && Object.keys(map).length > 0 - /* 🔹 BEDENSİZ / AKSBİR */ + /* 🔹 BEDENSİZ / AKSBİR */ if (!hasAnyBeden) { const allowBlankPayload = grpKey === 'aksbir' || row._deleteSignal === true @@ -3111,9 +3101,9 @@ export const useOrderEntryStore = defineStore('orderentry', { const qty = toNum(row.qty ?? row.Qty1 ?? row.miktar ?? 0) - // ✅ ComboKey stabil: bedenKey = '_' + // ✅ ComboKey stabil: bedenKey = '_' const bedenKey = '_' - // ✅ Payload: boş string + // ✅ Payload: boÅŸ string const bedenPayload = '' let orderLineId = '' @@ -3137,7 +3127,7 @@ export const useOrderEntryStore = defineStore('orderentry', { continue } - /* 🔹 BEDENLİ */ + /* 🔹 BEDENLİ */ for (const [bedenRaw, qtyRaw] of Object.entries(map)) { const isBlankBeden = safeStr(bedenRaw) === '' if ( @@ -3150,14 +3140,14 @@ export const useOrderEntryStore = defineStore('orderentry', { const qty = toNum(qtyRaw) - // ✅ payload beden: '' / 'S' / 'M' ... + // ✅ payload beden: '' / 'S' / 'M' ... const bedenPayload = normBeden(bedenRaw) - // ✅ combokey beden: boşsa '_' ile stabil kalsın + // ✅ combokey beden: boÅŸsa '_' ile stabil kalsın const bedenKey = bedenPayload || '_' let orderLineId = '' if (this.mode === 'edit') { - // lineIdMap anahtarı sizde hangi bedenle tutuluyorsa ikisini de dene + // lineIdMap anahtarı sizde hangi bedenle tutuluyorsa ikisini de dene orderLineId = safeStr(lineIdMap?.[bedenKey]) || safeStr(lineIdMap?.[bedenPayload]) || @@ -3184,18 +3174,18 @@ export const useOrderEntryStore = defineStore('orderentry', { lines.forEach((ln, i) => { ln.SortOrder = i + 1 }) /* ======================================================= - ASSERT — payload’da "_" OLAMAZ + ASSERT — payload’da "_" OLAMAZ ======================================================= */ if (lines.some(l => (l.ItemDim1Code || '') === '_' )) { - console.error('❌ Payload’da "_" yakalandı', lines.filter(l => l.ItemDim1Code === '_')) + console.error('❌ Payload’da "_" yakalandı', lines.filter(l => l.ItemDim1Code === '_')) throw new Error('Payload ItemDim1Code "_" olamaz') } /* ======================================================= - 🔍 DEBUG — BUILD FINAL ORDER JSON OUTPUT + 🔍 DEBUG — BUILD FINAL ORDER JSON OUTPUT ======================================================= */ - console.groupCollapsed('%c📦 BUILD FINAL ORDER JSON', 'color:#c9a873;font-weight:bold') + console.groupCollapsed('%c📦 BUILD FINAL ORDER JSON', 'color:#c9a873;font-weight:bold') - console.log('🧾 HEADER:', header) + console.log('🧾 HEADER:', header) console.table( lines.map((l, i) => ({ @@ -3224,7 +3214,7 @@ export const useOrderEntryStore = defineStore('orderentry', { ,/* =========================================================== - ✅ STORE ACTIONS — FIXED HELPERS + ✅ STORE ACTIONS — FIXED HELPERS - setRowErrorByClientKey - clearRowErrorByClientKey - applyTerminToRowsIfEmpty @@ -3258,14 +3248,14 @@ export const useOrderEntryStore = defineStore('orderentry', { if (!dateStr) return if (!Array.isArray(this.summaryRows)) return - // ❗ reassign YOK — patch/mutate + // ❗ reassign YOK — patch/mutate for (const r of this.summaryRows) { if (!r?.terminTarihi || r.terminTarihi === '') { r.terminTarihi = dateStr } } - // opsiyonel ama genelde doğru: + // opsiyonel ama genelde doÄŸru: this.persistLocalStorage?.() } @@ -3286,7 +3276,7 @@ export const useOrderEntryStore = defineStore('orderentry', { /* =========================================================== - 🔹 BEDEN LABEL NORMALİZASYONU (exported helper) + 🔹 BEDEN LABEL NORMALİZASYONU (exported helper) =========================================================== */ export function normalizeBedenLabel(v) { if (v === null || v === undefined) return ' ' @@ -3304,19 +3294,19 @@ export function normalizeBedenLabel(v) { } if (map[s]) return map[s] - // tamamen sayıysa string olarak döndür + // tamamen sayıysa string olarak döndür if (/^\d+$/.test(s)) return s - // virgüllü değer geldiyse ilkini al + // virgüllü deÄŸer geldiyse ilkini al if (s.includes(',')) return s.split(',')[0].trim() return s } /* =========================================================== - 🔹 BEDEN GRUBU ALGILAMA HELPER’I + 🔹 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). + 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). ----------------------------------------------------------- =========================================================== */ export function detectBedenGroup(bedenList, urunAnaGrubu = '', urunKategori = '') { @@ -3328,25 +3318,25 @@ export function detectBedenGroup(bedenList, urunAnaGrubu = '', urunKategori = '' .toUpperCase() .trim() .replace(/\(.*?\)/g, '') - .replace(/[^A-ZÇĞİÖŞÜ0-9\s]/g, '') + .replace(/[^A-ZÇĞİÖŞÜ0-9\s]/g, '') .replace(/\s+/g, ' ') const kat = (urunKategori || '').toUpperCase().trim() -// 🔸 Aksesuar ise "aksbir" +// 🔸 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','ÇORAP', + 'FULAR','MENDIL','MENDİL','KASKOL','ASKI', + 'YAKA','KOL DUGMESI','KOL DÜĞMESİ' ] - const giyimGruplari = ['GÖMLEK','CEKET','PANTOLON','MONT','YELEK','TAKIM','TSHIRT','TİŞÖRT'] - // 🔸 Pantolon özel durumu + const giyimGruplari = ['GÖMLEK','CEKET','PANTOLON','MONT','YELEK','TAKIM','TSHIRT','TİŞÖRT'] + // 🔸 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' - // 🔸 Tamamen numerik (örneğin 39-44 arası) → ayakkabı + 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) @@ -3354,17 +3344,17 @@ export function detectBedenGroup(bedenList, urunAnaGrubu = '', urunKategori = '' if (diffs.every(d => d === 1) && nums[0] >= 35 && nums[0] <= 46) return 'ayk' } - // 🔸 Yaş grubu (çocuk/garson) - if (kat.includes('GARSON') || kat.includes('ÇOCUK')) return 'yas' + // 🔸 YaÅŸ grubu (çocuk/garson) + if (kat.includes('GARSON') || kat.includes('ÇOCUK')) return 'yas' - // 🔸 Harfli beden varsa doğrudan "gom" (gömlek, üst giyim) + // 🔸 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' - // 🔸 Varsayılan: takım elbise + // 🔸 Varsayılan: takım elbise return 'tak' } @@ -3421,9 +3411,9 @@ export function toSummaryRowFromForm(form) { /* =========================================================== - 🔹 TOPLAM HESAPLAMA (EXPORT) + 🔹 TOPLAM HESAPLAMA (EXPORT) ----------------------------------------------------------- - Hem store içinde hem de component tarafında kullanılabilir. + Hem store içinde hem de component tarafında kullanılabilir. =========================================================== */ export function updateTotals(f) { f.adet = (f.bedenler || []).reduce((a, b) => a + Number(b || 0), 0) @@ -3433,11 +3423,11 @@ export function updateTotals(f) { } /* =========================================================== - 🔹 EXPORT SET — Tek Merkezli Dışa Aktarımlar + 🔹 EXPORT SET — Tek Merkezli Dışa Aktarımlar =========================================================== */ /** - * 🧩 Shared Reactive Refs + * 🧩 Shared Reactive Refs * ----------------------------------------------------------- * import { sharedOrderEntryRefs } from 'src/stores/orderentryStore' * const { stockMap, bedenStock, sizeCache } = sharedOrderEntryRefs