Files
inventory/inventory-server/src/routes/config.js
2025-04-08 21:26:00 -04:00

325 lines
10 KiB
JavaScript

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;