const express = require('express'); const router = express.Router(); // Debug middleware router.use((req, res, next) => { console.log(`[Config Route] ${req.method} ${req.path}`); next(); }); // ===== GLOBAL SETTINGS ===== // Get all global settings router.get('/global', async (req, res) => { const pool = req.app.locals.pool; try { console.log('[Config Route] Fetching global settings...'); const { rows } = await pool.query('SELECT * FROM settings_global ORDER BY setting_key'); console.log('[Config Route] Sending global settings:', rows); res.json(rows); } catch (error) { console.error('[Config Route] Error fetching global settings:', error); res.status(500).json({ error: 'Failed to fetch global settings', details: error.message }); } }); // Update global settings router.put('/global', async (req, res) => { const pool = req.app.locals.pool; try { console.log('[Config Route] Updating global settings:', req.body); // Validate request if (!Array.isArray(req.body)) { return res.status(400).json({ error: 'Request body must be an array of settings' }); } // Begin transaction const client = await pool.connect(); try { await client.query('BEGIN'); for (const setting of req.body) { if (!setting.setting_key || !setting.setting_value) { throw new Error('Each setting must have a key and value'); } await client.query( `UPDATE settings_global SET setting_value = $1, updated_at = CURRENT_TIMESTAMP WHERE setting_key = $2`, [setting.setting_value, setting.setting_key] ); } await client.query('COMMIT'); res.json({ success: true }); } catch (error) { await client.query('ROLLBACK'); throw error; } finally { client.release(); } } catch (error) { console.error('[Config Route] Error updating global settings:', error); res.status(500).json({ error: 'Failed to update global settings', details: error.message }); } }); // ===== PRODUCT SETTINGS ===== // Get product settings with pagination and search router.get('/products', async (req, res) => { const pool = req.app.locals.pool; try { console.log('[Config Route] Fetching product settings...'); const page = parseInt(req.query.page) || 1; const pageSize = parseInt(req.query.pageSize) || 10; const offset = (page - 1) * pageSize; const search = req.query.search || ''; // Get total count for pagination const countQuery = search ? `SELECT COUNT(*) FROM settings_product sp JOIN products p ON sp.pid::text = p.pid::text WHERE sp.pid::text ILIKE $1 OR p.title ILIKE $1` : 'SELECT COUNT(*) FROM settings_product'; const countParams = search ? [`%${search}%`] : []; const { rows: countResult } = await pool.query(countQuery, countParams); const total = parseInt(countResult[0].count); // Get paginated settings const query = search ? `SELECT sp.*, p.title as product_name FROM settings_product sp JOIN products p ON sp.pid::text = p.pid::text WHERE sp.pid::text ILIKE $1 OR p.title ILIKE $1 ORDER BY sp.pid LIMIT $2 OFFSET $3` : `SELECT sp.*, p.title as product_name FROM settings_product sp JOIN products p ON sp.pid::text = p.pid::text ORDER BY sp.pid LIMIT $1 OFFSET $2`; const queryParams = search ? [`%${search}%`, pageSize, offset] : [pageSize, offset]; const { rows } = await pool.query(query, queryParams); const response = { items: rows, total, page, pageSize }; console.log(`[Config Route] Sending ${rows.length} product settings`); res.json(response); } catch (error) { console.error('[Config Route] Error fetching product settings:', error); res.status(500).json({ error: 'Failed to fetch product settings', details: error.message }); } }); // Update product settings router.put('/products/:pid', async (req, res) => { const pool = req.app.locals.pool; try { const { pid } = req.params; const { lead_time_days, days_of_stock, safety_stock, forecast_method, exclude_from_forecast } = req.body; console.log(`[Config Route] Updating product settings for ${pid}:`, req.body); // Check if product exists const { rows: checkProduct } = await pool.query( 'SELECT 1 FROM settings_product WHERE pid::text = $1', [pid] ); if (checkProduct.length === 0) { // Insert if it doesn't exist await pool.query( `INSERT INTO settings_product (pid, lead_time_days, days_of_stock, safety_stock, forecast_method, exclude_from_forecast) VALUES ($1, $2, $3, $4, $5, $6)`, [pid, lead_time_days, days_of_stock, safety_stock, forecast_method, exclude_from_forecast] ); } else { // Update if it exists await pool.query( `UPDATE settings_product SET lead_time_days = $2, days_of_stock = $3, safety_stock = $4, forecast_method = $5, exclude_from_forecast = $6, updated_at = CURRENT_TIMESTAMP WHERE pid::text = $1`, [pid, lead_time_days, days_of_stock, safety_stock, forecast_method, exclude_from_forecast] ); } res.json({ success: true }); } catch (error) { console.error(`[Config Route] Error updating product settings for ${req.params.pid}:`, error); res.status(500).json({ error: 'Failed to update product settings', details: error.message }); } }); // Reset product settings to defaults router.post('/products/:pid/reset', async (req, res) => { const pool = req.app.locals.pool; try { const { pid } = req.params; console.log(`[Config Route] Resetting product settings for ${pid}`); // Reset by setting everything to null/default await pool.query( `UPDATE settings_product SET lead_time_days = NULL, days_of_stock = NULL, safety_stock = 0, forecast_method = NULL, exclude_from_forecast = false, updated_at = CURRENT_TIMESTAMP WHERE pid::text = $1`, [pid] ); res.json({ success: true }); } catch (error) { console.error(`[Config Route] Error resetting product settings for ${req.params.pid}:`, error); res.status(500).json({ error: 'Failed to reset product settings', details: error.message }); } }); // ===== VENDOR SETTINGS ===== // Get vendor settings with pagination and search router.get('/vendors', async (req, res) => { const pool = req.app.locals.pool; try { console.log('[Config Route] Fetching vendor settings...'); const page = parseInt(req.query.page) || 1; const pageSize = parseInt(req.query.pageSize) || 10; const offset = (page - 1) * pageSize; const search = req.query.search || ''; // Get total count for pagination const countQuery = search ? 'SELECT COUNT(*) FROM settings_vendor WHERE vendor ILIKE $1' : 'SELECT COUNT(*) FROM settings_vendor'; const countParams = search ? [`%${search}%`] : []; const { rows: countResult } = await pool.query(countQuery, countParams); const total = parseInt(countResult[0].count); // Get paginated settings const query = search ? `SELECT * FROM settings_vendor WHERE vendor ILIKE $1 ORDER BY vendor LIMIT $2 OFFSET $3` : `SELECT * FROM settings_vendor ORDER BY vendor LIMIT $1 OFFSET $2`; const queryParams = search ? [`%${search}%`, pageSize, offset] : [pageSize, offset]; const { rows } = await pool.query(query, queryParams); const response = { items: rows, total, page, pageSize }; console.log(`[Config Route] Sending ${rows.length} vendor settings`); res.json(response); } catch (error) { console.error('[Config Route] Error fetching vendor settings:', error); res.status(500).json({ error: 'Failed to fetch vendor settings', details: error.message }); } }); // Update vendor settings router.put('/vendors/:vendor', async (req, res) => { const pool = req.app.locals.pool; try { const vendor = req.params.vendor; const { default_lead_time_days, default_days_of_stock } = req.body; console.log(`[Config Route] Updating vendor settings for ${vendor}:`, req.body); // Check if vendor exists const { rows: checkVendor } = await pool.query( 'SELECT 1 FROM settings_vendor WHERE vendor = $1', [vendor] ); if (checkVendor.length === 0) { // Insert if it doesn't exist await pool.query( `INSERT INTO settings_vendor (vendor, default_lead_time_days, default_days_of_stock) VALUES ($1, $2, $3)`, [vendor, default_lead_time_days, default_days_of_stock] ); } else { // Update if it exists await pool.query( `UPDATE settings_vendor SET default_lead_time_days = $2, default_days_of_stock = $3, updated_at = CURRENT_TIMESTAMP WHERE vendor = $1`, [vendor, default_lead_time_days, default_days_of_stock] ); } res.json({ success: true }); } catch (error) { console.error(`[Config Route] Error updating vendor settings for ${req.params.vendor}:`, error); res.status(500).json({ error: 'Failed to update vendor settings', details: error.message }); } }); // Reset vendor settings to defaults router.post('/vendors/:vendor/reset', async (req, res) => { const pool = req.app.locals.pool; try { const vendor = req.params.vendor; console.log(`[Config Route] Resetting vendor settings for ${vendor}`); // Reset by setting everything to null await pool.query( `UPDATE settings_vendor SET default_lead_time_days = NULL, default_days_of_stock = NULL, updated_at = CURRENT_TIMESTAMP WHERE vendor = $1`, [vendor] ); res.json({ success: true }); } catch (error) { console.error(`[Config Route] Error resetting vendor settings for ${req.params.vendor}:`, error); res.status(500).json({ error: 'Failed to reset vendor settings', details: error.message }); } }); // Export the router module.exports = router;