Merge remote-tracking branch 'origin/master'

This commit is contained in:
M_Kececi
2026-02-20 17:47:10 +03:00
parent 66df9b0f10
commit ac55f5a96c
3 changed files with 125 additions and 33 deletions

View File

@@ -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.' })

View File

@@ -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', {