const asyncHandler = require("../Middleware/async"); const sequelize = require("sequelize"); const DBInfo = require("../Model/Database"); const ItemModel = require("../Model/ItemModel"); const CategoryModel = require("../Model/CategoryModel"); const SupplierItemModel = require("../Model/SupplierItemModel"); const ErrorResponse = require("../utils/ErrorResponse"); const SuccessResponse = require("../utils/SuccessResponse"); const fs = require("fs"); const dateFormat = require("dateformat"); const path = require("path"); const { log } = require("console"); const CategoryDetail = require("../Model/CategoryDetailModel"); exports.getAllItemsByStore = asyncHandler(async (req, res, next) => { try { let items = await ItemModel.findAll({ where: { DB_CODE: req.user.DB_CODE, }, }); console.log("DB CODE ", req.user.DB_CODE); const folderPath = path.join( process.env.ITEM_IMAGE_LOCATION, req.user.DB_CODE ); // Use Promise.all to wait for all promises to resolve items = await Promise.all( items.map(async (item) => { let itemObject = item.get({ plain: true }); try { // Get category name var category = await CategoryDetail.findOne({ where: { ID: item.CAT_CODE, // DB_CODE: req.user.DB_CODE }, }); if (category) { itemObject.CAT_DESC_EN = category.DESC_EN; itemObject.CAT_DESC_KH = category.DESC_KH; itemObject.CAT_DESC_CN = category.DESC_CN; } } catch (catErr) { console.error("Error fetching category", catErr); // Optionally handle specific category fetch error } // Check existence of the image file const imagePath = path.join(folderPath, `${item.ITEM_CODE}.jpg`); itemObject.ITEM_IMG = fs.existsSync(imagePath) ? imagePath : ""; return itemObject; }) ); res.status(200).send({ success: true, data: items, }); } catch (err) { console.error("ERROR GET ALL ITEMS", err); return next(new ErrorResponse(err.message, 400)); } }); exports.createItemByStore = asyncHandler(async (req, res, next) => { try { var date = dateFormat(new Date(), "yyyy-mm-dd HH:mm:ss"); const data = JSON.parse(req.body["data"]); const items = data["items"]; var photo = req.file.path; let imageData = fs.readFileSync(req.file.path); const itemCode = items["ITEM_CODE"]; const itemBarCode = items["ITEM_BCODE"]; const itemDes = items["ITEM_DESC"]; const unitStock = items["UNIT_STOCK"] ?? "1"; const unitSale = items["UNIT_SALE"] ?? "1"; const catCode = items["CATE_CODE"]; // CAT_CODE -> CAT_DETAIL_ID const supplierCode = items["SUPP_CODE"]; const itemCost1 = items["ITEM_COST1"]; const itemPrice1 = items["ITEM_PRICE1"]; if (!itemBarCode || !itemDes || !catCode || !itemCost1 || !itemPrice1) { throw "Please provide all required fields"; } // var itemCode = await generateNextItemCode(); const existingItem = await ItemModel.findOne({ where: { ITEM_CODE: itemCode, DB_CODE: req.user.DB_CODE, }, }); if (existingItem) { throw `ITEM_CODE ${itemCode} already exists`; } await ItemModel.sequelize.transaction(async (t) => { const item = await ItemModel.create({ ITEM_CODE: itemCode, ITEM_BCODE: itemBarCode, ITEM_DESC: itemDes, DB_CODE: req.user.DB_CODE, UNIT_STOCK: unitStock, UNIT_SALE: unitSale, CAT_CODE: catCode, ITEM_STAT: "A", USER_CREA: req.user.USER_NAME, DATE_CREA: date.toString(), ITEM_TYPE: "S", // S -> Kit Stock N -> Min Kit Stock I-> ដំណើរការទំនិញ ITEM_PRICE1: itemPrice1, ITEM_COST1: itemCost1, ITEM_COST2: 0, ITEM_PRICE2: 0, ITEM_CUS1: "", ITEM_CUS2: "", ITEM_CUS3: "", ITEM_CUS4: "", ITEM_CUS5: "", ITEM_CUS6: "", ITEM_CUS7: "", ITEM_CUS8: "", ITEM_CUS9_KH: "", ITEM_CUS10_KH: "", USER_UPDT: req.user.USER_NAME, DATE_UPDT: date, }); // add to TDITEMSP table await SupplierItemModel.create({ ITEM_CODE: itemCode, DB_CODE: req.user.DB_CODE, SUPP_CODE: supplierCode, SUPP_COST: itemCost1, SUPP_UNIT: "1", }); let folderPath = process.env.ITEM_IMAGE_LOCATION + "/" + req.user.DB_CODE + "/"; if (!fs.existsSync(folderPath)) fs.mkdirSync(folderPath, { recursive: true, }); log("ITEM CODE ", item.ITEM_CODE); fs.writeFileSync(folderPath + item.ITEM_CODE + ".jpg", imageData); fs.unlinkSync(req.file.path); res.send(new SuccessResponse("Operation Successful")); }); } catch (err) { console.log("ERROR CREATE ITEM", err); fs.unlinkSync(req.file.path); return next(new ErrorResponse(err, 400)); } }); exports.updateByItemCode = asyncHandler(async (req, res, next) => { try { const itemCode = req.params.item_code; const updateData = req.body; const item = await ItemModel.findOne({ where: { ITEM_CODE: itemCode, DB_CODE: req.user.DB_CODE }, }); if (!item) { return next(new ErrorResponse("Item not found", 404)); } await item.update(updateData); res.status(200).send({ success: true, data: item, }); } catch (err) { console.error("ERROR UPDATE ITEM", err); return next(new ErrorResponse(err.message, 400)); } }); exports.deleteByItemCode = asyncHandler(async (req, res, next) => { try { const itemCode = req.params.item_code; const item = await ItemModel.findOne({ where: { ITEM_CODE: itemCode, DB_CODE: req.user.DB_CODE }, }); if (!item) { return next(new ErrorResponse("Item not found", 404)); } // check user permission to delete item await item.destroy(); res.status(200).send({ success: true, data: {}, message: `Item with ITEM_CODE ${itemCode} deleted successfully`, }); } catch (err) { console.error("ERROR DELETE ITEM", err); return next(new ErrorResponse(err.message, 400)); } }); exports.checkIfItemExist = asyncHandler(async (req, res, next) => { try { const item = await ItemModel.findOne({ where: { ITEM_CODE: req.params.item_code, DB_CODE: req.user.DB_CODE, }, }); if (!item) { return next(new ErrorResponse("Item not found", 400)); } res.status(200).send({ success: true, data: item, }); } catch (err) { console.log("ERROR CHECK ITEM", err); return next(new ErrorResponse(err, 400)); } }); async function generateNextItemCode() { try { const lastItem = await ItemModel.findOne({ order: [["ITEM_CODE", "DESC"]], }); console.log("LAST ITEM ", lastItem); if (!lastItem) { return "0001"; // Starting point if no suppliers are present } console.log("LAST ITEM CODE ", lastItem.ITEM_CODE); let nextCode = parseInt(lastItem.ITEM_CODE, 10) + 1; console.log("NEXT CODE ", nextCode); // Check if the number is less than 10000 for zero-padding if (nextCode < 10000) { return nextCode.toString().padStart(4, "0"); } else { // If it's 10000 or more, just return the number return nextCode.toString(); } } catch (e) { console.log("CATCH ERROR IN GENERATE ITEM CODE ", e); } }