Merge remote-tracking branch 'origin/master'
This commit is contained in:
@@ -26,6 +26,15 @@
|
||||
readonly
|
||||
/>
|
||||
</div>
|
||||
<div class="col-3">
|
||||
<q-input
|
||||
v-model="descFilter"
|
||||
label="Aciklama Ara"
|
||||
filled
|
||||
dense
|
||||
clearable
|
||||
/>
|
||||
</div>
|
||||
<div class="col-2">
|
||||
<q-input
|
||||
:model-value="header?.OrderNumber || ''"
|
||||
@@ -61,8 +70,8 @@
|
||||
bordered
|
||||
dense
|
||||
separator="cell"
|
||||
row-key="OrderLineID"
|
||||
:rows="rows"
|
||||
row-key="RowKey"
|
||||
:rows="filteredRows"
|
||||
:columns="columns"
|
||||
:loading="store.loading"
|
||||
no-data-label="Uretime verilecek urun bulunamadi"
|
||||
@@ -77,7 +86,7 @@
|
||||
flat
|
||||
round
|
||||
dense
|
||||
:loading="rowSavingId === props.row.OrderLineID"
|
||||
:loading="rowSavingId === props.row.RowKey"
|
||||
@click="onRowSubmit(props.row)"
|
||||
>
|
||||
<q-tooltip>Satiri Guncelle</q-tooltip>
|
||||
@@ -200,6 +209,7 @@ const cariLabel = computed(() => {
|
||||
})
|
||||
|
||||
const rows = ref([])
|
||||
const descFilter = ref('')
|
||||
const productOptions = ref([])
|
||||
const productSearch = ref('')
|
||||
const rowSavingId = ref('')
|
||||
@@ -209,6 +219,7 @@ const columns = [
|
||||
{ name: 'OldColor', label: 'Eski Urun Rengi', field: 'OldColor', align: 'left', sortable: true, style: 'min-width:120px;white-space:nowrap', headerStyle: 'min-width:120px;white-space:nowrap' },
|
||||
{ name: 'OldDim2', label: 'Eski 2. Renk', field: 'OldDim2', align: 'left', sortable: true, style: 'min-width:110px;white-space:nowrap', headerStyle: 'min-width:110px;white-space:nowrap' },
|
||||
{ name: 'OldDesc', label: 'Eski Aciklama', field: 'OldDesc', align: 'left', sortable: false, style: 'min-width:180px;white-space:nowrap', headerStyle: 'min-width:180px;white-space:nowrap' },
|
||||
{ name: 'OldSizes', label: 'Bedenler', field: 'OldSizesLabel', align: 'left', sortable: false, style: 'min-width:160px;white-space:nowrap', headerStyle: 'min-width:160px;white-space:nowrap' },
|
||||
{ name: 'NewItemCode', label: 'Yeni Urun Kodu', field: 'NewItemCode', align: 'left', sortable: false, style: 'min-width:190px;', headerStyle: 'min-width:190px;' },
|
||||
{ name: 'NewColor', label: 'Yeni Urun Rengi', field: 'NewColor', align: 'left', sortable: false, style: 'min-width:160px;', headerStyle: 'min-width:160px;' },
|
||||
{ name: 'NewDim2', label: 'Yeni 2. Renk', field: 'NewDim2', align: 'left', sortable: false, style: 'min-width:160px;', headerStyle: 'min-width:160px;' },
|
||||
@@ -227,13 +238,7 @@ watch(orderHeaderID, async (id) => {
|
||||
watch(
|
||||
() => store.items,
|
||||
(items) => {
|
||||
rows.value = (items || []).map(item => ({
|
||||
...item,
|
||||
NewItemCode: '',
|
||||
NewColor: '',
|
||||
NewDim2: '',
|
||||
NewDesc: ''
|
||||
}))
|
||||
rows.value = groupItems(items || [])
|
||||
},
|
||||
{ immediate: true }
|
||||
)
|
||||
@@ -260,6 +265,14 @@ const filteredProducts = computed(() => {
|
||||
).slice(0, 50)
|
||||
})
|
||||
|
||||
const filteredRows = computed(() => {
|
||||
const needle = String(descFilter.value || '').toLowerCase().trim()
|
||||
if (!needle) return rows.value
|
||||
return rows.value.filter(r =>
|
||||
String(r?.OldDesc || '').toLowerCase().includes(needle)
|
||||
)
|
||||
})
|
||||
|
||||
function onSelectProduct (row, code) {
|
||||
productSearch.value = ''
|
||||
onNewItemChange(row, code)
|
||||
@@ -310,14 +323,83 @@ function isValidModelCode (value) {
|
||||
return /^[A-Z][0-9]{3}-[A-Z]{3}[0-9]{5}$/.test(text)
|
||||
}
|
||||
|
||||
function buildGroupKey (item) {
|
||||
const parts = [
|
||||
String(item?.OldItemCode || '').trim(),
|
||||
String(item?.OldColor || '').trim(),
|
||||
String(item?.OldDim2 || '').trim(),
|
||||
String(item?.OldDesc || '').trim(),
|
||||
String(item?.OldDim3 || '').trim()
|
||||
]
|
||||
return parts.join('||')
|
||||
}
|
||||
|
||||
function formatSizes (sizeMap) {
|
||||
const entries = Object.entries(sizeMap || {})
|
||||
if (!entries.length) return { list: [], label: '-' }
|
||||
entries.sort((a, b) => String(a[0]).localeCompare(String(b[0])))
|
||||
const label = entries.map(([k, v]) => (v > 1 ? `${k}(${v})` : k)).join(', ')
|
||||
return { list: entries.map(([k]) => k), label }
|
||||
}
|
||||
|
||||
function groupItems (items) {
|
||||
const map = new Map()
|
||||
|
||||
for (const it of items) {
|
||||
const key = buildGroupKey(it)
|
||||
if (!map.has(key)) {
|
||||
map.set(key, {
|
||||
RowKey: key,
|
||||
OrderHeaderID: it.OrderHeaderID,
|
||||
OldItemCode: it.OldItemCode,
|
||||
OldColor: it.OldColor,
|
||||
OldDim2: it.OldDim2,
|
||||
OldDim3: it.OldDim3,
|
||||
OldDesc: it.OldDesc,
|
||||
OrderLineIDs: [],
|
||||
OldSizes: [],
|
||||
OldSizesLabel: '',
|
||||
NewItemCode: '',
|
||||
NewColor: '',
|
||||
NewDim2: '',
|
||||
NewDesc: '',
|
||||
IsVariantMissing: !!it.IsVariantMissing
|
||||
})
|
||||
}
|
||||
|
||||
const g = map.get(key)
|
||||
if (it?.OrderLineID) g.OrderLineIDs.push(it.OrderLineID)
|
||||
|
||||
const size = String(it?.OldDim1 || '').trim()
|
||||
if (size !== '') {
|
||||
g.__sizeMap = g.__sizeMap || {}
|
||||
g.__sizeMap[size] = (g.__sizeMap[size] || 0) + 1
|
||||
}
|
||||
if (it?.IsVariantMissing) g.IsVariantMissing = true
|
||||
}
|
||||
|
||||
const out = []
|
||||
for (const g of map.values()) {
|
||||
const sizes = formatSizes(g.__sizeMap || {})
|
||||
g.OldSizes = sizes.list
|
||||
g.OldSizesLabel = sizes.label
|
||||
delete g.__sizeMap
|
||||
out.push(g)
|
||||
}
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
function buildPayloadLines () {
|
||||
return rows.value.map(r => ({
|
||||
OrderLineID: r.OrderLineID,
|
||||
NewItemCode: String(r.NewItemCode || '').trim(),
|
||||
NewColor: String(r.NewColor || '').trim(),
|
||||
NewDim2: String(r.NewDim2 || '').trim(),
|
||||
NewDesc: String(r.NewDesc || '').trim()
|
||||
}))
|
||||
return rows.value.flatMap(r =>
|
||||
(r.OrderLineIDs || []).map(id => ({
|
||||
OrderLineID: id,
|
||||
NewItemCode: String(r.NewItemCode || '').trim(),
|
||||
NewColor: String(r.NewColor || '').trim(),
|
||||
NewDim2: String(r.NewDim2 || '').trim(),
|
||||
NewDesc: String(r.NewDesc || '').trim()
|
||||
}))
|
||||
)
|
||||
}
|
||||
|
||||
async function refreshAll () {
|
||||
@@ -327,22 +409,31 @@ async function refreshAll () {
|
||||
}
|
||||
|
||||
async function onRowSubmit (row) {
|
||||
const line = {
|
||||
OrderLineID: row.OrderLineID,
|
||||
const baseLine = {
|
||||
NewItemCode: String(row.NewItemCode || '').trim(),
|
||||
NewColor: String(row.NewColor || '').trim(),
|
||||
NewDim2: String(row.NewDim2 || '').trim(),
|
||||
NewDesc: String(row.NewDesc || '').trim()
|
||||
}
|
||||
|
||||
if (!line.NewItemCode || !line.NewColor) {
|
||||
if (!baseLine.NewItemCode || !baseLine.NewColor) {
|
||||
$q.notify({ type: 'negative', message: 'Yeni urun ve renk zorunludur.' })
|
||||
return
|
||||
}
|
||||
|
||||
rowSavingId.value = row.OrderLineID
|
||||
const lines = (row.OrderLineIDs || []).map(id => ({
|
||||
OrderLineID: id,
|
||||
...baseLine
|
||||
}))
|
||||
|
||||
if (!lines.length) {
|
||||
$q.notify({ type: 'negative', message: 'Satir bulunamadi.' })
|
||||
return
|
||||
}
|
||||
|
||||
rowSavingId.value = row.RowKey
|
||||
try {
|
||||
const validate = await store.validateUpdates(orderHeaderID.value, [line])
|
||||
const validate = await store.validateUpdates(orderHeaderID.value, lines)
|
||||
const missingCount = validate?.missingCount || 0
|
||||
if (missingCount > 0) {
|
||||
const missingList = (validate?.missing || []).map(v => (
|
||||
@@ -355,13 +446,13 @@ async function onRowSubmit (row) {
|
||||
ok: { label: 'Ekle ve Guncelle', color: 'primary' },
|
||||
cancel: { label: 'Vazgec', flat: true }
|
||||
}).onOk(async () => {
|
||||
await store.applyUpdates(orderHeaderID.value, [line], true)
|
||||
await store.applyUpdates(orderHeaderID.value, lines, true)
|
||||
await store.fetchItems(orderHeaderID.value)
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
await store.applyUpdates(orderHeaderID.value, [line], false)
|
||||
await store.applyUpdates(orderHeaderID.value, lines, false)
|
||||
await store.fetchItems(orderHeaderID.value)
|
||||
} catch (err) {
|
||||
$q.notify({ type: 'negative', message: 'Islem basarisiz.' })
|
||||
|
||||
@@ -2684,17 +2684,18 @@ export const useOrderEntryStore = defineStore('orderentry', {
|
||||
// 🧪 PRE-VALIDATE — prItemVariant ön kontrol
|
||||
// - invalid varsa CREATE/UPDATE ÇALIŞMAZ
|
||||
// =======================================================
|
||||
const linesToValidate =
|
||||
isNew
|
||||
? lines
|
||||
: lines.filter(l => l._deleteSignal === true || l._dirty === true || !l.OrderLineID)
|
||||
if (!isNew) {
|
||||
const linesToValidate = lines.filter(
|
||||
l => l._deleteSignal === true || l._dirty === true || !l.OrderLineID
|
||||
)
|
||||
|
||||
const v = await api.post('/order/validate', { header, lines: linesToValidate })
|
||||
const invalid = v?.data?.invalid || []
|
||||
const v = await api.post('/order/validate', { header, lines: linesToValidate })
|
||||
const invalid = v?.data?.invalid || []
|
||||
|
||||
if (invalid.length > 0) {
|
||||
await this.showInvalidVariantDialog?.($q, invalid)
|
||||
return // ❌ create / update ÇALIŞMAZ
|
||||
if (invalid.length > 0) {
|
||||
await this.showInvalidVariantDialog?.($q, invalid)
|
||||
return // ❌ update ÇALIŞMAZ
|
||||
}
|
||||
}
|
||||
|
||||
console.log('📤 submitAllReal payload', {
|
||||
|
||||
Reference in New Issue
Block a user