spreader stuff

This commit is contained in:
Jake Kasper
2025-08-24 13:41:12 -04:00
parent 3ad4782021
commit 229454c466
10 changed files with 616 additions and 17 deletions

View File

@@ -0,0 +1,241 @@
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(),
spreaderBrand: Joi.string().max(100).required(),
spreaderModel: Joi.string().max(100).optional(),
settingValue: Joi.string().max(20).required(),
rateDescription: Joi.string().max(200).optional(),
notes: Joi.string().optional()
}).xor('productId', 'userProductId'); // Must have either productId or userProductId, but not both
const idParamSchema = Joi.object({
id: 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(idParamSchema), async (req, res, next) => {
try {
const productId = req.params.productId;
const result = await pool.query(
`SELECT * FROM product_spreader_settings
WHERE product_id = $1
ORDER BY spreader_brand, spreader_model NULLS LAST, setting_value`,
[productId]
);
res.json({
success: true,
data: {
settings: result.rows.map(row => ({
id: row.id,
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(idParamSchema), 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 * FROM product_spreader_settings
WHERE user_product_id = $1
ORDER BY spreader_brand, spreader_model NULLS LAST, setting_value`,
[userProductId]
);
res.json({
success: true,
data: {
settings: result.rows.map(row => ({
id: row.id,
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, 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);
}
}
const result = await pool.query(
`INSERT INTO product_spreader_settings
(product_id, user_product_id, spreader_brand, spreader_model, setting_value, rate_description, notes)
VALUES ($1, $2, $3, $4, $5, $6, $7)
RETURNING *`,
[productId, userProductId, 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,
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, 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);
}
const result = await pool.query(
`UPDATE product_spreader_settings
SET spreader_brand = $1, spreader_model = $2, setting_value = $3,
rate_description = $4, notes = $5
WHERE id = $6
RETURNING *`,
[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,
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;