account for advanced edit

This commit is contained in:
Jake Kasper
2025-08-22 08:40:21 -04:00
parent bb365d918d
commit f95422325c
3 changed files with 98 additions and 15 deletions

View File

@@ -82,10 +82,12 @@ router.get('/', async (req, res, next) => {
// Get user's custom products
const userProductsQuery = `
SELECT up.*, p.name as base_product_name, p.brand, p.product_type, pc.name as category_name
SELECT up.*, p.name as base_product_name, p.brand as base_brand, p.product_type as base_product_type,
pc.name as category_name, upc.name as custom_category_name
FROM user_products up
LEFT JOIN products p ON up.product_id = p.id
LEFT JOIN product_categories pc ON p.category_id = pc.id
LEFT JOIN product_categories upc ON up.category_id = upc.id
WHERE up.user_id = $1
ORDER BY COALESCE(up.custom_name, p.name)
`;
@@ -112,14 +114,23 @@ router.get('/', async (req, res, next) => {
baseProductId: product.product_id,
baseProductName: product.base_product_name,
customName: product.custom_name,
brand: product.brand,
categoryName: product.category_name,
productType: product.product_type,
// Use custom fields if available, otherwise fall back to base product
brand: product.custom_brand || product.base_brand,
customBrand: product.custom_brand,
categoryId: product.category_id,
categoryName: product.custom_category_name || product.category_name,
productType: product.custom_product_type || product.base_product_type,
customProductType: product.custom_product_type,
activeIngredients: product.custom_active_ingredients,
customActiveIngredients: product.custom_active_ingredients,
description: product.custom_description,
customDescription: product.custom_description,
customRateAmount: parseFloat(product.custom_rate_amount),
customRateUnit: product.custom_rate_unit,
notes: product.notes,
isShared: false,
createdAt: product.created_at
createdAt: product.created_at,
updatedAt: product.updated_at
}))
}
});
@@ -292,7 +303,19 @@ router.post('/:id/rates', validateParams(idParamSchema), validateRequest(product
// @access Private
router.post('/user', validateRequest(userProductSchema), async (req, res, next) => {
try {
const { productId, customName, customRateAmount, customRateUnit, notes } = req.body;
const {
productId,
customName,
customRateAmount,
customRateUnit,
notes,
// Advanced fields for creating custom products
brand,
categoryId,
productType,
activeIngredients,
description
} = req.body;
// If based on existing product, verify it exists
if (productId) {
@@ -312,10 +335,13 @@ router.post('/user', validateRequest(userProductSchema), async (req, res, next)
}
const result = await pool.query(
`INSERT INTO user_products (user_id, product_id, custom_name, custom_rate_amount, custom_rate_unit, notes)
VALUES ($1, $2, $3, $4, $5, $6)
`INSERT INTO user_products (user_id, product_id, custom_name, custom_brand, category_id,
custom_product_type, custom_active_ingredients, custom_description,
custom_rate_amount, custom_rate_unit, notes)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)
RETURNING *`,
[req.user.id, productId, customName, customRateAmount, customRateUnit, notes]
[req.user.id, productId, customName, brand, categoryId, productType, activeIngredients,
description, customRateAmount, customRateUnit, notes]
);
const userProduct = result.rows[0];
@@ -328,10 +354,16 @@ router.post('/user', validateRequest(userProductSchema), async (req, res, next)
id: userProduct.id,
baseProductId: userProduct.product_id,
customName: userProduct.custom_name,
customBrand: userProduct.custom_brand,
categoryId: userProduct.category_id,
customProductType: userProduct.custom_product_type,
customActiveIngredients: userProduct.custom_active_ingredients,
customDescription: userProduct.custom_description,
customRateAmount: parseFloat(userProduct.custom_rate_amount),
customRateUnit: userProduct.custom_rate_unit,
notes: userProduct.notes,
createdAt: userProduct.created_at
createdAt: userProduct.created_at,
updatedAt: userProduct.updated_at
}
}
});
@@ -393,7 +425,25 @@ router.get('/user/:id', validateParams(idParamSchema), async (req, res, next) =>
router.put('/user/:id', validateParams(idParamSchema), validateRequest(userProductSchema), async (req, res, next) => {
try {
const userProductId = req.params.id;
const { productId, customName, customRateAmount, customRateUnit, notes } = req.body;
const {
productId,
customName,
customRateAmount,
customRateUnit,
notes,
isAdvancedEdit,
// Advanced edit fields (will be ignored for now as schema doesn't support them)
brand,
categoryId,
productType,
activeIngredients,
description
} = req.body;
// Log warning if advanced edit is attempted (not fully supported yet)
if (isAdvancedEdit) {
console.warn(`Advanced edit attempted for user product ${userProductId}. Only basic fields will be updated.`);
}
// Check if user product exists and belongs to user
const checkResult = await pool.query(
@@ -419,11 +469,24 @@ router.put('/user/:id', validateParams(idParamSchema), validateRequest(userProdu
const result = await pool.query(
`UPDATE user_products
SET product_id = $1, custom_name = $2, custom_rate_amount = $3,
custom_rate_unit = $4, notes = $5, updated_at = CURRENT_TIMESTAMP
WHERE id = $6
SET product_id = $1, custom_name = $2, custom_brand = $3, category_id = $4,
custom_product_type = $5, custom_active_ingredients = $6, custom_description = $7,
custom_rate_amount = $8, custom_rate_unit = $9, notes = $10, updated_at = CURRENT_TIMESTAMP
WHERE id = $11
RETURNING *`,
[productId, customName, customRateAmount, customRateUnit, notes, userProductId]
[
productId,
customName,
brand,
categoryId,
productType,
activeIngredients,
description,
customRateAmount,
customRateUnit,
notes,
userProductId
]
);
const userProduct = result.rows[0];
@@ -436,6 +499,11 @@ router.put('/user/:id', validateParams(idParamSchema), validateRequest(userProdu
id: userProduct.id,
baseProductId: userProduct.product_id,
customName: userProduct.custom_name,
customBrand: userProduct.custom_brand,
categoryId: userProduct.category_id,
customProductType: userProduct.custom_product_type,
customActiveIngredients: userProduct.custom_active_ingredients,
customDescription: userProduct.custom_description,
customRateAmount: parseFloat(userProduct.custom_rate_amount),
customRateUnit: userProduct.custom_rate_unit,
notes: userProduct.notes,

View File

@@ -100,6 +100,11 @@ CREATE TABLE user_products (
user_id INTEGER REFERENCES users(id) ON DELETE CASCADE,
product_id INTEGER REFERENCES products(id),
custom_name VARCHAR(255),
custom_brand VARCHAR(100),
category_id INTEGER REFERENCES product_categories(id),
custom_product_type VARCHAR(50) CHECK (custom_product_type IN ('granular', 'liquid')),
custom_active_ingredients TEXT,
custom_description TEXT,
custom_rate_amount DECIMAL(8, 4),
custom_rate_unit VARCHAR(50),
notes TEXT,

View File

@@ -0,0 +1,10 @@
-- Migration: Add advanced fields to user_products table
-- This allows users to have fully customizable products with their own brand, category, etc.
-- Add the advanced fields
ALTER TABLE user_products
ADD COLUMN custom_brand VARCHAR(100),
ADD COLUMN category_id INTEGER REFERENCES product_categories(id),
ADD COLUMN custom_product_type VARCHAR(50) CHECK (custom_product_type IN ('granular', 'liquid')),
ADD COLUMN custom_active_ingredients TEXT,
ADD COLUMN custom_description TEXT;