Update import tables schema with minor changes, add new metrics schema
This commit is contained in:
@@ -102,35 +102,40 @@ router.get('/stock/metrics', async (req, res) => {
|
||||
// Returns purchase order metrics by vendor
|
||||
router.get('/purchase/metrics', async (req, res) => {
|
||||
try {
|
||||
// First check if there are any purchase orders in the database
|
||||
const { rows: [poCount] } = await executeQuery(`
|
||||
SELECT COUNT(*) as count FROM purchase_orders
|
||||
`);
|
||||
|
||||
const { rows: [poMetrics] } = await executeQuery(`
|
||||
SELECT
|
||||
COALESCE(COUNT(DISTINCT CASE
|
||||
WHEN po.receiving_status < $1
|
||||
WHEN po.receiving_status NOT IN ('partial_received', 'full_received', 'paid')
|
||||
THEN po.po_id
|
||||
END), 0)::integer as active_pos,
|
||||
COALESCE(COUNT(DISTINCT CASE
|
||||
WHEN po.receiving_status < $1
|
||||
WHEN po.receiving_status NOT IN ('partial_received', 'full_received', 'paid')
|
||||
AND po.expected_date < CURRENT_DATE
|
||||
THEN po.po_id
|
||||
END), 0)::integer as overdue_pos,
|
||||
COALESCE(SUM(CASE
|
||||
WHEN po.receiving_status < $1
|
||||
WHEN po.receiving_status NOT IN ('partial_received', 'full_received', 'paid')
|
||||
THEN po.ordered
|
||||
ELSE 0
|
||||
END), 0)::integer as total_units,
|
||||
ROUND(COALESCE(SUM(CASE
|
||||
WHEN po.receiving_status < $1
|
||||
WHEN po.receiving_status NOT IN ('partial_received', 'full_received', 'paid')
|
||||
THEN po.ordered * po.cost_price
|
||||
ELSE 0
|
||||
END), 0)::numeric, 3) as total_cost,
|
||||
ROUND(COALESCE(SUM(CASE
|
||||
WHEN po.receiving_status < $1
|
||||
WHEN po.receiving_status NOT IN ('partial_received', 'full_received', 'paid')
|
||||
THEN po.ordered * p.price
|
||||
ELSE 0
|
||||
END), 0)::numeric, 3) as total_retail
|
||||
FROM purchase_orders po
|
||||
JOIN products p ON po.pid = p.pid
|
||||
`, [ReceivingStatus.PartialReceived]);
|
||||
`);
|
||||
|
||||
const { rows: vendorOrders } = await executeQuery(`
|
||||
SELECT
|
||||
@@ -141,15 +146,15 @@ router.get('/purchase/metrics', async (req, res) => {
|
||||
ROUND(COALESCE(SUM(po.ordered * p.price), 0)::numeric, 3) as retail
|
||||
FROM purchase_orders po
|
||||
JOIN products p ON po.pid = p.pid
|
||||
WHERE po.receiving_status < $1
|
||||
WHERE po.receiving_status NOT IN ('partial_received', 'full_received', 'paid')
|
||||
GROUP BY po.vendor
|
||||
HAVING ROUND(COALESCE(SUM(po.ordered * po.cost_price), 0)::numeric, 3) > 0
|
||||
ORDER BY cost DESC
|
||||
`, [ReceivingStatus.PartialReceived]);
|
||||
`);
|
||||
|
||||
// If no data or missing metrics, provide dummy data
|
||||
if (!poMetrics || vendorOrders.length === 0) {
|
||||
console.log('No purchase metrics found, returning dummy data');
|
||||
// If no purchase orders exist at all in the database, return dummy data
|
||||
if (parseInt(poCount.count) === 0) {
|
||||
console.log('No purchase orders found in database, returning dummy data');
|
||||
|
||||
return res.json({
|
||||
activePurchaseOrders: 12,
|
||||
@@ -164,6 +169,20 @@ router.get('/purchase/metrics', async (req, res) => {
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
// If no active purchase orders match the criteria, return zeros instead of dummy data
|
||||
if (vendorOrders.length === 0) {
|
||||
console.log('No active purchase orders matching criteria, returning zeros');
|
||||
|
||||
return res.json({
|
||||
activePurchaseOrders: parseInt(poMetrics.active_pos) || 0,
|
||||
overduePurchaseOrders: parseInt(poMetrics.overdue_pos) || 0,
|
||||
onOrderUnits: parseInt(poMetrics.total_units) || 0,
|
||||
onOrderCost: parseFloat(poMetrics.total_cost) || 0,
|
||||
onOrderRetail: parseFloat(poMetrics.total_retail) || 0,
|
||||
vendorOrders: []
|
||||
});
|
||||
}
|
||||
|
||||
// Format response to match PurchaseMetricsData interface
|
||||
const response = {
|
||||
@@ -184,19 +203,15 @@ router.get('/purchase/metrics', async (req, res) => {
|
||||
res.json(response);
|
||||
} catch (err) {
|
||||
console.error('Error fetching purchase metrics:', err);
|
||||
|
||||
// Return dummy data on error
|
||||
res.json({
|
||||
activePurchaseOrders: 12,
|
||||
overduePurchaseOrders: 3,
|
||||
onOrderUnits: 1250,
|
||||
onOrderCost: 12500,
|
||||
onOrderRetail: 25000,
|
||||
vendorOrders: [
|
||||
{ vendor: "Test Vendor 1", orders: 5, units: 500, cost: 5000, retail: 10000 },
|
||||
{ vendor: "Test Vendor 2", orders: 4, units: 400, cost: 4000, retail: 8000 },
|
||||
{ vendor: "Test Vendor 3", orders: 3, units: 350, cost: 3500, retail: 7000 }
|
||||
]
|
||||
res.status(500).json({
|
||||
error: 'Failed to fetch purchase metrics',
|
||||
details: err.message,
|
||||
activePurchaseOrders: 0,
|
||||
overduePurchaseOrders: 0,
|
||||
onOrderUnits: 0,
|
||||
onOrderCost: 0,
|
||||
onOrderRetail: 0,
|
||||
vendorOrders: []
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -1018,17 +1033,17 @@ router.get('/vendor/performance', async (req, res) => {
|
||||
THEN EXTRACT(EPOCH FROM (po.received_date - po.date))/86400
|
||||
ELSE NULL END)::numeric, 2), 0) as avg_lead_time,
|
||||
COALESCE(ROUND(SUM(CASE
|
||||
WHEN po.status = 'completed' AND po.received_date <= po.expected_date
|
||||
WHEN po.status = 'done' AND po.received_date <= po.expected_date
|
||||
THEN 1
|
||||
ELSE 0
|
||||
END)::numeric * 100.0 / NULLIF(COUNT(*)::numeric, 0), 2), 0) as on_time_delivery_rate,
|
||||
COALESCE(ROUND(AVG(CASE
|
||||
WHEN po.status = 'completed'
|
||||
WHEN po.status = 'done'
|
||||
THEN po.received::numeric / NULLIF(po.ordered::numeric, 0) * 100
|
||||
ELSE NULL
|
||||
END)::numeric, 2), 0) as avg_fill_rate,
|
||||
COUNT(CASE WHEN po.status = 'open' THEN 1 END)::integer as active_orders,
|
||||
COUNT(CASE WHEN po.status = 'open' AND po.expected_date < CURRENT_DATE THEN 1 END)::integer as overdue_orders
|
||||
COUNT(CASE WHEN po.status IN ('created', 'electronically_ready_send', 'ordered', 'preordered', 'electronically_sent', 'receiving_started') THEN 1 END)::integer as active_orders,
|
||||
COUNT(CASE WHEN po.status IN ('created', 'electronically_ready_send', 'ordered', 'preordered', 'electronically_sent', 'receiving_started') AND po.expected_date < CURRENT_DATE THEN 1 END)::integer as overdue_orders
|
||||
FROM purchase_orders po
|
||||
WHERE po.date >= CURRENT_DATE - INTERVAL '180 days'
|
||||
GROUP BY po.vendor
|
||||
@@ -1165,7 +1180,7 @@ router.get('/key-metrics', async (req, res) => {
|
||||
SELECT
|
||||
COUNT(DISTINCT po_id) as total_pos,
|
||||
SUM(ordered * cost_price) as total_po_value,
|
||||
COUNT(CASE WHEN status = 'open' THEN 1 END) as open_pos
|
||||
COUNT(CASE WHEN status IN ('created', 'electronically_ready_send', 'ordered', 'preordered', 'electronically_sent', 'receiving_started') THEN 1 END) as open_pos
|
||||
FROM purchase_orders
|
||||
WHERE order_date >= CURRENT_DATE - INTERVAL '${days} days'
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user