const db = require("../models"); const Product = db.Product; const fs = require("fs"); const csv = require("csv-parser"); const path = require("path"); const UnitMaster = db.UnitMaster; exports.createProduct = async (req, res) => { try { const data = await Product.create(req.body); res.status(201).send({'status':"success",'message':"created successfully",'data': data }); } catch (error) { res.status(500).send({'status':"failed",'message':err.message }); } }; exports.getAllProducts = async (req, res) => { try { const data = await Product.findAll({ include: [ { model: UnitMaster, as: "unit", attributes: ["uom"], }, ], }); res.status(200).send({'status':"success",'message':"Fetched successfully",'product_count': data.length, 'data': data }); } catch (error) { res.status(500).send({'status':"failed",'message':err.message }); } }; exports.getProductById = async (req, res) => { try { const data = await Product.findByPk(req.params.id); if (!data) res.status(404).send({'status':"failed",'message':"Record Not found",'data': "" }); res.status(200).send({'status':"success",'message':"Fetched successfully",'data': data }); } catch (error) { res.status(500).send({'status':"failed",'message':err.message }); } }; exports.updateProduct = async (req, res) => { try { const [updated] = await Product.update(req.body, { where: { id: req.params.id } }); if (!updated) res.status(404).send({'status':"failed",'message':"Record Not found",'data': "" }); res.status(200).send({'status':"success",'message':"Updated successfully",'data': "" }); } catch (error) { res.status(500).send({'status':"failed",'message':err.message }); } }; exports.deleteProduct = async (req, res) => { try { const deleted = await Product.destroy({ where: { id: req.params.id } }); if (!deleted) res.status(404).send({'status':"failed",'message':"Record Not found",'data': "" }); res.status(200).send({'status':"success",'message':"Deleted successfully",'data': "" }); } catch (error) { res.status(500).send({'status':"failed",'message':err.message }); } }; exports.uploadProductsFromCSV = async (req, res) => { try { // Check if file exists if (!req.file) { return res.status(400).send({ status: "failed", message: "No file uploaded" }); } const filePath = req.file.path; // Validate file type if (!req.file.originalname.endsWith(".csv")) { fs.unlinkSync(filePath); return res.status(400).send({ status: "failed", message: "Invalid file type. Only CSV files are allowed.", }); } // Validate userId if (!req.body.userId || isNaN(req.body.userId)) { fs.unlinkSync(filePath); return res.status(400).send({ status: "failed", message: "Invalid or missing userId. Must be an integer.", }); } const results = []; const userId = parseInt(req.body.userId); console.log(userId, "userId"); // Read CSV and clean headers/values fs.createReadStream(filePath) .pipe(csv()) .on("data", (row) => { // Trim all keys and values to handle spaces in header names or values const cleanRow = {}; for (const key in row) { cleanRow[key.trim()] = row[key] ? row[key].trim() : null; } results.push(cleanRow); }) .on("end", async () => { try { // Check for empty CSV if (results.length === 0) { fs.unlinkSync(filePath); return res.status(400).send({ status: "failed", message: "CSV file is empty or invalid.", }); } console.log(results, "results"); // Fetch existing products by hs_code const hsCodes = results.map((r) => r.hs_code); const existingProducts = await Product.findAll({ where: { hs_code: hsCodes }, }); const existingHsCodes = existingProducts.map((p) => p.hs_code); const toInsert = []; const duplicates = []; // Process CSV rows for (const row of results) { const hsCode = row.hs_code?.trim(); const productName = row.product_name?.trim(); const description = row.hs_description?.trim(); if (!hsCode || !productName) continue; // skip invalid rows if (existingHsCodes.includes(hsCode)) { duplicates.push(hsCode); } else { toInsert.push({ hs_code: hsCode, product_name: productName, hs_description: description, created_by: userId, created_at: new Date(), }); } } // Bulk insert new records let inserted = []; if (toInsert.length > 0) { inserted = await Product.bulkCreate(toInsert, { validate: true }); } // Delete file after processing fs.unlinkSync(filePath); // Send success response return res.status(200).send({ status: "success", message: `${inserted.length} products inserted successfully.`, inserted_count: inserted.length, duplicate_hs_codes: duplicates, }); } catch (err) { if (fs.existsSync(filePath)) fs.unlinkSync(filePath); return res.status(500).send({ status: "failed", message: err.message, }); } }); } catch (error) { return res.status(500).send({ status: "failed", message: error.message }); } }; exports.downloadProductSample = async (req, res) => { try { const filePath = path.join(__dirname, "../writable/uploads/sample_files/products_upload_sample.csv"); return res.download(filePath, "products_upload_sample.csv"); } catch (err) { return res.status(500).send({ status: "failed", message: err.message }); } };