Merge remote-tracking branch 'origin/master'
This commit is contained in:
@@ -11,6 +11,14 @@
|
||||
:loading="store.loading"
|
||||
@click="refreshAll"
|
||||
/>
|
||||
<q-btn
|
||||
class="q-ml-sm"
|
||||
color="secondary"
|
||||
icon="save"
|
||||
label="Secili Degisiklikleri Kaydet"
|
||||
:loading="store.saving"
|
||||
@click="onBulkSubmit"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="filter-bar row q-col-gutter-md">
|
||||
@@ -76,6 +84,27 @@
|
||||
:rows-per-page-options="[0]"
|
||||
hide-bottom
|
||||
>
|
||||
<template #header-cell-select="props">
|
||||
<q-th :props="props" class="text-center" style="width: 44px">
|
||||
<q-checkbox
|
||||
size="sm"
|
||||
:model-value="allSelectedVisible"
|
||||
:indeterminate="someSelectedVisible && !allSelectedVisible"
|
||||
@update:model-value="toggleSelectAllVisible"
|
||||
/>
|
||||
</q-th>
|
||||
</template>
|
||||
|
||||
<template #body-cell-select="props">
|
||||
<q-td :props="props" class="text-center" style="width: 44px">
|
||||
<q-checkbox
|
||||
size="sm"
|
||||
:model-value="!!selectedMap[props.row.RowKey]"
|
||||
@update:model-value="(val) => toggleRowSelection(props.row.RowKey, val)"
|
||||
/>
|
||||
</q-td>
|
||||
</template>
|
||||
|
||||
<template #body-cell-actions="props">
|
||||
<q-td :props="props" class="text-center">
|
||||
<q-btn
|
||||
@@ -98,6 +127,7 @@
|
||||
v-model="props.row.NewItemCode"
|
||||
dense
|
||||
filled
|
||||
maxlength="13"
|
||||
label="Yeni Urun"
|
||||
@update:model-value="val => onNewItemChange(props.row, val)"
|
||||
>
|
||||
@@ -143,10 +173,12 @@
|
||||
emit-value
|
||||
map-options
|
||||
use-input
|
||||
new-value-mode="add-unique"
|
||||
dense
|
||||
filled
|
||||
label="Yeni Renk"
|
||||
@update:model-value="() => onNewColorChange(props.row)"
|
||||
@new-value="(val, done) => onCreateColorValue(props.row, val, done)"
|
||||
/>
|
||||
</q-td>
|
||||
</template>
|
||||
@@ -161,9 +193,11 @@
|
||||
emit-value
|
||||
map-options
|
||||
use-input
|
||||
new-value-mode="add-unique"
|
||||
dense
|
||||
filled
|
||||
label="Yeni 2. Renk"
|
||||
@new-value="(val, done) => onCreateSecondColorValue(props.row, val, done)"
|
||||
/>
|
||||
</q-td>
|
||||
</template>
|
||||
@@ -214,8 +248,10 @@ const descFilter = ref('')
|
||||
const productOptions = ref([])
|
||||
const productSearch = ref('')
|
||||
const rowSavingId = ref('')
|
||||
const selectedMap = ref({})
|
||||
|
||||
const columns = [
|
||||
{ name: 'select', label: '', field: 'select', align: 'center', sortable: false, style: 'width:44px;', headerStyle: 'width:44px;' },
|
||||
{ name: 'OldItemCode', label: 'Eski Urun Kodu', field: 'OldItemCode', align: 'left', sortable: true, style: 'min-width:120px;white-space:nowrap', headerStyle: 'min-width:120px;white-space:nowrap', headerClasses: 'col-old', classes: 'col-old' },
|
||||
{ name: 'OldColor', label: 'Eski Urun Rengi', field: 'OldColor', align: 'left', sortable: true, style: 'min-width:100px;white-space:nowrap', headerStyle: 'min-width:100px;white-space:nowrap', headerClasses: 'col-old', classes: 'col-old' },
|
||||
{ name: 'OldDim2', label: 'Eski 2. Renk', field: 'OldDim2', align: 'left', sortable: true, style: 'min-width:90px;white-space:nowrap', headerStyle: 'min-width:90px;white-space:nowrap', headerClasses: 'col-old', classes: 'col-old' },
|
||||
@@ -274,18 +310,21 @@ const filteredRows = computed(() => {
|
||||
)
|
||||
})
|
||||
|
||||
const visibleRowKeys = computed(() => filteredRows.value.map(r => r.RowKey))
|
||||
const selectedVisibleCount = computed(() => visibleRowKeys.value.filter(k => !!selectedMap.value[k]).length)
|
||||
const allSelectedVisible = computed(() => visibleRowKeys.value.length > 0 && selectedVisibleCount.value === visibleRowKeys.value.length)
|
||||
const someSelectedVisible = computed(() => selectedVisibleCount.value > 0)
|
||||
|
||||
function onSelectProduct (row, code) {
|
||||
productSearch.value = ''
|
||||
onNewItemChange(row, code)
|
||||
}
|
||||
|
||||
function onNewItemChange (row, val) {
|
||||
const next = String(val || '').trim()
|
||||
if (next && !isValidModelCode(next)) {
|
||||
$q.notify({ type: 'negative', message: 'Model kodu formati gecersiz. Ornek: S000-DMY00001' })
|
||||
row.NewItemCode = ''
|
||||
row.NewColor = ''
|
||||
row.NewDim2 = ''
|
||||
const next = String(val || '').trim().toUpperCase()
|
||||
if (next.length > 13) {
|
||||
$q.notify({ type: 'negative', message: 'Model kodu en fazla 13 karakter olabilir.' })
|
||||
row.NewItemCode = next.slice(0, 13)
|
||||
return
|
||||
}
|
||||
row.NewItemCode = next ? next.toUpperCase() : ''
|
||||
@@ -297,6 +336,7 @@ function onNewItemChange (row, val) {
|
||||
}
|
||||
|
||||
function onNewColorChange (row) {
|
||||
row.NewColor = normalizeShortCode(row.NewColor, 3)
|
||||
row.NewDim2 = ''
|
||||
if (row.NewItemCode && row.NewColor) {
|
||||
store.fetchSecondColors(row.NewItemCode, row.NewColor)
|
||||
@@ -319,9 +359,91 @@ function getSecondColorOptions (row) {
|
||||
return store.secondColorOptionsByKey[key] || []
|
||||
}
|
||||
|
||||
function isValidModelCode (value) {
|
||||
const text = String(value || '').trim().toUpperCase()
|
||||
return /^[A-Z][0-9]{3}-[A-Z]{3}[0-9]{5}$/.test(text)
|
||||
function toggleRowSelection (rowKey, checked) {
|
||||
const next = { ...selectedMap.value }
|
||||
if (checked) next[rowKey] = true
|
||||
else delete next[rowKey]
|
||||
selectedMap.value = next
|
||||
}
|
||||
|
||||
function toggleSelectAllVisible (checked) {
|
||||
const next = { ...selectedMap.value }
|
||||
for (const key of visibleRowKeys.value) {
|
||||
if (checked) next[key] = true
|
||||
else delete next[key]
|
||||
}
|
||||
selectedMap.value = next
|
||||
}
|
||||
|
||||
function onCreateColorValue (row, val, done) {
|
||||
const code = normalizeShortCode(val, 3)
|
||||
if (!code) {
|
||||
done(null)
|
||||
return
|
||||
}
|
||||
row.NewColor = code
|
||||
onNewColorChange(row)
|
||||
done(code, 'add-unique')
|
||||
}
|
||||
|
||||
function onCreateSecondColorValue (row, val, done) {
|
||||
const code = normalizeShortCode(val, 3)
|
||||
if (!code) {
|
||||
done(null)
|
||||
return
|
||||
}
|
||||
row.NewDim2 = code
|
||||
done(code, 'add-unique')
|
||||
}
|
||||
|
||||
function normalizeShortCode (value, maxLen) {
|
||||
return String(value || '').trim().toUpperCase().slice(0, maxLen)
|
||||
}
|
||||
|
||||
function validateRowInput (row) {
|
||||
const newItemCode = String(row.NewItemCode || '').trim().toUpperCase()
|
||||
const newColor = normalizeShortCode(row.NewColor, 3)
|
||||
const newDim2 = normalizeShortCode(row.NewDim2, 3)
|
||||
const oldColor = String(row.OldColor || '').trim()
|
||||
const oldDim2 = String(row.OldDim2 || '').trim()
|
||||
|
||||
if (!newItemCode) return 'Yeni model kodu zorunludur.'
|
||||
if (newItemCode.length !== 13) return 'Yeni model kodu 13 karakter olmalidir.'
|
||||
if (oldColor && !newColor) return 'Eski kayitta 1. renk oldugu icin yeni 1. renk zorunludur.'
|
||||
if (newColor && newColor.length !== 3) return 'Yeni 1. renk kodu 3 karakter olmalidir.'
|
||||
if (oldDim2 && !newDim2) return 'Eski kayitta 2. renk oldugu icin yeni 2. renk zorunludur.'
|
||||
if (newDim2 && newDim2.length !== 3) return 'Yeni 2. renk kodu 3 karakter olmalidir.'
|
||||
if (newDim2 && !newColor) return '2. renk girmek icin 1. renk zorunludur.'
|
||||
|
||||
row.NewItemCode = newItemCode
|
||||
row.NewColor = newColor
|
||||
row.NewDim2 = newDim2
|
||||
return ''
|
||||
}
|
||||
|
||||
function collectLinesFromRows (selectedRows) {
|
||||
const lines = []
|
||||
for (const row of selectedRows) {
|
||||
const errMsg = validateRowInput(row)
|
||||
if (errMsg) {
|
||||
return { errMsg, lines: [] }
|
||||
}
|
||||
|
||||
const baseLine = {
|
||||
NewItemCode: String(row.NewItemCode || '').trim().toUpperCase(),
|
||||
NewColor: normalizeShortCode(row.NewColor, 3),
|
||||
NewDim2: normalizeShortCode(row.NewDim2, 3),
|
||||
NewDesc: String((row.NewDesc || row.OldDesc) || '').trim()
|
||||
}
|
||||
|
||||
for (const id of (row.OrderLineIDs || [])) {
|
||||
lines.push({
|
||||
OrderLineID: id,
|
||||
...baseLine
|
||||
})
|
||||
}
|
||||
}
|
||||
return { errMsg: '', lines }
|
||||
}
|
||||
|
||||
function buildGroupKey (item) {
|
||||
@@ -416,23 +538,12 @@ async function refreshAll () {
|
||||
}
|
||||
|
||||
async function onRowSubmit (row) {
|
||||
const baseLine = {
|
||||
NewItemCode: String(row.NewItemCode || '').trim(),
|
||||
NewColor: String(row.NewColor || '').trim(),
|
||||
NewDim2: String(row.NewDim2 || '').trim(),
|
||||
NewDesc: String((row.NewDesc || row.OldDesc) || '').trim()
|
||||
}
|
||||
|
||||
if (!baseLine.NewItemCode || !baseLine.NewColor) {
|
||||
$q.notify({ type: 'negative', message: 'Yeni urun ve renk zorunludur.' })
|
||||
const { errMsg, lines } = collectLinesFromRows([row])
|
||||
if (errMsg) {
|
||||
$q.notify({ type: 'negative', message: errMsg })
|
||||
return
|
||||
}
|
||||
|
||||
const lines = (row.OrderLineIDs || []).map(id => ({
|
||||
OrderLineID: id,
|
||||
...baseLine
|
||||
}))
|
||||
|
||||
if (!lines.length) {
|
||||
$q.notify({ type: 'negative', message: 'Satir bulunamadi.' })
|
||||
return
|
||||
@@ -467,6 +578,52 @@ async function onRowSubmit (row) {
|
||||
rowSavingId.value = ''
|
||||
}
|
||||
}
|
||||
|
||||
async function onBulkSubmit () {
|
||||
const selectedRows = rows.value.filter(r => !!selectedMap.value[r.RowKey])
|
||||
if (!selectedRows.length) {
|
||||
$q.notify({ type: 'warning', message: 'Lutfen en az bir satir seciniz.' })
|
||||
return
|
||||
}
|
||||
|
||||
const { errMsg, lines } = collectLinesFromRows(selectedRows)
|
||||
if (errMsg) {
|
||||
$q.notify({ type: 'negative', message: errMsg })
|
||||
return
|
||||
}
|
||||
if (!lines.length) {
|
||||
$q.notify({ type: 'negative', message: 'Secili satirlarda guncellenecek kayit bulunamadi.' })
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
const validate = await store.validateUpdates(orderHeaderID.value, lines)
|
||||
const missingCount = validate?.missingCount || 0
|
||||
if (missingCount > 0) {
|
||||
const missingList = (validate?.missing || []).map(v => (
|
||||
`${v.ItemCode} / ${v.ColorCode} / ${v.ItemDim1Code} / ${v.ItemDim2Code}`
|
||||
))
|
||||
$q.dialog({
|
||||
title: 'Eksik Varyantlar',
|
||||
message: `Eksik varyant bulundu: ${missingCount}<br><br>${missingList.join('<br>')}`,
|
||||
html: true,
|
||||
ok: { label: 'Ekle ve Guncelle', color: 'primary' },
|
||||
cancel: { label: 'Vazgec', flat: true }
|
||||
}).onOk(async () => {
|
||||
await store.applyUpdates(orderHeaderID.value, lines, true)
|
||||
await store.fetchItems(orderHeaderID.value)
|
||||
selectedMap.value = {}
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
await store.applyUpdates(orderHeaderID.value, lines, false)
|
||||
await store.fetchItems(orderHeaderID.value)
|
||||
selectedMap.value = {}
|
||||
} catch (err) {
|
||||
$q.notify({ type: 'negative', message: 'Toplu kayit islemi basarisiz.' })
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
Reference in New Issue
Block a user