add: error_code api

This commit is contained in:
2025-12-02 15:22:20 +07:00
parent feff905d8f
commit f797685a4f
6 changed files with 488 additions and 55 deletions

View File

@@ -0,0 +1,105 @@
const ErrorCodeService = require('../services/error_code.service');
const { setResponse, setResponsePaging } = require('../helpers/utils');
const { ErrorHandler } = require('../helpers/error');
class ErrorCodeController {
// Get all error codes with pagination and search
static async getAll(req, res) {
try {
const queryParams = req.query;
const results = await ErrorCodeService.getAllErrorCodes(queryParams);
const response = await setResponsePaging(queryParams, results, 'Error codes found');
res.status(response.statusCode).json(response);
} catch (error) {
const response = setResponse(error.message, error.statusCode || 500);
res.status(response.statusCode).json(response);
}
}
// Get error code by ID
static async getById(req, res) {
try {
const { id } = req.params;
const result = await ErrorCodeService.getErrorCodeById(id);
const response = setResponse(result, 200, 'Error code found');
res.status(response.statusCode).json(response);
} catch (error) {
const response = setResponse(error.message, error.statusCode || 500);
res.status(response.statusCode).json(response);
}
}
// Get error codes by brand ID with pagination and search
static async getByBrandId(req, res) {
try {
const { brandId } = req.params;
const queryParams = {
...req.query,
brand_id: brandId
};
const results = await ErrorCodeService.getAllErrorCodes(queryParams);
const response = await setResponsePaging(queryParams, results, 'Error codes found');
res.status(response.statusCode).json(response);
} catch (error) {
const response = setResponse(error.message, error.statusCode || 500);
res.status(response.statusCode).json(response);
}
}
// Create error code with solutions and spareparts
static async create(req, res) {
try {
const { brandId } = req.params;
const createdBy = req.user?.user_id || null;
const data = {
...req.body,
created_by: createdBy
};
const result = await ErrorCodeService.createErrorCodeWithFullData(brandId, data);
const response = setResponse(result, 201, 'Error code created successfully');
res.status(response.statusCode).json(response);
} catch (error) {
const response = setResponse(error.message, error.statusCode || 500);
res.status(response.statusCode).json(response);
}
}
// Update error code with solutions and spareparts
static async update(req, res) {
try {
const { brandId, errorCode } = req.params;
const updatedBy = req.user?.user_id || null;
const data = {
...req.body,
updated_by: updatedBy
};
const result = await ErrorCodeService.updateErrorCodeWithFullData(brandId, errorCode, data);
const response = setResponse(result, 200, 'Error code updated successfully');
res.status(response.statusCode).json(response);
} catch (error) {
const response = setResponse(error.message, error.statusCode || 500);
res.status(response.statusCode).json(response);
}
}
// Soft delete error code
static async delete(req, res) {
try {
const { brandId, errorCode } = req.params;
const deletedBy = req.user?.user_id || null;
const result = await ErrorCodeService.deleteErrorCode(brandId, errorCode, deletedBy);
const response = setResponse(result, 200, 'Error code deleted successfully');
res.status(response.statusCode).json(response);
} catch (error) {
const response = setResponse(error.message, error.statusCode || 500);
res.status(response.statusCode).json(response);
}
}
}
module.exports = ErrorCodeController;

View File

@@ -64,10 +64,76 @@ const getErrorCodeByIdDb = async (error_code_id) => {
return result.recordset[0];
};
const getErrorCodeByBrandAndCodeDb = 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];
};
// Get all error codes with pagination and search
const getAllErrorCodesDb = async (searchParams = {}) => {
let queryParams = [];
// Pagination
if (searchParams.limit) {
const page = Number(searchParams.page ?? 1) - 1;
queryParams = [Number(searchParams.limit ?? 10), page];
}
// Search across multiple columns
const { whereOrConditions, whereParamOr } = pool.buildStringOrIlike(
["a.error_code", "a.error_code_name", "a.error_code_description"],
searchParams.criteria,
queryParams
);
queryParams = whereParamOr ? whereParamOr : queryParams;
// Filter conditions
const { whereConditions, whereParamAnd } = pool.buildFilterQuery(
[
{ column: "a.is_active", param: searchParams.status, type: "string" },
{ column: "a.brand_id", param: searchParams.brand_id, type: "number" },
],
queryParams
);
queryParams = whereParamAnd ? whereParamAnd : queryParams;
const queryText = `
SELECT
COUNT(*) OVER() AS total_data,
a.*,
b.brand_name,
b.brand_type,
b.brand_manufacture,
b.brand_model
FROM brand_code a
LEFT JOIN m_brands b ON a.brand_id = b.brand_id
WHERE a.deleted_at IS NULL
${whereConditions.length > 0 ? `AND ${whereConditions.join(' AND ')}` : ''}
${whereOrConditions ? whereOrConditions : ''}
ORDER BY a.error_code_id DESC
${searchParams.limit ? `OFFSET $2 * $1 ROWS FETCH NEXT $1 ROWS ONLY` : ''}
`;
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 };
};
module.exports = {
getErrorCodesByBrandIdDb,
getErrorCodeByIdDb,
getErrorCodeByBrandAndCodeDb,
createErrorCodeDb,
updateErrorCodeDb,
deleteErrorCodeDb,
getAllErrorCodesDb,
};

View File

@@ -0,0 +1,19 @@
const express = require('express');
const ErrorCodeController = require('../controllers/error_code.controller');
const verifyToken = require('../middleware/verifyToken');
const verifyAccess = require('../middleware/verifyAccess');
const router = express.Router();
router.route('/brand/:brandId')
.get(verifyToken.verifyAccessToken, ErrorCodeController.getByBrandId)
.post(verifyToken.verifyAccessToken, verifyAccess(), ErrorCodeController.create);
router.route('/brand/:brandId/:errorCode')
.put(verifyToken.verifyAccessToken, verifyAccess(), ErrorCodeController.update)
.delete(verifyToken.verifyAccessToken, verifyAccess(), ErrorCodeController.delete);
router.route('/:id')
.get(verifyToken.verifyAccessToken, ErrorCodeController.getById);
module.exports = router;

View File

@@ -18,6 +18,7 @@ const notificationError = require("./notification_error.route")
const notificationErrorSparepart = require("./notification_error_sparepart.route")
const sparepart = require("./sparepart.route")
const notificationErrorLog = require("./notification_error_log.route")
const errorCode = require("./error_code.route")
router.use("/auth", auth);
router.use("/user", users);
@@ -38,5 +39,6 @@ router.use("/notification", notificationError)
router.use("/notification-sparepart", notificationErrorSparepart)
router.use("/sparepart", sparepart)
router.use("/notification-log", notificationErrorLog)
router.use("/error-code", errorCode)
module.exports = router;

View File

@@ -51,66 +51,13 @@ class BrandService {
}
}
// Get brand by ID with complete data
// Get brand by ID (without error codes)
static async getBrandById(id) {
try {
const brand = await getBrandByIdDb(id);
if (!brand) throw new ErrorHandler(404, "Brand not found");
const errorCodes = await getErrorCodesByBrandIdDb(brand.brand_id);
const errorCodesWithSolutionsAndSpareparts = await Promise.all(
errorCodes.map(async (errorCode) => {
const solutions = await getSolutionsByErrorCodeIdDb(
errorCode.error_code_id
);
// Get spareparts for this error code
const errorCodeSpareparts = await getSparepartsByErrorCodeIdDb(errorCode.error_code_id);
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);
}
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;
})
);
return {
...errorCode,
solution: solutionsWithFiles,
spareparts: errorCodeSpareparts,
};
})
);
return {
...brand,
error_code: errorCodesWithSolutionsAndSpareparts,
};
return brand;
} catch (error) {
throw new ErrorHandler(error.statusCode, error.message);
}

View File

@@ -0,0 +1,294 @@
const { ErrorHandler } = require("../helpers/error");
const {
getErrorCodesByBrandIdDb,
getErrorCodeByIdDb,
getErrorCodeByBrandAndCodeDb,
createErrorCodeDb,
updateErrorCodeDb,
deleteErrorCodeDb,
getAllErrorCodesDb,
} = require("../db/brand_code.db");
const {
getSolutionsByErrorCodeIdDb,
createSolutionDb,
updateSolutionDb,
deleteSolutionDb,
} = require("../db/brand_code_solution.db");
const {
getSparepartsByErrorCodeIdDb,
insertMultipleErrorCodeSparepartsDb,
updateErrorCodeSparepartsDb,
} = require("../db/brand_sparepart.db");
const { getFileUploadByPathDb } = require("../db/file_uploads.db");
class ErrorCodeService {
// Get all error codes with pagination and search
static async getAllErrorCodes(param) {
try {
const results = await getAllErrorCodesDb(param);
// Enhance with solutions and spareparts for each error code
const errorCodesWithDetails = await Promise.all(
results.data.map(async (errorCode) => {
const solutions = await getSolutionsByErrorCodeIdDb(errorCode.error_code_id);
const spareparts = await getSparepartsByErrorCodeIdDb(errorCode.error_code_id);
const solutionsWithFiles = await Promise.all(
solutions.map(async (solution) => {
let fileData = null;
if (solution.path_solution && solution.type_solution !== "text") {
fileData = await getFileUploadByPathDb(solution.path_solution);
}
return {
...solution,
file_upload_name: fileData?.file_upload_name || null,
path_document: fileData?.path_document || null,
};
})
);
return {
...errorCode,
solution: solutionsWithFiles,
spareparts: spareparts,
};
})
);
return {
...results,
data: errorCodesWithDetails,
};
} catch (error) {
throw new ErrorHandler(error.statusCode, error.message);
}
}
// Get error code by ID with complete data
static async getErrorCodeById(id) {
try {
const errorCode = await getErrorCodeByIdDb(id);
if (!errorCode) throw new ErrorHandler(404, "Error code not found");
const solutions = await getSolutionsByErrorCodeIdDb(errorCode.error_code_id);
const spareparts = await getSparepartsByErrorCodeIdDb(errorCode.error_code_id);
const solutionsWithFiles = await Promise.all(
solutions.map(async (solution) => {
let fileData = null;
if (solution.path_solution && solution.type_solution !== "text") {
fileData = await getFileUploadByPathDb(solution.path_solution);
}
return {
...solution,
file_upload_name: fileData?.file_upload_name || null,
path_document: fileData?.path_document || null,
};
})
);
return {
...errorCode,
solution: solutionsWithFiles,
spareparts: spareparts,
};
} catch (error) {
throw new ErrorHandler(error.statusCode, error.message);
}
}
// Get error codes by brand ID
static async getErrorCodesByBrandId(brandId) {
try {
const errorCodes = await getErrorCodesByBrandIdDb(brandId);
const errorCodesWithDetails = await Promise.all(
errorCodes.map(async (errorCode) => {
const solutions = await getSolutionsByErrorCodeIdDb(errorCode.error_code_id);
const spareparts = await getSparepartsByErrorCodeIdDb(errorCode.error_code_id);
const solutionsWithFiles = await Promise.all(
solutions.map(async (solution) => {
let fileData = null;
if (solution.path_solution && solution.type_solution !== "text") {
fileData = await getFileUploadByPathDb(solution.path_solution);
}
return {
...solution,
file_upload_name: fileData?.file_upload_name || null,
path_document: fileData?.path_document || null,
};
})
);
return {
...errorCode,
solution: solutionsWithFiles,
spareparts: spareparts,
};
})
);
return errorCodesWithDetails;
} catch (error) {
throw new ErrorHandler(error.statusCode, error.message);
}
}
// Create error code with solutions and spareparts
static async createErrorCodeWithFullData(brandId, data) {
try {
if (!data || typeof data !== "object") data = {};
if (
!data.solution ||
!Array.isArray(data.solution) ||
data.solution.length === 0
) {
throw new ErrorHandler(
400,
"Error code must have at least 1 solution"
);
}
const errorId = await createErrorCodeDb(brandId, {
error_code: data.error_code,
error_code_name: data.error_code_name,
error_code_description: data.error_code_description,
error_code_color: data.error_code_color,
path_icon: data.path_icon,
is_active: data.is_active,
created_by: data.created_by,
});
if (!errorId) {
throw new Error("Failed to create error code");
}
// Create sparepart relationships for this error code
if (data.spareparts && Array.isArray(data.spareparts)) {
await insertMultipleErrorCodeSparepartsDb(errorId, data.spareparts, data.created_by);
}
// Create solutions for this error code
if (data.solution && Array.isArray(data.solution)) {
for (const solutionData of data.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.created_by,
});
}
}
const createdErrorCode = await this.getErrorCodeById(errorId);
return createdErrorCode;
} catch (error) {
throw new ErrorHandler(500, `Create error code failed: ${error.message}`);
}
}
// Update error code with solutions and spareparts
static async updateErrorCodeWithFullData(brandId, errorCode, data) {
try {
const existingErrorCode = await getErrorCodeByBrandAndCodeDb(brandId, errorCode);
if (!existingErrorCode) throw new ErrorHandler(404, "Error code not found");
// Update error code
await updateErrorCodeDb(brandId, errorCode, {
error_code_name: data.error_code_name,
error_code_description: data.error_code_description,
error_code_color: data.error_code_color,
path_icon: data.path_icon,
is_active: data.is_active,
updated_by: data.updated_by,
});
// Update spareparts if provided
if (data.spareparts && Array.isArray(data.spareparts)) {
await updateErrorCodeSparepartsDb(existingErrorCode.error_code_id, data.spareparts, data.updated_by);
}
// Update solutions if provided
if (data.solution && Array.isArray(data.solution)) {
const existingSolutions = await getSolutionsByErrorCodeIdDb(existingErrorCode.error_code_id);
const incomingSolutionNames = data.solution.map((s) => s.solution_name);
// Update or create solutions
for (const solutionData of data.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(existingErrorCode.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);
}
}
}
const updatedErrorCode = await this.getErrorCodeById(existingErrorCode.error_code_id);
return updatedErrorCode;
} catch (error) {
throw new ErrorHandler(500, `Update error code failed: ${error.message}`);
}
}
// Soft delete error code
static async deleteErrorCode(brandId, errorCode, deletedBy) {
try {
const errorCodeExist = await getErrorCodeByBrandAndCodeDb(brandId, errorCode);
if (!errorCodeExist) {
throw new ErrorHandler(404, "Error code not found");
}
const result = await deleteErrorCodeDb(brandId, errorCode, deletedBy);
return result;
} catch (error) {
throw new ErrorHandler(error.statusCode, error.message);
}
}
}
module.exports = ErrorCodeService;