const express = require('express'); const pool = require('../config/database'); const { validateRequest, validateParams } = require('../utils/validation'); const { AppError } = require('../middleware/errorHandler'); const Joi = require('joi'); const router = express.Router(); // Validation schemas const spreaderSettingSchema = Joi.object({ productId: Joi.number().integer().positive().optional(), userProductId: Joi.number().integer().positive().optional(), equipmentId: Joi.number().integer().positive().optional(), // Link to user_equipment // Legacy fields for backward compatibility spreaderBrand: Joi.string().max(100).optional(), spreaderModel: Joi.string().max(100).allow(null, '').optional(), settingValue: Joi.string().max(20).required(), rateDescription: Joi.string().max(200).allow(null, '').optional(), notes: Joi.string().allow(null, '').optional() }).xor('productId', 'userProductId'); // Must have either productId or userProductId, but not both const idParamSchema = Joi.object({ id: Joi.number().integer().positive().required() }); const userProductIdParamSchema = Joi.object({ userProductId: Joi.number().integer().positive().required() }); const productIdParamSchema = Joi.object({ productId: Joi.number().integer().positive().required() }); // @route GET /api/product-spreader-settings/product/:productId // @desc Get spreader settings for a specific product // @access Private router.get('/product/:productId', validateParams(productIdParamSchema), async (req, res, next) => { try { const productId = req.params.productId; const result = await pool.query( `SELECT pss.*, ue.custom_name as equipment_name, ue.manufacturer, ue.model as equipment_model FROM product_spreader_settings pss LEFT JOIN user_equipment ue ON pss.equipment_id = ue.id WHERE pss.product_id = $1 ORDER BY ue.custom_name NULLS LAST, pss.spreader_brand, pss.spreader_model NULLS LAST, pss.setting_value`, [productId] ); res.json({ success: true, data: { settings: result.rows.map(row => ({ id: row.id, equipmentId: row.equipment_id, equipmentName: row.equipment_name, equipmentManufacturer: row.manufacturer, equipmentModel: row.equipment_model, // Legacy fields spreaderBrand: row.spreader_brand, spreaderModel: row.spreader_model, settingValue: row.setting_value, rateDescription: row.rate_description, notes: row.notes, createdAt: row.created_at })) } }); } catch (error) { next(error); } }); // @route GET /api/product-spreader-settings/user-product/:userProductId // @desc Get spreader settings for a specific user product // @access Private router.get('/user-product/:userProductId', validateParams(userProductIdParamSchema), async (req, res, next) => { try { const userProductId = req.params.userProductId; // Verify the user product belongs to the requesting user const productCheck = await pool.query( 'SELECT id FROM user_products WHERE id = $1 AND user_id = $2', [userProductId, req.user.id] ); if (productCheck.rows.length === 0) { throw new AppError('User product not found', 404); } const result = await pool.query( `SELECT pss.*, ue.custom_name as equipment_name, ue.manufacturer, ue.model as equipment_model FROM product_spreader_settings pss LEFT JOIN user_equipment ue ON pss.equipment_id = ue.id WHERE pss.user_product_id = $1 ORDER BY ue.custom_name NULLS LAST, pss.spreader_brand, pss.spreader_model NULLS LAST, pss.setting_value`, [userProductId] ); res.json({ success: true, data: { settings: result.rows.map(row => ({ id: row.id, equipmentId: row.equipment_id, equipmentName: row.equipment_name, equipmentManufacturer: row.manufacturer, equipmentModel: row.equipment_model, // Legacy fields spreaderBrand: row.spreader_brand, spreaderModel: row.spreader_model, settingValue: row.setting_value, rateDescription: row.rate_description, notes: row.notes, createdAt: row.created_at })) } }); } catch (error) { next(error); } }); // @route POST /api/product-spreader-settings // @desc Add spreader setting to product // @access Private router.post('/', validateRequest(spreaderSettingSchema), async (req, res, next) => { try { const { productId, userProductId, equipmentId, spreaderBrand, spreaderModel, settingValue, rateDescription, notes } = req.body; // If it's a user product, verify ownership if (userProductId) { const productCheck = await pool.query( 'SELECT id FROM user_products WHERE id = $1 AND user_id = $2', [userProductId, req.user.id] ); if (productCheck.rows.length === 0) { throw new AppError('User product not found', 404); } } // If equipment ID is provided, verify it belongs to the user if (equipmentId) { const equipmentCheck = await pool.query( 'SELECT id FROM user_equipment WHERE id = $1 AND user_id = $2', [equipmentId, req.user.id] ); if (equipmentCheck.rows.length === 0) { throw new AppError('Equipment not found', 404); } } const result = await pool.query( `INSERT INTO product_spreader_settings (product_id, user_product_id, equipment_id, spreader_brand, spreader_model, setting_value, rate_description, notes) VALUES ($1, $2, $3, $4, $5, $6, $7, $8) RETURNING *`, [productId, userProductId, equipmentId, spreaderBrand, spreaderModel, settingValue, rateDescription, notes] ); const setting = result.rows[0]; res.status(201).json({ success: true, message: 'Spreader setting added successfully', data: { setting: { id: setting.id, equipmentId: setting.equipment_id, spreaderBrand: setting.spreader_brand, spreaderModel: setting.spreader_model, settingValue: setting.setting_value, rateDescription: setting.rate_description, notes: setting.notes, createdAt: setting.created_at } } }); } catch (error) { next(error); } }); // @route PUT /api/product-spreader-settings/:id // @desc Update spreader setting // @access Private router.put('/:id', validateParams(idParamSchema), validateRequest(spreaderSettingSchema), async (req, res, next) => { try { const settingId = req.params.id; const { productId, userProductId, equipmentId, spreaderBrand, spreaderModel, settingValue, rateDescription, notes } = req.body; // Check if setting exists and user has permission to edit it let checkQuery; let checkParams; if (userProductId) { checkQuery = ` SELECT pss.* FROM product_spreader_settings pss JOIN user_products up ON pss.user_product_id = up.id WHERE pss.id = $1 AND up.user_id = $2 `; checkParams = [settingId, req.user.id]; } else { // For shared products, any authenticated user can edit (you might want to restrict this) checkQuery = 'SELECT * FROM product_spreader_settings WHERE id = $1'; checkParams = [settingId]; } const settingCheck = await pool.query(checkQuery, checkParams); if (settingCheck.rows.length === 0) { throw new AppError('Spreader setting not found', 404); } // If equipment ID is provided, verify it belongs to the user if (equipmentId) { const equipmentCheck = await pool.query( 'SELECT id FROM user_equipment WHERE id = $1 AND user_id = $2', [equipmentId, req.user.id] ); if (equipmentCheck.rows.length === 0) { throw new AppError('Equipment not found', 404); } } const result = await pool.query( `UPDATE product_spreader_settings SET equipment_id = $1, spreader_brand = $2, spreader_model = $3, setting_value = $4, rate_description = $5, notes = $6 WHERE id = $7 RETURNING *`, [equipmentId, spreaderBrand, spreaderModel, settingValue, rateDescription, notes, settingId] ); const setting = result.rows[0]; res.json({ success: true, message: 'Spreader setting updated successfully', data: { setting: { id: setting.id, equipmentId: setting.equipment_id, spreaderBrand: setting.spreader_brand, spreaderModel: setting.spreader_model, settingValue: setting.setting_value, rateDescription: setting.rate_description, notes: setting.notes, updatedAt: setting.updated_at } } }); } catch (error) { next(error); } }); // @route DELETE /api/product-spreader-settings/:id // @desc Delete spreader setting // @access Private router.delete('/:id', validateParams(idParamSchema), async (req, res, next) => { try { const settingId = req.params.id; // Check if setting exists and user has permission to delete it const settingCheck = await pool.query( `SELECT pss.* FROM product_spreader_settings pss LEFT JOIN user_products up ON pss.user_product_id = up.id WHERE pss.id = $1 AND (pss.product_id IS NOT NULL OR up.user_id = $2)`, [settingId, req.user.id] ); if (settingCheck.rows.length === 0) { throw new AppError('Spreader setting not found', 404); } await pool.query('DELETE FROM product_spreader_settings WHERE id = $1', [settingId]); res.json({ success: true, message: 'Spreader setting deleted successfully' }); } catch (error) { next(error); } }); module.exports = router;