Fix product performance grouped JSON build

This commit is contained in:
M_Kececi
2026-07-13 22:43:51 +03:00
parent b80b5024f4
commit 3e0253f6be
2 changed files with 112 additions and 15 deletions
@@ -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)