account for advanced edit
This commit is contained in:
@@ -82,10 +82,12 @@ router.get('/', async (req, res, next) => {
|
|||||||
|
|
||||||
// Get user's custom products
|
// Get user's custom products
|
||||||
const userProductsQuery = `
|
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
|
FROM user_products up
|
||||||
LEFT JOIN products p ON up.product_id = p.id
|
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 pc ON p.category_id = pc.id
|
||||||
|
LEFT JOIN product_categories upc ON up.category_id = upc.id
|
||||||
WHERE up.user_id = $1
|
WHERE up.user_id = $1
|
||||||
ORDER BY COALESCE(up.custom_name, p.name)
|
ORDER BY COALESCE(up.custom_name, p.name)
|
||||||
`;
|
`;
|
||||||
@@ -112,14 +114,23 @@ router.get('/', async (req, res, next) => {
|
|||||||
baseProductId: product.product_id,
|
baseProductId: product.product_id,
|
||||||
baseProductName: product.base_product_name,
|
baseProductName: product.base_product_name,
|
||||||
customName: product.custom_name,
|
customName: product.custom_name,
|
||||||
brand: product.brand,
|
// Use custom fields if available, otherwise fall back to base product
|
||||||
categoryName: product.category_name,
|
brand: product.custom_brand || product.base_brand,
|
||||||
productType: product.product_type,
|
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),
|
customRateAmount: parseFloat(product.custom_rate_amount),
|
||||||
customRateUnit: product.custom_rate_unit,
|
customRateUnit: product.custom_rate_unit,
|
||||||
notes: product.notes,
|
notes: product.notes,
|
||||||
isShared: false,
|
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
|
// @access Private
|
||||||
router.post('/user', validateRequest(userProductSchema), async (req, res, next) => {
|
router.post('/user', validateRequest(userProductSchema), async (req, res, next) => {
|
||||||
try {
|
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 based on existing product, verify it exists
|
||||||
if (productId) {
|
if (productId) {
|
||||||
@@ -312,10 +335,13 @@ router.post('/user', validateRequest(userProductSchema), async (req, res, next)
|
|||||||
}
|
}
|
||||||
|
|
||||||
const result = await pool.query(
|
const result = await pool.query(
|
||||||
`INSERT INTO user_products (user_id, product_id, custom_name, custom_rate_amount, custom_rate_unit, notes)
|
`INSERT INTO user_products (user_id, product_id, custom_name, custom_brand, category_id,
|
||||||
VALUES ($1, $2, $3, $4, $5, $6)
|
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 *`,
|
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];
|
const userProduct = result.rows[0];
|
||||||
@@ -328,10 +354,16 @@ router.post('/user', validateRequest(userProductSchema), async (req, res, next)
|
|||||||
id: userProduct.id,
|
id: userProduct.id,
|
||||||
baseProductId: userProduct.product_id,
|
baseProductId: userProduct.product_id,
|
||||||
customName: userProduct.custom_name,
|
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),
|
customRateAmount: parseFloat(userProduct.custom_rate_amount),
|
||||||
customRateUnit: userProduct.custom_rate_unit,
|
customRateUnit: userProduct.custom_rate_unit,
|
||||||
notes: userProduct.notes,
|
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) => {
|
router.put('/user/:id', validateParams(idParamSchema), validateRequest(userProductSchema), async (req, res, next) => {
|
||||||
try {
|
try {
|
||||||
const userProductId = req.params.id;
|
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
|
// Check if user product exists and belongs to user
|
||||||
const checkResult = await pool.query(
|
const checkResult = await pool.query(
|
||||||
@@ -419,11 +469,24 @@ router.put('/user/:id', validateParams(idParamSchema), validateRequest(userProdu
|
|||||||
|
|
||||||
const result = await pool.query(
|
const result = await pool.query(
|
||||||
`UPDATE user_products
|
`UPDATE user_products
|
||||||
SET product_id = $1, custom_name = $2, custom_rate_amount = $3,
|
SET product_id = $1, custom_name = $2, custom_brand = $3, category_id = $4,
|
||||||
custom_rate_unit = $4, notes = $5, updated_at = CURRENT_TIMESTAMP
|
custom_product_type = $5, custom_active_ingredients = $6, custom_description = $7,
|
||||||
WHERE id = $6
|
custom_rate_amount = $8, custom_rate_unit = $9, notes = $10, updated_at = CURRENT_TIMESTAMP
|
||||||
|
WHERE id = $11
|
||||||
RETURNING *`,
|
RETURNING *`,
|
||||||
[productId, customName, customRateAmount, customRateUnit, notes, userProductId]
|
[
|
||||||
|
productId,
|
||||||
|
customName,
|
||||||
|
brand,
|
||||||
|
categoryId,
|
||||||
|
productType,
|
||||||
|
activeIngredients,
|
||||||
|
description,
|
||||||
|
customRateAmount,
|
||||||
|
customRateUnit,
|
||||||
|
notes,
|
||||||
|
userProductId
|
||||||
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
const userProduct = result.rows[0];
|
const userProduct = result.rows[0];
|
||||||
@@ -436,6 +499,11 @@ router.put('/user/:id', validateParams(idParamSchema), validateRequest(userProdu
|
|||||||
id: userProduct.id,
|
id: userProduct.id,
|
||||||
baseProductId: userProduct.product_id,
|
baseProductId: userProduct.product_id,
|
||||||
customName: userProduct.custom_name,
|
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),
|
customRateAmount: parseFloat(userProduct.custom_rate_amount),
|
||||||
customRateUnit: userProduct.custom_rate_unit,
|
customRateUnit: userProduct.custom_rate_unit,
|
||||||
notes: userProduct.notes,
|
notes: userProduct.notes,
|
||||||
|
|||||||
@@ -100,6 +100,11 @@ CREATE TABLE user_products (
|
|||||||
user_id INTEGER REFERENCES users(id) ON DELETE CASCADE,
|
user_id INTEGER REFERENCES users(id) ON DELETE CASCADE,
|
||||||
product_id INTEGER REFERENCES products(id),
|
product_id INTEGER REFERENCES products(id),
|
||||||
custom_name VARCHAR(255),
|
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_amount DECIMAL(8, 4),
|
||||||
custom_rate_unit VARCHAR(50),
|
custom_rate_unit VARCHAR(50),
|
||||||
notes TEXT,
|
notes TEXT,
|
||||||
|
|||||||
10
database/migrations/add_advanced_fields_to_user_products.sql
Normal file
10
database/migrations/add_advanced_fields_to_user_products.sql
Normal 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;
|
||||||
Reference in New Issue
Block a user