Fix product performance grouped JSON build
This commit is contained in:
@@ -3525,6 +3525,7 @@ function shouldAverageField (field) {
|
||||
}
|
||||
|
||||
function weightFieldForMetric (field) {
|
||||
if (field.startsWith('stock_turnover')) return `sales_qty_${countPeriodSuffix(field)}`
|
||||
if (field.includes('_180d')) return 'sales_qty_180d'
|
||||
if (field.includes('_365d')) return 'sales_qty_365d'
|
||||
if (field.includes('_total')) return 'sales_qty_total'
|
||||
@@ -3538,6 +3539,7 @@ function applyDerivedGroupMetrics (out, sourceRows, groupField = '') {
|
||||
const isGroup = Boolean(String(groupField || '').trim())
|
||||
const preservedCustomerScores = {}
|
||||
const preservedProductScores = {}
|
||||
const preservedStockTurnovers = {}
|
||||
for (const suffix of ['90d', '180d', '365d', 'total']) {
|
||||
if (Object.prototype.hasOwnProperty.call(out, `customer_score_${suffix}`)) {
|
||||
preservedCustomerScores[suffix] = Number(out[`customer_score_${suffix}`] || 0)
|
||||
@@ -3545,6 +3547,9 @@ function applyDerivedGroupMetrics (out, sourceRows, groupField = '') {
|
||||
if (Object.prototype.hasOwnProperty.call(out, `performance_score_${suffix}`)) {
|
||||
preservedProductScores[suffix] = Number(out[`performance_score_${suffix}`] || 0)
|
||||
}
|
||||
if (isGroup && Object.prototype.hasOwnProperty.call(out, `stock_turnover_${suffix}`)) {
|
||||
preservedStockTurnovers[suffix] = Number(out[`stock_turnover_${suffix}`] || 0)
|
||||
}
|
||||
}
|
||||
if (
|
||||
Object.prototype.hasOwnProperty.call(out, 'performance_score') &&
|
||||
@@ -3565,6 +3570,9 @@ function applyDerivedGroupMetrics (out, sourceRows, groupField = '') {
|
||||
else if (qty <= 0 && stockQty > 0) out[`stock_days_${suffix}`] = 9999
|
||||
else if (!Object.prototype.hasOwnProperty.call(out, `stock_days_${suffix}`)) out[`stock_days_${suffix}`] = 0
|
||||
out[`stock_turnover_${suffix}`] = annualizedStockTurnover(qty, turnoverBase, days)
|
||||
if (Object.prototype.hasOwnProperty.call(preservedStockTurnovers, suffix)) {
|
||||
out[`stock_turnover_${suffix}`] = preservedStockTurnovers[suffix]
|
||||
}
|
||||
if (qty > 0) out[`avg_price_usd_${suffix}`] = sales / qty
|
||||
const { costPrice, basePrice } = periodCostPair(out, suffix)
|
||||
out[`base_price_usd_${suffix}`] = basePrice
|
||||
@@ -3917,6 +3925,12 @@ function distinctRevenueMarketCount (sourceRows, suffix, fallbackField) {
|
||||
const values = new Set()
|
||||
for (const row of sourceRows) {
|
||||
if (Number(row?.[salesField] || 0) <= 0) continue
|
||||
const marketKeys = stringListFromRow(row, `__market_keys_${suffix}`)
|
||||
for (const key of marketKeys) {
|
||||
const value = displayMarketName(key)
|
||||
if (value && value !== 'STOK' && value !== '-') values.add(value)
|
||||
}
|
||||
if (marketKeys.length > 0) continue
|
||||
const value = displayMarketName(row?.market_key)
|
||||
if (value && value !== 'STOK' && value !== '-') values.add(value)
|
||||
}
|
||||
@@ -3931,6 +3945,11 @@ function distinctRevenueCustomerCount (sourceRows, suffix, fallbackField) {
|
||||
const values = new Set()
|
||||
for (const row of sourceRows) {
|
||||
if (Number(row?.[salesField] || 0) <= 0) continue
|
||||
const customerKeys = stringListFromRow(row, `__customer_keys_${suffix}`)
|
||||
for (const code of customerKeys) {
|
||||
if (code && code !== '-') values.add(code)
|
||||
}
|
||||
if (customerKeys.length > 0) continue
|
||||
const code = String(row?.customer_code || '').trim()
|
||||
if (code && code !== '-') values.add(code)
|
||||
}
|
||||
@@ -3940,6 +3959,22 @@ function distinctRevenueCustomerCount (sourceRows, suffix, fallbackField) {
|
||||
}, 0)
|
||||
}
|
||||
|
||||
function stringListFromRow (row, field) {
|
||||
const value = row?.[field]
|
||||
if (Array.isArray(value)) return value.map(item => String(item || '').trim()).filter(Boolean)
|
||||
const text = String(value || '').trim()
|
||||
if (!text) return []
|
||||
if (text.startsWith('[')) {
|
||||
try {
|
||||
const parsed = JSON.parse(text)
|
||||
return Array.isArray(parsed) ? parsed.map(item => String(item || '').trim()).filter(Boolean) : []
|
||||
} catch {
|
||||
return []
|
||||
}
|
||||
}
|
||||
return [text]
|
||||
}
|
||||
|
||||
function distinctSummary (sourceRows, field, fallbackField) {
|
||||
const values = new Set()
|
||||
for (const row of sourceRows) {
|
||||
@@ -4351,9 +4386,10 @@ function groupedOrExistingStockTurnover (row, suffix, periodDays) {
|
||||
const avgStock = Number(row?.[`avg_stock_${suffix}`] || 0)
|
||||
const stockQty = Number(row?.stock_qty || 0)
|
||||
if (row?.__group) {
|
||||
if (avgStock > 0) return stockTurnover(salesQty, avgStock, periodDays)
|
||||
const current = Number(row?.[`stock_turnover_${suffix}`])
|
||||
return Number.isFinite(current) ? current : 0
|
||||
if (Number.isFinite(current)) return current
|
||||
if (avgStock > 0) return stockTurnover(salesQty, avgStock, periodDays)
|
||||
return 0
|
||||
}
|
||||
const stockBase = avgStock > 0 ? avgStock : stockQty
|
||||
return existingOrStockTurnover(row?.[`stock_turnover_${suffix}`], salesQty, stockBase, periodDays)
|
||||
|
||||
Reference in New Issue
Block a user