Merge remote-tracking branch 'origin/master'

This commit is contained in:
2026-02-16 16:04:13 +03:00
parent 5124ad78af
commit 14d71ba925
2 changed files with 415 additions and 415 deletions

View File

@@ -1 +1 @@
<!DOCTYPE html><html><head><title>Baggi SS</title><meta charset=utf-8><meta name=description content="A Quasar Project"><meta name=format-detection content="telephone=no"><meta name=msapplication-tap-highlight content=no><meta name=viewport content="user-scalable=no,initial-scale=1,maximum-scale=1,minimum-scale=1,width=device-width"><link rel=icon type=image/png sizes=128x128 href=/icons/favicon-128x128.png><link rel=icon type=image/png sizes=96x96 href=/icons/favicon-96x96.png><link rel=icon type=image/png sizes=32x32 href=/icons/favicon-32x32.png><link rel=icon type=image/png sizes=16x16 href=/icons/favicon-16x16.png><link rel=icon type=image/ico href=/favicon.ico><script defer src=/js/vendor.1e1ff7a5.js></script><script defer src=/js/app.b52a63d5.js></script><link href=/css/vendor.724dcfab.css rel=stylesheet><link href=/css/app.53116624.css rel=stylesheet></head><body><div id=q-app></div></body></html> <!DOCTYPE html><html><head><title>Baggi SS</title><meta charset=utf-8><meta name=description content="A Quasar Project"><meta name=format-detection content="telephone=no"><meta name=msapplication-tap-highlight content=no><meta name=viewport content="user-scalable=no,initial-scale=1,maximum-scale=1,minimum-scale=1,width=device-width"><link rel=icon type=image/png sizes=128x128 href=/icons/favicon-128x128.png><link rel=icon type=image/png sizes=96x96 href=/icons/favicon-96x96.png><link rel=icon type=image/png sizes=32x32 href=/icons/favicon-32x32.png><link rel=icon type=image/png sizes=16x16 href=/icons/favicon-16x16.png><link rel=icon type=image/ico href=/favicon.ico><script defer src=/js/vendor.1e1ff7a5.js></script><script defer src=/js/app.f6769585.js></script><link href=/css/vendor.724dcfab.css rel=stylesheet><link href=/css/app.53116624.css rel=stylesheet></head><body><div id=q-app></div></body></html>

View File

@@ -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 { defineStore } from 'pinia'
import api, { extractApiErrorDetail } from 'src/services/api' import api, { extractApiErrorDetail } from 'src/services/api'
import dayjs from 'src/boot/dayjs' 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' 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 // - trim + UPPER
// - dim1 boÅŸsa " " // - dim1 boşsa " "
// - dim2 boÅŸsa "" // - dim2 boşsa ""
// =========================================================== // ===========================================================
const BEDEN_EMPTY = '_' const BEDEN_EMPTY = '_'
@@ -33,7 +33,7 @@ export function buildComboKey(row, beden) {
const bdn = normUpper(beden) const bdn = normUpper(beden)
const bedenFinal = bdn === '' ? BEDEN_EMPTY : bdn const bedenFinal = bdn === '' ? BEDEN_EMPTY : bdn
// 🔒 KANONİK SIRA // 🔒 KANONİK SIRA
return `${model}||${renk}||${renk2}||${bedenFinal}` return `${model}||${renk}||${renk2}||${bedenFinal}`
} }
@@ -61,10 +61,10 @@ export const stockMap = ref({})
export const bedenStock = ref([]) export const bedenStock = ref([])
export const sizeCache = 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() { function newGuid() {
@@ -73,7 +73,7 @@ function newGuid() {
// 🔑 Her beden satırı için deterministik clientKey üretimi // 🔑 Her beden satırıin deterministik clientKey üretimi
function makeLineClientKey(row, grpKey, beden) { function makeLineClientKey(row, grpKey, beden) {
const base = const base =
row.clientRowKey || 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', { export const useOrderEntryStore = defineStore('orderentry', {
state: () => ({ state: () => ({
@@ -145,12 +145,12 @@ export const useOrderEntryStore = defineStore('orderentry', {
getters: { getters: {
getDraftKey() { getDraftKey() {
// NEW taslak → GLOBAL ama tekil // NEW taslak GLOBAL ama tekil
return 'bss_orderentry_new_draft' return 'bss_orderentry_new_draft'
}, },
getEditKey() { getEditKey() {
// EDIT → OrderHeaderID’ye baÄŸlı // EDIT OrderHeaderIDye bağlı
const id = this.header?.OrderHeaderID const id = this.header?.OrderHeaderID
return id ? `bss_orderentry_edit:${id}` : null 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 - TEK SOURCE OF TRUTH: BEDEN_SCHEMA
=========================================================== */ =========================================================== */
initSchemaMap() { initSchemaMap() {
@@ -222,7 +222,7 @@ export const useOrderEntryStore = defineStore('orderentry', {
this.schemaMap = map this.schemaMap = map
console.log( console.log(
'🧩 schemaMap INIT edildi:', '🧩 schemaMap INIT edildi:',
Object.keys(this.schemaMap) Object.keys(this.schemaMap)
) )
}, },
@@ -244,32 +244,32 @@ export const useOrderEntryStore = defineStore('orderentry', {
0 0
) )
// Header sadece GÖSTERİM / BACKEND için // Header sadece GÖSTERİM / BACKEND için
if (this.header) { if (this.header) {
this.header.TotalAmount = Number(total.toFixed(2)) this.header.TotalAmount = Number(total.toFixed(2))
} }
return total return total
} catch (err) { } catch (err) {
console.error('❌ updateHeaderTotals hata:', err) console.error(' updateHeaderTotals hata:', err)
return 0 return 0
} }
} }
, ,
/* =========================================================== /* ===========================================================
🚨 showInvalidVariantDialog — FINAL 🚨 showInvalidVariantDialog FINAL
----------------------------------------------------------- -----------------------------------------------------------
✔ prItemVariant olmayan satırları listeler prItemVariant olmayan satırları listeler
✔ Satıra tıkla → scroll + highlight Satıra tıkla scroll + highlight
✔ Kaydı BLOKLAYAN tek UI noktası Kaydı BLOKLAYAN tek UI noktası
=========================================================== */ =========================================================== */
async showInvalidVariantDialog($q, invalidList = []) { async showInvalidVariantDialog($q, invalidList = []) {
if (!Array.isArray(invalidList) || invalidList.length === 0) return if (!Array.isArray(invalidList) || invalidList.length === 0) return
return new Promise(resolve => { return new Promise(resolve => {
const dlg = $q.dialog({ const dlg = $q.dialog({
title: '🚨 Tanımsız Ürün Kombinasyonları', title: '🚨 Tanımsız Ürün Kombinasyonları',
message: ` message: `
<div style="max-height:60vh;overflow:auto"> <div style="max-height:60vh;overflow:auto">
${invalidList.map((v, i) => ` ${invalidList.map((v, i) => `
@@ -288,12 +288,12 @@ export const useOrderEntryStore = defineStore('orderentry', {
#${i + 1} | Item: ${v.itemCode} #${i + 1} | Item: ${v.itemCode}
</div> </div>
<div style="font-size:13px"> <div style="font-size:13px">
Beden: ${v.dim1 || '(boÅŸ)'} | Beden: ${v.dim1 || '(boş)'} |
Renk: ${v.colorCode || '-'} | Renk: ${v.colorCode || '-'} |
Qty: ${v.qty1} Qty: ${v.qty1}
</div> </div>
<div style="font-size:12px;color:#c10015"> <div style="font-size:12px;color:#c10015">
Sebep: ${v.reason || 'Tanımsız ürün kombinasyonu'} Sebep: ${v.reason || 'Tanımsız ürün kombinasyonu'}
</div> </div>
</div> </div>
`).join('')} `).join('')}
@@ -301,7 +301,7 @@ export const useOrderEntryStore = defineStore('orderentry', {
`, `,
html: true, html: true,
ok: { ok: {
label: 'Düzelt', label: 'Düzelt',
color: 'negative' color: 'negative'
}, },
cancel: false, cancel: false,
@@ -310,7 +310,7 @@ export const useOrderEntryStore = defineStore('orderentry', {
.onOk(() => resolve()) .onOk(() => resolve())
.onDismiss(() => 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(() => { setTimeout(() => {
if (!dlg) return if (!dlg) return
const nodes = document.querySelectorAll('.invalid-row') const nodes = document.querySelectorAll('.invalid-row')
@@ -325,42 +325,42 @@ export const useOrderEntryStore = defineStore('orderentry', {
} }
, ,
/* =========================================================== /* ===========================================================
🎯 scrollToInvalidRow — FINAL 🎯 scrollToInvalidRow FINAL
----------------------------------------------------------- -----------------------------------------------------------
✔ ClientKey bazlı scroll ClientKey bazlı scroll
✔ Hem summaryRows hem orders destekli Hem summaryRows hem orders destekli
✔ Highlight otomatik kalkar Highlight otomatik kalkar
=========================================================== */ =========================================================== */
scrollToInvalidRow(clientKey) { scrollToInvalidRow(clientKey) {
if (!clientKey) return if (!clientKey) return
// 1️⃣ Store içindeki satırı bul // 1️⃣ Store içindeki satırı bul
const idx = this.summaryRows?.findIndex( const idx = this.summaryRows?.findIndex(
r => r.clientKey === clientKey r => r.clientKey === clientKey
) )
if (idx === -1) { if (idx === -1) {
console.warn('❌ Satır bulunamadı:', clientKey) console.warn(' Satır bulunamadı:', clientKey)
return return
} }
// 2️⃣ DOM node // 2️⃣ DOM node
const el = document.querySelector( const el = document.querySelector(
`[data-clientkey="${clientKey}"]` `[data-clientkey="${clientKey}"]`
) )
if (!el) { if (!el) {
console.warn('❌ DOM satırı bulunamadı:', clientKey) console.warn(' DOM satırı bulunamadı:', clientKey)
return return
} }
// 3️⃣ Scroll // 3️⃣ Scroll
el.scrollIntoView({ el.scrollIntoView({
behavior: 'smooth', behavior: 'smooth',
block: 'center' block: 'center'
}) })
// 4️⃣ Highlight // 4️⃣ Highlight
el.classList.add('invalid-highlight') el.classList.add('invalid-highlight')
setTimeout(() => { setTimeout(() => {
@@ -375,10 +375,10 @@ export const useOrderEntryStore = defineStore('orderentry', {
const res = await api.get(`/orders/check/${orderHeaderID}`) 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 return res?.data?.exists === true
} catch (err) { } catch (err) {
console.warn("âš  checkHeaderExists hata:", err) console.warn(" checkHeaderExists hata:", err)
return false return false
} }
} }
@@ -393,7 +393,7 @@ export const useOrderEntryStore = defineStore('orderentry', {
} catch (err) { } catch (err) {
const detail = await extractApiErrorDetail(err) const detail = await extractApiErrorDetail(err)
const status = err?.status || err?.response?.status || '-' 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) throw new Error(detail)
} }
} }
@@ -403,7 +403,7 @@ export const useOrderEntryStore = defineStore('orderentry', {
try { try {
const orderId = id || this.header?.OrderHeaderID const orderId = id || this.header?.OrderHeaderID
if (!orderId) { if (!orderId) {
console.error('❌ PDF ID bulunamadı') console.error(' PDF ID bulunamadı')
return return
} }
@@ -421,7 +421,7 @@ export const useOrderEntryStore = defineStore('orderentry', {
const detail = await extractApiErrorDetail(err) const detail = await extractApiErrorDetail(err)
const orderId = id || this.header?.OrderHeaderID || '-' const orderId = id || this.header?.OrderHeaderID || '-'
const status = err?.status || err?.response?.status || '-' const status = err?.status || err?.response?.status || '-'
console.error(` PDF açma hatası [${status}] order=${orderId}: ${detail}`) console.error(`? PDF a<EFBFBD>ma hatas<EFBFBD> [${status}] order=${orderId}: ${detail}`)
throw new Error(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 - header + orders + summaryRows restore edilir
- groupedRows hydrate edilmez / resetlenmez / dokunulmaz - 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') { if (this.mode === 'new') {
const raw = localStorage.getItem(this.getDraftKey) const raw = localStorage.getItem(this.getDraftKey)
if (raw) { if (raw) {
@@ -458,11 +458,11 @@ export const useOrderEntryStore = defineStore('orderentry', {
this.header = payload.header || {} this.header = payload.header || {}
this.orders = payload.orders || [] this.orders = payload.orders || []
this.summaryRows = payload.summaryRows || this.orders this.summaryRows = payload.summaryRows || this.orders
console.log('♻️ NEW draft restore edildi (global)') console.log('♻️ NEW draft restore edildi (global)')
return return
} catch {} } catch {}
} }
console.log('⚪ NEW draft yok, boÅŸ baÅŸlatılıyor') console.log(' NEW draft yok, boş başlatılıyor')
return return
} }
if (!this.schemaMap || !Object.keys(this.schemaMap).length) { if (!this.schemaMap || !Object.keys(this.schemaMap).length) {
@@ -470,7 +470,7 @@ export const useOrderEntryStore = defineStore('orderentry', {
} }
try { try {
console.log('🧩 [initFromRoute] orderId:', orderId) console.log('🧩 [initFromRoute] orderId:', orderId)
const lastTxn = localStorage.getItem('bss_last_txn') || null const lastTxn = localStorage.getItem('bss_last_txn') || null
@@ -500,18 +500,18 @@ export const useOrderEntryStore = defineStore('orderentry', {
if (hasData(fromRoute)) { if (hasData(fromRoute)) {
chosenId = orderId chosenId = orderId
chosenPayload = fromRoute chosenPayload = fromRoute
console.log('✅ [initFromRoute] Route ID snapshot seçildi:', chosenId) console.log(' [initFromRoute] Route ID snapshot seçildi:', chosenId)
} else if (hasData(fromLast)) { } else if (hasData(fromLast)) {
chosenId = lastTxn chosenId = lastTxn
chosenPayload = fromLast 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) { 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 = {
...(this.header || {}), ...(this.header || {}),
@@ -521,12 +521,12 @@ export const useOrderEntryStore = defineStore('orderentry', {
this.orders = [] this.orders = []
this.summaryRows = [] this.summaryRows = []
// ❗ groupedRows'a DOKUNMA // groupedRows'a DOKUNMA
return return
} }
/* ------------------------------------------------------- /* -------------------------------------------------------
✅ SNAPSHOT RESTORE (SAFE CLONE) SNAPSHOT RESTORE (SAFE CLONE)
-------------------------------------------------------- */ -------------------------------------------------------- */
this.header = { this.header = {
...(chosenPayload.header || {}), ...(chosenPayload.header || {}),
@@ -544,22 +544,22 @@ export const useOrderEntryStore = defineStore('orderentry', {
this.orders = orders this.orders = orders
this.summaryRows = summaryRows this.summaryRows = summaryRows
// ❗ groupedRows hydrate edilmez, resetlenmez // groupedRows hydrate edilmez, resetlenmez
/* ------------------------------------------------------- /* -------------------------------------------------------
🔁 lastTxn SENKRON 🔁 lastTxn SENKRON
-------------------------------------------------------- */ -------------------------------------------------------- */
try { try {
localStorage.setItem('bss_last_txn', chosenId) localStorage.setItem('bss_last_txn', chosenId)
} catch (e) { } 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) { if (router && orderId && orderId !== chosenId) {
console.log('🔁 [initFromRoute] Route ID düzeltiliyor →', chosenId) console.log('🔁 [initFromRoute] Route ID düzeltiliyor ', chosenId)
await router.replace({ await router.replace({
name: 'order-entry', name: 'order-entry',
params: { orderHeaderID: chosenId } params: { orderHeaderID: chosenId }
@@ -567,19 +567,19 @@ export const useOrderEntryStore = defineStore('orderentry', {
} }
console.log( console.log(
'✅ [initFromRoute] Restore tamam. Satır sayısı:', ' [initFromRoute] Restore tamam. Satır sayısı:',
this.summaryRows.length this.summaryRows.length
) )
} catch (err) { } 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 }) { async startNewOrder({ $q }) {
@@ -597,7 +597,7 @@ export const useOrderEntryStore = defineStore('orderentry', {
orderNumber = res.data.OrderNumber orderNumber = res.data.OrderNumber
} }
} catch { } catch {
console.info('ℹ️ Backend order number yok, LOCAL kullanıldı') console.info(' Backend order number yok, LOCAL kullanıldı')
} }
this.mode = 'new' this.mode = 'new'
@@ -617,10 +617,10 @@ export const useOrderEntryStore = defineStore('orderentry', {
this.orders = [] this.orders = []
this.summaryRows = [] this.summaryRows = []
// ✅ fingerprint bazlı sistem için reset // fingerprint bazlı sistem için reset
this._lastSavedFingerprint = null this._lastSavedFingerprint = null
// ✅ NEW draft hemen yazılır // NEW draft hemen yazılır
this.persistLocalStorage?.() this.persistLocalStorage?.()
return this.header return this.header
@@ -647,7 +647,7 @@ export const useOrderEntryStore = defineStore('orderentry', {
const ex = map.get(key) const ex = map.get(key)
ex.Qty1 = (Number(ex.Qty1) || 0) + (Number(ln.Qty1) || 0) 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 if (!ex.OrderLineID && ln.OrderLineID) ex.OrderLineID = ln.OrderLineID
} }
return Array.from(map.values()) 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() { resetCoreState() {
this.orders = [] this.orders = []
@@ -666,14 +666,14 @@ export const useOrderEntryStore = defineStore('orderentry', {
this.editingKey = null this.editingKey = null
this.currentOrderId = null this.currentOrderId = null
},resetForNewOrder() { },resetForNewOrder() {
// mevcut her ÅŸeyi temizle // mevcut her şeyi temizle
this.header = { this.header = {
OrderHeaderID: this.header?.OrderHeaderID || null, OrderHeaderID: this.header?.OrderHeaderID || null,
OrderDate: new Date().toISOString().slice(0,10), OrderDate: new Date().toISOString().slice(0,10),
CurrAccCode: null, CurrAccCode: null,
DocCurrencyCode: 'TRY', DocCurrencyCode: 'TRY',
PriceCurrencyCode: 'TRY', PriceCurrencyCode: 'TRY',
// ihtiyaç duyduÄŸun diÄŸer default header alanları // ihtiyaç duyduğun diğer default header alanları
} }
this.orders = [] this.orders = []
@@ -685,7 +685,7 @@ export const useOrderEntryStore = defineStore('orderentry', {
} }
, ,
resetForEdit() { resetForEdit() {
// EDIT modda grid temizlenmez — sadece UI state resetlenir // EDIT modda grid temizlenmez sadece UI state resetlenir
this.editingKey = null this.editingKey = null
this.groupedRows = [] this.groupedRows = []
this.mode = 'edit' this.mode = 'edit'
@@ -694,9 +694,9 @@ export const useOrderEntryStore = defineStore('orderentry', {
,markAsSaved() { ,markAsSaved() {
try { try {
this._lastSavedFingerprint = this._persistFingerprint() this._lastSavedFingerprint = this._persistFingerprint()
console.log('✅ markAsSaved → fingerprint senkron') console.log(' markAsSaved fingerprint senkron')
} catch (e) { } catch (e) {
console.warn('⚠️ markAsSaved hata:', e) console.warn('⚠️ markAsSaved hata:', e)
} }
} }
,clearLocalSnapshot() { ,clearLocalSnapshot() {
@@ -704,12 +704,12 @@ export const useOrderEntryStore = defineStore('orderentry', {
const id = this.header?.OrderHeaderID const id = this.header?.OrderHeaderID
if (!id) return if (!id) return
localStorage.removeItem(`bss_orderentry_data:${id}`) localStorage.removeItem(`bss_orderentry_data:${id}`)
console.log('🧹 Local snapshot temizlendi:', id) console.log('🧹 Local snapshot temizlendi:', id)
} catch (e) { } catch (e) {
console.warn('⚠️ clearLocalSnapshot hata:', e) console.warn('⚠️ clearLocalSnapshot hata:', e)
} }
},/* =========================================================== },/* ===========================================================
🧹 HARD CLEAN — ALL ORDERENTRY SNAPSHOTS 🧹 HARD CLEAN ALL ORDERENTRY SNAPSHOTS
=========================================================== */ =========================================================== */
clearAllOrderSnapshots () { clearAllOrderSnapshots () {
Object.keys(localStorage) Object.keys(localStorage)
@@ -718,7 +718,7 @@ export const useOrderEntryStore = defineStore('orderentry', {
k.startsWith('bss_orderentry_edit:') k.startsWith('bss_orderentry_edit:')
) )
.forEach(k => { .forEach(k => {
console.log('🧹 snapshot silindi:', k) console.log('🧹 snapshot silindi:', k)
localStorage.removeItem(k) localStorage.removeItem(k)
}) })
@@ -730,18 +730,18 @@ export const useOrderEntryStore = defineStore('orderentry', {
, ,
/* =========================================================== /* ===========================================================
🧹 Store Hard Reset — Submit Sonrası Temizlik (FIXED) 🧹 Store Hard Reset Submit Sonrası Temizlik (FIXED)
- Grid, header, toplamlar, local state'ler sıfırlanır - Grid, header, toplamlar, local state'ler sıfırlanır
- persistKey / lastSnapshotKey NULL yapılmaz (config sabit kalır) - persistKey / lastSnapshotKey NULL yapılmaz (config sabit kalır)
- localStorage txn/snapshot temizliÄŸi güvenli yapılır - localStorage txn/snapshot temizliği güvenli yapılır
=========================================================== */ =========================================================== */
hardResetAfterSubmit() { hardResetAfterSubmit() {
try { try {
// 🔑 mevcut id’yi yakala (local temizliÄŸi için) // 🔑 mevcut idyi yakala (local temizliği için)
const id = this.header?.OrderHeaderID || null const id = this.header?.OrderHeaderID || null
/* ------------------------------------------------------- /* -------------------------------------------------------
1) Grid ve satırlar 1) Grid ve satırlar
-------------------------------------------------------- */ -------------------------------------------------------- */
this.orders = [] this.orders = []
this.summaryRows = [] this.summaryRows = []
@@ -761,12 +761,12 @@ export const useOrderEntryStore = defineStore('orderentry', {
/* ------------------------------------------------------- /* -------------------------------------------------------
4) Snapshot / transaction meta 4) Snapshot / transaction meta
⚠️ persistKey / lastSnapshotKey store config → NULL YAPMA ⚠️ persistKey / lastSnapshotKey store config NULL YAPMA
-------------------------------------------------------- */ -------------------------------------------------------- */
this.activeTransactionId = null this.activeTransactionId = null
this.submitted = false this.submitted = false
// fingerprint / debounce meta varsa sıfırla // fingerprint / debounce meta varsa sıfırla
this._lastSavedFingerprint = null this._lastSavedFingerprint = null
this._lastPersistFingerprint = null this._lastPersistFingerprint = null
if (this._persistTimeout) { 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 { try {
if (id) { if (id) {
@@ -785,32 +785,32 @@ export const useOrderEntryStore = defineStore('orderentry', {
localStorage.removeItem('bss_last_txn') localStorage.removeItem('bss_last_txn')
localStorage.removeItem('bss_active_new_header') localStorage.removeItem('bss_active_new_header')
} catch (e) { } 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) { } 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) Backend authoritative (orderlist açılışı local'i dikkate almaz)
✔ mode=new → backend çaÄŸrısı YOK mode=new backend çağrısı YOK
✔ normalizeOrderLines → grpKey + bedenMap garanti normalizeOrderLines grpKey + bedenMap garanti
✔ isClosed varsa → view, yoksa → edit isClosed varsa view, yoksa edit
✔ Form sync opsiyonel Form sync opsiyonel
✔ İlk açılışta snapshot yazılır (edit boyunca persist ile güncellenir) ✔ İlk açılışta snapshot yazılır (edit boyunca persist ile güncellenir)
=========================================================== */ =========================================================== */
async openExistingForEdit( async openExistingForEdit(
orderId, orderId,
{ $q = null, form = null, productCache = null } = {} { $q = null, form = null, productCache = null } = {}
) { ) {
// 🔑 schemaMap garanti // 🔑 schemaMap garanti
if (!this.schemaMap || !Object.keys(this.schemaMap).length) { if (!this.schemaMap || !Object.keys(this.schemaMap).length) {
this.initSchemaMap?.() this.initSchemaMap?.()
} }
@@ -818,25 +818,25 @@ export const useOrderEntryStore = defineStore('orderentry', {
if (!orderId) return false if (!orderId) return false
/* ======================================================= /* =======================================================
🟦 NEW MODE — ASLA backend çaÄŸrısı yok 🟦 NEW MODE ASLA backend çağrısı yok
======================================================= */ ======================================================= */
if (this.mode === 'new') { if (this.mode === 'new') {
console.log('⚪ openExistingForEdit skip (mode=new)') console.log(' openExistingForEdit skip (mode=new)')
return false return false
} }
// productCache hem ref hem reactive olabilir → güvenli oku // productCache hem ref hem reactive olabilir → güvenli oku
const pc = const pc =
productCache?.value productCache?.value
? productCache.value ? productCache.value
: (productCache && typeof productCache === 'object' ? productCache : {}) : (productCache && typeof productCache === 'object' ? productCache : {})
try { 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') this.setMode?.('edit')
/* ======================================================= /* =======================================================
🔹 BACKEND — authoritative load 🔹 BACKEND authoritative load
======================================================= */ ======================================================= */
const res = await api.get(`/order/get/${orderId}`) const res = await api.get(`/order/get/${orderId}`)
const backend = res?.data const backend = res?.data
@@ -846,8 +846,8 @@ export const useOrderEntryStore = defineStore('orderentry', {
} }
/* ======================================================= /* =======================================================
🔹 HEADER — SADECE BACKEND 🔹 HEADER SADECE BACKEND
(orderlist açılışında local merge YOK) (orderlist açılışında local merge YOK)
======================================================= */ ======================================================= */
this.header = { this.header = {
...backend.header, ...backend.header,
@@ -855,11 +855,11 @@ export const useOrderEntryStore = defineStore('orderentry', {
} }
/* ======================================================= /* =======================================================
🔹 NORMALIZE LINES (TEK KAYNAK) 🔹 NORMALIZE LINES (TEK KAYNAK)
normalizeOrderLines ÅŸu alanları üretmeli: normalizeOrderLines şu alanları üretmeli:
✔ row.grpKey row.grpKey
✔ row.bedenMap[grpKey] row.bedenMap[grpKey]
✔ row.isClosed (boolean) row.isClosed (boolean)
======================================================= */ ======================================================= */
const normalized = this.normalizeOrderLines( const normalized = this.normalizeOrderLines(
backend.lines || [], backend.lines || [],
@@ -871,31 +871,31 @@ export const useOrderEntryStore = defineStore('orderentry', {
this.summaryRows = [...this.orders] this.summaryRows = [...this.orders]
/* ======================================================= /* =======================================================
🔹 MODE KARARI (BACKEND SATIRLARI ÜZERİNDEN) 🔹 MODE KARARI (BACKEND SATIRLARI ÜZERİNDEN)
- herhangi bir isClosed=true → view - herhangi bir isClosed=true view
- deÄŸilse → edit - değilse edit
======================================================= */ ======================================================= */
const hasClosedLine = (this.summaryRows || []).some(r => r?.isClosed === true) const hasClosedLine = (this.summaryRows || []).some(r => r?.isClosed === true)
this.setMode?.(hasClosedLine ? 'view' : 'edit') this.setMode?.(hasClosedLine ? 'view' : 'edit')
/* ======================================================= /* =======================================================
🔹 FORM SYNC (opsiyonel) 🔹 FORM SYNC (opsiyonel)
======================================================= */ ======================================================= */
if (form) { if (form) {
Object.assign(form, this.header) Object.assign(form, this.header)
} }
/* ======================================================= /* =======================================================
🔹 LOCAL SNAPSHOT (edit boyunca tutulacak temel) 🔹 LOCAL SNAPSHOT (edit boyunca tutulacak temel)
- Açılışta snapshot yaz - Açılışta snapshot yaz
- Sonraki deÄŸiÅŸikliklerde zaten persistLocalStorage çaÄŸrıları var - Sonraki değişikliklerde zaten persistLocalStorage çağrıları var
======================================================= */ ======================================================= */
this.persistLocalStorage?.() this.persistLocalStorage?.()
try { try {
localStorage.setItem('bss_last_txn', String(orderId)) localStorage.setItem('bss_last_txn', String(orderId))
} catch {} } catch {}
console.log('✅ openExistingForEdit OK:', { console.log(' openExistingForEdit OK:', {
id: orderId, id: orderId,
rows: this.summaryRows.length, rows: this.summaryRows.length,
mode: this.mode, mode: this.mode,
@@ -904,13 +904,13 @@ export const useOrderEntryStore = defineStore('orderentry', {
return true return true
} catch (err) { } catch (err) {
console.error('❌ openExistingForEdit hata:', err) console.error(' openExistingForEdit hata:', err)
// new deÄŸilse uyar // new değilse uyar
if (this.mode !== 'new') { if (this.mode !== 'new') {
$q?.notify?.({ $q?.notify?.({
type: 'negative', 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) - Tek assign (double overwrite YOK)
- groupedRows hydrate edilmez - groupedRows hydrate edilmez
- mode ASLA set edilmez - mode ASLA set edilmez
- header + rows güvenli restore - header + rows güvenli restore
=========================================================== */ =========================================================== */
async hydrateFromLocalStorage(orderId, log = false) {if (this.mode === 'new') { async hydrateFromLocalStorage(orderId, log = false) {if (this.mode === 'new') {
return this.hydrateFromLocalStorageIfExists() return this.hydrateFromLocalStorageIfExists()
@@ -936,15 +936,15 @@ export const useOrderEntryStore = defineStore('orderentry', {
const payload = JSON.parse(localStorage.getItem(key) || 'null') const payload = JSON.parse(localStorage.getItem(key) || 'null')
if (!payload) { if (!payload) {
log && console.log('ℹ️ hydrate → snapshot yok:', orderId) log && console.log(' hydrate snapshot yok:', orderId)
return null return null
} }
// 🔑 source bilgisi (mode set edilmez) // 🔑 source bilgisi (mode set edilmez)
this.source = payload.source || 'local' this.source = payload.source || 'local'
/* ------------------------------------------------------- /* -------------------------------------------------------
MSSQL tarih helper’ları MSSQL tarih helperları
-------------------------------------------------------- */ -------------------------------------------------------- */
const safeDateTime = v => { const safeDateTime = v => {
if (!v) return null if (!v) return null
@@ -994,11 +994,11 @@ export const useOrderEntryStore = defineStore('orderentry', {
? payload.summaryRows ? payload.summaryRows
: orders : orders
// ❌ groupedRows hydrate edilmez (computed olmalı) // groupedRows hydrate edilmez (computed olmalı)
this.groupedRows = [] this.groupedRows = []
/* ------------------------------------------------------- /* -------------------------------------------------------
SNAPSHOT ÖZET SNAPSHOT ÖZET
-------------------------------------------------------- */ -------------------------------------------------------- */
const output = { const output = {
type : payload.submitted === true ? 'submitted' : 'draft', type : payload.submitted === true ? 'submitted' : 'draft',
@@ -1011,11 +1011,11 @@ export const useOrderEntryStore = defineStore('orderentry', {
payload.header?.IsSubmitted === true payload.header?.IsSubmitted === true
} }
log && console.log('♻️ hydrate sonuc (FIXED):', output) log && console.log('♻️ hydrate sonuc (FIXED):', output)
return output return output
} catch (err) { } catch (err) {
console.warn('⚠️ hydrateFromLocalStorage hata:', err) console.warn('⚠️ hydrateFromLocalStorage hata:', err)
return null return null
} }
} }
@@ -1027,11 +1027,11 @@ export const useOrderEntryStore = defineStore('orderentry', {
let raw = null let raw = null
if (this.mode === 'new') { if (this.mode === 'new') {
raw = localStorage.getItem(this.getDraftKey) // ✅ raw = localStorage.getItem(this.getDraftKey) //
} }
if (this.mode === 'edit') { if (this.mode === 'edit') {
const key = this.getEditKey // ✅ const key = this.getEditKey //
if (key) raw = localStorage.getItem(key) if (key) raw = localStorage.getItem(key)
} }
@@ -1043,7 +1043,7 @@ export const useOrderEntryStore = defineStore('orderentry', {
this.orders = payload.orders || [] this.orders = payload.orders || []
this.summaryRows = payload.summaryRows || this.orders this.summaryRows = payload.summaryRows || this.orders
console.log('♻️ hydrate OK:', this.mode) console.log('♻️ hydrate OK:', this.mode)
return true return true
} catch (err) { } catch (err) {
@@ -1055,8 +1055,8 @@ export const useOrderEntryStore = defineStore('orderentry', {
, ,
/* =========================================================== /* ===========================================================
🔀 mergeOrders (local + backend) 🔀 mergeOrders (local + backend)
normalizeISO → kaldırıldı normalizeISO kaldırıldı
safe MSSQL helpers eklendi safe MSSQL helpers eklendi
=========================================================== */ =========================================================== */
mergeOrders(local, backend, preferLocal = true) { mergeOrders(local, backend, preferLocal = true) {
@@ -1087,12 +1087,12 @@ export const useOrderEntryStore = defineStore('orderentry', {
const map = new Map() const map = new Map()
// Backend satırları // Backend satırları
for (const b of (backend?.lines || backend?.orders || [])) { for (const b of (backend?.lines || backend?.orders || [])) {
map.set(getKey(b), { ...b, _src: 'backend' }) map.set(getKey(b), { ...b, _src: 'backend' })
} }
// Local satırları merge et // Local satırları merge et
for (const l of (local?.orders || [])) { for (const l of (local?.orders || [])) {
const k = getKey(l) const k = getKey(l)
if (map.has(k)) { if (map.has(k)) {
@@ -1105,10 +1105,10 @@ export const useOrderEntryStore = defineStore('orderentry', {
} }
const mergedOrders = Array.from(map.values()) 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 => { const safeDateTime = v => {
if (!v) return null if (!v) return null
@@ -1141,14 +1141,14 @@ export const useOrderEntryStore = defineStore('orderentry', {
, ,
markRowSource(row) { markRowSource(row) {
if (row._src === 'local-only') return '🟠 Offline' if (row._src === 'local-only') return '🟠 Offline'
if (row._src === 'local') return '🔵 Local' if (row._src === 'local') return '🔵 Local'
return '⚪ Backend' return ' Backend'
} }
, ,
/* =========================================================== /* ===========================================================
🔄 mergeAndPersistBackendOrder (edit mode) 🔄 mergeAndPersistBackendOrder (edit mode)
=========================================================== */ =========================================================== */
mergeAndPersistBackendOrder(orderId, backendPayload) { mergeAndPersistBackendOrder(orderId, backendPayload) {
const key = `bss_orderentry_data:${orderId}` const key = `bss_orderentry_data:${orderId}`
@@ -1163,7 +1163,7 @@ export const useOrderEntryStore = defineStore('orderentry', {
updatedAt: new Date().toISOString() updatedAt: new Date().toISOString()
})) }))
console.log(`💾 mergeAndPersistBackendOrder → ${orderId} localStorage’a yazıldı`) console.log(`💾 mergeAndPersistBackendOrder ${orderId} localStoragea 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') { if (this.mode === 'new') {
localStorage.setItem(this.getDraftKey, JSON.stringify(payload)) localStorage.setItem(this.getDraftKey, JSON.stringify(payload))
// 🔒 sadece aktif new header bilgisi // 🔒 sadece aktif new header bilgisi
this.setActiveNewHeader?.(this.header?.OrderHeaderID) this.setActiveNewHeader?.(this.header?.OrderHeaderID)
return return
} }
/* =============================== /* ===============================
🔵 EDIT MODE — ID BAZLI 🔵 EDIT MODE ID BAZLI
=============================== */ =============================== */
if (this.mode === 'edit') { if (this.mode === 'edit') {
const key = this.getEditKey const key = this.getEditKey
@@ -1211,26 +1211,26 @@ export const useOrderEntryStore = defineStore('orderentry', {
clearEditSnapshotIfExists() { clearEditSnapshotIfExists() {
if (this.mode !== 'edit') return if (this.mode !== 'edit') return
const key = this.getEditKey // ✅ const key = this.getEditKey //
if (!key) return if (!key) return
localStorage.removeItem(key) localStorage.removeItem(key)
console.log('🧹 EDIT snapshot silindi:', key) console.log('🧹 EDIT snapshot silindi:', key)
} }
,/* =========================================================== ,/* ===========================================================
🧠 _persistFingerprint — kritik state’leri tek stringe indirger 🧠 _persistFingerprint kritik stateleri tek stringe indirger
- X3: orders+header yetmez → mode, summaryRows, id/no, map’ler dahil - X3: orders+header yetmez mode, summaryRows, id/no, mapler dahil
=========================================================== */ =========================================================== */
_persistFingerprint() { _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ığıin önemli
// (istersen burada sadece length + rowKey listesi gibi optimize ederiz) // (istersen burada sadece length + rowKey listesi gibi optimize ederiz)
const ordersSnap = JSON.stringify(this.orders || []) 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 h = this.header || {}
const headerSnap = JSON.stringify({ const headerSnap = JSON.stringify({
OrderHeaderID: h.OrderHeaderID || '', OrderHeaderID: h.OrderHeaderID || '',
@@ -1240,14 +1240,14 @@ export const useOrderEntryStore = defineStore('orderentry', {
ExchangeRate: h.ExchangeRate ?? null 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 sr = Array.isArray(this.summaryRows) ? this.summaryRows : []
const summaryMeta = JSON.stringify({ const summaryMeta = JSON.stringify({
len: sr.length, len: sr.length,
keys: sr.map(r => this.getRowKey?.(r) || r?.key || r?.id || '').filter(Boolean) keys: sr.map(r => this.getRowKey?.(r) || r?.key || r?.id || '').filter(Boolean)
}) })
// 🔹 comboLineIds / lineIdMap gibi kritik map’ler // 🔹 comboLineIds / lineIdMap gibi kritik mapler
// (sende hangisi varsa onu otomatik topluyoruz) // (sende hangisi varsa onu otomatik topluyoruz)
const mapSnap = JSON.stringify({ const mapSnap = JSON.stringify({
lineIdMap: this.lineIdMap || null, lineIdMap: this.lineIdMap || null,
@@ -1256,15 +1256,15 @@ export const useOrderEntryStore = defineStore('orderentry', {
comboLineIdSet: this.comboLineIdSet ? Array.from(this.comboLineIdSet) : null comboLineIdSet: this.comboLineIdSet ? Array.from(this.comboLineIdSet) : null
}) })
// 🔹 mode // 🔹 mode
const modeSnap = String(this.mode || 'new') const modeSnap = String(this.mode || 'new')
// ✅ Tek fingerprint // Tek fingerprint
return `${modeSnap}|${headerSnap}|${summaryMeta}|${mapSnap}|${ordersSnap}` 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 - fingerprint: mode + header(id/no) + summaryRows meta + lineIdMap/combo + orders
=========================================================== */ =========================================================== */
_safePersistDebounced(delay = 1200) { _safePersistDebounced(delay = 1200) {
@@ -1272,7 +1272,7 @@ export const useOrderEntryStore = defineStore('orderentry', {
this._persistTimeout = setTimeout(() => { this._persistTimeout = setTimeout(() => {
try { try {
// ✅ Persist guard’ları (varsa) // Persist guardları (varsa)
if (this.preventPersist) return if (this.preventPersist) return
if (this._uiBusy) return if (this._uiBusy) return
@@ -1285,9 +1285,9 @@ export const useOrderEntryStore = defineStore('orderentry', {
this._lastPersistFingerprint = fp this._lastPersistFingerprint = fp
this.persistLocalStorage() 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) { } catch (err) {
console.warn('⚠️ Debounce persist hata:', err) console.warn('⚠️ Debounce persist hata:', err)
} }
}, delay) }, 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) { async fetchMinPrice(model, currency, $q) {
try { try {
@@ -1303,17 +1303,17 @@ export const useOrderEntryStore = defineStore('orderentry', {
params: { model, currency } params: { model, currency }
}) })
const data = res?.data || {} const data = res?.data || {}
console.log('💰 [store.fetchMinPrice] yanıt:', data) console.log('💰 [store.fetchMinPrice] yanıt:', data)
return { return {
price: Number(data.price || 0), price: Number(data.price || 0),
rateToTRY: Number(data.rateToTRY || 1), rateToTRY: Number(data.rateToTRY || 1),
priceTRY: Number(data.priceTRY || 0) priceTRY: Number(data.priceTRY || 0)
} }
} catch (err) { } catch (err) {
console.error('❌ [store.fetchMinPrice] Min fiyat alınamadı:', err) console.error(' [store.fetchMinPrice] Min fiyat alınamadı:', err)
$q?.notify?.({ $q?.notify?.({
type: 'warning', type: 'warning',
message: 'Min. fiyat bilgisi alınamadı, kontrol atlandı ⚠️', message: 'Min. fiyat bilgisi alınamadı, kontrol atlandı ⚠️',
position: 'top-right' position: 'top-right'
}) })
return { price: 0, rateToTRY: 1, priceTRY: 0 } return { price: 0, rateToTRY: 1, priceTRY: 0 }
@@ -1323,13 +1323,13 @@ export const useOrderEntryStore = defineStore('orderentry', {
applyCurrencyToLines(newPB) { applyCurrencyToLines(newPB) {
if (!newPB) return if (!newPB) return
// 🔹 Header // 🔹 Header
if (this.header) { if (this.header) {
this.header.DocCurrencyCode = newPB this.header.DocCurrencyCode = newPB
this.header.PriceCurrencyCode = newPB this.header.PriceCurrencyCode = newPB
} }
// 🔹 Lines // 🔹 Lines
if (Array.isArray(this.orders)) { if (Array.isArray(this.orders)) {
this.orders = this.orders.map(r => ({ this.orders = this.orders.map(r => ({
...r, ...r,
@@ -1339,7 +1339,7 @@ export const useOrderEntryStore = defineStore('orderentry', {
})) }))
} }
// 🔹 Summary // 🔹 Summary
if (Array.isArray(this.summaryRows)) { if (Array.isArray(this.summaryRows)) {
this.summaryRows = this.summaryRows.map(r => ({ this.summaryRows = this.summaryRows.map(r => ({
...r, ...r,
@@ -1349,14 +1349,14 @@ export const useOrderEntryStore = defineStore('orderentry', {
})) }))
} }
// ❗ totalAmount SET ETME // totalAmount SET ETME
// ✔️ TEK MERKEZ // ✔️ TEK MERKEZ
this.updateHeaderTotals?.() this.updateHeaderTotals?.()
} }
, ,
/* =========================================================== /* ===========================================================
💠 HEADER SET & CURRENCY PROPAGATION 💠 HEADER SET & CURRENCY PROPAGATION
=========================================================== */ =========================================================== */
setHeaderFields(fields, opts = {}) { setHeaderFields(fields, opts = {}) {
const { const {
@@ -1364,13 +1364,13 @@ export const useOrderEntryStore = defineStore('orderentry', {
immediatePersist = false immediatePersist = false
} = opts } = opts
// 1️⃣ HEADER // 1️⃣ HEADER
this.header = { this.header = {
...(this.header || {}), ...(this.header || {}),
...fields ...fields
} }
// 2️⃣ SATIRLARA GERÇEKTEN YAY // 2️⃣ SATIRLARA GERÇEKTEN YAY
if (applyCurrencyToLines && Array.isArray(this.summaryRows)) { if (applyCurrencyToLines && Array.isArray(this.summaryRows)) {
this.summaryRows = this.summaryRows.map(r => ({ this.summaryRows = this.summaryRows.map(r => ({
...r, ...r,
@@ -1380,11 +1380,11 @@ export const useOrderEntryStore = defineStore('orderentry', {
})) }))
} }
// 3️⃣ STORE ORDERS REFERANSI // 3️⃣ STORE ORDERS REFERANSI
this.orders = [...this.summaryRows] this.orders = [...this.summaryRows]
// 4️⃣ PERSIST // 4️⃣ PERSIST
if (immediatePersist) { if (immediatePersist) {
this.persistLocalStorage('header-change') this.persistLocalStorage('header-change')
} }
@@ -1408,12 +1408,12 @@ export const useOrderEntryStore = defineStore('orderentry', {
cnt++ 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') { saveSnapshot(tag = 'snapshot') {
try { try {
@@ -1431,26 +1431,26 @@ export const useOrderEntryStore = defineStore('orderentry', {
} }
localStorage.setItem(key, JSON.stringify(snap)) localStorage.setItem(key, JSON.stringify(snap))
console.log(`📸 Snapshot kaydedildi [${key}]`) console.log(`📸 Snapshot kaydedildi [${key}]`)
} catch (err) { } 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) { loadFromStorage(force = false) {
try { try {
const raw = localStorage.getItem(this.getPersistKey) const raw = localStorage.getItem(this.getPersistKey)
if (!raw) { if (!raw) {
console.info('ℹ️ LocalStorage boÅŸ, grid baÅŸlatılmadı.') console.info(' LocalStorage boş, grid başlatılmadı.')
return false return false
} }
if (!force && this.mode === 'edit') { 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 return false
} }
@@ -1461,21 +1461,21 @@ export const useOrderEntryStore = defineStore('orderentry', {
this.currentOrderId = data.currentOrderId || null this.currentOrderId = data.currentOrderId || null
this.selectedCustomer = data.selectedCustomer || null this.selectedCustomer = data.selectedCustomer || null
// 🔧 Temiz ID // 🔧 Temiz ID
this.header.OrderHeaderID = data.header?.OrderHeaderID || null this.header.OrderHeaderID = data.header?.OrderHeaderID || null
this.mode = data.mode || 'new' this.mode = data.mode || 'new'
this.lastSavedAt = data.savedAt || null 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.applyHeaderCurrencyToOrders()
this._safePersistDebounced(200) this._safePersistDebounced(200)
return data return data
} catch (err) { } catch (err) {
console.warn('⚠️ localStorage okuma hatası:', err) console.warn('⚠️ localStorage okuma hatası:', err)
return false return false
} }
} }
@@ -1484,23 +1484,23 @@ export const useOrderEntryStore = defineStore('orderentry', {
clearStorage() { clearStorage() {
try { try {
localStorage.removeItem(this.getPersistKey) localStorage.removeItem(this.getPersistKey)
console.log(`🗑️ LocalStorage temizlendi [${this.getPersistKey}]`) console.log(`🗑️ LocalStorage temizlendi [${this.getPersistKey}]`)
} catch (err) { } catch (err) {
console.warn('⚠️ clearStorage hatası:', err) console.warn('⚠️ clearStorage hatası:', err)
} }
} }
, ,
clearNewDraft() { clearNewDraft() {
localStorage.removeItem(this.getDraftKey) // ✅ localStorage.removeItem(this.getDraftKey) //
localStorage.removeItem('bss_last_txn') localStorage.removeItem('bss_last_txn')
console.log('🧹 NEW taslak temizlendi') console.log('🧹 NEW taslak temizlendi')
} }
, ,
// =========================================================== // ===========================================================
// 🔹 isSameCombo — STORE LEVEL (TEK KAYNAK) // 🔹 isSameCombo STORE LEVEL (TEK KAYNAK)
// - model ZORUNLU eÅŸleÅŸir // - model ZORUNLU eşleşir
// - renk / renk2 boÅŸsa → joker // - renk / renk2 boşsa joker
// =========================================================== // ===========================================================
isSameCombo(a, b) { isSameCombo(a, b) {
if (!a || !b) return false 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) // - v6.5 korunur (stok+min fiyat + this.loadProductSizes)
// - ✅ NEW MODE: dupIdx artık _deleteSignal satırlarını BAŞTAN hariç tutar // - NEW MODE: dupIdx artık _deleteSignal satırlarını BAŞTAN hariç tutar
// - EDIT MODE: sameCombo → update, combo deÄŸiÅŸti → delete + insert (korundu) // - EDIT MODE: sameCombo update, combo değişti → delete + insert (korundu)
// - lineIdMap koruması korunur // - lineIdMap koruması korunur
// =========================================================== // ===========================================================
async saveOrUpdateRowUnified({ async saveOrUpdateRowUnified({
form, form,
@@ -1536,7 +1536,7 @@ export const useOrderEntryStore = defineStore('orderentry', {
$q = null $q = null
}) { }) {
try { try {
console.log('🔥 saveOrUpdateRowUnified v6.6', { console.log('🔥 saveOrUpdateRowUnified v6.6', {
model: form?.model, model: form?.model,
mode: this.mode, mode: this.mode,
editingKey: this.editingKey editingKey: this.editingKey
@@ -1552,10 +1552,10 @@ export const useOrderEntryStore = defineStore('orderentry', {
: [] : []
/* ======================================================= /* =======================================================
1️⃣ ZORUNLU KONTROLLER 1️⃣ ZORUNLU KONTROLLER
======================================================= */ ======================================================= */
if (!form?.model) { if (!form?.model) {
$q?.notify?.({ type: 'warning', message: 'Model seçiniz' }) $q?.notify?.({ type: 'warning', message: 'Model seçiniz' })
return false return false
} }
@@ -1564,28 +1564,28 @@ export const useOrderEntryStore = defineStore('orderentry', {
} }
/* ======================================================= /* =======================================================
2️⃣ STOK KONTROLÜ (FIXED) 2️⃣ STOK KONTROLÜ (FIXED)
- stok guard’dan önce this.loadProductSizes(form,true,$q) - stok guarddan önce this.loadProductSizes(form,true,$q)
- opsiyonel callback loadProductSizes(true) - opsiyonel callback loadProductSizes(true)
- tek dialog + doÄŸru await - tek dialog + doğru await
======================================================= */ ======================================================= */
// ✅ store fonksiyonu // store fonksiyonu
try { try {
if (typeof this.loadProductSizes === 'function') { if (typeof this.loadProductSizes === 'function') {
await this.loadProductSizes(form, true, $q) await this.loadProductSizes(form, true, $q)
} }
} catch (err) { } 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 { try {
if (typeof loadProductSizes === 'function') { if (typeof loadProductSizes === 'function') {
await loadProductSizes(true) await loadProductSizes(true)
} }
} catch (err) { } catch (err) {
console.warn('âš  loadProductSizes hata:', err) console.warn(' loadProductSizes hata:', err)
} }
const stockMapLocal = stockMap?.value || stockMap || {} const stockMapLocal = stockMap?.value || stockMap || {}
@@ -1605,16 +1605,16 @@ export const useOrderEntryStore = defineStore('orderentry', {
if (overLimit.length && $q) { if (overLimit.length && $q) {
const msg = overLimit const msg = overLimit
.map(x => `• <b>${x.beden}</b>: ${x.girilen} (Stok: ${x.stok})`) .map(x => ` <b>${x.beden}</b>: ${x.girilen} (Stok: ${x.stok})`)
.join('<br>') .join('<br>')
const stokOK = await new Promise(resolve => { const stokOK = await new Promise(resolve => {
$q.dialog({ $q.dialog({
title: 'Stok Uyarısı', title: 'Stok Uyarısı',
message: `Bazı bedenlerde stoktan fazla giriÅŸ yaptınız:<br><br>${msg}`, message: `Bazı bedenlerde stoktan fazla giriş yaptınız:<br><br>${msg}`,
html: true, html: true,
ok: { label: 'Devam', color: 'primary' }, ok: { label: 'Devam', color: 'primary' },
cancel: { label: 'İptal', color: 'negative' } cancel: { label: 'İptal', color: 'negative' }
}) })
.onOk(() => resolve(true)) .onOk(() => resolve(true))
.onCancel(() => resolve(false)) .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 let fiyatOK = true
try { try {
@@ -1643,13 +1643,13 @@ export const useOrderEntryStore = defineStore('orderentry', {
if (minFiyat > 0 && girilen > 0 && girilen < minFiyat && $q) { if (minFiyat > 0 && girilen > 0 && girilen < minFiyat && $q) {
fiyatOK = await new Promise(resolve => { fiyatOK = await new Promise(resolve => {
$q.dialog({ $q.dialog({
title: 'Fiyat Uyarısı', title: 'Fiyat Uyarısı',
message: message:
`<b>Min. Fiyat:</b> ${minFiyat} ${form.pb}<br>` + `<b>Min. Fiyat:</b> ${minFiyat} ${form.pb}<br>` +
`<b>GirdiÄŸiniz:</b> ${girilen} ${form.pb}`, `<b>Girdiğiniz:</b> ${girilen} ${form.pb}`,
html: true, html: true,
ok: { label: 'Devam', color: 'primary' }, ok: { label: 'Devam', color: 'primary' },
cancel: { label: 'İptal', color: 'negative' } cancel: { label: 'İptal', color: 'negative' }
}) })
.onOk(() => resolve(true)) .onOk(() => resolve(true))
.onCancel(() => resolve(false)) .onCancel(() => resolve(false))
@@ -1657,12 +1657,12 @@ export const useOrderEntryStore = defineStore('orderentry', {
}) })
} }
} catch (err) { } catch (err) {
console.warn('âš  Min fiyat hata:', err) console.warn(' Min fiyat hata:', err)
} }
if (!fiyatOK) return false if (!fiyatOK) return false
/* ======================================================= /* =======================================================
4️⃣ TOPLAM HESABI 4️⃣ TOPLAM HESABI
======================================================= */ ======================================================= */
const adet = (form.bedenler || []).reduce((a, b) => a + Number(b || 0), 0) const adet = (form.bedenler || []).reduce((a, b) => a + Number(b || 0), 0)
form.adet = adet form.adet = adet
@@ -1671,7 +1671,7 @@ export const useOrderEntryStore = defineStore('orderentry', {
const newRow = toSummaryRowFromForm(form) const newRow = toSummaryRowFromForm(form)
/* ======================================================= /* =======================================================
5️⃣ EDIT MODE (editingKey ZORUNLU) 5️⃣ EDIT MODE (editingKey ZORUNLU)
======================================================= */ ======================================================= */
if (this.editingKey) { if (this.editingKey) {
const idx = rows.findIndex(r => getKey(r) === this.editingKey) const idx = rows.findIndex(r => getKey(r) === this.editingKey)
@@ -1684,13 +1684,13 @@ export const useOrderEntryStore = defineStore('orderentry', {
const prev = rows[idx] const prev = rows[idx]
if (this.isRowLocked?.(prev)) { if (this.isRowLocked?.(prev)) {
$q?.notify?.({ type: 'warning', message: 'Satır kapalı' }) $q?.notify?.({ type: 'warning', message: 'Satır kapalı' })
this.editingKey = null this.editingKey = null
resetEditor?.(true) resetEditor?.(true)
return false return false
} }
// ✅ kritik: store-level // kritik: store-level
const sameCombo = this.isSameCombo(prev, newRow) const sameCombo = this.isSameCombo(prev, newRow)
const preservedLineIdMap = const preservedLineIdMap =
@@ -1700,7 +1700,7 @@ export const useOrderEntryStore = defineStore('orderentry', {
? { ...newRow.lineIdMap } ? { ...newRow.lineIdMap }
: {} : {}
/* ===== SAME COMBO → UPDATE ===== */ /* ===== SAME COMBO UPDATE ===== */
if (sameCombo) { if (sameCombo) {
rows[idx] = { rows[idx] = {
...prev, ...prev,
@@ -1720,11 +1720,11 @@ export const useOrderEntryStore = defineStore('orderentry', {
resetEditor?.(true) resetEditor?.(true)
recalcVat?.() recalcVat?.()
$q?.notify?.({ type: 'positive', message: 'Satır güncellendi' }) $q?.notify?.({ type: 'positive', message: 'Satır güncellendi' })
return true return true
} }
/* ===== COMBO CHANGED → DELETE + INSERT ===== */ /* ===== COMBO CHANGED DELETE + INSERT ===== */
const grpKey = const grpKey =
prev?.grpKey || prev?.grpKey ||
Object.keys(prev?.bedenMap || {})[0] || Object.keys(prev?.bedenMap || {})[0] ||
@@ -1780,22 +1780,22 @@ export const useOrderEntryStore = defineStore('orderentry', {
resetEditor?.(true) resetEditor?.(true)
recalcVat?.() recalcVat?.()
$q?.notify?.({ type: 'positive', message: 'Kombinasyon deÄŸiÅŸti' }) $q?.notify?.({ type: 'positive', message: 'Kombinasyon değişti' })
return true return true
} }
/* ======================================================= /* =======================================================
6️⃣ NEW MODE (MERGE / INSERT) — COMBO SAFE 6️⃣ NEW MODE (MERGE / INSERT) COMBO SAFE
- aynı combo → bedenMap merge (satır sayısı artmaz) - aynı combo bedenMap merge (satır sayısı artmaz)
- farklı combo → yeni satır - farklı combo yeni satır
- ✅ FIX: _deleteSignal satırlarını dup aramasında hariç tut - FIX: _deleteSignal satırlarını dup aramasında hariç tut
======================================================= */ ======================================================= */
const dupIdx = rows.findIndex(r => const dupIdx = rows.findIndex(r =>
!r?._deleteSignal && !r?._deleteSignal &&
this.isSameCombo(r, newRow) this.isSameCombo(r, newRow)
) )
// helper: bedenMap çıkar (gruplu ya da düz) // helper: bedenMap çıkar (gruplu ya da düz)
const extractMap = (row) => { const extractMap = (row) => {
const grpKey = const grpKey =
row?.grpKey || row?.grpKey ||
@@ -1813,15 +1813,15 @@ export const useOrderEntryStore = defineStore('orderentry', {
if (dupIdx !== -1) { if (dupIdx !== -1) {
const prev = rows[dupIdx] 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) { if (prev?._deleteSignal !== true) {
const { grpKey: prevGrp, map: prevMap } = extractMap(prev) const { grpKey: prevGrp, map: prevMap } = extractMap(prev)
const { grpKey: newGrp, map: newMap } = extractMap(newRow) const { grpKey: newGrp, map: newMap } = extractMap(newRow)
// hangi grpKey kullanılacak? // hangi grpKey kullanılacak?
const grpKey = newRow?.grpKey || prevGrp || newGrp || 'GENEL' const grpKey = newRow?.grpKey || prevGrp || newGrp || 'GENEL'
// MERGE: bedenleri topluyoruz (override deÄŸil) // MERGE: bedenleri topluyoruz (override değil)
const merged = { ...(prevMap || {}) } const merged = { ...(prevMap || {}) }
for (const [k, v] of Object.entries(newMap || {})) { for (const [k, v] of Object.entries(newMap || {})) {
const beden = (k == null || String(k).trim() === '') const beden = (k == null || String(k).trim() === '')
@@ -1863,12 +1863,12 @@ export const useOrderEntryStore = defineStore('orderentry', {
resetEditor?.(true) resetEditor?.(true)
recalcVat?.() 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 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({ rows.push({
...newRow, ...newRow,
id: newRow.id || crypto.randomUUID(), id: newRow.id || crypto.randomUUID(),
@@ -1884,12 +1884,12 @@ export const useOrderEntryStore = defineStore('orderentry', {
resetEditor?.(true) resetEditor?.(true)
recalcVat?.() recalcVat?.()
$q?.notify?.({ type: 'positive', message: 'Yeni satır eklendi' }) $q?.notify?.({ type: 'positive', message: 'Yeni satır eklendi' })
return true return true
} catch (err) { } catch (err) {
console.error('❌ saveOrUpdateRowUnified:', err) console.error(' saveOrUpdateRowUnified:', err)
$q?.notify?.({ type: 'negative', message: 'Satır kaydı baÅŸarısız' }) $q?.notify?.({ type: 'negative', message: 'Satır kaydı başarısız' })
return false 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) { setTransaction(id, autoResume = true) {
if (!id) return if (!id) return
// 🔧 temiz ID // 🔧 temiz ID
this.header.OrderHeaderID = id this.header.OrderHeaderID = id
localStorage.setItem('bss_last_txn', id) localStorage.setItem('bss_last_txn', id)
console.log('🔄 Transaction deÄŸiÅŸtirildi:', id) console.log('🔄 Transaction değiştirildi:', id)
if (autoResume) { if (autoResume) {
const hasData = Array.isArray(this.orders) && this.orders.length > 0 const hasData = Array.isArray(this.orders) && this.orders.length > 0
if (!hasData) { if (!hasData) {
const ok = this.hydrateFromLocalStorage(id,true) 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 { } 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() { clearTransaction() {
try { try {
@@ -1942,22 +1942,22 @@ export const useOrderEntryStore = defineStore('orderentry', {
localStorage.removeItem('bss_last_txn') localStorage.removeItem('bss_last_txn')
console.log('🧹 Transaction temizlendi') console.log('🧹 Transaction temizlendi')
} catch (err) { } 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) { isRowLocked(row) {
if (!row) return false if (!row) return false
// Sadece edit modunda, // Sadece edit modunda,
// ve backend'den gelen gerçek OrderLineID varsa, // ve backend'den gelen gerçek OrderLineID varsa,
// ve IsClosed=1 ise satır kilitli // ve IsClosed=1 ise satır kilitli
return ( return (
this.mode === 'edit' && this.mode === 'edit' &&
!!row.OrderLineID && !!row.OrderLineID &&
@@ -1990,10 +1990,10 @@ export const useOrderEntryStore = defineStore('orderentry', {
aciklama: row.aciklama || old.aciklama, aciklama: row.aciklama || old.aciklama,
updatedAt: dayjs().toISOString() 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 { } else {
this.orders.push(toRaw(row)) 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() this.persistLocalStorage()
@@ -2009,7 +2009,7 @@ export const useOrderEntryStore = defineStore('orderentry', {
} }
this.persistLocalStorage() this.persistLocalStorage()
this.saveSnapshot('after-update') 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.persistLocalStorage()
this.saveSnapshot('after-remove') 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) { removeSelectedRow(row, $q = null) {
if (!row) return if (!row) return
// 1) Kilitli satır silinemez // 1) Kilitli satır silinemez
if (this.isRowLocked(row)) { if (this.isRowLocked(row)) {
$q?.notify?.({ $q?.notify?.({
type: 'warning', type: 'warning',
message: '🔒 Bu satır (IsClosed=1) kapatılmış. Silinemez.' message: '🔒 Bu satır (IsClosed=1) kapatılmış. Silinemez.'
}) })
return false return false
} }
// 2) Kullanıcıya onay sor // 2) Kullanıcıya onay sor
return new Promise(resolve => { return new Promise(resolve => {
$q?.dialog({ $q?.dialog({
title: 'Satır Sil', title: 'Satır Sil',
message: `${row.model} / ${row.renk} / ${row.renk2} kombinasyonu silinsin mi?`, message: `${row.model} / ${row.renk} / ${row.renk2} kombinasyonu silinsin mi?`,
ok: { label: 'Evet', color: 'negative' }, ok: { label: 'Evet', color: 'negative' },
cancel: { label: 'Vazgeç' } cancel: { label: 'Vazgeç' }
}) })
.onOk(() => { .onOk(() => {
this.removeRowInternal(row) this.removeRowInternal(row)
@@ -2056,9 +2056,9 @@ export const useOrderEntryStore = defineStore('orderentry', {
removeRowInternal(row) { removeRowInternal(row) {
if (!row) return false if (!row) return false
// 1️⃣ Kilit kontrolü // 1️⃣ Kilit kontrolü
if (this.isRowLocked(row)) { if (this.isRowLocked(row)) {
console.warn('🔒 Kilitli satır silinemez.') console.warn('🔒 Kilitli satır silinemez.')
return false return false
} }
@@ -2073,27 +2073,27 @@ export const useOrderEntryStore = defineStore('orderentry', {
const idx = this.summaryRows.findIndex(r => getKey(r) === rowKey) const idx = this.summaryRows.findIndex(r => getKey(r) === rowKey)
if (idx === -1) return false if (idx === -1) return false
console.log('🗑️ X2 removeRowInternal →', row) console.log('🗑️ X2 removeRowInternal ', row)
// 🔐 UI BUSY // 🔐 UI BUSY
this._uiBusy = true this._uiBusy = true
this.preventPersist = true this.preventPersist = true
try { try {
// 2️⃣ UI’dan kaldır // 2️⃣ UIdan kaldır
this.summaryRows.splice(idx, 1) this.summaryRows.splice(idx, 1)
// orders = UI satırları (temiz kopya) // orders = UI satırları (temiz kopya)
this.orders = [...this.summaryRows] this.orders = [...this.summaryRows]
// 3️⃣ EDIT MODE → DELETE SİNYALİ // 3️⃣ EDIT MODE DELETE SİNYALİ
if (this.mode === 'edit') { if (this.mode === 'edit') {
const grpKey = const grpKey =
row.grpKey || row.grpKey ||
Object.keys(row.bedenMap || {})[0] || Object.keys(row.bedenMap || {})[0] ||
'tak' 'tak'
// ✅ lineIdMap referansı (varsa) // lineIdMap referansı (varsa)
const lineIdMap = const lineIdMap =
(row.lineIdMap && typeof row.lineIdMap === 'object') (row.lineIdMap && typeof row.lineIdMap === 'object')
? { ...row.lineIdMap } ? { ...row.lineIdMap }
@@ -2101,7 +2101,7 @@ export const useOrderEntryStore = defineStore('orderentry', {
const emptyMap = {} const emptyMap = {}
// Öncelik: bedenMap[grpKey] → lineIdMap → fallback // Öncelik: bedenMap[grpKey] lineIdMap fallback
if (row.bedenMap && row.bedenMap[grpKey]) { if (row.bedenMap && row.bedenMap[grpKey]) {
for (const beden of Object.keys(row.bedenMap[grpKey] || {})) { for (const beden of Object.keys(row.bedenMap[grpKey] || {})) {
emptyMap[beden] = 0 emptyMap[beden] = 0
@@ -2117,21 +2117,21 @@ export const useOrderEntryStore = defineStore('orderentry', {
const deleteSignalRow = { const deleteSignalRow = {
...row, ...row,
// 🔴 UI KEY // 🔴 UI KEY
id: `DEL::${row.id || row.OrderLineID || crypto.randomUUID()}`, id: `DEL::${row.id || row.OrderLineID || crypto.randomUUID()}`,
// 🔴 BACKEND DELETE SIGNAL // 🔴 BACKEND DELETE SIGNAL
adet: 0, adet: 0,
Qty1: 0, Qty1: 0,
tutar: 0, tutar: 0,
// 🔴 CRITICAL: duplicate guard'a girmesin // 🔴 CRITICAL: duplicate guard'a girmesin
ComboKey: '', ComboKey: '',
// 🔴 legacy tekil alan (varsa kalsın) // 🔴 legacy tekil alan (varsa kalsın)
OrderLineID: row.OrderLineID || null, OrderLineID: row.OrderLineID || null,
// ✅ CRITICAL // CRITICAL
grpKey, grpKey,
bedenMap: { [grpKey]: emptyMap }, bedenMap: { [grpKey]: emptyMap },
lineIdMap, lineIdMap,
@@ -2140,21 +2140,21 @@ export const useOrderEntryStore = defineStore('orderentry', {
_deleteSignal: true _deleteSignal: true
} }
console.log('📡 DELETE sinyali üretildi:', deleteSignalRow) console.log('📡 DELETE sinyali üretildi:', deleteSignalRow)
this.orders.push(deleteSignalRow) this.orders.push(deleteSignalRow)
} }
// 4️⃣ Totals (persist YOK) // 4️⃣ Totals (persist YOK)
this.updateHeaderTotals?.() this.updateHeaderTotals?.()
} finally { } finally {
// 🔓 GUARD KAPAT // 🔓 GUARD KAPAT
this.preventPersist = false this.preventPersist = false
this._uiBusy = false this._uiBusy = false
} }
// 5️⃣ TEK VE KONTROLLÜ persist // 5️⃣ TEK VE KONTROLLÜ persist
this.persistLocalStorage() this.persistLocalStorage()
return true 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 grpKey SADECE burada set edilir
✔ detectBedenGroup SADECE store’da kullanılır detectBedenGroup SADECE storeda kullanılır
✔ aksbir → ' ' bedeni = GERÇEK adet aksbir ' ' bedeni = GERÇEK adet
✔ backend satırlarında BEDEN → OrderLineID map’i üretilir backend satırlarında BEDEN OrderLineID mapi üretilir
=========================================================== */ =========================================================== */
normalizeOrderLines(lines, pbFallback = 'USD') { normalizeOrderLines(lines, pbFallback = 'USD') {
if (!Array.isArray(lines)) return [] if (!Array.isArray(lines)) return []
@@ -2188,17 +2188,17 @@ export const useOrderEntryStore = defineStore('orderentry', {
raw.IsClosed?.Bool === true raw.IsClosed?.Bool === true
/* ======================================================= /* =======================================================
1️⃣ UI / SNAPSHOT KAYNAKLI SATIR 1️⃣ UI / SNAPSHOT KAYNAKLI SATIR
------------------------------------------------------- -------------------------------------------------------
✔ ComboKey YOK ComboKey YOK
✔ Sadece model / renk / renk2 bazında gruplanır Sadece model / renk / renk2 bazında gruplanır
======================================================= */ ======================================================= */
if (raw.bedenMap && Object.keys(raw.bedenMap).length) { if (raw.bedenMap && Object.keys(raw.bedenMap).length) {
const model = (raw.model || raw.ItemCode || '').trim() const model = (raw.model || raw.ItemCode || '').trim()
const renk = (raw.renk || raw.ColorCode || '').trim() const renk = (raw.renk || raw.ColorCode || '').trim()
const renk2 = (raw.renk2 || raw.ItemDim2Code || '').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 modelKey = `${model}||${renk}||${renk2}`
const grpKey = raw.grpKey || 'tak' 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 ComboKey YOK
✔ Sadece model / renk / renk2 bazlı gruplanır Sadece model / renk / renk2 bazlı gruplanır
✔ BEDEN sadece bedenMap + lineIdMap için kullanılır BEDEN sadece bedenMap + lineIdMap için kullanılır
======================================================= */ ======================================================= */
const model = (raw.Model || raw.ItemCode || '').trim() const model = (raw.Model || raw.ItemCode || '').trim()
const renk = (raw.ColorCode || '').trim() const renk = (raw.ColorCode || '').trim()
const renk2 = (raw.ItemDim2Code || '').trim() const renk2 = (raw.ItemDim2Code || '').trim()
// ❗ BEDEN HARİÇ — üst seviye grup anahtarı // BEDEN HARİÇ — üst seviye grup anahtarı
const modelKey = `${model}||${renk}||${renk2}` const modelKey = `${model}||${renk}||${renk2}`
merged[modelKey] ??= [] merged[modelKey] ??= []
@@ -2265,8 +2265,8 @@ export const useOrderEntryStore = defineStore('orderentry', {
fiyat: Number(raw.Price || 0), fiyat: Number(raw.Price || 0),
pb: raw.DocCurrencyCode || pbFallback, pb: raw.DocCurrencyCode || pbFallback,
__tmpMap: {}, // beden → qty __tmpMap: {}, // beden qty
lineIdMap: {}, // beden → OrderLineID lineIdMap: {}, // beden OrderLineID
adet: 0, adet: 0,
tutar: 0, tutar: 0,
@@ -2279,7 +2279,7 @@ export const useOrderEntryStore = defineStore('orderentry', {
} }
/* ------------------------------------------------------- /* -------------------------------------------------------
🔑 BEDEN → OrderLineID (DETERMINISTIC & SAFE) 🔑 BEDEN OrderLineID (DETERMINISTIC & SAFE)
-------------------------------------------------------- */ -------------------------------------------------------- */
const rawLineId = const rawLineId =
raw.OrderLineID || 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 = [] const out = []
@@ -2312,7 +2312,7 @@ export const useOrderEntryStore = defineStore('orderentry', {
const bedenList = Object.keys(row.__tmpMap) const bedenList = Object.keys(row.__tmpMap)
// 🔒 TEK VE KESİN KARAR // 🔒 TEK VE KESİN KARAR
const grpKey = detectBedenGroup( const grpKey = detectBedenGroup(
bedenList, bedenList,
row.urunAnaGrubu, row.urunAnaGrubu,
@@ -2340,9 +2340,9 @@ export const useOrderEntryStore = defineStore('orderentry', {
row.tutar = Number((row.adet * Number(row.fiyat || 0)).toFixed(2)) row.tutar = Number((row.adet * Number(row.fiyat || 0)).toFixed(2))
/* =================================================== /* ===================================================
🔒 AKSBİR — BOŞLUK BEDEN GERÇEK ADETİ ALIR 🔒 AKSBİR — BOŞLUK BEDEN GERÇEK ADETİ ALIR
❗ STD’ye dönme YOK STDye dönme YOK
❗ 0 yazma YOK 0 yazma YOK
=================================================== */ =================================================== */
if (grpKey === 'aksbir') { if (grpKey === 'aksbir') {
row.bedenMap[grpKey] ??= {} row.bedenMap[grpKey] ??= {}
@@ -2355,7 +2355,7 @@ export const useOrderEntryStore = defineStore('orderentry', {
} }
console.log( console.log(
`📦 normalizeOrderLines (v9 + lineIdMap) → ${out.length} satır` `📦 normalizeOrderLines (v9 + lineIdMap) ${out.length} satır`
) )
return out 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 * grpKey SADECE form.grpKey
* ✔ schemaMap TEK OTORİTE * schemaMap TEK OTORİTE
* ✔ edit modda BEDEN LABEL DOKUNULMAZ * edit modda BEDEN LABEL DOKUNULMAZ
* ✔ ' ' (boÅŸ beden) korunur * ' ' (boş beden) korunur
* =========================================================== * ===========================================================
*/ */
async loadProductSizes(form, forceRefresh = false, $q = null) { async loadProductSizes(form, forceRefresh = false, $q = null) {
@@ -2385,7 +2385,7 @@ export const useOrderEntryStore = defineStore('orderentry', {
try { try {
const grpKey = form.grpKey const grpKey = form.grpKey
if (!grpKey) { if (!grpKey) {
console.warn('⛔ loadProductSizes iptal → grpKey yok') console.warn(' loadProductSizes iptal grpKey yok')
return return
} }
@@ -2394,18 +2394,18 @@ export const useOrderEntryStore = defineStore('orderentry', {
const cacheKey = `${form.model}_${colorKey}_${color2Key}_${grpKey}` const cacheKey = `${form.model}_${colorKey}_${color2Key}_${grpKey}`
/* ======================================================= /* =======================================================
♻️ CACHE (LABEL DOKUNMADAN) ♻️ CACHE (LABEL DOKUNMADAN)
======================================================= */ ======================================================= */
if (!forceRefresh && sizeCache.value?.[cacheKey]) { if (!forceRefresh && sizeCache.value?.[cacheKey]) {
const cached = sizeCache.value[cacheKey] const cached = sizeCache.value[cacheKey]
bedenStock.value = [...cached.stockArray] bedenStock.value = [...cached.stockArray]
stockMap.value = { ...cached.stockMap } stockMap.value = { ...cached.stockMap }
console.log(`♻️ loadProductSizes CACHE → ${grpKey}`) console.log(`♻️ loadProductSizes CACHE ${grpKey}`)
return return
} }
/* ======================================================= /* =======================================================
📡 API 📡 API
======================================================= */ ======================================================= */
const params = { code: form.model } const params = { code: form.model }
if (form.renk) params.color = form.renk if (form.renk) params.color = form.renk
@@ -2421,7 +2421,7 @@ export const useOrderEntryStore = defineStore('orderentry', {
} }
/* ======================================================= /* =======================================================
📦 STOK MAP (' ' KORUNUR) 📦 STOK MAP (' ' KORUNUR)
======================================================= */ ======================================================= */
const apiStockMap = {} const apiStockMap = {}
for (const x of data) { for (const x of data) {
@@ -2443,7 +2443,7 @@ export const useOrderEntryStore = defineStore('orderentry', {
) )
/* ======================================================= /* =======================================================
💾 CACHE 💾 CACHE
======================================================= */ ======================================================= */
sizeCache.value[cacheKey] = { sizeCache.value[cacheKey] = {
labels: [...form.bedenLabels], labels: [...form.bedenLabels],
@@ -2451,14 +2451,14 @@ export const useOrderEntryStore = defineStore('orderentry', {
stockMap: { ...stockMap.value } stockMap: { ...stockMap.value }
} }
console.log(`✅ loadProductSizes FINAL v4.2 → ${grpKey}`) console.log(` loadProductSizes FINAL v4.2 ${grpKey}`)
} catch (err) { } catch (err) {
console.error('❌ loadProductSizes hata:', err) console.error(' loadProductSizes hata:', err)
$q?.notify?.({ type: 'negative', message: 'Beden / stok alınamadı' }) $q?.notify?.({ type: 'negative', message: 'Beden / stok alınamadı' })
} finally { } finally {
store._uiBusy = prevBusy store._uiBusy = prevBusy
store.preventPersist = prevPrevent store.preventPersist = prevPrevent
console.log('🧩 Editor beden hydrate', { console.log('🧩 Editor beden hydrate', {
grpKey: form.grpKey, grpKey: form.grpKey,
labels: form.bedenLabels, labels: form.bedenLabels,
values: form.bedenler 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 // f.adet / f.tutar hesaplanır
// ✔ store.totalAmount ASLA set edilmez // store.totalAmount ASLA set edilmez
// ✔ gerçek toplam → header.TotalAmount // gerçek toplam header.TotalAmount
// ======================================================= // =======================================================
updateTotals(f) { updateTotals(f) {
// 1️⃣ Satır adet // 1️⃣ Satır adet
f.adet = (f.bedenler || []).reduce( f.adet = (f.bedenler || []).reduce(
(a, b) => a + Number(b || 0), (a, b) => a + Number(b || 0),
0 0
) )
// 2️⃣ Satır tutar // 2️⃣ Satır tutar
const fiyat = Number(f.fiyat) || 0 const fiyat = Number(f.fiyat) || 0
f.tutar = Number((f.adet * fiyat).toFixed(2)) 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) { if (this.header) {
const total = (this.summaryRows || []).reduce( const total = (this.summaryRows || []).reduce(
(sum, r) => sum + Number(r?.tutar || 0), (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) { activeGroupKeyForRow(row) {
const g = (row?.urunAnaGrubu || '').toUpperCase() const g = (row?.urunAnaGrubu || '').toUpperCase()
@@ -2517,27 +2517,27 @@ export const useOrderEntryStore = defineStore('orderentry', {
return 'tak' return 'tak'
}, },
/* ======================================================= /* =======================================================
🔹 MODE YÖNETİMİ — new / edit arası geçiÅŸ 🔹 MODE YÖNETİMİ — new / edit arası geçiş
======================================================= */ ======================================================= */
setMode(mode) { setMode(mode) {
if (!['new', 'edit', 'view'].includes(mode)) { if (!['new', 'edit', 'view'].includes(mode)) {
console.warn('⚠️ Geçersiz mode:', mode) console.warn('⚠️ Geçersiz mode:', mode)
return return
} }
this.mode = mode 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ı) NEW INSERT, EDIT UPDATE (tek karar noktası)
✔ Controlled submit → route guard SUSAR Controlled submit route guard SUSAR
✔ Snapshot temizliÄŸi route öncesi Snapshot temizliği route öncesi
✔ Kaydet → edit replace → backend reload Kaydet edit replace backend reload
✔ Listeye giderken guard popup 1 kez bypass Listeye giderken guard popup 1 kez bypass
✔ ✅ PRE-VALIDATE → prItemVariant olmayan kombinasyonlar kaydı DURDURUR ✔ ✅ PRE-VALIDATE prItemVariant olmayan kombinasyonlar kaydı DURDURUR
=========================================================== */ =========================================================== */
async submitAllReal($q, router, form, summaryRows, productCache) { async submitAllReal($q, router, form, summaryRows, productCache) {
let serverOrderId = null let serverOrderId = null
@@ -2546,17 +2546,17 @@ export const useOrderEntryStore = defineStore('orderentry', {
try { try {
this.loading = true this.loading = true
// 🔒 Kontrollü submit → route leave guard susar // 🔒 Kontrollü submit route leave guard susar
this.isControlledSubmit = true this.isControlledSubmit = true
const isNew = this.mode === 'new' const isNew = this.mode === 'new'
const { header, lines } = this.buildFinalOrderJson() const { header, lines } = this.buildFinalOrderJson()
// ======================================================= // =======================================================
// 🧾 DEBUG — FRONTEND → BACKEND GİDEN PAYLOAD // 🧾 DEBUG FRONTEND BACKEND GİDEN PAYLOAD
// ======================================================= // =======================================================
console.groupCollapsed( console.groupCollapsed(
`%c📤 ORDER PAYLOAD (${this.mode})`, `%c📤 ORDER PAYLOAD (${this.mode})`,
'color:#c9a873;font-weight:bold' 'color:#c9a873;font-weight:bold'
) )
@@ -2579,21 +2579,21 @@ export const useOrderEntryStore = defineStore('orderentry', {
console.groupEnd() console.groupEnd()
// ======================================================= // =======================================================
// 🧾 DEBUG (opsiyonel helper) // 🧾 DEBUG (opsiyonel helper)
// ======================================================= // =======================================================
this.debugOrderPayload?.(header, lines, 'PRE-VALIDATE') this.debugOrderPayload?.(header, lines, 'PRE-VALIDATE')
// ======================================================= // =======================================================
// 🧩 DUMMY CURRENCY PAYLOAD (model geniÅŸletmeden) // 🧩 DUMMY CURRENCY PAYLOAD (model genişletmeden)
// - trOrderLineCurrency için gerekli alanları satıra basar // - trOrderLineCurrency için gerekli alanları satıra basar
// - örnek satırdaki gibi: PriceVI/AmountVI = KDV dahil, Price/Amount = KDV hariç // - örnek satırdaki gibi: PriceVI/AmountVI = KDV dahil, Price/Amount = KDV hariç
// ======================================================= // =======================================================
const r2 = (n) => Number((Number(n) || 0).toFixed(2)) const r2 = (n) => Number((Number(n) || 0).toFixed(2))
const r4 = (n) => Number((Number(n) || 0).toFixed(4)) const r4 = (n) => Number((Number(n) || 0).toFixed(4))
for (const ln of lines) { for (const ln of lines) {
const qty = Number(ln?.Qty1 || 0) 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 vatRate = Number(ln?.VatRate || 0)
const exRate = Number(ln?.PriceExchangeRate || header?.ExchangeRate || 1) || 1 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' const docCurrency = String(ln?.DocCurrencyCode || header?.DocCurrencyCode || 'TRY').trim() || 'TRY'
// Backend model alanları // Backend model alanları
ln.RelationCurrencyCode = docCurrency ln.RelationCurrencyCode = docCurrency
ln.DocPrice = unitWithVat ln.DocPrice = unitWithVat
ln.DocAmount = net ln.DocAmount = net
@@ -2618,7 +2618,7 @@ export const useOrderEntryStore = defineStore('orderentry', {
ln.VatDeducation = 0 ln.VatDeducation = 0
ln.NetAmount = net 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.CurrencyCode = docCurrency
ln.ExchangeRate = exRate ln.ExchangeRate = exRate
ln.PriceVI = unitWithVat ln.PriceVI = unitWithVat
@@ -2630,25 +2630,25 @@ export const useOrderEntryStore = defineStore('orderentry', {
} }
// ======================================================= // =======================================================
// 🧪 PRE-VALIDATE — prItemVariant ön kontrol // 🧪 PRE-VALIDATE prItemVariant ön kontrol
// - invalid varsa CREATE/UPDATE ÇALIŞMAZ // - invalid varsa CREATE/UPDATE ÇALIŞMAZ
// ======================================================= // =======================================================
const v = await api.post('/order/validate', { header, lines }) const v = await api.post('/order/validate', { header, lines })
const invalid = v?.data?.invalid || [] const invalid = v?.data?.invalid || []
if (invalid.length > 0) { if (invalid.length > 0) {
await this.showInvalidVariantDialog?.($q, invalid) 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, mode: this.mode,
lines: lines.length, lines: lines.length,
deletes: lines.filter(l => l._deleteSignal).length deletes: lines.filter(l => l._deleteSignal).length
}) })
/* ======================================================= /* =======================================================
🚀 API CALL — TEK NOKTA 🚀 API CALL TEK NOKTA
======================================================= */ ======================================================= */
const resp = await api.post( const resp = await api.post(
isNew ? '/order/create' : '/order/update', isNew ? '/order/create' : '/order/update',
@@ -2669,11 +2669,11 @@ export const useOrderEntryStore = defineStore('orderentry', {
header?.OrderNumber header?.OrderNumber
if (!serverOrderId) { if (!serverOrderId) {
throw new Error('OrderHeaderID backend’den dönmedi') throw new Error('OrderHeaderID backendden dönmedi')
} }
/* ======================================================= /* =======================================================
🔁 MODE SWITCH → EDIT 🔁 MODE SWITCH EDIT
======================================================= */ ======================================================= */
this.setMode('edit') this.setMode('edit')
@@ -2685,25 +2685,25 @@ export const useOrderEntryStore = defineStore('orderentry', {
} }
/* ======================================================= /* =======================================================
🧹 KRİTİK: Snapshot + Dirty temizliÄŸi 🧹 KRİTİK: Snapshot + Dirty temizliği
❗ ROUTE deÄŸiÅŸmeden ÖNCE ROUTE değişmeden ÖNCE
======================================================= */ ======================================================= */
this.updateHeaderTotals?.() this.updateHeaderTotals?.()
this.markAsSaved?.() 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() this.clearAllOrderSnapshots()
$q.notify({ $q.notify({
type: 'positive', type: 'positive',
message: `SipariÅŸ kaydedildi: ${serverOrderNo || ''}`.trim() message: `Sipariş kaydedildi: ${serverOrderNo || ''}`.trim()
}) })
/* ======================================================= /* =======================================================
🔀 ROUTE REPLACE (EDIT MODE) 🔀 ROUTE REPLACE (EDIT MODE)
- aynı sayfa → param deÄŸiÅŸti - aynı sayfa param değişti
- guard 1 kez bypass - guard 1 kez bypass
======================================================= */ ======================================================= */
this.allowRouteLeaveOnce = true 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, { await this.openExistingForEdit(serverOrderId, {
$q, $q,
@@ -2725,21 +2725,21 @@ export const useOrderEntryStore = defineStore('orderentry', {
}) })
/* ======================================================= /* =======================================================
❓ USER NEXT STEP USER NEXT STEP
======================================================= */ ======================================================= */
const choice = await new Promise(resolve => { const choice = await new Promise(resolve => {
$q.dialog({ $q.dialog({
title: 'SipariÅŸ Kaydedildi', title: 'Sipariş Kaydedildi',
options: { options: {
type: 'radio', type: 'radio',
model: 'continue', model: 'continue',
items: [ items: [
{ label: '✏️ Düzenlemeye Devam', value: 'continue' }, { label: '✏️ Düzenlemeye Devam', value: 'continue' },
{ label: '🖨 Yazdır', value: 'print' }, { label: '🖨 Yazdır', value: 'print' },
{ label: '📋 Listeye Dön', value: 'list' } { label: '📋 Listeye Dön', value: 'list' }
] ]
}, },
ok: { label: 'Seç' }, ok: { label: 'Seç' },
cancel: { label: 'Kapat' } cancel: { label: 'Kapat' }
}) })
.onOk(v => resolve(v)) .onOk(v => resolve(v))
@@ -2747,7 +2747,7 @@ export const useOrderEntryStore = defineStore('orderentry', {
}) })
/* ======================================================= /* =======================================================
🧭 USER ROUTING 🧭 USER ROUTING
======================================================= */ ======================================================= */
if (choice === 'print') { if (choice === 'print') {
const id = this.header?.OrderHeaderID || serverOrderId const id = this.header?.OrderHeaderID || serverOrderId
@@ -2755,12 +2755,12 @@ export const useOrderEntryStore = defineStore('orderentry', {
try { try {
await this.downloadOrderPdf(id) await this.downloadOrderPdf(id)
} catch (pdfErr) { } 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({ $q.notify({
type: 'warning', type: 'warning',
message: message:
pdfErr?.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 return
} }
// continue → sayfada kal (hiçbir ÅŸey yapma) // continue sayfada kal (hiçbir şey yapma)
} catch (err) { } catch (err) {
console.error('❌ submitAllReal:', err) console.error(' submitAllReal:', err)
$q.notify({ $q.notify({
type: 'negative', type: 'negative',
@@ -2784,11 +2784,11 @@ export const useOrderEntryStore = defineStore('orderentry', {
err?.response?.data?.detail || err?.response?.data?.detail ||
err?.response?.data?.message || err?.response?.data?.message ||
err?.message || err?.message ||
'Kayıt sırasında hata' 'Kayıt sırasında hata'
}) })
} finally { } finally {
// 🔓 Guard’lar normale dönsün // 🔓 Guardlar normale dönsün
this.isControlledSubmit = false this.isControlledSubmit = false
this.loading = false this.loading = false
} }
@@ -2797,28 +2797,28 @@ export const useOrderEntryStore = defineStore('orderentry', {
, ,
/* ======================================================= /* =======================================================
🧪 SUBMIT ALL TEST 🧪 SUBMIT ALL TEST
======================================================= */ ======================================================= */
async submitAllTest($q = null) { async submitAllTest($q = null) {
try { try {
const { header, lines } = this.buildFinalOrderJson() 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(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)) console.log(JSON.stringify(lines, null, 2))
$q?.notify?.({ $q?.notify?.({
type: 'info', 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' position: 'top'
}) })
} catch (err) { } catch (err) {
console.error('❌ submitAllTest hata:', err) console.error(' submitAllTest hata:', err)
$q?.notify?.({ $q?.notify?.({
type: 'negative', type: 'negative',
message: 'Gösterimde hata oluÅŸtu ❌', message: 'Gösterimde hata oluştu ',
position: 'top' position: 'top'
}) })
} }
@@ -2826,15 +2826,15 @@ export const useOrderEntryStore = defineStore('orderentry', {
/* ======================================================= /* =======================================================
🧹 KAYIT SONRASI TEMİZLİK 🧹 KAYIT SONRASI TEMİZLİK
======================================================= */ ======================================================= */
afterSubmit(opts = { afterSubmit(opts = {
keepLocalStorage: true, keepLocalStorage: true,
backendPayload: null, backendPayload: null,
resetMode: true // 🔑 yeni resetMode: true // 🔑 yeni
}) { }) {
try { try {
console.log('🧹 afterSubmit baÅŸlatıldı', opts) console.log('🧹 afterSubmit başlatıldı', opts)
if (opts?.backendPayload?.header?.OrderHeaderID) { if (opts?.backendPayload?.header?.OrderHeaderID) {
this.mergeAndPersistBackendOrder( this.mergeAndPersistBackendOrder(
@@ -2855,14 +2855,14 @@ export const useOrderEntryStore = defineStore('orderentry', {
this.editingKey = null this.editingKey = null
this.currentOrderId = null this.currentOrderId = null
// 🔐 MODE RESET OPSİYONEL // 🔐 MODE RESET OPSİYONEL
if (opts.resetMode === true) { if (opts.resetMode === true) {
this.mode = 'new' this.mode = 'new'
} }
console.log('✅ afterSubmit tamamlandı.') console.log(' afterSubmit tamamlandı.')
} catch (err) { } 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) ComboKey TEK OTORİTE buildComboKey (bedenKey ile)
✔ UI/Map placeholder: '_' (bedenKey) UI/Map placeholder: '_' (bedenKey)
✔ DB/payload: '' (bedenPayload) → "_" ASLA GİTMEZ DB/payload: '' (bedenPayload) "_" ASLA GİTMEZ
✔ payload içinde aynı ComboKey TEK satır payload içinde aynı ComboKey TEK satır
✔ backend duplicate guard %100 uyumlu (ComboKey stabil) backend duplicate guard %100 uyumlu (ComboKey stabil)
✔ Final assert: payload’da "_" yakalanırsa patlatır Final assert: payloadda "_" yakalanırsa patlatır
=========================================================== */ =========================================================== */
buildFinalOrderJson () { buildFinalOrderJson () {
const auth = useAuthStore() const auth = useAuthStore()
@@ -2894,7 +2894,7 @@ export const useOrderEntryStore = defineStore('orderentry', {
const formatTimeOnly = v => dayjs(v).format('HH:mm:ss') const formatTimeOnly = v => dayjs(v).format('HH:mm:ss')
const formatDateTime = v => (v ? dayjs(v).format('YYYY-MM-DD HH:mm:ss') : null) const formatDateTime = v => (v ? dayjs(v).format('YYYY-MM-DD HH:mm:ss') : null)
// ✅ Payload beden normalize: "_" / "-" / "" => '' // Payload beden normalize: "_" / "-" / "" => ''
const normBeden = (v) => { const normBeden = (v) => {
const s = safeStr(v) const s = safeStr(v)
if (s === '' || s === '_' || s === '-') return '' // payload empty 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 lines = []
const lineByCombo = new Map() // 🔒 KEY = ComboKey const lineByCombo = new Map() // 🔒 KEY = ComboKey
const pushOrMerge = (row, ctx) => { const pushOrMerge = (row, ctx) => {
const { const {
grpKey, grpKey,
bedenKey, // ✅ sadece ComboKey / Map için ('_' olabilir) bedenKey, // sadece ComboKey / Map için ('_' olabilir)
bedenPayload, // ✅ DB için ('' / 'S' / 'M' ...) bedenPayload, // DB için ('' / 'S' / 'M' ...)
qty, qty,
orderLineId, orderLineId,
isDeleteSignal isDeleteSignal
@@ -2966,7 +2966,7 @@ export const useOrderEntryStore = defineStore('orderentry', {
if (qty <= 0 && !isDeleteSignal) return 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 comboKey = buildComboKey(row, bedenKey)
const makeLine = () => ({ const makeLine = () => ({
@@ -2980,7 +2980,7 @@ export const useOrderEntryStore = defineStore('orderentry', {
ItemCode: safeStr(row.model), ItemCode: safeStr(row.model),
ColorCode: safeStr(row.renk), ColorCode: safeStr(row.renk),
// ✅ PAYLOAD: "_" ASLA YOK // PAYLOAD: "_" ASLA YOK
ItemDim1Code: bedenPayload, ItemDim1Code: bedenPayload,
ItemDim2Code: safeStr(row.renk2), ItemDim2Code: safeStr(row.renk2),
@@ -3091,7 +3091,7 @@ export const useOrderEntryStore = defineStore('orderentry', {
const hasAnyBeden = const hasAnyBeden =
map && typeof map === 'object' && Object.keys(map).length > 0 map && typeof map === 'object' && Object.keys(map).length > 0
/* 🔹 BEDENSİZ / AKSBİR */ /* 🔹 BEDENSİZ / AKSBİR */
if (!hasAnyBeden) { if (!hasAnyBeden) {
const allowBlankPayload = const allowBlankPayload =
grpKey === 'aksbir' || row._deleteSignal === true grpKey === 'aksbir' || row._deleteSignal === true
@@ -3101,9 +3101,9 @@ export const useOrderEntryStore = defineStore('orderentry', {
const qty = toNum(row.qty ?? row.Qty1 ?? row.miktar ?? 0) const qty = toNum(row.qty ?? row.Qty1 ?? row.miktar ?? 0)
// ✅ ComboKey stabil: bedenKey = '_' // ComboKey stabil: bedenKey = '_'
const bedenKey = '_' const bedenKey = '_'
// ✅ Payload: boÅŸ string // Payload: boş string
const bedenPayload = '' const bedenPayload = ''
let orderLineId = '' let orderLineId = ''
@@ -3127,7 +3127,7 @@ export const useOrderEntryStore = defineStore('orderentry', {
continue continue
} }
/* 🔹 BEDENLİ */ /* 🔹 BEDENLİ */
for (const [bedenRaw, qtyRaw] of Object.entries(map)) { for (const [bedenRaw, qtyRaw] of Object.entries(map)) {
const isBlankBeden = safeStr(bedenRaw) === '' const isBlankBeden = safeStr(bedenRaw) === ''
if ( if (
@@ -3140,14 +3140,14 @@ export const useOrderEntryStore = defineStore('orderentry', {
const qty = toNum(qtyRaw) const qty = toNum(qtyRaw)
// ✅ payload beden: '' / 'S' / 'M' ... // payload beden: '' / 'S' / 'M' ...
const bedenPayload = normBeden(bedenRaw) const bedenPayload = normBeden(bedenRaw)
// ✅ combokey beden: boÅŸsa '_' ile stabil kalsın // combokey beden: boşsa '_' ile stabil kalsın
const bedenKey = bedenPayload || '_' const bedenKey = bedenPayload || '_'
let orderLineId = '' let orderLineId = ''
if (this.mode === 'edit') { if (this.mode === 'edit') {
// lineIdMap anahtarı sizde hangi bedenle tutuluyorsa ikisini de dene // lineIdMap anahtarı sizde hangi bedenle tutuluyorsa ikisini de dene
orderLineId = orderLineId =
safeStr(lineIdMap?.[bedenKey]) || safeStr(lineIdMap?.[bedenKey]) ||
safeStr(lineIdMap?.[bedenPayload]) || safeStr(lineIdMap?.[bedenPayload]) ||
@@ -3174,18 +3174,18 @@ export const useOrderEntryStore = defineStore('orderentry', {
lines.forEach((ln, i) => { ln.SortOrder = i + 1 }) lines.forEach((ln, i) => { ln.SortOrder = i + 1 })
/* ======================================================= /* =======================================================
ASSERT — payload’da "_" OLAMAZ ASSERT payloadda "_" OLAMAZ
======================================================= */ ======================================================= */
if (lines.some(l => (l.ItemDim1Code || '') === '_' )) { if (lines.some(l => (l.ItemDim1Code || '') === '_' )) {
console.error('❌ Payload’da "_" yakalandı', lines.filter(l => l.ItemDim1Code === '_')) console.error(' Payloadda "_" yakalandı', lines.filter(l => l.ItemDim1Code === '_'))
throw new Error('Payload ItemDim1Code "_" olamaz') 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( console.table(
lines.map((l, i) => ({ lines.map((l, i) => ({
@@ -3214,7 +3214,7 @@ export const useOrderEntryStore = defineStore('orderentry', {
,/* =========================================================== ,/* ===========================================================
✅ STORE ACTIONS — FIXED HELPERS STORE ACTIONS FIXED HELPERS
- setRowErrorByClientKey - setRowErrorByClientKey
- clearRowErrorByClientKey - clearRowErrorByClientKey
- applyTerminToRowsIfEmpty - applyTerminToRowsIfEmpty
@@ -3248,14 +3248,14 @@ export const useOrderEntryStore = defineStore('orderentry', {
if (!dateStr) return if (!dateStr) return
if (!Array.isArray(this.summaryRows)) return if (!Array.isArray(this.summaryRows)) return
// ❗ reassign YOK — patch/mutate // reassign YOK patch/mutate
for (const r of this.summaryRows) { for (const r of this.summaryRows) {
if (!r?.terminTarihi || r.terminTarihi === '') { if (!r?.terminTarihi || r.terminTarihi === '') {
r.terminTarihi = dateStr r.terminTarihi = dateStr
} }
} }
// opsiyonel ama genelde doÄŸru: // opsiyonel ama genelde doğru:
this.persistLocalStorage?.() 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) { export function updateTotals(f) {
f.adet = (f.bedenler || []).reduce((a, b) => a + Number(b || 0), 0) 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' * import { sharedOrderEntryRefs } from 'src/stores/orderentryStore'
* const { stockMap, bedenStock, sizeCache } = sharedOrderEntryRefs * const { stockMap, bedenStock, sizeCache } = sharedOrderEntryRefs