const { outputProgress } = require('./utils/progress'); const { getConnection } = require('./utils/db'); async function calculateFinancialMetrics(startTime, totalProducts, processedCount) { const connection = await getConnection(); try { outputProgress({ status: 'running', operation: 'Calculating financial metrics', current: Math.floor(totalProducts * 0.6), total: totalProducts, elapsed: formatElapsedTime(startTime), remaining: estimateRemaining(startTime, Math.floor(totalProducts * 0.6), totalProducts), rate: calculateRate(startTime, Math.floor(totalProducts * 0.6)), percentage: '60' }); await connection.query(` UPDATE product_metrics pm JOIN ( SELECT p.pid, p.cost_price * p.stock_quantity as inventory_value, SUM(o.quantity * o.price) as total_revenue, SUM(o.quantity * p.cost_price) as cost_of_goods_sold, SUM(o.quantity * (o.price - p.cost_price)) as gross_profit, MIN(o.date) as first_sale_date, MAX(o.date) as last_sale_date, DATEDIFF(MAX(o.date), MIN(o.date)) + 1 as calculation_period_days FROM products p LEFT JOIN orders o ON p.pid = o.pid WHERE o.canceled = false AND DATE(o.date) >= DATE_SUB(CURDATE(), INTERVAL 12 MONTH) GROUP BY p.pid ) fin ON pm.pid = fin.pid SET pm.inventory_value = COALESCE(fin.inventory_value, 0), pm.total_revenue = COALESCE(fin.total_revenue, 0), pm.cost_of_goods_sold = COALESCE(fin.cost_of_goods_sold, 0), pm.gross_profit = COALESCE(fin.gross_profit, 0), pm.gmroi = CASE WHEN COALESCE(fin.inventory_value, 0) > 0 AND fin.calculation_period_days > 0 THEN (COALESCE(fin.gross_profit, 0) * (365.0 / fin.calculation_period_days)) / COALESCE(fin.inventory_value, 0) ELSE 0 END `); // Update time-based aggregates with financial metrics await connection.query(` UPDATE product_time_aggregates pta JOIN ( SELECT p.pid, YEAR(o.date) as year, MONTH(o.date) as month, p.cost_price * p.stock_quantity as inventory_value, SUM(o.quantity * (o.price - p.cost_price)) as gross_profit, COUNT(DISTINCT DATE(o.date)) as days_in_period FROM products p LEFT JOIN orders o ON p.pid = o.pid WHERE o.canceled = false GROUP BY p.pid, YEAR(o.date), MONTH(o.date) ) fin ON pta.pid = fin.pid AND pta.year = fin.year AND pta.month = fin.month SET pta.inventory_value = COALESCE(fin.inventory_value, 0), pta.gmroi = CASE WHEN COALESCE(fin.inventory_value, 0) > 0 AND fin.days_in_period > 0 THEN (COALESCE(fin.gross_profit, 0) * (365.0 / fin.days_in_period)) / COALESCE(fin.inventory_value, 0) ELSE 0 END `); return Math.floor(totalProducts * 0.7); } finally { connection.release(); } } module.exports = calculateFinancialMetrics;