diff --git a/controllers/brand.controller.js b/controllers/brand.controller.js index 9e1f73e..4820f71 100644 --- a/controllers/brand.controller.js +++ b/controllers/brand.controller.js @@ -4,7 +4,6 @@ const { createFileUploadDb } = require('../db/file_uploads.db'); const { insertBrandSchema, updateBrandSchema, - uploadSolutionSchema } = require('../validate/brand.schema'); class BrandController { @@ -23,6 +22,9 @@ class BrandController { const { id } = req.params; const results = await BrandService.getBrandById(id); + + // console.log('Brand response structure:', JSON.stringify(results, null, 2)); + const response = await setResponse(results, 'Brand found'); res.status(response.statusCode).json(response); @@ -98,14 +100,8 @@ class BrandController { // Soft delete brand by ID static async delete(req, res) { const { id } = req.params; - // Get brand by ID first to get name for deletion - const brand = await BrandService.getBrandById(id); - if (!brand) { - const response = await setResponse([], 'Brand not found', 404); - return res.status(response.statusCode).json(response); - } - const results = await BrandService.deleteBrand(brand.brand_name, req.user.user_id); + const results = await BrandService.deleteBrand(id, req.user.user_id); const response = await setResponse(results, 'Brand deleted successfully'); res.status(response.statusCode).json(response); diff --git a/db/brand.db.js b/db/brand.db.js index 0d985b4..e305bad 100644 --- a/db/brand.db.js +++ b/db/brand.db.js @@ -102,14 +102,14 @@ const updateBrandDb = async (brandName, data) => { return getBrandByNameDb(brandName); }; -// Soft delete brand by name -const deleteBrandDb = async (brandName, deletedBy) => { +// Soft delete brand +const deleteBrandDb = async (id, deletedBy) => { const queryText = ` UPDATE m_brands SET deleted_at = CURRENT_TIMESTAMP, deleted_by = $1 - WHERE brand_name = $2 AND deleted_at IS NULL + WHERE brand_id = $2 AND deleted_at IS NULL `; - await pool.query(queryText, [deletedBy, brandName]); + await pool.query(queryText, [deletedBy, id]); return true; }; @@ -131,33 +131,6 @@ const checkBrandNameExistsDb = async (brandName, excludeId = null) => { return result.recordset.length > 0; }; -// Get brand with error codes count -const getBrandsWithErrorCodeCountDb = async (searchParams = {}) => { - let queryParams = []; - - const queryText = ` - SELECT - a.brand_id, - a.brand_name, - a.brand_type, - a.brand_manufacture, - a.brand_model, - a.brand_code, - a.is_active, - a.created_at, - COUNT(bc.error_code_id) as error_code_count - FROM m_brands a - LEFT JOIN brand_code bc ON a.brand_id = bc.brand_id AND bc.deleted_at IS NULL - WHERE a.deleted_at IS NULL - GROUP BY - a.brand_id, a.brand_name, a.brand_type, a.brand_manufacture, - a.brand_model, a.brand_code, a.is_active, a.created_at - ORDER BY a.brand_name - `; - - const result = await pool.query(queryText, queryParams); - return result.recordset; -}; module.exports = { getAllBrandsDb, @@ -167,5 +140,4 @@ module.exports = { updateBrandDb, deleteBrandDb, checkBrandNameExistsDb, - getBrandsWithErrorCodeCountDb, }; \ No newline at end of file diff --git a/db/brand_code.db.js b/db/brand_code.db.js index aac38b7..ec64d0c 100644 --- a/db/brand_code.db.js +++ b/db/brand_code.db.js @@ -13,17 +13,6 @@ const getErrorCodesByBrandIdDb = async (brandId) => { return result.recordset; }; -// Get error code by brand ID and error code -const getErrorCodeByBrandIdAndCodeDb = async (brandId, errorCode) => { - const queryText = ` - SELECT - a.* - FROM brand_code a - WHERE a.brand_id = $1 AND a.error_code = $2 AND a.deleted_at IS NULL - `; - const result = await pool.query(queryText, [brandId, errorCode]); - return result.recordset[0]; -}; // Create error code for brand const createErrorCodeDb = async (brandId, data) => { @@ -66,29 +55,10 @@ const deleteErrorCodeDb = async (brandId, errorCode, deletedBy) => { return true; }; -// Check if error code exists for brand -const checkErrorCodeExistsDb = async (brandId, errorCode, excludeId = null) => { - let queryText = ` - SELECT error_code_id - FROM brand_code - WHERE brand_id = $1 AND error_code = $2 AND deleted_at IS NULL - `; - let values = [brandId, errorCode]; - - if (excludeId) { - queryText += ` AND error_code_id != $3`; - values.push(excludeId); - } - - const result = await pool.query(queryText, values); - return result.recordset.length > 0; -}; module.exports = { getErrorCodesByBrandIdDb, - getErrorCodeByBrandIdAndCodeDb, createErrorCodeDb, updateErrorCodeDb, deleteErrorCodeDb, - checkErrorCodeExistsDb, }; \ No newline at end of file diff --git a/db/brand_code_solution.db.js b/db/brand_code_solution.db.js index 92283bd..7c252bb 100644 --- a/db/brand_code_solution.db.js +++ b/db/brand_code_solution.db.js @@ -52,22 +52,9 @@ const deleteSolutionDb = async (solutionId, deletedBy) => { return true; }; -// Get solution by ID -const getSolutionByIdDb = async (solutionId) => { - const queryText = ` - SELECT - a.* - FROM brand_code_solution a - WHERE a.brand_code_solution_id = $1 AND a.deleted_at IS NULL - `; - const result = await pool.query(queryText, [solutionId]); - return result.recordset[0]; -}; - module.exports = { getSolutionsByErrorCodeIdDb, createSolutionDb, updateSolutionDb, deleteSolutionDb, - getSolutionByIdDb, }; \ No newline at end of file diff --git a/services/brand.service.js b/services/brand.service.js index 9bb2884..33be0d4 100644 --- a/services/brand.service.js +++ b/services/brand.service.js @@ -15,7 +15,6 @@ const { createErrorCodeDb, updateErrorCodeDb, deleteErrorCodeDb, - checkErrorCodeExistsDb, } = require('../db/brand_code.db'); // Solution operations @@ -58,15 +57,31 @@ class BrandService { const solutionsWithFiles = await Promise.all( solutions.map(async (solution) => { let fileData = null; + // console.log('Processing solution:', { + // solution_id: solution.brand_code_solution_id, + // path_solution: solution.path_solution, + // type_solution: solution.type_solution + // }); + if (solution.path_solution && solution.type_solution !== 'text') { fileData = await getFileUploadByPathDb(solution.path_solution); + console.log('File data found:', fileData); } - return { + const enhancedSolution = { ...solution, file_upload_name: fileData?.file_upload_name || null, path_document: fileData?.path_document || null }; + + // console.log('Enhanced solution:', { + // solution_id: enhancedSolution.brand_code_solution_id, + // original_path_solution: enhancedSolution.path_solution, + // path_document: enhancedSolution.path_document, + // file_upload_name: enhancedSolution.file_upload_name + // }); + + return enhancedSolution; }) ); @@ -125,7 +140,6 @@ class BrandService { const brandId = createdBrand.brand_id; for (const errorCodeData of data.error_code) { - // Use separate db function for error codes const errorId = await createErrorCodeDb(brandId, { error_code: errorCodeData.error_code, error_code_name: errorCodeData.error_code_name, @@ -141,7 +155,6 @@ class BrandService { // Create solutions for this error code if (errorCodeData.solution && Array.isArray(errorCodeData.solution)) { for (const solutionData of errorCodeData.solution) { - // Use separate db function for solutions await createSolutionDb(errorId, { solution_name: solutionData.solution_name, type_solution: solutionData.type_solution, @@ -161,17 +174,16 @@ class BrandService { } } - // Soft delete brand by name (convert to ID for database operation) - static async deleteBrand(brandName, userId) { + // Soft delete brand by ID + static async deleteBrand(id, userId) { try { - // Get brand by name first to get ID - const brandExist = await getBrandByNameDb(brandName); + const brandExist = await getBrandByIdDb(id); if (!brandExist) { throw new ErrorHandler(404, 'Brand not found'); } - const result = await deleteBrandDb(brandName, userId); + const result = await deleteBrandDb(id, userId); return result; } catch (error) { @@ -185,7 +197,6 @@ class BrandService { const existingBrand = await getBrandByIdDb(id); if (!existingBrand) throw new ErrorHandler(404, 'Brand not found'); - // Check if brand name already exists (excluding current brand) if (data.brand_name && data.brand_name !== existingBrand.brand_name) { const brandExists = await checkBrandNameExistsDb(data.brand_name, id); if (brandExists) { @@ -206,6 +217,7 @@ class BrandService { if (data.error_code && Array.isArray(data.error_code)) { const existingErrorCodes = await getErrorCodesByBrandIdDb(id); + const incomingErrorCodes = data.error_code.map(ec => ec.error_code); // Create/update/delete error codes for (const errorCodeData of data.error_code) { @@ -222,15 +234,41 @@ class BrandService { }); if (errorCodeData.solution && Array.isArray(errorCodeData.solution)) { + const existingSolutions = await getSolutionsByErrorCodeIdDb(existingEC.error_code_id); + const incomingSolutionNames = errorCodeData.solution.map(s => s.solution_name); + + // Update or create solutions for (const solutionData of errorCodeData.solution) { - await createSolutionDb(existingEC.error_code_id, { - solution_name: solutionData.solution_name, - type_solution: solutionData.type_solution, - text_solution: solutionData.text_solution || null, - path_solution: solutionData.path_solution || null, - is_active: solutionData.is_active, - created_by: data.updated_by - }); + const existingSolution = existingSolutions.find(s => s.solution_name === solutionData.solution_name); + + if (existingSolution) { + // Update existing solution + await updateSolutionDb(existingSolution.brand_code_solution_id, { + solution_name: solutionData.solution_name, + type_solution: solutionData.type_solution, + text_solution: solutionData.text_solution || null, + path_solution: solutionData.path_solution || null, + is_active: solutionData.is_active, + updated_by: data.updated_by + }); + } else { + // Create new solution + await createSolutionDb(existingEC.error_code_id, { + solution_name: solutionData.solution_name, + type_solution: solutionData.type_solution, + text_solution: solutionData.text_solution || null, + path_solution: solutionData.path_solution || null, + is_active: solutionData.is_active, + created_by: data.updated_by + }); + } + } + + // Delete solutions that are not in the incoming request + for (const existingSolution of existingSolutions) { + if (!incomingSolutionNames.includes(existingSolution.solution_name)) { + await deleteSolutionDb(existingSolution.brand_code_solution_id, data.updated_by); + } } } } else { @@ -256,6 +294,12 @@ class BrandService { } } } + + for (const existingEC of existingErrorCodes) { + if (!incomingErrorCodes.includes(existingEC.error_code)) { + await deleteErrorCodeDb(id, existingEC.error_code, data.updated_by); + } + } } return await this.getBrandById(id); diff --git a/validate/brand.schema.js b/validate/brand.schema.js index ac6cf98..450972e 100644 --- a/validate/brand.schema.js +++ b/validate/brand.schema.js @@ -5,17 +5,18 @@ const Joi = require("joi"); // ======================== const insertBrandSchema = Joi.object({ brand_name: Joi.string().max(100).required(), - brand_type: Joi.string().max(50).optional(), - brand_manufacture: Joi.string().max(100).optional(), - brand_model: Joi.string().max(100).optional(), + brand_type: Joi.string().max(50).optional().allow(''), + brand_manufacture: Joi.string().max(100).required(), + brand_model: Joi.string().max(100).optional().allow(''), is_active: Joi.boolean().required(), - description: Joi.string().max(255).optional(), + description: Joi.string().max(255).optional().allow(''), error_code: Joi.array().items( Joi.object({ error_code: Joi.string().max(100).required(), error_code_name: Joi.string().max(100).required(), - error_code_description: Joi.string().optional(), + error_code_description: Joi.string().optional().allow(''), is_active: Joi.boolean().required(), + what_action_to_take: Joi.string().optional().allow(''), solution: Joi.array().items( Joi.object({ solution_name: Joi.string().max(100).required(), @@ -40,17 +41,18 @@ const insertBrandSchema = Joi.object({ // Update Brand Validation const updateBrandSchema = Joi.object({ brand_name: Joi.string().max(100).required(), - brand_type: Joi.string().max(50).optional(), - brand_manufacture: Joi.string().max(100).optional(), - brand_model: Joi.string().max(100).optional(), + brand_type: Joi.string().max(50).optional().allow(''), + brand_manufacture: Joi.string().max(100).required(), + brand_model: Joi.string().max(100).optional().allow(''), is_active: Joi.boolean().required(), - description: Joi.string().max(255).optional(), + description: Joi.string().max(255).optional().allow(''), error_code: Joi.array().items( Joi.object({ error_code: Joi.string().max(100).required(), error_code_name: Joi.string().max(100).required(), - error_code_description: Joi.string().optional(), + error_code_description: Joi.string().optional().allow(''), is_active: Joi.boolean().required(), + what_action_to_take: Joi.string().optional().allow(''), solution: Joi.array().items( Joi.object({ solution_name: Joi.string().max(100).required(), @@ -69,7 +71,7 @@ const updateBrandSchema = Joi.object({ }) ).min(1).required() }) - ).optional() + ).optional() }).min(1); module.exports = {