325 lines
10 KiB
JavaScript
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;
|