product performance grouped kpi improvements
This commit is contained in:
@@ -1390,12 +1390,13 @@
|
||||
flat
|
||||
bordered
|
||||
dense
|
||||
class="dialog-detail-table"
|
||||
title="Satış / Müşteri Özeti"
|
||||
row-key="detail_key"
|
||||
:rows="detailSalesRows"
|
||||
:columns="detailSalesColumns"
|
||||
:loading="detailLoading"
|
||||
:pagination="{ rowsPerPage: 50 }"
|
||||
:pagination="{ rowsPerPage: 0, sortBy: 'sales_usd', descending: true }"
|
||||
/>
|
||||
</section>
|
||||
</div>
|
||||
@@ -1431,12 +1432,13 @@
|
||||
flat
|
||||
bordered
|
||||
dense
|
||||
class="dialog-stock-table"
|
||||
title="Beden Stok"
|
||||
row-key="size_code"
|
||||
:rows="detailStockSizes"
|
||||
:columns="detailStockColumns"
|
||||
:loading="detailLoading"
|
||||
:pagination="{ rowsPerPage: 50 }"
|
||||
:pagination="{ rowsPerPage: 0 }"
|
||||
virtual-scroll
|
||||
:virtual-scroll-item-size="48"
|
||||
/>
|
||||
@@ -1446,12 +1448,13 @@
|
||||
flat
|
||||
bordered
|
||||
dense
|
||||
class="dialog-detail-table"
|
||||
title="Satış / Müşteri Özeti"
|
||||
row-key="detail_key"
|
||||
:rows="detailSalesRows"
|
||||
:columns="detailSalesColumns"
|
||||
:loading="detailLoading"
|
||||
:pagination="{ rowsPerPage: 50 }"
|
||||
:pagination="{ rowsPerPage: 0, sortBy: 'sales_usd', descending: true }"
|
||||
virtual-scroll
|
||||
:virtual-scroll-item-size="48"
|
||||
/>
|
||||
@@ -2304,7 +2307,7 @@ const imageDialogInfoRows = computed(() => {
|
||||
{ key: 'color', label: 'Renk', value: colorCode || '-' },
|
||||
{ key: 'yaka', label: 'Yaka', value: yakaCode || '-' },
|
||||
{ key: 'category', label: 'Kategori', value: productCategoryValue(row) || '-' },
|
||||
{ key: 'hanger', label: 'Askılı/Yan', value: row.askili_yan || '-' },
|
||||
{ key: 'hanger', label: 'Askılı/Yan', value: cleanOptionalGroupValue(row.askili_yan) },
|
||||
{ key: 'first', label: 'İlk Grup', value: productFirstGroupValue(row) || '-' },
|
||||
{ key: 'main', label: 'Ana Grup', value: productMainGroupValue(row) || '-' },
|
||||
{ key: 'sub', label: 'Alt Grup', value: row.urun_alt_grubu || '-' },
|
||||
@@ -2539,6 +2542,10 @@ const allProductGroupsExpanded = computed(() => {
|
||||
})
|
||||
|
||||
function appendGroupRows (out, sourceRows, level, parentKeys, levels = groupLevels) {
|
||||
appendGroupRowsAt(out, sourceRows, level, 0, parentKeys, levels)
|
||||
}
|
||||
|
||||
function appendGroupRowsAt (out, sourceRows, level, visualLevel, parentKeys, levels = groupLevels) {
|
||||
if (level >= levels.length) {
|
||||
out.push(...sortProductLeafRows(sourceRows))
|
||||
return
|
||||
@@ -2555,10 +2562,14 @@ function appendGroupRows (out, sourceRows, level, parentKeys, levels = groupLeve
|
||||
Array.from(grouped.entries())
|
||||
.sort((a, b) => a[0].localeCompare(b[0], 'tr'))
|
||||
.forEach(([value, groupRows]) => {
|
||||
if (shouldSkipGroupValue(groupDef.key, value)) {
|
||||
appendGroupRowsAt(out, groupRows, level + 1, visualLevel, parentKeys, levels)
|
||||
return
|
||||
}
|
||||
const key = [...parentKeys, `${groupDef.key}:${value}`].join('|')
|
||||
out.push(makeGroupRow(key, level, groupDef, value, groupRows))
|
||||
out.push(makeGroupRow(key, visualLevel, groupDef, value, groupRows))
|
||||
if (isGroupExpanded(key)) {
|
||||
appendGroupRows(out, groupRows, level + 1, [...parentKeys, `${groupDef.key}:${value}`], levels)
|
||||
appendGroupRowsAt(out, groupRows, level + 1, visualLevel + 1, [...parentKeys, `${groupDef.key}:${value}`], levels)
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -2592,6 +2603,10 @@ function collectGroupKeys (out, sourceRows, level, parentKeys, levels = groupLev
|
||||
.sort((a, b) => a[0].localeCompare(b[0], 'tr'))
|
||||
.forEach(([value, groupRows]) => {
|
||||
if (out.length >= maxBulkExpandKeys) return
|
||||
if (shouldSkipGroupValue(groupDef.key, value)) {
|
||||
collectGroupKeys(out, groupRows, level + 1, parentKeys, levels, maxLevel)
|
||||
return
|
||||
}
|
||||
const key = [...parentKeys, `${groupDef.key}:${value}`].join('|')
|
||||
out.push(key)
|
||||
if (level < maxLevel) {
|
||||
@@ -3001,6 +3016,13 @@ function normalizeGroupValue (value) {
|
||||
return String(value || '').trim()
|
||||
}
|
||||
|
||||
function shouldSkipGroupValue (field, value) {
|
||||
const text = String(value || '').trim()
|
||||
if (field === 'urun_ilk_grubu') return !text || text === '-'
|
||||
if (field === 'askili_yan') return !text || text === '-'
|
||||
return false
|
||||
}
|
||||
|
||||
function isGroupExpanded (key) {
|
||||
return expandedGroups.value[key] === true
|
||||
}
|
||||
@@ -3230,8 +3252,14 @@ function productMainGroupValue (row) {
|
||||
return row?.urun_ana_grubu || ''
|
||||
}
|
||||
|
||||
function cleanOptionalGroupValue (value) {
|
||||
const text = String(value || '').trim()
|
||||
return text === '-' ? '' : text
|
||||
}
|
||||
|
||||
function cleanProductFirstGroupValue (value) {
|
||||
const text = String(value || '').trim()
|
||||
if (text === '-') return ''
|
||||
const normalized = text
|
||||
.toLocaleUpperCase('tr-TR')
|
||||
.replaceAll('İ', 'I')
|
||||
@@ -3247,6 +3275,7 @@ function rawProductCellValue (row, name) {
|
||||
switch (name) {
|
||||
case 'kategori': return productCategoryValue(row)
|
||||
case 'urun_ilk_grubu': return productFirstGroupValue(row)
|
||||
case 'askili_yan': return cleanOptionalGroupValue(row?.askili_yan)
|
||||
case 'urun_ana_grubu': return productMainGroupValue(row)
|
||||
case 'market_key': return displayMarketName(row.market_key)
|
||||
case 'performance_bucket': return bucketLabel(row.performance_bucket)
|
||||
@@ -3259,6 +3288,7 @@ function rawColumnCellValue (row, col) {
|
||||
switch (name) {
|
||||
case 'kategori': return productCategoryValue(row)
|
||||
case 'urun_ilk_grubu': return productFirstGroupValue(row)
|
||||
case 'askili_yan': return cleanOptionalGroupValue(row?.askili_yan)
|
||||
case 'urun_ana_grubu': return productMainGroupValue(row)
|
||||
case 'market_key': return displayMarketName(row.market_key)
|
||||
case 'performance_bucket': return bucketLabel(row.performance_bucket)
|
||||
@@ -3743,13 +3773,13 @@ async function loadProductDetailRows (row) {
|
||||
}
|
||||
if (!params.product_code) return
|
||||
const [salesResp, stockResp] = await Promise.all([
|
||||
api.get('/pricing/product-performance/sales-details', { params: { ...params, limit: 200 }, timeout: 60000 }),
|
||||
api.get('/pricing/product-performance/sales-details', { params: { ...params, limit: 500 }, timeout: 60000 }),
|
||||
api.get('/pricing/product-performance/stock-sizes', { params, timeout: 60000 })
|
||||
])
|
||||
detailSalesRows.value = (Array.isArray(salesResp?.data) ? salesResp.data : []).map((item, idx) => ({
|
||||
...item,
|
||||
detail_key: `${item.sales_date}|${item.ref_number}|${item.customer_code}|${idx}`
|
||||
}))
|
||||
})).sort((a, b) => Number(b.sales_usd || 0) - Number(a.sales_usd || 0))
|
||||
detailStockSizes.value = Array.isArray(stockResp?.data) ? stockResp.data : []
|
||||
} catch (err) {
|
||||
Notify.create({ type: 'negative', message: err?.response?.data || err?.message || 'Ürün detay analizi alınamadı' })
|
||||
@@ -4884,6 +4914,103 @@ onMounted(reload)
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.product-performance-dialog {
|
||||
background: #f6f7f9;
|
||||
}
|
||||
|
||||
.product-performance-dialog :deep(.q-table__container),
|
||||
.product-image-dialog :deep(.q-table__container) {
|
||||
width: 100%;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.product-performance-dialog :deep(.q-table__middle),
|
||||
.product-image-dialog :deep(.q-table__middle) {
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.dialog-detail-table,
|
||||
.dialog-stock-table {
|
||||
width: 100%;
|
||||
min-width: 0;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
.dialog-detail-table :deep(.q-table),
|
||||
.dialog-stock-table :deep(.q-table) {
|
||||
width: 100%;
|
||||
table-layout: fixed;
|
||||
}
|
||||
|
||||
.dialog-detail-table :deep(.q-table th),
|
||||
.dialog-detail-table :deep(.q-table td),
|
||||
.dialog-stock-table :deep(.q-table th),
|
||||
.dialog-stock-table :deep(.q-table td) {
|
||||
padding: 4px 5px;
|
||||
white-space: normal;
|
||||
overflow-wrap: anywhere;
|
||||
word-break: break-word;
|
||||
line-height: 1.18;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.dialog-detail-table :deep(.q-table th) {
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
.dialog-detail-table :deep(.q-table th:nth-child(1)),
|
||||
.dialog-detail-table :deep(.q-table td:nth-child(1)) {
|
||||
width: 9%;
|
||||
}
|
||||
|
||||
.dialog-detail-table :deep(.q-table th:nth-child(2)),
|
||||
.dialog-detail-table :deep(.q-table td:nth-child(2)) {
|
||||
width: 12%;
|
||||
}
|
||||
|
||||
.dialog-detail-table :deep(.q-table th:nth-child(3)),
|
||||
.dialog-detail-table :deep(.q-table td:nth-child(3)) {
|
||||
width: 11%;
|
||||
}
|
||||
|
||||
.dialog-detail-table :deep(.q-table th:nth-child(4)),
|
||||
.dialog-detail-table :deep(.q-table td:nth-child(4)) {
|
||||
width: 9%;
|
||||
}
|
||||
|
||||
.dialog-detail-table :deep(.q-table th:nth-child(5)),
|
||||
.dialog-detail-table :deep(.q-table td:nth-child(5)) {
|
||||
width: 12%;
|
||||
}
|
||||
|
||||
.dialog-detail-table :deep(.q-table th:nth-child(6)),
|
||||
.dialog-detail-table :deep(.q-table td:nth-child(6)) {
|
||||
width: 23%;
|
||||
}
|
||||
|
||||
.dialog-detail-table :deep(.q-table th:nth-child(7)),
|
||||
.dialog-detail-table :deep(.q-table td:nth-child(7)),
|
||||
.dialog-detail-table :deep(.q-table th:nth-child(8)),
|
||||
.dialog-detail-table :deep(.q-table td:nth-child(8)),
|
||||
.dialog-detail-table :deep(.q-table th:nth-child(9)),
|
||||
.dialog-detail-table :deep(.q-table td:nth-child(9)) {
|
||||
width: 8%;
|
||||
white-space: nowrap;
|
||||
overflow-wrap: normal;
|
||||
word-break: normal;
|
||||
}
|
||||
|
||||
.dialog-stock-table :deep(.q-table th:nth-child(1)),
|
||||
.dialog-stock-table :deep(.q-table td:nth-child(1)) {
|
||||
width: 58%;
|
||||
}
|
||||
|
||||
.dialog-stock-table :deep(.q-table th:nth-child(2)),
|
||||
.dialog-stock-table :deep(.q-table td:nth-child(2)) {
|
||||
width: 42%;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
@media (max-width: 1260px) {
|
||||
.product-image-dialog-body {
|
||||
overflow: auto;
|
||||
|
||||
Reference in New Issue
Block a user