diff --git a/ui/dist/spa/index.html b/ui/dist/spa/index.html index f352493..fd5d1cc 100644 --- a/ui/dist/spa/index.html +++ b/ui/dist/spa/index.html @@ -1 +1 @@ -Baggi SS
\ No newline at end of file +Baggi SS
\ No newline at end of file diff --git a/ui/src/stores/orderentryStore.js b/ui/src/stores/orderentryStore.js index 392d601..6030e9b 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, { 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}` } @@ -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 } } @@ -393,7 +393,7 @@ export const useOrderEntryStore = defineStore('orderentry', { } catch (err) { const detail = await extractApiErrorDetail(err) const status = err?.status || err?.response?.status || '-' - console.error(`❌ fetchOrderPdf hata [${status}] order=${orderId}: ${detail}`) + console.error(`? fetchOrderPdf hata [${status}] order=${orderId}: ${detail}`) throw new Error(detail) } } @@ -403,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 } @@ -421,7 +421,7 @@ export const useOrderEntryStore = defineStore('orderentry', { 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}`) + console.error(`? PDF a�ma hatas� [${status}] order=${orderId}: ${detail}`) throw new Error(detail) } } @@ -442,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) { @@ -458,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) { @@ -470,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 @@ -500,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 || {}), @@ -521,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 || {}), @@ -544,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 } @@ -567,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 }) { @@ -597,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' @@ -617,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 @@ -647,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()) @@ -656,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 = [] @@ -666,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 = [] @@ -685,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' @@ -694,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() { @@ -704,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) @@ -718,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) }) @@ -730,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 = [] @@ -761,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) { @@ -775,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) { @@ -785,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?.() } @@ -818,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 @@ -846,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, @@ -855,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 || [], @@ -871,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, @@ -904,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' }) } @@ -920,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() @@ -936,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 @@ -994,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', @@ -1011,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 } } @@ -1027,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) } @@ -1043,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) { @@ -1055,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) { @@ -1087,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)) { @@ -1105,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 @@ -1141,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}` @@ -1163,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ı`) } , @@ -1180,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 @@ -1211,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 || '', @@ -1240,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, @@ -1256,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) { @@ -1272,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 @@ -1285,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) } @@ -1295,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 { @@ -1303,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 } @@ -1323,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, @@ -1339,7 +1339,7 @@ export const useOrderEntryStore = defineStore('orderentry', { })) } - // 🔹 Summary + // 🔹 Summary if (Array.isArray(this.summaryRows)) { this.summaryRows = this.summaryRows.map(r => ({ ...r, @@ -1349,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 { @@ -1364,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, @@ -1380,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') } @@ -1408,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 { @@ -1431,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 } @@ -1461,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 } } @@ -1484,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 @@ -1521,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, @@ -1536,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 @@ -1552,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 } @@ -1564,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 || {} @@ -1605,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)) @@ -1625,7 +1625,7 @@ export const useOrderEntryStore = defineStore('orderentry', { } /* ======================================================= - 3️⃣ FİYAT (MIN) KONTROLÜ (FIXED) + 3️⃣ FİYAT (MIN) KONTROLÜ (FIXED) ======================================================= */ let fiyatOK = true try { @@ -1643,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)) @@ -1657,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 @@ -1671,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) @@ -1684,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 = @@ -1700,7 +1700,7 @@ export const useOrderEntryStore = defineStore('orderentry', { ? { ...newRow.lineIdMap } : {} - /* ===== SAME COMBO → UPDATE ===== */ + /* ===== SAME COMBO → UPDATE ===== */ if (sameCombo) { rows[idx] = { ...prev, @@ -1720,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] || @@ -1780,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 || @@ -1813,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() === '') @@ -1863,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(), @@ -1884,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 } } @@ -1900,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).') } } } @@ -1925,7 +1925,7 @@ export const useOrderEntryStore = defineStore('orderentry', { /* =========================================================== - 🧹 clearTransaction — sadece NEW MODE taslaklarını temizler + 🧹 clearTransaction — sadece NEW MODE taslaklarını temizler =========================================================== */ clearTransaction() { try { @@ -1942,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 && @@ -1990,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() @@ -2009,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}`) }, @@ -2023,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) @@ -2056,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 } @@ -2073,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 } @@ -2101,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 @@ -2117,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, @@ -2140,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 @@ -2164,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 [] @@ -2188,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' @@ -2225,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] ??= [] @@ -2265,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, @@ -2279,7 +2279,7 @@ export const useOrderEntryStore = defineStore('orderentry', { } /* ------------------------------------------------------- - 🔑 BEDEN → OrderLineID (DETERMINISTIC & SAFE) + 🔑 BEDEN → OrderLineID (DETERMINISTIC & SAFE) -------------------------------------------------------- */ const rawLineId = raw.OrderLineID || @@ -2299,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 = [] @@ -2312,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, @@ -2340,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] ??= {} @@ -2355,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 @@ -2365,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) { @@ -2385,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 } @@ -2394,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 @@ -2421,7 +2421,7 @@ export const useOrderEntryStore = defineStore('orderentry', { } /* ======================================================= - 📦 STOK MAP (' ' KORUNUR) + 📦 STOK MAP (' ' KORUNUR) ======================================================= */ const apiStockMap = {} for (const x of data) { @@ -2443,7 +2443,7 @@ export const useOrderEntryStore = defineStore('orderentry', { ) /* ======================================================= - 💾 CACHE + 💾 CACHE ======================================================= */ sizeCache.value[cacheKey] = { labels: [...form.bedenLabels], @@ -2451,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 @@ -2473,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), @@ -2505,7 +2505,7 @@ export const useOrderEntryStore = defineStore('orderentry', { , // ======================================================= - // 🔸 GRUP ANAHTARI TESPİTİ + // 🔸 GRUP ANAHTARI TESPİTİ // ======================================================= activeGroupKeyForRow(row) { const g = (row?.urunAnaGrubu || '').toUpperCase() @@ -2517,27 +2517,27 @@ export const useOrderEntryStore = defineStore('orderentry', { 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 @@ -2546,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' ) @@ -2579,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 @@ -2604,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 @@ -2618,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 @@ -2630,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', @@ -2669,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') @@ -2685,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 @@ -2715,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, @@ -2725,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)) @@ -2747,7 +2747,7 @@ export const useOrderEntryStore = defineStore('orderentry', { }) /* ======================================================= - 🧭 USER ROUTING + 🧭 USER ROUTING ======================================================= */ if (choice === 'print') { const id = this.header?.OrderHeaderID || serverOrderId @@ -2755,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ı.' }) } } @@ -2773,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', @@ -2784,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 } @@ -2797,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' }) } @@ -2826,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( @@ -2855,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) } } @@ -2870,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() @@ -2894,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 @@ -2949,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 @@ -2966,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 = () => ({ @@ -2980,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), @@ -3091,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 @@ -3101,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 = '' @@ -3127,7 +3127,7 @@ export const useOrderEntryStore = defineStore('orderentry', { continue } - /* 🔹 BEDENLİ */ + /* 🔹 BEDENLİ */ for (const [bedenRaw, qtyRaw] of Object.entries(map)) { const isBlankBeden = safeStr(bedenRaw) === '' if ( @@ -3140,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]) || @@ -3174,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) => ({ @@ -3214,7 +3214,7 @@ export const useOrderEntryStore = defineStore('orderentry', { ,/* =========================================================== - ✅ STORE ACTIONS — FIXED HELPERS + ✅ STORE ACTIONS — FIXED HELPERS - setRowErrorByClientKey - clearRowErrorByClientKey - applyTerminToRowsIfEmpty @@ -3248,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?.() } @@ -3454,9 +3454,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) @@ -3466,11 +3466,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