Files
bssapp/ui/src/stores/productionProductCostingDefaultQtyStore.js
T

170 lines
4.4 KiB
JavaScript

import { defineStore } from 'pinia'
import { computed, ref } from 'vue'
import { get, post, extractApiErrorDetail } from 'src/services/api'
const DRAFT_KEY = 'bssapp:production-product-costing:default-quantities:draft:v1'
function safeJsonParse (raw) {
try {
return JSON.parse(raw)
} catch {
return null
}
}
export const useProductionProductCostingDefaultQtyStore = defineStore('production_product_costing_default_qty', () => {
const rows = ref([])
const loading = ref(false)
const saving = ref(false)
const error = ref('')
// draftByNo: { [nHammaddeTuruNo]: { lDefaultMiktar } }
const draftByNo = ref({})
const persistTimer = ref(0)
const dirtyNos = computed(() => Object.keys(draftByNo.value || {}).map(k => Number(k)).filter(n => n > 0))
const hasUnsavedChanges = computed(() => dirtyNos.value.length > 0)
function schedulePersistDraft () {
try {
if (persistTimer.value) window.clearTimeout(persistTimer.value)
persistTimer.value = window.setTimeout(() => {
persistTimer.value = 0
persistDraftNow()
}, 350)
} catch {
persistDraftNow()
}
}
function persistDraftNow () {
try {
const payload = {
version: 1,
savedAt: new Date().toISOString(),
draftByNo: draftByNo.value || {}
}
localStorage.setItem(DRAFT_KEY, JSON.stringify(payload))
} catch {
// ignore
}
}
function hydrateDraft () {
try {
const raw = localStorage.getItem(DRAFT_KEY)
if (!raw) return
const payload = safeJsonParse(raw)
if (!payload || typeof payload !== 'object') return
if (!payload.draftByNo || typeof payload.draftByNo !== 'object') return
draftByNo.value = payload.draftByNo
} catch {
// ignore
}
}
function clearDraft () {
draftByNo.value = {}
try {
localStorage.removeItem(DRAFT_KEY)
} catch {
// ignore
}
}
function setDraft (nHammaddeTuruNo, patch) {
const no = Number(nHammaddeTuruNo || 0)
if (!(no > 0)) return
const prev = draftByNo.value?.[String(no)] || {}
draftByNo.value = {
...(draftByNo.value || {}),
[String(no)]: {
...prev,
...(patch || {})
}
}
schedulePersistDraft()
}
function getEffectiveRow (row) {
const no = Number(row?.nHammaddeTuruNo || 0)
if (!(no > 0)) return row
const draft = draftByNo.value?.[String(no)]
if (!draft) return row
return {
...row,
lDefaultMiktar: typeof draft.lDefaultMiktar === 'number' ? draft.lDefaultMiktar : row?.lDefaultMiktar,
__dirty: true
}
}
async function fetch ({ search = '', limit = 2000 } = {}) {
loading.value = true
error.value = ''
try {
const data = await get('/pricing/production-product-costing/default-quantities', {
search: String(search || '').trim(),
limit
})
const base = Array.isArray(data) ? data : []
rows.value = base.map(getEffectiveRow)
} catch (e) {
error.value = extractApiErrorDetail(e) || String(e?.message || e || 'Hata')
throw e
} finally {
loading.value = false
}
}
async function calcAvgForRow ({ nHammaddeTuruNo, topN = 10 } = {}) {
const no = Number(nHammaddeTuruNo || 0)
if (!(no > 0)) return null
const resp = await post('/pricing/production-product-costing/default-quantities/calc-avg', {
nHammaddeTuruNo: no,
topN: Number(topN || 10)
})
return resp
}
async function saveAll () {
if (!hasUnsavedChanges.value) return { updated: 0 }
saving.value = true
error.value = ''
try {
const items = dirtyNos.value.map(no => {
const patch = draftByNo.value?.[String(no)] || {}
return {
nHammaddeTuruNo: Number(no),
lDefaultMiktar: Number(patch.lDefaultMiktar || 0)
}
}).filter(it => it.nHammaddeTuruNo > 0 && it.lDefaultMiktar > 0)
const resp = await post('/pricing/production-product-costing/default-quantities/update-bulk', { items })
clearDraft()
return resp
} catch (e) {
error.value = extractApiErrorDetail(e) || String(e?.message || e || 'Hata')
throw e
} finally {
saving.value = false
}
}
hydrateDraft()
return {
rows,
loading,
saving,
error,
draftByNo,
dirtyNos,
hasUnsavedChanges,
fetch,
setDraft,
calcAvgForRow,
saveAll,
clearDraft
}
})