Overview tweaks
This commit is contained in:
@@ -21,8 +21,8 @@ router.get('/stock/metrics', async (req, res) => {
|
||||
COALESCE(COUNT(*), 0)::integer as total_products,
|
||||
COALESCE(COUNT(CASE WHEN current_stock > 0 THEN 1 END), 0)::integer as products_in_stock,
|
||||
COALESCE(SUM(CASE WHEN current_stock > 0 THEN current_stock END), 0)::integer as total_units,
|
||||
ROUND(COALESCE(SUM(CASE WHEN current_stock > 0 THEN current_stock_cost END), 0)::numeric, 3) as total_cost,
|
||||
ROUND(COALESCE(SUM(CASE WHEN current_stock > 0 THEN current_stock_retail END), 0)::numeric, 3) as total_retail
|
||||
ROUND(COALESCE(SUM(CASE WHEN current_stock > 0 THEN current_stock_cost END), 0)::numeric, 2) as total_cost,
|
||||
ROUND(COALESCE(SUM(CASE WHEN current_stock > 0 THEN current_stock_retail END), 0)::numeric, 2) as total_retail
|
||||
FROM product_metrics
|
||||
WHERE is_visible = true
|
||||
`);
|
||||
@@ -34,21 +34,21 @@ router.get('/stock/metrics', async (req, res) => {
|
||||
COALESCE(brand, 'Unbranded') as brand,
|
||||
COUNT(DISTINCT pid)::integer as variant_count,
|
||||
COALESCE(SUM(current_stock), 0)::integer as stock_units,
|
||||
ROUND(COALESCE(SUM(current_stock_cost), 0)::numeric, 3) as stock_cost,
|
||||
ROUND(COALESCE(SUM(current_stock_retail), 0)::numeric, 3) as stock_retail
|
||||
ROUND(COALESCE(SUM(current_stock_cost), 0)::numeric, 2) as stock_cost,
|
||||
ROUND(COALESCE(SUM(current_stock_retail), 0)::numeric, 2) as stock_retail
|
||||
FROM product_metrics
|
||||
WHERE current_stock > 0
|
||||
AND is_visible = true
|
||||
GROUP BY COALESCE(brand, 'Unbranded')
|
||||
HAVING ROUND(COALESCE(SUM(current_stock_cost), 0)::numeric, 3) > 0
|
||||
HAVING ROUND(COALESCE(SUM(current_stock_cost), 0)::numeric, 2) > 0
|
||||
),
|
||||
other_brands AS (
|
||||
SELECT
|
||||
'Other' as brand,
|
||||
SUM(variant_count)::integer as variant_count,
|
||||
SUM(stock_units)::integer as stock_units,
|
||||
ROUND(SUM(stock_cost)::numeric, 3) as stock_cost,
|
||||
ROUND(SUM(stock_retail)::numeric, 3) as stock_retail
|
||||
ROUND(SUM(stock_cost)::numeric, 2) as stock_cost,
|
||||
ROUND(SUM(stock_retail)::numeric, 2) as stock_retail
|
||||
FROM brand_totals
|
||||
WHERE stock_cost <= 5000
|
||||
),
|
||||
@@ -154,7 +154,10 @@ router.get('/purchase/metrics', async (req, res) => {
|
||||
vendor,
|
||||
SUM(on_order_qty)::integer AS units,
|
||||
ROUND(SUM(on_order_cost)::numeric, 2) AS cost,
|
||||
ROUND(SUM(on_order_retail)::numeric, 2) AS retail
|
||||
ROUND(SUM(on_order_retail)::numeric, 2) AS retail,
|
||||
SUM(SUM(on_order_qty)::integer) OVER () AS total_units,
|
||||
ROUND(SUM(SUM(on_order_cost)) OVER ()::numeric, 2) AS total_cost,
|
||||
ROUND(SUM(SUM(on_order_retail)) OVER ()::numeric, 2) AS total_retail
|
||||
FROM product_metrics
|
||||
WHERE is_visible = true AND on_order_qty > 0
|
||||
GROUP BY vendor
|
||||
@@ -169,9 +172,10 @@ router.get('/purchase/metrics', async (req, res) => {
|
||||
retail: parseFloat(v.retail) || 0
|
||||
}));
|
||||
|
||||
const onOrderUnits = vendorOrders.reduce((sum, v) => sum + v.units, 0);
|
||||
const onOrderCost = vendorOrders.reduce((sum, v) => sum + v.cost, 0);
|
||||
const onOrderRetail = vendorOrders.reduce((sum, v) => sum + v.retail, 0);
|
||||
const firstRow = vendorRows[0];
|
||||
const onOrderUnits = firstRow ? parseInt(firstRow.total_units) || 0 : 0;
|
||||
const onOrderCost = firstRow ? parseFloat(firstRow.total_cost) || 0 : 0;
|
||||
const onOrderRetail = firstRow ? parseFloat(firstRow.total_retail) || 0 : 0;
|
||||
|
||||
// Format response to match PurchaseMetricsData interface
|
||||
const response = {
|
||||
@@ -199,8 +203,8 @@ router.get('/replenishment/metrics', async (req, res) => {
|
||||
SELECT
|
||||
COUNT(DISTINCT pm.pid)::integer as products_to_replenish,
|
||||
COALESCE(SUM(pm.replenishment_units), 0)::integer as total_units_needed,
|
||||
ROUND(COALESCE(SUM(pm.replenishment_cost), 0)::numeric, 3) as total_cost,
|
||||
ROUND(COALESCE(SUM(pm.replenishment_retail), 0)::numeric, 3) as total_retail
|
||||
ROUND(COALESCE(SUM(pm.replenishment_cost), 0)::numeric, 2) as total_cost,
|
||||
ROUND(COALESCE(SUM(pm.replenishment_retail), 0)::numeric, 2) as total_retail
|
||||
FROM product_metrics pm
|
||||
WHERE pm.is_visible = true
|
||||
AND pm.is_replenishable = true
|
||||
@@ -216,8 +220,8 @@ router.get('/replenishment/metrics', async (req, res) => {
|
||||
pm.title,
|
||||
pm.current_stock::integer as current_stock,
|
||||
pm.replenishment_units::integer as replenish_qty,
|
||||
ROUND(pm.replenishment_cost::numeric, 3) as replenish_cost,
|
||||
ROUND(pm.replenishment_retail::numeric, 3) as replenish_retail,
|
||||
ROUND(pm.replenishment_cost::numeric, 2) as replenish_cost,
|
||||
ROUND(pm.replenishment_retail::numeric, 2) as replenish_retail,
|
||||
pm.status,
|
||||
pm.planning_period_days::text as planning_period
|
||||
FROM product_metrics pm
|
||||
@@ -552,7 +556,7 @@ router.get('/forecast/metrics', async (req, res) => {
|
||||
|
||||
return res.json({
|
||||
forecastSales: Math.round(totalUnits),
|
||||
forecastRevenue: totalRevenue.toFixed(2),
|
||||
forecastRevenue: parseFloat(totalRevenue.toFixed(2)),
|
||||
confidenceLevel,
|
||||
dailyForecasts,
|
||||
dailyForecastsByPhase,
|
||||
@@ -611,7 +615,7 @@ router.get('/forecast/metrics', async (req, res) => {
|
||||
|
||||
res.json({
|
||||
forecastSales: Math.round(dailyUnits * days),
|
||||
forecastRevenue: (dailyRevenue * days).toFixed(2),
|
||||
forecastRevenue: parseFloat((dailyRevenue * days).toFixed(2)),
|
||||
confidenceLevel: 0,
|
||||
dailyForecasts,
|
||||
categoryForecasts: categoryRows.map(c => ({
|
||||
@@ -794,10 +798,10 @@ router.get('/overstock/metrics', async (req, res) => {
|
||||
if (parseInt(countCheck.overstock_count) === 0) {
|
||||
return res.json({
|
||||
overstockedProducts: 0,
|
||||
total_excess_units: 0,
|
||||
total_excess_cost: 0,
|
||||
total_excess_retail: 0,
|
||||
category_data: []
|
||||
totalExcessUnits: 0,
|
||||
totalExcessCost: 0,
|
||||
totalExcessRetail: 0,
|
||||
categoryData: []
|
||||
});
|
||||
}
|
||||
|
||||
@@ -806,8 +810,8 @@ router.get('/overstock/metrics', async (req, res) => {
|
||||
SELECT
|
||||
COUNT(DISTINCT pid)::integer as total_overstocked,
|
||||
SUM(overstocked_units)::integer as total_excess_units,
|
||||
ROUND(SUM(overstocked_cost)::numeric, 3) as total_excess_cost,
|
||||
ROUND(SUM(overstocked_retail)::numeric, 3) as total_excess_retail
|
||||
ROUND(SUM(overstocked_cost)::numeric, 2) as total_excess_cost,
|
||||
ROUND(SUM(overstocked_retail)::numeric, 2) as total_excess_retail
|
||||
FROM product_metrics
|
||||
WHERE status = 'Overstock'
|
||||
AND is_visible = true
|
||||
@@ -819,8 +823,8 @@ router.get('/overstock/metrics', async (req, res) => {
|
||||
c.name as category_name,
|
||||
COUNT(DISTINCT pm.pid)::integer as overstocked_products,
|
||||
SUM(pm.overstocked_units)::integer as total_excess_units,
|
||||
ROUND(SUM(pm.overstocked_cost)::numeric, 3) as total_excess_cost,
|
||||
ROUND(SUM(pm.overstocked_retail)::numeric, 3) as total_excess_retail
|
||||
ROUND(SUM(pm.overstocked_cost)::numeric, 2) as total_excess_cost,
|
||||
ROUND(SUM(pm.overstocked_retail)::numeric, 2) as total_excess_retail
|
||||
FROM categories c
|
||||
JOIN product_categories pc ON c.cat_id = pc.cat_id
|
||||
JOIN product_metrics pm ON pc.pid = pm.pid
|
||||
@@ -850,10 +854,10 @@ router.get('/overstock/metrics', async (req, res) => {
|
||||
// Format response with explicit type conversion
|
||||
const response = {
|
||||
overstockedProducts: parseInt(summaryMetrics.total_overstocked) || 0,
|
||||
total_excess_units: parseInt(summaryMetrics.total_excess_units) || 0,
|
||||
total_excess_cost: parseFloat(summaryMetrics.total_excess_cost) || 0,
|
||||
total_excess_retail: parseFloat(summaryMetrics.total_excess_retail) || 0,
|
||||
category_data: categoryData.map(cat => ({
|
||||
totalExcessUnits: parseInt(summaryMetrics.total_excess_units) || 0,
|
||||
totalExcessCost: parseFloat(summaryMetrics.total_excess_cost) || 0,
|
||||
totalExcessRetail: parseFloat(summaryMetrics.total_excess_retail) || 0,
|
||||
categoryData: categoryData.map(cat => ({
|
||||
category: cat.category_name,
|
||||
products: parseInt(cat.overstocked_products) || 0,
|
||||
units: parseInt(cat.total_excess_units) || 0,
|
||||
|
||||
Reference in New Issue
Block a user