Fix initial errors in calculate metrics and get progress working in frontend
This commit is contained in:
@@ -43,15 +43,21 @@ function calculateRate(startTime, current) {
|
||||
|
||||
// Helper function to output progress
|
||||
function outputProgress(data) {
|
||||
process.stdout.write(JSON.stringify(data) + '\n');
|
||||
// Format as SSE event
|
||||
const event = {
|
||||
progress: data
|
||||
};
|
||||
process.stdout.write(JSON.stringify(event) + '\n');
|
||||
}
|
||||
|
||||
// Helper function to log errors
|
||||
function logError(error, context) {
|
||||
console.error(JSON.stringify({
|
||||
status: 'error',
|
||||
error: error.message || error,
|
||||
context
|
||||
progress: {
|
||||
status: 'error',
|
||||
error: error.message || error,
|
||||
context
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -71,15 +77,19 @@ let isCancelled = false;
|
||||
|
||||
function cancelCalculation() {
|
||||
isCancelled = true;
|
||||
process.stdout.write(JSON.stringify({
|
||||
status: 'cancelled',
|
||||
operation: 'Calculation cancelled',
|
||||
current: 0,
|
||||
total: 0,
|
||||
elapsed: null,
|
||||
remaining: null,
|
||||
rate: 0
|
||||
}) + '\n');
|
||||
// Format as SSE event
|
||||
const event = {
|
||||
progress: {
|
||||
status: 'cancelled',
|
||||
operation: 'Calculation cancelled',
|
||||
current: 0,
|
||||
total: 0,
|
||||
elapsed: null,
|
||||
remaining: null,
|
||||
rate: 0
|
||||
}
|
||||
};
|
||||
process.stdout.write(JSON.stringify(event) + '\n');
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
@@ -99,7 +109,7 @@ async function calculateMetrics() {
|
||||
const [countResult] = await connection.query('SELECT COUNT(*) as total FROM products');
|
||||
totalProducts = countResult[0].total;
|
||||
|
||||
// Initial progress
|
||||
// Initial progress with percentage
|
||||
outputProgress({
|
||||
status: 'running',
|
||||
operation: 'Processing products',
|
||||
@@ -107,7 +117,8 @@ async function calculateMetrics() {
|
||||
total: totalProducts,
|
||||
elapsed: '0s',
|
||||
remaining: 'Calculating...',
|
||||
rate: 0
|
||||
rate: 0,
|
||||
percentage: '0'
|
||||
});
|
||||
|
||||
// Process in batches of 100
|
||||
@@ -128,7 +139,8 @@ async function calculateMetrics() {
|
||||
total: totalProducts,
|
||||
elapsed: formatElapsedTime(startTime),
|
||||
remaining: estimateRemaining(startTime, processedCount, totalProducts),
|
||||
rate: calculateRate(startTime, processedCount)
|
||||
rate: calculateRate(startTime, processedCount),
|
||||
percentage: ((processedCount / totalProducts) * 100).toFixed(1)
|
||||
});
|
||||
|
||||
// Process the batch
|
||||
@@ -175,6 +187,14 @@ async function calculateMetrics() {
|
||||
const weekly_sales_avg = metrics.total_quantity_sold ? metrics.total_quantity_sold / 4 : 0;
|
||||
const monthly_sales_avg = metrics.total_quantity_sold || 0;
|
||||
|
||||
// Calculate margin percent with proper handling of edge cases
|
||||
let margin_percent = 0;
|
||||
if (metrics.total_revenue && metrics.total_revenue > 0) {
|
||||
margin_percent = ((metrics.total_revenue - metrics.total_cost) / metrics.total_revenue) * 100;
|
||||
// Handle -Infinity or Infinity cases
|
||||
margin_percent = isFinite(margin_percent) ? margin_percent : 0;
|
||||
}
|
||||
|
||||
// Update product metrics
|
||||
await connection.query(`
|
||||
INSERT INTO product_metrics (
|
||||
@@ -236,7 +256,7 @@ async function calculateMetrics() {
|
||||
weekly_sales_avg ? stock.stock_quantity / weekly_sales_avg : null,
|
||||
Math.ceil(daily_sales_avg * 14), // 14 days reorder point
|
||||
Math.ceil(daily_sales_avg * 7), // 7 days safety stock
|
||||
metrics.total_revenue ? ((metrics.total_revenue - metrics.total_cost) / metrics.total_revenue) * 100 : 0,
|
||||
margin_percent, // Use the properly handled margin percent
|
||||
metrics.total_revenue || 0,
|
||||
purchases.avg_lead_time_days || 0,
|
||||
purchases.last_purchase_date,
|
||||
@@ -257,7 +277,8 @@ async function calculateMetrics() {
|
||||
total: totalProducts,
|
||||
elapsed: formatElapsedTime(startTime),
|
||||
remaining: estimateRemaining(startTime, totalProducts, totalProducts),
|
||||
rate: calculateRate(startTime, totalProducts)
|
||||
rate: calculateRate(startTime, totalProducts),
|
||||
percentage: '100'
|
||||
});
|
||||
|
||||
// Calculate ABC classification
|
||||
@@ -288,7 +309,8 @@ async function calculateMetrics() {
|
||||
total: totalProducts,
|
||||
elapsed: formatElapsedTime(startTime),
|
||||
remaining: estimateRemaining(startTime, totalProducts, totalProducts),
|
||||
rate: calculateRate(startTime, totalProducts)
|
||||
rate: calculateRate(startTime, totalProducts),
|
||||
percentage: '100'
|
||||
});
|
||||
|
||||
// Calculate time-based aggregates
|
||||
@@ -386,7 +408,8 @@ async function calculateMetrics() {
|
||||
total: totalProducts,
|
||||
elapsed: formatElapsedTime(startTime),
|
||||
remaining: estimateRemaining(startTime, totalProducts, totalProducts),
|
||||
rate: calculateRate(startTime, totalProducts)
|
||||
rate: calculateRate(startTime, totalProducts),
|
||||
percentage: '100'
|
||||
});
|
||||
|
||||
// Calculate vendor metrics
|
||||
@@ -428,7 +451,8 @@ async function calculateMetrics() {
|
||||
total: totalProducts,
|
||||
elapsed: formatElapsedTime(startTime),
|
||||
remaining: '0s',
|
||||
rate: calculateRate(startTime, totalProducts)
|
||||
rate: calculateRate(startTime, totalProducts),
|
||||
percentage: '100'
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
@@ -440,7 +464,8 @@ async function calculateMetrics() {
|
||||
total: totalProducts || 0, // Use 0 if not yet defined
|
||||
elapsed: formatElapsedTime(startTime),
|
||||
remaining: null,
|
||||
rate: calculateRate(startTime, processedCount)
|
||||
rate: calculateRate(startTime, processedCount),
|
||||
percentage: ((processedCount / (totalProducts || 1)) * 100).toFixed(1)
|
||||
});
|
||||
} else {
|
||||
outputProgress({
|
||||
@@ -450,7 +475,8 @@ async function calculateMetrics() {
|
||||
total: totalProducts || 0, // Use 0 if not yet defined
|
||||
elapsed: formatElapsedTime(startTime),
|
||||
remaining: null,
|
||||
rate: calculateRate(startTime, processedCount)
|
||||
rate: calculateRate(startTime, processedCount),
|
||||
percentage: ((processedCount / (totalProducts || 1)) * 100).toFixed(1)
|
||||
});
|
||||
}
|
||||
throw error;
|
||||
|
||||
Reference in New Issue
Block a user