diff --git a/inventory-server/src/routes/dashboard.js b/inventory-server/src/routes/dashboard.js index 65a215b..1e748e8 100644 --- a/inventory-server/src/routes/dashboard.js +++ b/inventory-server/src/routes/dashboard.js @@ -3,7 +3,7 @@ const router = express.Router(); const db = require('../utils/db'); // Import status codes -const { RECEIVING_STATUS } = require('../types/status-codes'); +const { ReceivingStatus } = require('../types/status-codes'); // Helper function to execute queries using the connection pool async function executeQuery(sql, params = []) { @@ -104,26 +104,26 @@ router.get('/purchase/metrics', async (req, res) => { const [rows] = await executeQuery(` SELECT COALESCE(COUNT(DISTINCT CASE - WHEN po.receiving_status < ${RECEIVING_STATUS.PARTIAL_RECEIVED} + WHEN po.receiving_status < ${ReceivingStatus.PartialReceived} THEN po.po_id END), 0) as active_pos, COALESCE(COUNT(DISTINCT CASE - WHEN po.receiving_status < ${RECEIVING_STATUS.PARTIAL_RECEIVED} + WHEN po.receiving_status < ${ReceivingStatus.PartialReceived} AND po.expected_date < CURDATE() THEN po.po_id END), 0) as overdue_pos, COALESCE(SUM(CASE - WHEN po.receiving_status < ${RECEIVING_STATUS.PARTIAL_RECEIVED} + WHEN po.receiving_status < ${ReceivingStatus.PartialReceived} THEN po.ordered ELSE 0 END), 0) as total_units, CAST(COALESCE(SUM(CASE - WHEN po.receiving_status < ${RECEIVING_STATUS.PARTIAL_RECEIVED} + WHEN po.receiving_status < ${ReceivingStatus.PartialReceived} THEN po.ordered * po.cost_price ELSE 0 END), 0) AS DECIMAL(15,3)) as total_cost, CAST(COALESCE(SUM(CASE - WHEN po.receiving_status < ${RECEIVING_STATUS.PARTIAL_RECEIVED} + WHEN po.receiving_status < ${ReceivingStatus.PartialReceived} THEN po.ordered * p.price ELSE 0 END), 0) AS DECIMAL(15,3)) as total_retail @@ -132,28 +132,22 @@ router.get('/purchase/metrics', async (req, res) => { `); const poMetrics = rows[0]; - console.log('Raw poMetrics from database:', poMetrics); - console.log('poMetrics.active_pos:', poMetrics.active_pos); - console.log('poMetrics.overdue_pos:', poMetrics.overdue_pos); - console.log('poMetrics.total_units:', poMetrics.total_units); - console.log('poMetrics.total_cost:', poMetrics.total_cost); - console.log('poMetrics.total_retail:', poMetrics.total_retail); - const [vendorOrders] = await executeQuery(` SELECT po.vendor, - COUNT(DISTINCT po.po_id) as order_count, - COALESCE(SUM(po.ordered), 0) as ordered_units, - CAST(COALESCE(SUM(po.ordered * po.cost_price), 0) AS DECIMAL(15,3)) as order_cost, - CAST(COALESCE(SUM(po.ordered * p.price), 0) AS DECIMAL(15,3)) as order_retail + COUNT(DISTINCT po.po_id) as orders, + COALESCE(SUM(po.ordered), 0) as units, + CAST(COALESCE(SUM(po.ordered * po.cost_price), 0) AS DECIMAL(15,3)) as cost, + CAST(COALESCE(SUM(po.ordered * p.price), 0) AS DECIMAL(15,3)) as retail FROM purchase_orders po JOIN products p ON po.pid = p.pid - WHERE po.receiving_status < ${RECEIVING_STATUS.PARTIAL_RECEIVED} + WHERE po.receiving_status < ${ReceivingStatus.PartialReceived} GROUP BY po.vendor - HAVING order_cost > 0 - ORDER BY order_cost DESC + HAVING cost > 0 + ORDER BY cost DESC `); + // Format response to match PurchaseMetricsData interface const response = { activePurchaseOrders: parseInt(poMetrics.active_pos) || 0, overduePurchaseOrders: parseInt(poMetrics.overdue_pos) || 0, @@ -162,10 +156,10 @@ router.get('/purchase/metrics', async (req, res) => { onOrderRetail: parseFloat(poMetrics.total_retail) || 0, vendorOrders: vendorOrders.map(v => ({ vendor: v.vendor, - orders: parseInt(v.order_count) || 0, - units: parseInt(v.ordered_units) || 0, - cost: parseFloat(v.order_cost) || 0, - retail: parseFloat(v.order_retail) || 0 + orders: parseInt(v.orders) || 0, + units: parseInt(v.units) || 0, + cost: parseFloat(v.cost) || 0, + retail: parseFloat(v.retail) || 0 })) }; @@ -297,7 +291,7 @@ router.get('/forecast/metrics', async (req, res) => { COALESCE(SUM(cf.forecast_revenue), 0) as revenue, COALESCE(AVG(cf.confidence_level), 0) as confidence FROM category_forecasts cf - JOIN categories c ON cf.cat_id = c.cat_id + JOIN categories c ON cf.category_id = c.cat_id WHERE cf.forecast_date BETWEEN ? AND ? GROUP BY c.cat_id, c.name ORDER BY revenue DESC @@ -785,7 +779,7 @@ router.get('/trending/products', async (req, res) => { HAVING velocity_change > 0 ORDER BY velocity_change DESC LIMIT ? - `, [days, days, days, limit]); + `, [days, days, limit]); res.json(rows); } catch (err) { console.error('Error fetching trending products:', err); diff --git a/inventory-server/src/types/status-codes.js b/inventory-server/src/types/status-codes.js new file mode 100644 index 0000000..8c94f85 --- /dev/null +++ b/inventory-server/src/types/status-codes.js @@ -0,0 +1,79 @@ +// Purchase Order Status Codes +const PurchaseOrderStatus = { + Canceled: 0, + Created: 1, + ElectronicallyReadySend: 10, + Ordered: 11, + Preordered: 12, + ElectronicallySent: 13, + ReceivingStarted: 15, + Done: 50 +}; + +// Receiving Status Codes +const ReceivingStatus = { + Canceled: 0, + Created: 1, + PartialReceived: 30, + FullReceived: 40, + Paid: 50 +}; + +// Status Code Display Names +const PurchaseOrderStatusLabels = { + [PurchaseOrderStatus.Canceled]: 'Canceled', + [PurchaseOrderStatus.Created]: 'Created', + [PurchaseOrderStatus.ElectronicallyReadySend]: 'Ready to Send', + [PurchaseOrderStatus.Ordered]: 'Ordered', + [PurchaseOrderStatus.Preordered]: 'Preordered', + [PurchaseOrderStatus.ElectronicallySent]: 'Sent', + [PurchaseOrderStatus.ReceivingStarted]: 'Receiving Started', + [PurchaseOrderStatus.Done]: 'Done' +}; + +const ReceivingStatusLabels = { + [ReceivingStatus.Canceled]: 'Canceled', + [ReceivingStatus.Created]: 'Created', + [ReceivingStatus.PartialReceived]: 'Partially Received', + [ReceivingStatus.FullReceived]: 'Fully Received', + [ReceivingStatus.Paid]: 'Paid' +}; + +// Helper functions +function getPurchaseOrderStatusLabel(status) { + return PurchaseOrderStatusLabels[status] || 'Unknown'; +} + +function getReceivingStatusLabel(status) { + return ReceivingStatusLabels[status] || 'Unknown'; +} + +// Status checks +function isReceivingComplete(status) { + return status >= ReceivingStatus.PartialReceived; +} + +function isPurchaseOrderComplete(status) { + return status === PurchaseOrderStatus.Done; +} + +function isPurchaseOrderCanceled(status) { + return status === PurchaseOrderStatus.Canceled; +} + +function isReceivingCanceled(status) { + return status === ReceivingStatus.Canceled; +} + +module.exports = { + PurchaseOrderStatus, + ReceivingStatus, + PurchaseOrderStatusLabels, + ReceivingStatusLabels, + getPurchaseOrderStatusLabel, + getReceivingStatusLabel, + isReceivingComplete, + isPurchaseOrderComplete, + isPurchaseOrderCanceled, + isReceivingCanceled +}; \ No newline at end of file