100 lines
3.4 KiB
JavaScript
100 lines
3.4 KiB
JavaScript
const express = require('express');
|
|
const router = express.Router();
|
|
|
|
// Get all categories
|
|
router.get('/', async (req, res) => {
|
|
const pool = req.app.locals.pool;
|
|
try {
|
|
// Get all categories with metrics and hierarchy info
|
|
const { rows: categories } = await pool.query(`
|
|
SELECT
|
|
c.cat_id,
|
|
c.name,
|
|
c.type,
|
|
c.parent_id,
|
|
c.description,
|
|
c.status,
|
|
p.name as parent_name,
|
|
p.type as parent_type,
|
|
COALESCE(cm.product_count, 0) as product_count,
|
|
COALESCE(cm.active_products, 0) as active_products,
|
|
ROUND(COALESCE(cm.total_value, 0)::numeric, 3) as total_value,
|
|
COALESCE(cm.avg_margin, 0) as avg_margin,
|
|
COALESCE(cm.turnover_rate, 0) as turnover_rate,
|
|
COALESCE(cm.growth_rate, 0) as growth_rate
|
|
FROM categories c
|
|
LEFT JOIN categories p ON c.parent_id = p.cat_id
|
|
LEFT JOIN category_metrics cm ON c.cat_id = cm.category_id
|
|
ORDER BY
|
|
CASE
|
|
WHEN c.type = 10 THEN 1 -- sections first
|
|
WHEN c.type = 11 THEN 2 -- categories second
|
|
WHEN c.type = 12 THEN 3 -- subcategories third
|
|
WHEN c.type = 13 THEN 4 -- subsubcategories fourth
|
|
WHEN c.type = 20 THEN 5 -- themes fifth
|
|
WHEN c.type = 21 THEN 6 -- subthemes last
|
|
ELSE 7
|
|
END,
|
|
c.name ASC
|
|
`);
|
|
|
|
// Get overall stats
|
|
const { rows: [stats] } = await pool.query(`
|
|
SELECT
|
|
COUNT(DISTINCT c.cat_id) as totalCategories,
|
|
COUNT(DISTINCT CASE WHEN c.status = 'active' THEN c.cat_id END) as activeCategories,
|
|
ROUND(COALESCE(SUM(cm.total_value), 0)::numeric, 3) as totalValue,
|
|
COALESCE(ROUND(AVG(NULLIF(cm.avg_margin, 0))::numeric, 1), 0) as avgMargin,
|
|
COALESCE(ROUND(AVG(NULLIF(cm.growth_rate, 0))::numeric, 1), 0) as avgGrowth
|
|
FROM categories c
|
|
LEFT JOIN category_metrics cm ON c.cat_id = cm.category_id
|
|
`);
|
|
|
|
// Get type counts for filtering
|
|
const { rows: typeCounts } = await pool.query(`
|
|
SELECT
|
|
type,
|
|
COUNT(*)::integer as count
|
|
FROM categories
|
|
GROUP BY type
|
|
ORDER BY type
|
|
`);
|
|
|
|
res.json({
|
|
categories: categories.map(cat => ({
|
|
cat_id: cat.cat_id,
|
|
name: cat.name,
|
|
type: cat.type,
|
|
parent_id: cat.parent_id,
|
|
parent_name: cat.parent_name,
|
|
parent_type: cat.parent_type,
|
|
description: cat.description,
|
|
status: cat.status,
|
|
metrics: {
|
|
product_count: parseInt(cat.product_count),
|
|
active_products: parseInt(cat.active_products),
|
|
total_value: parseFloat(cat.total_value),
|
|
avg_margin: parseFloat(cat.avg_margin),
|
|
turnover_rate: parseFloat(cat.turnover_rate),
|
|
growth_rate: parseFloat(cat.growth_rate)
|
|
}
|
|
})),
|
|
typeCounts: typeCounts.map(tc => ({
|
|
type: tc.type,
|
|
count: tc.count // Already cast to integer in the query
|
|
})),
|
|
stats: {
|
|
totalCategories: parseInt(stats.totalcategories),
|
|
activeCategories: parseInt(stats.activecategories),
|
|
totalValue: parseFloat(stats.totalvalue),
|
|
avgMargin: parseFloat(stats.avgmargin),
|
|
avgGrowth: parseFloat(stats.avggrowth)
|
|
}
|
|
});
|
|
} catch (error) {
|
|
console.error('Error fetching categories:', error);
|
|
res.status(500).json({ error: 'Failed to fetch categories' });
|
|
}
|
|
});
|
|
|
|
module.exports = router;
|