From 8176eb2bdd53724fd8fb8f59790b15c42d50d3e9 Mon Sep 17 00:00:00 2001 From: mhmmdafif Date: Mon, 17 Nov 2025 16:01:29 +0700 Subject: [PATCH] repair brand device: add brand sparepart in 2 step --- controllers/brand_sparepart.controller.js | 99 ------ db/brand_sparepart.db.js | 131 ++------ routes/brand_sparepart.route.js | 20 -- routes/index.js | 2 - services/brand.service.js | 380 +++++++++++----------- services/brand_sparepart.service.js | 106 ------ validate/brand.schema.js | 181 +++++++---- validate/brand_sparepart.schema.js | 32 -- 8 files changed, 327 insertions(+), 624 deletions(-) delete mode 100644 controllers/brand_sparepart.controller.js delete mode 100644 routes/brand_sparepart.route.js delete mode 100644 services/brand_sparepart.service.js delete mode 100644 validate/brand_sparepart.schema.js diff --git a/controllers/brand_sparepart.controller.js b/controllers/brand_sparepart.controller.js deleted file mode 100644 index cbca77d..0000000 --- a/controllers/brand_sparepart.controller.js +++ /dev/null @@ -1,99 +0,0 @@ -const BrandSparepartService = require('../services/brand_sparepart.service'); -const { setResponse, setResponsePaging, checkValidate } = require('../helpers/utils'); -const { - insertBrandSparepartSchema, - updateBrandSparepartSchema, -} = require('../validate/brand_sparepart.schema'); - -class BrandSparepartController { - static async getAll(req, res) { - const queryParams = req.query; - - const results = await BrandSparepartService.getAllBrandSparepart(queryParams); - const response = await setResponsePaging(queryParams, results, 'Brand sparepart found'); - - res.status(response.statusCode).json(response); - } - - static async getById(req, res) { - const { id } = req.params; - - const results = await BrandSparepartService.getBrandSparepartById(id); - const response = await setResponse(results, 'Brand sparepart found'); - - res.status(response.statusCode).json(response); - } - - static async create(req, res) { - const { error, value } = await checkValidate(insertBrandSparepartSchema, req); - - if (error) { - return res.status(400).json(setResponse(error, 'Validation failed', 400)); - } - - try { - if (req.file) { - const file = req.file; - const ext = require('path').extname(file.originalname).toLowerCase(); - const typeDoc = ext === ".pdf" ? "PDF" : "IMAGE"; - const folder = typeDoc === "PDF" ? "pdf" : "images"; - const pathDocument = `${folder}/${file.filename}`; - - value.path_foto = pathDocument; - } - - value.created_by = req.user?.user_id || null; - - const results = await BrandSparepartService.createBrandSparepart(value); - const response = await setResponse(results, 'Brand sparepart created successfully'); - - return res.status(response.statusCode).json(response); - } catch (err) { - const response = setResponse([], err.message, err.statusCode || 500); - res.status(response.statusCode).json(response); - } - } - - static async update(req, res) { - const { id } = req.params; - - const { error, value } = await checkValidate(updateBrandSparepartSchema, req); - if (error) { - return res.status(400).json(setResponse(error, 'Validation failed', 400)); - } - - try { - if (req.file) { - const file = req.file; - const ext = require('path').extname(file.originalname).toLowerCase(); - const typeDoc = ext === ".pdf" ? "PDF" : "IMAGE"; - const folder = typeDoc === "PDF" ? "pdf" : "images"; - const pathDocument = `${folder}/${file.filename}`; - - value.path_foto = pathDocument; - } - - value.updated_by = req.user?.user_id || null; - - const results = await BrandSparepartService.updateBrandSparepart(id, value); - const response = await setResponse(results, 'Brand sparepart updated successfully'); - - res.status(response.statusCode).json(response); - - } catch (err) { - const response = setResponse([], err.message, err.statusCode || 500); - res.status(response.statusCode).json(response); - } - } - - static async delete(req, res) { - const { id } = req.params; - - const results = await BrandSparepartService.deleteBrandSparepart(id, req.user.user_id); - const response = await setResponse(results, 'Brand sparepart deleted successfully'); - - res.status(response.statusCode).json(response); - } -} - -module.exports = BrandSparepartController; diff --git a/db/brand_sparepart.db.js b/db/brand_sparepart.db.js index d490dd9..a0b17e4 100644 --- a/db/brand_sparepart.db.js +++ b/db/brand_sparepart.db.js @@ -1,126 +1,59 @@ const pool = require("../config"); -// Get all Contact -const getAllBrandSparepartsDb = async (searchParams = {}) => { - let queryParams = []; - - if (searchParams.limit) { - const page = Number(searchParams.page ?? 1) - 1; - queryParams = [Number(searchParams.limit ?? 10), page]; - } - - const { whereOrConditions, whereParamOr } = pool.buildStringOrIlike( - [ - "a.sparepart_name", - "a.brand_sparepart_description", - "a.is_active" - ], - searchParams.criteria, - queryParams - ); - - if (whereParamOr) queryParams = whereParamOr; - - const { whereConditions, whereParamAnd } = pool.buildFilterQuery( - [ - { column: "a.sparepart_name", param: searchParams.sparepart_name, type: "string" }, - { column: "a.brand_sparepart_description", param: searchParams.brand_sparepart_description, type: "string" }, - { column: "a.is_active", param: searchParams.code, type: "int" }, - ], - queryParams - ); - - if (whereParamAnd) queryParams = whereParamAnd; - +// Get solutions by error code ID +const getSparePartnsByErrorCodeIdDb = async (errorCodeId) => { const queryText = ` - SELECT - COUNT(*) OVER() AS total_data, + SELECT a.* FROM brand_sparepart a - WHERE a.deleted_at IS NULL - ${whereConditions.length > 0 ? ` AND ${whereConditions.join(" AND ")}` : ""} - ${whereOrConditions ? ` ${whereOrConditions}` : ""} - ORDER BY a.brand_sparepart_id ASC - ${searchParams.limit ? `OFFSET $2 * $1 ROWS FETCH NEXT $1 ROWS ONLY` : ''} + WHERE a.error_code_id = $1 AND a.deleted_at IS NULL + ORDER BY a.brand_sparepart_id `; - - const result = await pool.query(queryText, queryParams); - - const total = - result?.recordset?.length > 0 - ? parseInt(result.recordset[0].total_data, 10) - : 0; - - return { data: result.recordset, total }; -}; - -const getBrandSparepartByIdDb = async (id) => { - const queryText = ` - SELECT - a.* - FROM brand_sparepart a - WHERE a.brand_sparepart_id = $1 AND a.deleted_at IS NULL - `; - const result = await pool.query(queryText, [id]); + const result = await pool.query(queryText, [errorCodeId]); return result.recordset; }; -const createBrandSparepartDb = async (store) => { +// Create solution for error code +const createSparePartDb = async (errorCodeId, data) => { + const store = { + error_code_id: errorCodeId, + sparepart_name: data.sparepart_name, + brand_sparepart_description: data.brand_sparepart_description, + path_foto: data.path_foto, + is_active: data.is_active, + created_by: data.created_by + }; + const { query: queryText, values } = pool.buildDynamicInsert("brand_sparepart", store); const result = await pool.query(queryText, values); - const insertedId = result.recordset?.[0]?.inserted_id; - - return insertedId ? await getBrandSparepartByIdDb(insertedId) : null; + const insertedId = result.recordset[0]?.inserted_id; + return insertedId; }; - -const updateBrandSparepartDb = async (id, data) => { +// Update SparePartn +const updateSparePartDb = async (SparePartId, data) => { const store = { ...data }; - const whereData = { brand_sparepart_id: id }; - - const { query: queryText, values } = pool.buildDynamicUpdate( - "brand_sparepart", - store, - whereData - ); + const whereData = { brand_sparepart_id: SparePartId }; + const { query: queryText, values } = pool.buildDynamicUpdate("brand_sparepart", store, whereData); await pool.query(`${queryText} AND deleted_at IS NULL`, values); - return getBrandSparepartByIdDb(id); + return true; }; - -const deleteBrandSparepartDb = async (id, deletedBy) => { +// Soft delete SparePartn +const deleteSparePartDb = async (SparePartId, deletedBy) => { const queryText = ` UPDATE brand_sparepart SET deleted_at = CURRENT_TIMESTAMP, deleted_by = $1 WHERE brand_sparepart_id = $2 AND deleted_at IS NULL `; - await pool.query(queryText, [deletedBy, id]); + await pool.query(queryText, [deletedBy, SparePartId]); return true; }; -const checkBrandSparepartNameExistsDb = async (brandSparePartName, excludeId = null) => { - let queryText = ` - SELECT brand_sparepart_id - FROM brand_sparepart - WHERE sparepart_name = $1 AND deleted_at IS NULL - `; - let values = [brandSparePartName]; - - if (excludeId) { - queryText += ` AND brand_sparepart_id != $2`; - values.push(excludeId); - } - - const result = await pool.query(queryText, values); - return result.recordset.length > 0; -}; - module.exports = { - getAllBrandSparepartsDb, - getBrandSparepartByIdDb, - createBrandSparepartDb, - updateBrandSparepartDb, - deleteBrandSparepartDb, - checkBrandSparepartNameExistsDb -}; + getSparePartnsByErrorCodeIdDb, + createSparePartDb, + updateSparePartDb, + deleteSparePartDb, +}; \ No newline at end of file diff --git a/routes/brand_sparepart.route.js b/routes/brand_sparepart.route.js deleted file mode 100644 index 201e7b6..0000000 --- a/routes/brand_sparepart.route.js +++ /dev/null @@ -1,20 +0,0 @@ -const express = require('express'); -const BrandSparepartController = require('../controllers/brand_sparepart.controller'); -const verifyToken = require('../middleware/verifyToken'); -const verifyAccess = require('../middleware/verifyAccess'); -const upload = require('../middleware/uploads'); - -const router = express.Router(); - -router.route('/') - .get(verifyToken.verifyAccessToken, BrandSparepartController.getAll) - .post(verifyToken.verifyAccessToken, verifyAccess(), upload.single('path_foto') -, BrandSparepartController.create); - -router.route('/:id') - .get(verifyToken.verifyAccessToken, BrandSparepartController.getById) - .put(verifyToken.verifyAccessToken, verifyAccess(), upload.single('path_foto') -, BrandSparepartController.update) - .delete(verifyToken.verifyAccessToken, verifyAccess(), BrandSparepartController.delete); - -module.exports = router; \ No newline at end of file diff --git a/routes/index.js b/routes/index.js index 880c9a7..141c7f5 100644 --- a/routes/index.js +++ b/routes/index.js @@ -14,7 +14,6 @@ const unit = require("./unit.route") const UserSchedule = require("./user_schedule.route") const historyValue = require("./history_value.route") const contact = require("./contact.route") -const brandSparePart = require("./brand_sparepart.route") const notification = require("./notification.route") router.use("/auth", auth); @@ -32,7 +31,6 @@ router.use("/unit", unit); router.use("/user-schedule", UserSchedule) router.use("/history", historyValue) router.use("/contact", contact) -router.use("/brand-sparepart", brandSparePart) router.use("/notification", notification) diff --git a/services/brand.service.js b/services/brand.service.js index 2ebfc5e..3fb2b2e 100644 --- a/services/brand.service.js +++ b/services/brand.service.js @@ -17,6 +17,14 @@ const { deleteErrorCodeDb, } = require('../db/brand_code.db'); +// Sparepart operations +const { + getSparePartnsByErrorCodeIdDb, + createSparePartDb, + updateSparePartDb, + deleteSparePartDb, +} = require('../db/brand_sparepart.db'); + // Solution operations const { getSolutionsByErrorCodeIdDb, @@ -24,25 +32,21 @@ const { updateSolutionDb, deleteSolutionDb, } = require('../db/brand_code_solution.db'); + const { getFileUploadByPathDb } = require('../db/file_uploads.db'); const { ErrorHandler } = require('../helpers/error'); class BrandService { - // Get all brands + static async getAllBrands(param) { try { const results = await getAllBrandsDb(param); - - results.data.map(element => { - }); - return results; } catch (error) { throw new ErrorHandler(error.statusCode, error.message); } } - // Get brand by ID with complete data static async getBrandById(id) { try { const brand = await getBrandByIdDb(id); @@ -50,123 +54,109 @@ class BrandService { const errorCodes = await getErrorCodesByBrandIdDb(brand.brand_id); - const errorCodesWithSolutions = await Promise.all( + const errorCodesWithDetails = await Promise.all( errorCodes.map(async (errorCode) => { const solutions = await getSolutionsByErrorCodeIdDb(errorCode.error_code_id); - const solutionsWithFiles = await Promise.all( - solutions.map(async (solution) => { + const solutionsWithFile = await Promise.all( + solutions.map(async (s) => { 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); + if (s.path_solution && s.type_solution !== "text") { + fileData = await getFileUploadByPathDb(s.path_solution); } - const enhancedSolution = { - ...solution, + return { + ...s, 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; }) ); + const spareparts = await getSparePartnsByErrorCodeIdDb(errorCode.error_code_id); + return { ...errorCode, - solution: solutionsWithFiles + solution: solutionsWithFile, + sparepart: spareparts }; }) ); return { ...brand, - error_code: errorCodesWithSolutions + error_code: errorCodesWithDetails }; + } catch (error) { throw new ErrorHandler(error.statusCode, error.message); } } - // Create brand static async createBrandWithFullData(data) { try { - if (!data || typeof data !== 'object') data = {}; + if (!data || typeof data !== "object") data = {}; if (data.brand_name) { - const brandExists = await checkBrandNameExistsDb(data.brand_name); - if (brandExists) { - throw new ErrorHandler(400, 'Brand name already exists'); + const exists = await checkBrandNameExistsDb(data.brand_name); + if (exists) throw new ErrorHandler(400, "Brand name already exists"); + } + + if (!data.error_code || !Array.isArray(data.error_code)) { + throw new ErrorHandler(400, "Brand must have at least 1 error code"); + } + + for (const ec of data.error_code) { + if (!ec.solution || ec.solution.length === 0) { + throw new ErrorHandler(400, `Error code ${ec.error_code} must have at least 1 solution`); } } - if (!data.error_code || !Array.isArray(data.error_code) || data.error_code.length === 0) { - throw new ErrorHandler(400, 'Brand must have at least 1 error code with solution'); - } - - for (const errorCode of data.error_code) { - if (!errorCode.solution || !Array.isArray(errorCode.solution) || errorCode.solution.length === 0) { - throw new ErrorHandler(400, `Error code ${errorCode.error_code} must have at least 1 solution`); - } - } - - const brandData = { + const createdBrand = await createBrandDb({ brand_name: data.brand_name, brand_type: data.brand_type, brand_manufacture: data.brand_manufacture, brand_model: data.brand_model, is_active: data.is_active, created_by: data.created_by - }; - - const createdBrand = await createBrandDb(brandData); - if (!createdBrand) { - throw new Error('Failed to create brand'); - } + }); const brandId = createdBrand.brand_id; - - for (const errorCodeData of data.error_code) { + for (const ec of data.error_code) { const errorId = await createErrorCodeDb(brandId, { - error_code: errorCodeData.error_code, - error_code_name: errorCodeData.error_code_name, - error_code_description: errorCodeData.error_code_description, - error_code_color: errorCodeData.error_code_color, - path_icon: errorCodeData.path_icon, - is_active: errorCodeData.is_active, + error_code: ec.error_code, + error_code_name: ec.error_code_name, + error_code_description: ec.error_code_description, + error_code_color: ec.error_code_color, + path_icon: ec.path_icon, + is_active: ec.is_active, created_by: data.created_by }); - if (!errorId) { - throw new Error('Failed to create error code'); + for (const s of ec.solution) { + await createSolutionDb(errorId, { + solution_name: s.solution_name, + type_solution: s.type_solution, + text_solution: s.text_solution || null, + path_solution: s.path_solution || null, + is_active: s.is_active, + created_by: data.created_by + }); } - // Create solutions for this error code - if (errorCodeData.solution && Array.isArray(errorCodeData.solution)) { - for (const solutionData of errorCodeData.solution) { - await createSolutionDb(errorId, { - 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, + if (Array.isArray(ec.sparepart)) { + for (const sp of ec.sparepart) { + await createSparePartDb(errorId, { + sparepart_name: sp.sparepart_name, + brand_sparepart_description: sp.brand_sparepart_description, + path_foto: sp.path_foto || null, + is_active: sp.is_active, created_by: data.created_by }); } } + } return await this.getBrandById(brandId); @@ -176,143 +166,143 @@ class BrandService { } } - // Soft delete brand by ID - static async deleteBrand(id, userId) { - try { - const brandExist = await getBrandByIdDb(id); - - if (!brandExist) { - throw new ErrorHandler(404, 'Brand not found'); - } - - const result = await deleteBrandDb(id, userId); - - return result; - } catch (error) { - throw new ErrorHandler(error.statusCode, error.message); - } - } - - // Update brand static async updateBrandWithFullData(id, data) { try { - const existingBrand = await getBrandByIdDb(id); - if (!existingBrand) throw new ErrorHandler(404, 'Brand not found'); + const existingBrand = await getBrandByIdDb(id); + if (!existingBrand) throw new ErrorHandler(404, "Brand not found"); - if (data.brand_name && data.brand_name !== existingBrand.brand_name) { - const brandExists = await checkBrandNameExistsDb(data.brand_name, id); - if (brandExists) { - throw new ErrorHandler(400, 'Brand name already exists'); + await updateBrandDb(existingBrand.brand_name, { + brand_name: data.brand_name, + brand_type: data.brand_type, + brand_manufacture: data.brand_manufacture, + brand_model: data.brand_model, + is_active: data.is_active, + updated_by: data.updated_by + }); + + if (!data.error_code) return await this.getBrandById(id); + + const existingErrorCodes = await getErrorCodesByBrandIdDb(id); + + const incomingErrorCodes = data.error_code.map(ec => ec.error_code); + + for (const ec of data.error_code) { + const existsEC = existingErrorCodes.find(e => e.error_code === ec.error_code); + + let errorId = null; + + if (existsEC) { + await updateErrorCodeDb(existingBrand.brand_id, existsEC.error_code, { + error_code_name: ec.error_code_name, + error_code_description: ec.error_code_description, + error_code_color: ec.error_code_color, + path_icon: ec.path_icon, + is_active: ec.is_active, + updated_by: data.updated_by + }); + errorId = existsEC.error_code_id; + } else { + errorId = await createErrorCodeDb(id, { + error_code: ec.error_code, + error_code_name: ec.error_code_name, + error_code_description: ec.error_code_description, + error_code_color: ec.error_code_color, + path_icon: ec.path_icon, + is_active: ec.is_active, + created_by: data.updated_by + }); + } + + const existingSolutions = await getSolutionsByErrorCodeIdDb(errorId); + const incomingSolutionNames = ec.solution?.map(s => s.solution_name) || []; + + for (const s of ec.solution || []) { + const existsSolution = existingSolutions.find(es => es.solution_name === s.solution_name); + + if (existsSolution) { + await updateSolutionDb(existsSolution.brand_code_solution_id, { + solution_name: s.solution_name, + type_solution: s.type_solution, + text_solution: s.text_solution || null, + path_solution: s.path_solution || null, + is_active: s.is_active, + updated_by: data.updated_by + }); + } else { + await createSolutionDb(errorId, { + solution_name: s.solution_name, + type_solution: s.type_solution, + text_solution: s.text_solution || null, + path_solution: s.path_solution || null, + is_active: s.is_active, + created_by: data.updated_by + }); } } - const brandData = { - brand_name: data.brand_name, - brand_type: data.brand_type, - brand_manufacture: data.brand_manufacture, - brand_model: data.brand_model, - is_active: data.is_active, - updated_by: data.updated_by - }; - - await updateBrandDb(existingBrand.brand_name, brandData); - - 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) { - // Check if error code already exists - const existingEC = existingErrorCodes.find(ec => ec.error_code === errorCodeData.error_code); - - if (existingEC) { - // Update existing error code using separate db function - await updateErrorCodeDb(existingEC.brand_id, existingEC.error_code, { - error_code_name: errorCodeData.error_code_name, - error_code_description: errorCodeData.error_code_description, - error_code_color: errorCodeData.error_code_color, - path_icon: errorCodeData.path_icon, - is_active: errorCodeData.is_active, - updated_by: data.updated_by - }); - - 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) { - 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 { - const errorId = await createErrorCodeDb(id, { - error_code: errorCodeData.error_code, - error_code_name: errorCodeData.error_code_name, - error_code_description: errorCodeData.error_code_description, - error_code_color: errorCodeData.error_code_color, - path_icon: errorCodeData.path_icon, - is_active: errorCodeData.is_active, - created_by: data.updated_by - }); - - if (errorCodeData.solution && Array.isArray(errorCodeData.solution)) { - for (const solutionData of errorCodeData.solution) { - await createSolutionDb(errorId, { - 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 - }); - } - } - } - } - - for (const existingEC of existingErrorCodes) { - if (!incomingErrorCodes.includes(existingEC.error_code)) { - await deleteErrorCodeDb(id, existingEC.error_code, data.updated_by); - } + for (const es of existingSolutions) { + if (!incomingSolutionNames.includes(es.solution_name)) { + await deleteSolutionDb(es.brand_code_solution_id, data.updated_by); } } + const existingSpareparts = await getSparePartnsByErrorCodeIdDb(errorId); + const incomingSparepartNames = ec.sparepart?.map(sp => sp.sparepart_name) || []; + + for (const sp of ec.sparepart || []) { + const existsSP = existingSpareparts.find(es => es.sparepart_name === sp.sparepart_name); + + if (existsSP) { + await updateSparePartDb(existsSP.brand_sparepart_id, { + sparepart_name: sp.sparepart_name, + brand_sparepart_description: sp.brand_sparepart_description, + path_foto: sp.path_foto || null, + is_active: sp.is_active, + updated_by: data.updated_by + }); + } else { + await createSparePartDb(errorId, { + sparepart_name: sp.sparepart_name, + brand_sparepart_description: sp.brand_sparepart_description, + path_foto: sp.path_foto || null, + is_active: sp.is_active, + created_by: data.updated_by + }); + } + } + + for (const es of existingSpareparts) { + if (!incomingSparepartNames.includes(es.sparepart_name)) { + await deleteSparePartDb(es.brand_sparepart_id, data.updated_by); + } + } + + } + + for (const ec of existingErrorCodes) { + if (!incomingErrorCodes.includes(ec.error_code)) { + await deleteErrorCodeDb(id, ec.error_code, data.updated_by); + } + } + return await this.getBrandById(id); + } catch (error) { throw new ErrorHandler(500, `Update failed: ${error.message}`); } } + + static async deleteBrand(id, userId) { + try { + const exist = await getBrandByIdDb(id); + if (!exist) throw new ErrorHandler(404, "Brand not found"); + + return await deleteBrandDb(id, userId); + + } catch (error) { + throw new ErrorHandler(error.statusCode, error.message); + } + } } -module.exports = BrandService; \ No newline at end of file +module.exports = BrandService; diff --git a/services/brand_sparepart.service.js b/services/brand_sparepart.service.js deleted file mode 100644 index 8926286..0000000 --- a/services/brand_sparepart.service.js +++ /dev/null @@ -1,106 +0,0 @@ -const { - getAllBrandSparepartsDb, - getBrandSparepartByIdDb, - createBrandSparepartDb, - updateBrandSparepartDb, - deleteBrandSparepartDb, - checkBrandSparepartNameExistsDb, -} = require('../db/brand_sparepart.db'); - -const { ErrorHandler } = require('../helpers/error'); - -class BrandSparepartService { - static async getAllBrandSparepart(param) { - try { - const results = await getAllBrandSparepartsDb(param); - results.data.map((item) => {}); - return results; - } catch (error) { - throw new ErrorHandler(error.statusCode || 500, error.message); - } - } - - static async getBrandSparepartById(id) { - try { - const brandSparepart = await getBrandSparepartByIdDb(id); - if (!brandSparepart) throw new ErrorHandler(404, 'Brand sparepart not found'); - return brandSparepart; - } catch (error) { - throw new ErrorHandler(error.statusCode || 500, error.message); - } - } - - static async createBrandSparepart(data) { - try { - if (!data || typeof data !== 'object') data = {}; - - if (data.sparepart_name) { - const exists = await checkBrandSparepartNameExistsDb(data.sparepart_name); - if (exists) throw new ErrorHandler(400, 'Brand sparepart name already exists'); - } - - const insertData = { - sparepart_name: data.sparepart_name, - brand_sparepart_description: data.brand_sparepart_description, - path_foto: data.path_foto, - error_code_id: data.error_code_id, - is_active: data.is_active, - created_by: data.created_by, - }; - - const created = await createBrandSparepartDb(insertData); - if (!created) throw new ErrorHandler(500, 'Failed to create brand sparepart'); - - return created; - } catch (error) { - throw new ErrorHandler(error.statusCode || 500, error.message); - } - } - - static async updateBrandSparepart(id, data) { - try { - const existing = await getBrandSparepartByIdDb(id); - if (!existing) throw new ErrorHandler(404, 'Brand sparepart not found'); - - if ( - data.sparepart_name && - data.sparepart_name !== existing.sparepart_name - ) { - const exists = await checkBrandSparepartNameExistsDb(data.sparepart_name, id); - if (exists) throw new ErrorHandler(400, 'Brand sparepart name already exists'); - } - - const updateData = { - sparepart_name: data.sparepart_name, - brand_sparepart_description: data.brand_sparepart_description, - path_foto: data.path_foto || existing.path_foto, - error_code_id: data.error_code_id, - is_active: data.is_active ?? existing.is_active, - updated_by: data.updated_by || null, - }; - - const updated = await updateBrandSparepartDb(id, updateData); - if (!updated) throw new ErrorHandler(500, 'Failed to update brand sparepart'); - - return await this.getBrandSparepartById(id); - } catch (error) { - throw new ErrorHandler(error.statusCode || 500, error.message); - } - } - - static async deleteBrandSparepart(id, userId) { - try { - const existing = await getBrandSparepartByIdDb(id); - if (!existing) throw new ErrorHandler(404, 'Brand sparepart not found'); - - const deleted = await deleteBrandSparepartDb(id, userId); - if (!deleted) throw new ErrorHandler(500, 'Failed to delete brand sparepart'); - - return deleted; - } catch (error) { - throw new ErrorHandler(error.statusCode || 500, error.message); - } - } -} - -module.exports = BrandSparepartService; diff --git a/validate/brand.schema.js b/validate/brand.schema.js index 1f07a6f..b9209ad 100644 --- a/validate/brand.schema.js +++ b/validate/brand.schema.js @@ -4,81 +4,120 @@ const Joi = require("joi"); // Brand Validation // ======================== const insertBrandSchema = Joi.object({ - brand_name: Joi.string().max(100).required(), - 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().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().allow(''), - error_code_color: Joi.string().optional().allow(''), - path_icon: 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(), - type_solution: Joi.string().valid('text', 'pdf', 'image', 'video', 'link').required(), - text_solution: Joi.when('type_solution', { - is: 'text', - then: Joi.string().required(), - otherwise: Joi.string().optional().allow('') - }), - path_solution: Joi.when('type_solution', { - is: 'text', - then: Joi.string().optional().allow(''), - otherwise: Joi.string().required() - }), - is_active: Joi.boolean().required() - }) - ).min(1).required() - }) - ).min(1).required() + brand_name: Joi.string().max(100).required(), + 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().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().allow(""), + error_code_color: Joi.string().optional().allow(""), + path_icon: 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(), + type_solution: Joi.string() + .valid("text", "pdf", "image", "video", "link") + .required(), + text_solution: Joi.when("type_solution", { + is: "text", + then: Joi.string().required(), + otherwise: Joi.string().optional().allow(""), + }), + path_solution: Joi.when("type_solution", { + is: "text", + then: Joi.string().optional().allow(""), + otherwise: Joi.string().required(), + }), + is_active: Joi.boolean().required(), + }) + ) + .min(1) + .required(), + sparepart: Joi.array() + .items( + Joi.object({ + sparepart_name: Joi.string().max(100).optional(), + brand_sparepart_description: Joi.string() + .max(255) + .optional(), + path_foto: Joi.string().optional().allow(""), + is_active: Joi.boolean().required(), + }) + ) + .optional(), + }) + ) + .min(1) + .required(), }); // Update Brand Validation const updateBrandSchema = Joi.object({ - brand_name: Joi.string().max(100).required(), - 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().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().allow(''), - error_code_color: Joi.string().optional().allow(''), - path_icon: 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(), - type_solution: Joi.string().valid('text', 'pdf', 'image', 'video', 'link').required(), - text_solution: Joi.when('type_solution', { - is: 'text', - then: Joi.string().required(), - otherwise: Joi.string().optional().allow('') - }), - path_solution: Joi.when('type_solution', { - is: 'text', - then: Joi.string().optional().allow(''), - otherwise: Joi.string().required() - }), - is_active: Joi.boolean().optional() - }) - ).min(1).required() - }) - ).optional() + brand_name: Joi.string().max(100).required(), + 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().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().allow(""), + error_code_color: Joi.string().optional().allow(""), + path_icon: 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(), + type_solution: Joi.string() + .valid("text", "pdf", "image", "video", "link") + .required(), + text_solution: Joi.when("type_solution", { + is: "text", + then: Joi.string().required(), + otherwise: Joi.string().optional().allow(""), + }), + path_solution: Joi.when("type_solution", { + is: "text", + then: Joi.string().optional().allow(""), + otherwise: Joi.string().required(), + }), + is_active: Joi.boolean().optional(), + }) + ) + .min(1) + .required(), + sparepart: Joi.array() + .items( + Joi.object({ + sparepart_name: Joi.string().max(100).optional(), + brand_sparepart_description: Joi.string() + .max(255) + .optional(), + path_foto: Joi.string().optional().allow(""), + is_active: Joi.boolean().required(), + }) + ) + .optional(), + }) + ) + .optional(), }).min(1); module.exports = { - insertBrandSchema, - updateBrandSchema -}; \ No newline at end of file + insertBrandSchema, + updateBrandSchema, +}; diff --git a/validate/brand_sparepart.schema.js b/validate/brand_sparepart.schema.js deleted file mode 100644 index 757b05a..0000000 --- a/validate/brand_sparepart.schema.js +++ /dev/null @@ -1,32 +0,0 @@ -const Joi = require("joi"); - -// ======================== -// Brand Validation -// ======================== -const insertBrandSparepartSchema = Joi.object({ - sparepart_name: Joi.string().max(255).required(), - brand_sparepart_description: Joi.string().max(255).required(), - is_active: Joi.boolean().required(), - error_code_id: Joi.number().required().messages({ - "any.required": "error_code_id is required", - "number.base": "error_code_id must be a number", - }), - path_foto: Joi.string().max(255).optional().allow(''), -}); - -// Update Brand Validation -const updateBrandSparepartSchema = Joi.object({ - sparepart_name: Joi.string().max(255).required(), - brand_sparepart_description: Joi.string().max(255).required(), - is_active: Joi.boolean().optional(), - error_code_id: Joi.number().required().messages({ - "any.required": "error_code_id is required", - "number.base": "error_code_id must be a number", - }), - path_foto: Joi.string().max(255).optional().allow(''), -}); - -module.exports = { - insertBrandSparepartSchema, - updateBrandSparepartSchema, -};