GWM : product upload and get previous quarter data
This commit is contained in:
parent
ec77398eff
commit
6724b13765
@ -1,5 +1,9 @@
|
|||||||
const db = require("../models");
|
const db = require("../models");
|
||||||
const Product = db.Product;
|
const Product = db.Product;
|
||||||
|
const fs = require("fs");
|
||||||
|
const csv = require("csv-parser");
|
||||||
|
const path = require("path");
|
||||||
|
|
||||||
|
|
||||||
exports.createProduct = async (req, res) => {
|
exports.createProduct = async (req, res) => {
|
||||||
try {
|
try {
|
||||||
@ -66,3 +70,50 @@ exports.deleteProduct = async (req, res) => {
|
|||||||
res.status(500).send({'status':"failed",'message':err.message });
|
res.status(500).send({'status':"failed",'message':err.message });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
exports.uploadProductsFromCSV = async (req, res) => {
|
||||||
|
try {
|
||||||
|
if (!req.file) {
|
||||||
|
return res.status(400).send({ status: "failed", message: "No file uploaded" });
|
||||||
|
}
|
||||||
|
|
||||||
|
const results = [];
|
||||||
|
const filePath = req.file.path;
|
||||||
|
|
||||||
|
// Read CSV and store rows
|
||||||
|
fs.createReadStream(filePath)
|
||||||
|
.pipe(csv())
|
||||||
|
.on("data", (row) => {
|
||||||
|
results.push(row);
|
||||||
|
})
|
||||||
|
.on("end", async () => {
|
||||||
|
try {
|
||||||
|
// Insert all rows into Product table
|
||||||
|
const inserted = await Product.bulkCreate(results, { validate: true });
|
||||||
|
fs.unlinkSync(filePath); // delete file after processing
|
||||||
|
|
||||||
|
res.status(201).send({
|
||||||
|
status: "success",
|
||||||
|
message: `${inserted.length} products inserted successfully`,
|
||||||
|
data: inserted,
|
||||||
|
});
|
||||||
|
} catch (dbErr) {
|
||||||
|
res.status(500).send({
|
||||||
|
status: "failed",
|
||||||
|
message: dbErr.message,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
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 });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|||||||
@ -526,3 +526,48 @@ exports.getQuarterPeriods = async (req, res) => {
|
|||||||
return res.status(500).json({ status: "failed", message: err.message });
|
return res.status(500).json({ status: "failed", message: err.message });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
exports.getPreviousForecastData = async (req, res) => {
|
||||||
|
try {
|
||||||
|
|
||||||
|
const { establishment_id, quarter, year, product_id } = req.query;
|
||||||
|
|
||||||
|
if(!establishment_id || !quarter || !year || !product_id){
|
||||||
|
return res.status(400).json({ status:"failed", message:"Missing required query params" });
|
||||||
|
}
|
||||||
|
|
||||||
|
// find submission id
|
||||||
|
const submission = await Submission.findOne({
|
||||||
|
where : { establishment_id, quarter, year },
|
||||||
|
});
|
||||||
|
|
||||||
|
if(!submission){
|
||||||
|
return res.status(404).json({ status:"failed", message:"No previous submission found" });
|
||||||
|
}
|
||||||
|
|
||||||
|
// find submission product row
|
||||||
|
const submissionProduct = await SubmissionProduct.findOne({
|
||||||
|
where : {
|
||||||
|
submission_id : submission.id,
|
||||||
|
product_id
|
||||||
|
},
|
||||||
|
include:[
|
||||||
|
{
|
||||||
|
model: Product,
|
||||||
|
as: "product",
|
||||||
|
attributes:["product_name","hs_code"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
if(!submissionProduct){
|
||||||
|
return res.status(404).json({ status:"failed", message:"No previous product row found" });
|
||||||
|
}
|
||||||
|
|
||||||
|
return res.status(200).json({ status:"success", data: submissionProduct });
|
||||||
|
|
||||||
|
} catch (err) {
|
||||||
|
return res.status(500).json({ status:"failed", message: err.message });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|||||||
@ -18,6 +18,13 @@ const dashboardController = require("../controllers/dashboard.controller");
|
|||||||
const notificationTemplateController = require("../controllers/notificationTemplate.controller");
|
const notificationTemplateController = require("../controllers/notificationTemplate.controller");
|
||||||
const quarterlyWindowsController = require("../controllers/quarterlyWindowsConfiguration.controller");
|
const quarterlyWindowsController = require("../controllers/quarterlyWindowsConfiguration.controller");
|
||||||
|
|
||||||
|
const path = require("path");
|
||||||
|
const multer = require("multer");
|
||||||
|
const upload = multer({ dest: "../writable/uploads/products_bulk_uploads_files" });
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1015,6 +1022,62 @@ router.put("/products/:id",[verifySignature, verifyToken], productController.upd
|
|||||||
*/
|
*/
|
||||||
router.delete("/products/:id",[verifySignature, verifyToken], productController.deleteProduct);
|
router.delete("/products/:id",[verifySignature, verifyToken], productController.deleteProduct);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @swagger
|
||||||
|
* /api/products/uploadCSV:
|
||||||
|
* post:
|
||||||
|
* summary: Upload products in bulk using CSV file
|
||||||
|
* description: This API accepts CSV file and inserts multiple products in bulk. CSV header columns must match Product table columns.
|
||||||
|
* tags: [Products]
|
||||||
|
* security:
|
||||||
|
* - appSignature: []
|
||||||
|
* - bearerAuth: []
|
||||||
|
* requestBody:
|
||||||
|
* required: true
|
||||||
|
* content:
|
||||||
|
* multipart/form-data:
|
||||||
|
* schema:
|
||||||
|
* type: object
|
||||||
|
* properties:
|
||||||
|
* file:
|
||||||
|
* type: string
|
||||||
|
* format: binary
|
||||||
|
* description: CSV file to upload
|
||||||
|
* responses:
|
||||||
|
* 201:
|
||||||
|
* description: Products uploaded successfully
|
||||||
|
* 400:
|
||||||
|
* description: No file uploaded
|
||||||
|
* 500:
|
||||||
|
* description: Server error
|
||||||
|
*/
|
||||||
|
router.post("/products/uploadCSV",[ verifySignature, verifyToken, upload.single("file")], productController.uploadProductsFromCSV);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @swagger
|
||||||
|
* /api/products/download-sample:
|
||||||
|
* get:
|
||||||
|
* summary: Download sample CSV template for bulk product upload
|
||||||
|
* tags: [Products]
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: Sample CSV file downloaded successfully
|
||||||
|
* content:
|
||||||
|
* text/csv:
|
||||||
|
* schema:
|
||||||
|
* type: string
|
||||||
|
* format: binary
|
||||||
|
* 404:
|
||||||
|
* description: File not found
|
||||||
|
* 500:
|
||||||
|
* description: Server error
|
||||||
|
*/
|
||||||
|
router.get("/download-sample-product-upload-file",[verifySignature, verifyToken], productController.downloadProductSample);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -1964,6 +2027,43 @@ router.put("/approveOrRejectSubmission/:id",[verifySignature, verifyToken], subm
|
|||||||
*/
|
*/
|
||||||
router.post("/getQuarterPeriods",[verifySignature, verifyToken], submissionController.getQuarterPeriods);
|
router.post("/getQuarterPeriods",[verifySignature, verifyToken], submissionController.getQuarterPeriods);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @swagger
|
||||||
|
* /api/submissions/getPreviousForecastData:
|
||||||
|
* get:
|
||||||
|
* summary: Get Previous and Forecast Data based on Establishment + Quarter + Year + Product
|
||||||
|
* tags: [Submissions]
|
||||||
|
* security:
|
||||||
|
* - appSignature: []
|
||||||
|
* - bearerAuth: []
|
||||||
|
* parameters:
|
||||||
|
* - in: query
|
||||||
|
* name: establishment_id
|
||||||
|
* required: true
|
||||||
|
* schema: { type: integer }
|
||||||
|
* - in: query
|
||||||
|
* name: quarter
|
||||||
|
* required: true
|
||||||
|
* schema: { type: string, enum: [Q1, Q2, Q3, Q4] }
|
||||||
|
* - in: query
|
||||||
|
* name: year
|
||||||
|
* required: true
|
||||||
|
* schema: { type: integer }
|
||||||
|
* - in: query
|
||||||
|
* name: product_id
|
||||||
|
* required: true
|
||||||
|
* schema: { type: integer }
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: Previous forecast data fetched successfully
|
||||||
|
* 404:
|
||||||
|
* description: Not found
|
||||||
|
* 500:
|
||||||
|
* description: Server error
|
||||||
|
*/
|
||||||
|
router.get("/submissions/getPreviousForecastData", submissionController.getPreviousForecastData);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
12
package-lock.json
generated
12
package-lock.json
generated
@ -11,6 +11,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"bcryptjs": "^3.0.2",
|
"bcryptjs": "^3.0.2",
|
||||||
"cors": "^2.8.5",
|
"cors": "^2.8.5",
|
||||||
|
"csv-parser": "^3.2.0",
|
||||||
"dotenv": "^17.2.3",
|
"dotenv": "^17.2.3",
|
||||||
"exceljs": "^4.4.0",
|
"exceljs": "^4.4.0",
|
||||||
"express": "^5.1.0",
|
"express": "^5.1.0",
|
||||||
@ -724,6 +725,17 @@
|
|||||||
"node": ">= 10"
|
"node": ">= 10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/csv-parser": {
|
||||||
|
"version": "3.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/csv-parser/-/csv-parser-3.2.0.tgz",
|
||||||
|
"integrity": "sha512-fgKbp+AJbn1h2dcAHKIdKNSSjfp43BZZykXsCjzALjKy80VXQNHPFJ6T9Afwdzoj24aMkq8GwDS7KGcDPpejrA==",
|
||||||
|
"bin": {
|
||||||
|
"csv-parser": "bin/csv-parser"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/dayjs": {
|
"node_modules/dayjs": {
|
||||||
"version": "1.11.18",
|
"version": "1.11.18",
|
||||||
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.18.tgz",
|
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.18.tgz",
|
||||||
|
|||||||
@ -13,6 +13,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"bcryptjs": "^3.0.2",
|
"bcryptjs": "^3.0.2",
|
||||||
"cors": "^2.8.5",
|
"cors": "^2.8.5",
|
||||||
|
"csv-parser": "^3.2.0",
|
||||||
"dotenv": "^17.2.3",
|
"dotenv": "^17.2.3",
|
||||||
"exceljs": "^4.4.0",
|
"exceljs": "^4.4.0",
|
||||||
"express": "^5.1.0",
|
"express": "^5.1.0",
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user