236 lines
6.8 KiB
Vue
236 lines
6.8 KiB
Vue
<template>
|
|
<q-page class="q-pa-md">
|
|
<div class="sticky-stack">
|
|
<div class="save-toolbar">
|
|
<div class="row items-center justify-between q-col-gutter-sm">
|
|
<div class="col-auto text-weight-bold">Maliyet Varsayilan Miktarlar</div>
|
|
<div class="col-auto row items-center q-gutter-sm">
|
|
<q-btn
|
|
dense
|
|
outline
|
|
color="grey-8"
|
|
icon="undo"
|
|
label="Taslagi Temizle"
|
|
:disable="!hasUnsavedChanges"
|
|
@click="onClearDraft"
|
|
/>
|
|
<q-btn
|
|
dense
|
|
color="primary"
|
|
icon="save"
|
|
label="Degisiklikleri Kaydet"
|
|
:loading="saving"
|
|
:disable="!hasUnsavedChanges"
|
|
@click="onSaveAll"
|
|
/>
|
|
<q-btn
|
|
dense
|
|
outline
|
|
color="grey-8"
|
|
icon="refresh"
|
|
label="Yenile"
|
|
:loading="loading || saving"
|
|
@click="fetchRows"
|
|
/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="filter-bar q-mb-md">
|
|
<div class="row q-col-gutter-sm items-center">
|
|
<div class="col-12 col-md-4">
|
|
<q-input v-model="search" dense filled clearable label="Ara (Hammadde No)" @update:model-value="debouncedFetch" />
|
|
</div>
|
|
<div class="col-12 col-md-auto text-grey-7">
|
|
Kayit: {{ Array.isArray(rows) ? rows.length : 0 }} | Degisen: {{ dirtyNos.length }}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<q-banner v-if="error" class="bg-red text-white q-mb-md">
|
|
{{ error }}
|
|
</q-banner>
|
|
|
|
<q-table
|
|
flat
|
|
bordered
|
|
dense
|
|
row-key="nHammaddeTuruNo"
|
|
:rows="rows"
|
|
:columns="columns"
|
|
:loading="loading"
|
|
:rows-per-page-options="[0]"
|
|
hide-bottom
|
|
>
|
|
<template #body-cell-actions="props">
|
|
<q-td :props="props">
|
|
<q-btn
|
|
dense
|
|
flat
|
|
icon="calculate"
|
|
color="primary"
|
|
@click="onCalcAvg(props.row)"
|
|
>
|
|
<q-tooltip>Son 10 Ortalama</q-tooltip>
|
|
</q-btn>
|
|
</q-td>
|
|
</template>
|
|
<template #body-cell-lDefaultMiktar="props">
|
|
<q-td :props="props">
|
|
<q-input
|
|
:model-value="props.row.lDefaultMiktar"
|
|
dense
|
|
filled
|
|
type="number"
|
|
step="0.0001"
|
|
@update:model-value="val => onEditQty(props.row, val)"
|
|
style="max-width: 140px"
|
|
/>
|
|
</q-td>
|
|
</template>
|
|
<template #body-cell-bAktif="props">
|
|
<q-td :props="props">
|
|
<q-toggle
|
|
:model-value="Boolean(props.row.bAktif)"
|
|
@update:model-value="val => onEditActive(props.row, val)"
|
|
/>
|
|
</q-td>
|
|
</template>
|
|
</q-table>
|
|
</q-page>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { computed, onMounted, onUnmounted, ref, watch } from 'vue'
|
|
import { useQuasar } from 'quasar'
|
|
import { onBeforeRouteLeave } from 'vue-router'
|
|
import { storeToRefs } from 'pinia'
|
|
import { useProductionProductCostingDefaultQtyStore } from 'src/stores/productionProductCostingDefaultQtyStore'
|
|
|
|
const $q = useQuasar()
|
|
|
|
const store = useProductionProductCostingDefaultQtyStore()
|
|
const { rows, loading, saving, error, dirtyNos, hasUnsavedChanges } = storeToRefs(store)
|
|
|
|
const search = ref('')
|
|
|
|
const columns = [
|
|
{ name: 'nHammaddeTuruNo', label: 'HammaddeTuruNo', field: 'nHammaddeTuruNo', align: 'left', sortable: true },
|
|
{ name: 'sAciklama', label: 'Aciklama', field: 'sAciklama', align: 'left', sortable: true },
|
|
{ name: 'lDefaultMiktar', label: 'Varsayilan Miktar', field: 'lDefaultMiktar', align: 'right', sortable: true },
|
|
{ name: 'dteCalcTarihi', label: 'Hesap Tarihi', field: 'dteCalcTarihi', align: 'left', sortable: true },
|
|
{ name: 'bAktif', label: 'Aktif', field: 'bAktif', align: 'center', sortable: true },
|
|
{ name: 'actions', label: '', field: '__actions', align: 'right', sortable: false }
|
|
]
|
|
|
|
let debounceTimer = null
|
|
function debouncedFetch () {
|
|
if (debounceTimer) window.clearTimeout(debounceTimer)
|
|
debounceTimer = window.setTimeout(() => fetchRows(), 250)
|
|
}
|
|
|
|
async function fetchRows () {
|
|
await store.fetch({
|
|
search: String(search.value || '').trim()
|
|
})
|
|
}
|
|
|
|
function onEditQty (row, val) {
|
|
const no = Number(row?.nHammaddeTuruNo || 0)
|
|
const qty = Number(val || 0)
|
|
if (!(no > 0)) return
|
|
store.setDraft(no, { lDefaultMiktar: qty })
|
|
// keep table row in sync visually
|
|
row.lDefaultMiktar = qty
|
|
}
|
|
|
|
function onEditActive (row, val) {
|
|
const no = Number(row?.nHammaddeTuruNo || 0)
|
|
if (!(no > 0)) return
|
|
store.setDraft(no, { bAktif: Boolean(val) })
|
|
row.bAktif = Boolean(val)
|
|
}
|
|
|
|
async function onCalcAvg (row) {
|
|
const no = Number(row?.nHammaddeTuruNo || 0)
|
|
if (!(no > 0)) return
|
|
try {
|
|
const resp = await store.calcAvgForRow({ nHammaddeTuruNo: no, topN: 10 })
|
|
const qty = Number(resp?.lDefaultMiktar || 0)
|
|
if (qty > 0) {
|
|
store.setDraft(no, { lDefaultMiktar: qty })
|
|
row.lDefaultMiktar = qty
|
|
$q.notify({ type: 'positive', message: `Ortalama yazildi (n=${Number(resp?.nSampleCount || 0)})`, position: 'top-right' })
|
|
} else {
|
|
$q.notify({ type: 'warning', message: 'Ortalama bulunamadi', position: 'top-right' })
|
|
}
|
|
} catch (e) {
|
|
$q.notify({ type: 'negative', message: String(e?.message || e || 'Hata'), position: 'top-right' })
|
|
}
|
|
}
|
|
|
|
async function onSaveAll () {
|
|
try {
|
|
const resp = await store.saveAll()
|
|
await fetchRows()
|
|
$q.notify({ type: 'positive', message: `Kaydedildi (${Number(resp?.updated || 0)})`, position: 'top-right' })
|
|
} catch (e) {
|
|
$q.notify({ type: 'negative', message: String(e?.message || e || 'Kaydedilemedi'), position: 'top-right' })
|
|
}
|
|
}
|
|
|
|
function onClearDraft () {
|
|
$q.dialog({
|
|
title: 'Taslak Temizlensin mi?',
|
|
message: 'Kaydedilmemis degisiklikler silinecek.',
|
|
cancel: true,
|
|
persistent: true
|
|
}).onOk(() => {
|
|
store.clearDraft()
|
|
fetchRows()
|
|
})
|
|
}
|
|
|
|
function ensureBeforeUnloadGuard (enabled) {
|
|
if (!enabled) {
|
|
window.onbeforeunload = null
|
|
return
|
|
}
|
|
window.onbeforeunload = (e) => {
|
|
e.preventDefault()
|
|
e.returnValue = ''
|
|
return ''
|
|
}
|
|
}
|
|
|
|
watch(hasUnsavedChanges, (v) => ensureBeforeUnloadGuard(Boolean(v)))
|
|
|
|
onBeforeRouteLeave((to, from, next) => {
|
|
if (!hasUnsavedChanges.value) return next()
|
|
$q.dialog({
|
|
title: 'Kaydedilmemis Degisiklikler Var',
|
|
message: 'Sayfadan cikmak istiyor musunuz?',
|
|
cancel: true,
|
|
persistent: true
|
|
}).onOk(() => next()).onCancel(() => next(false))
|
|
})
|
|
|
|
onMounted(() => {
|
|
fetchRows()
|
|
})
|
|
onUnmounted(() => {
|
|
window.onbeforeunload = null
|
|
})
|
|
</script>
|
|
|
|
<style scoped>
|
|
.sticky-stack {
|
|
position: sticky;
|
|
top: var(--header-h);
|
|
z-index: 100;
|
|
background: #fff;
|
|
padding-top: 8px;
|
|
}
|
|
</style>
|