Fix product performance grouped JSON build
This commit is contained in:
@@ -1850,7 +1850,6 @@ const columns = [
|
||||
{ name: 'customer_count_total', label: 'Genel Müşteri', field: row => formatNumber(row.customer_count_total, 0), align: 'right', sortable: true },
|
||||
{ name: 'sales_index_90d', label: 'Piyasa End.', field: row => formatNumber(row.sales_index_90d, 2), align: 'right', sortable: true },
|
||||
{ name: 'sales_index_total', label: 'Genel Endeks', field: row => formatNumber(row.sales_index_total, 2), align: 'right', sortable: true },
|
||||
{ name: 'performance_score', label: 'Skor', field: row => formatNumber(row.performance_score, 2), align: 'right', sortable: true },
|
||||
{ name: 'performance_bucket', label: 'Durum', field: 'performance_bucket', align: 'left' },
|
||||
{ name: 'recommendation', label: 'Öneri', field: 'recommendation', align: 'left' }
|
||||
]
|
||||
@@ -2085,7 +2084,7 @@ const generalColumns = [
|
||||
{ name: 'customer_count_total', label: 'Toplam Müşteri', field: row => formatNumber(row.customer_count_total, 0), align: 'right', sortable: true },
|
||||
{ name: 'invoice_count_total', label: 'Fatura', field: row => formatNumber(row.invoice_count_total, 0), align: 'right', sortable: true },
|
||||
{ name: 'sales_index_total', label: 'Genel Endeks', field: row => formatNumber(row.sales_index_total, 2), align: 'right', sortable: true },
|
||||
{ name: 'performance_score', label: 'Genel Skor', field: row => formatNumber(row.performance_score, 2), align: 'right', sortable: true },
|
||||
{ name: 'performance_score_total', label: 'Genel Skor', field: row => formatNumber(row.performance_score_total ?? row.performance_score, 2), align: 'right', sortable: true },
|
||||
{ name: 'performance_bucket', label: 'Durum', field: 'performance_bucket', align: 'left', sortable: true },
|
||||
{ name: 'first_sale_date', label: 'İlk Satış', field: 'first_sale_date', align: 'left', sortable: true },
|
||||
{ name: 'last_sale_date', label: 'Son Satış', field: 'last_sale_date', align: 'left', sortable: true },
|
||||
@@ -2355,7 +2354,6 @@ const salesBreakdownColumns = [
|
||||
{ name: 'gross_margin_cost_total', label: 'Genel Çıplak Marj', field: row => formatPercent(row.gross_margin_cost_total), align: 'right', sortable: true },
|
||||
{ name: 'customer_score_total', label: 'Genel Müşteri Skor', field: row => formatNumber(row.customer_score_total, 2), align: 'right', sortable: true },
|
||||
{ name: 'sales_index_90d', label: 'Endeks', field: row => formatNumber(row.sales_index_90d, 2), align: 'right', sortable: true },
|
||||
{ name: 'performance_score', label: 'Skor', field: row => formatNumber(row.performance_score, 2), align: 'right', sortable: true },
|
||||
{ name: 'performance_bucket', label: 'Durum', field: 'performance_bucket', align: 'left', sortable: true },
|
||||
{ name: 'last_sale_date', label: 'Son Satış', field: 'last_sale_date', align: 'left', sortable: true },
|
||||
{ name: 'recommendation', label: 'Öneri', field: 'recommendation', align: 'left' }
|
||||
@@ -2427,7 +2425,6 @@ const metricLabelOverrides = {
|
||||
gross_margin_cost_365d: '360G Çıplak Marj',
|
||||
gross_margin_base_total: 'Genel Taban Marj',
|
||||
gross_margin_cost_total: 'Genel Çıplak Marj',
|
||||
performance_score: 'Skor',
|
||||
performance_score_90d: '90G Ürün Skor',
|
||||
performance_score_180d: '180G Ürün Skor',
|
||||
performance_score_365d: '360G Ürün Skor',
|
||||
@@ -2666,7 +2663,10 @@ const visibleOrderAnalysisColumns = computed(() => {
|
||||
function performanceCardsForRow (row) {
|
||||
const source = row || {}
|
||||
return [
|
||||
{ key: 'score', label: 'Skor', value: formatNumber(source.performance_score, 2) },
|
||||
{ key: 'score90', label: '90G Skor', value: formatNumber(source.performance_score_90d ?? source.performance_score, 2) },
|
||||
{ key: 'score180', label: '180G Skor', value: formatNumber(source.performance_score_180d, 2) },
|
||||
{ key: 'score360', label: '360G Skor', value: formatNumber(source.performance_score_365d, 2) },
|
||||
{ key: 'scoreTotal', label: 'Genel Skor', value: formatNumber(source.performance_score_total ?? source.performance_score, 2) },
|
||||
{ key: 'stock', label: 'Stok', value: formatNumber(source.stock_qty, 0) },
|
||||
{ key: 'sales90', label: '90G Satış', value: formatNumber(source.sales_qty_90d, 0) },
|
||||
{ key: 'sales180', label: '180G Satış', value: formatNumber(source.sales_qty_180d, 0) },
|
||||
@@ -3285,6 +3285,9 @@ function compareGroupedBucketsForTable (tableKey, left, right, groupDef) {
|
||||
|
||||
function groupedBucketSortValue (sourceRows, sortBy) {
|
||||
if (!sourceRows?.length) return 0
|
||||
if (shouldUseDerivedGroupSortValue(sortBy)) {
|
||||
return sortValueForColumnName(aggregateGroupFields(sourceRows), sortBy)
|
||||
}
|
||||
if (sortBy === 'stock_qty') return distinctVariantStockQty(sourceRows)
|
||||
if (sortBy === 'idle_cost_usd') return distinctVariantStockCost(sourceRows)
|
||||
if (sortBy === 'base_price_usd' || sortBy === 'cost_price_usd') return weightedAverageProductCost(sourceRows, sortBy)
|
||||
@@ -3293,6 +3296,10 @@ function groupedBucketSortValue (sourceRows, sortBy) {
|
||||
return sortValueForColumnName(sourceRows[0], sortBy)
|
||||
}
|
||||
|
||||
function shouldUseDerivedGroupSortValue (sortBy) {
|
||||
return /^(performance_score|stock_turnover|stock_days|avg_price_usd|unit_profit|gross_profit|gross_margin|market_count|customer_count|sales_index)/i.test(String(sortBy || ''))
|
||||
}
|
||||
|
||||
function sortProductGroupedTableRows (tableRows, sortBy, descending) {
|
||||
const source = Array.isArray(tableRows) ? tableRows : []
|
||||
if (backendGroupedSupportedTab(activeTab.value)) return source
|
||||
@@ -3528,15 +3535,8 @@ function weightFieldForMetric (field) {
|
||||
|
||||
function applyDerivedGroupMetrics (out, sourceRows, groupField = '') {
|
||||
Object.assign(out, normalizeProductCostFields(out))
|
||||
const preservedPerformanceScores = {}
|
||||
if (Object.prototype.hasOwnProperty.call(out, 'performance_score')) {
|
||||
preservedPerformanceScores['90d'] = Number(out.performance_score || 0)
|
||||
}
|
||||
const preservedCustomerScores = {}
|
||||
for (const suffix of ['90d', '180d', '365d', 'total']) {
|
||||
if (Object.prototype.hasOwnProperty.call(out, `performance_score_${suffix}`)) {
|
||||
preservedPerformanceScores[suffix] = Number(out[`performance_score_${suffix}`] || 0)
|
||||
}
|
||||
if (Object.prototype.hasOwnProperty.call(out, `customer_score_${suffix}`)) {
|
||||
preservedCustomerScores[suffix] = Number(out[`customer_score_${suffix}`] || 0)
|
||||
}
|
||||
@@ -3596,9 +3596,7 @@ function applyDerivedGroupMetrics (out, sourceRows, groupField = '') {
|
||||
out[`customer_score_${suffix}`] = Object.prototype.hasOwnProperty.call(preservedCustomerScores, suffix)
|
||||
? preservedCustomerScores[suffix]
|
||||
: customerSalesPeriodScore(periodMetricSource(out, suffix))
|
||||
out[`performance_score_${suffix}`] = Object.prototype.hasOwnProperty.call(preservedPerformanceScores, suffix)
|
||||
? preservedPerformanceScores[suffix]
|
||||
: productSalesPeriodScore(productPeriodMetricSource(out, suffix))
|
||||
out[`performance_score_${suffix}`] = productSalesPeriodScore(productPeriodMetricSource(out, suffix))
|
||||
}
|
||||
out.performance_score = Number(out.performance_score_90d || 0)
|
||||
}
|
||||
@@ -3707,8 +3705,8 @@ function productScore100 ({ suffix = '90d', salesUSD = 0, margin = 0, stockTurno
|
||||
0.30 * marginScore(margin) +
|
||||
0.20 * ratioScore(stockTurnover, stockTurnoverTarget(suffix)) +
|
||||
0.20 * revenue +
|
||||
0.15 * ratioScore(marketCount, marketSpreadTarget(suffix)) +
|
||||
0.15 * ratioScore(customerCount, customerSpreadTarget(suffix))
|
||||
0.05 * ratioScore(marketCount, marketSpreadTarget(suffix)) +
|
||||
0.25 * ratioScore(customerCount, customerSpreadTarget(suffix))
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3777,16 +3775,16 @@ function stockTurnoverTarget () {
|
||||
|
||||
function marketSpreadTarget (suffix) {
|
||||
if (suffix === '90d') return 3
|
||||
if (suffix === '180d') return 5
|
||||
if (suffix === '180d') return 3
|
||||
if (suffix === '365d') return 6
|
||||
return 8
|
||||
return 6
|
||||
}
|
||||
|
||||
function customerSpreadTarget (suffix) {
|
||||
if (suffix === '90d') return 8
|
||||
if (suffix === '180d') return 15
|
||||
if (suffix === '365d') return 18
|
||||
return 25
|
||||
if (suffix === '180d') return 20
|
||||
if (suffix === '365d') return 50
|
||||
return 50
|
||||
}
|
||||
|
||||
function periodCount (row, prefix, suffix) {
|
||||
|
||||
Reference in New Issue
Block a user