Merge remote-tracking branch 'origin/master'

This commit is contained in:
M_Kececi
2026-06-04 18:23:23 +03:00
parent 5b8880693e
commit e1e9d4baf1

View File

@@ -292,7 +292,7 @@
<script setup>
import { computed, onActivated, onBeforeUnmount, onMounted, ref } from 'vue'
import { Notify } from 'quasar'
import { Dialog, Notify } from 'quasar'
import api, { download } from 'src/services/api'
import { usePermissionStore } from 'stores/permissionStore'
@@ -539,6 +539,7 @@ const selectedDirtyCount = computed(() => rows.value.reduce((count, row) => coun
const selectedCount = computed(() => Object.keys(selectedKeyMap.value || {}).length)
const copySelectedCount = computed(() => copySelectedKeys.value.length)
const canCopySelected = computed(() => copySelectedCount.value >= 2)
const hasUnsavedLocalChanges = computed(() => rows.value.some(row => Boolean(row?._dirty)))
const hasAnyFilter = computed(() => {
return [...headerFilterFieldSet].some(field => hasFilter(field))
})
@@ -878,7 +879,10 @@ async function onImportFileChange (event) {
return
}
const importItems = []
const rowMap = new Map(rows.value.map(row => [buildImportRowKeyFromObject(row), row]))
let matched = 0
let updated = 0
let skipped = 0
for (let i = 1; i < matrix.length; i++) {
const csvRow = matrix[i]
@@ -887,10 +891,14 @@ async function onImportFileChange (event) {
identity[field] = String(csvRow[keyHeaderIndexes[label]] ?? '').trim().replace(/^'/, '').replace(/^=\s*"([\s\S]*)"$/, '$1')
}
const item = {
...identity,
is_active: true
const target = rowMap.get(buildImportRowKeyFromObject(identity))
if (!target) {
skipped++
continue
}
matched++
let rowChanged = false
for (const [headerLabel, field] of Object.entries(importFieldMap)) {
const idx = headers.indexOf(headerLabel)
if (idx < 0) continue
@@ -898,33 +906,34 @@ async function onImportFileChange (event) {
if (field === 'is_active') {
const next = parseImportedBoolean(rawValue)
if (next !== null) item.is_active = next
if (next !== null && Boolean(target.is_active) !== next) {
target.is_active = next
rowChanged = true
}
continue
}
item[field] = parseImportedNumber(rawValue)
const next = parseImportedNumber(rawValue)
if (Number(target[field] ?? 0) !== next) {
target[field] = next
rowChanged = true
}
importItems.push(item)
}
if (importItems.length === 0) {
Notify.create({ type: 'warning', message: 'CSV icinde islenecek satir bulunamadi' })
if (rowChanged) {
markDirty(target)
updated++
}
}
if (matched === 0) {
Notify.create({ type: 'warning', message: 'CSV icindeki satirlar ekrandaki kayitlarla eslesmedi' })
return
}
const response = await api.request({
method: 'POST',
url: '/pricing/pricing-rules/import',
data: { items: importItems },
timeout: 180000
})
await loadRows()
const stats = response?.data || {}
Notify.create({
type: 'positive',
message: `CSV yuklendi. Islenen: ${stats.processed ?? importItems.length}, eslesen: ${stats.matched ?? stats.updated ?? importItems.length}, kaydedilen: ${stats.updated ?? importItems.length}, atlanan: ${stats.skipped ?? 0}, hata: ${stats.error_count ?? 0}`
message: `CSV yuklendi. Islenen: ${matrix.length - 1}, eslesen: ${matched}, guncellenen: ${updated}, atlanan: ${skipped}`
})
} catch (err) {
Notify.create({ type: 'negative', message: err?.message || 'CSV okunamadi' })
@@ -1031,6 +1040,21 @@ function clearAllFilters () {
}
async function refreshRows () {
if (hasUnsavedLocalChanges.value) {
const confirmed = await new Promise(resolve => {
Dialog.create({
title: 'Degisiklikler silinecek',
message: 'Kaydedilmemis tum degisiklikler silinecek. Devam etmek istiyor musunuz?',
cancel: true,
persistent: true
})
.onOk(() => resolve(true))
.onCancel(() => resolve(false))
.onDismiss(() => resolve(false))
})
if (!confirmed) return
}
clearAllFilters()
selectedKeyMap.value = {}
copySelectedKeys.value = []