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 Product = db.Product;
|
||||
const fs = require("fs");
|
||||
const csv = require("csv-parser");
|
||||
const path = require("path");
|
||||
|
||||
|
||||
exports.createProduct = async (req, res) => {
|
||||
try {
|
||||
@ -66,3 +70,50 @@ exports.deleteProduct = async (req, res) => {
|
||||
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 });
|
||||
}
|
||||
};
|
||||
|
||||
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,8 +18,15 @@ const dashboardController = require("../controllers/dashboard.controller");
|
||||
const notificationTemplateController = require("../controllers/notificationTemplate.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" });
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* tags:
|
||||
@ -1015,6 +1022,62 @@ router.put("/products/:id",[verifySignature, verifyToken], productController.upd
|
||||
*/
|
||||
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);
|
||||
|
||||
/**
|
||||
* @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": {
|
||||
"bcryptjs": "^3.0.2",
|
||||
"cors": "^2.8.5",
|
||||
"csv-parser": "^3.2.0",
|
||||
"dotenv": "^17.2.3",
|
||||
"exceljs": "^4.4.0",
|
||||
"express": "^5.1.0",
|
||||
@ -724,6 +725,17 @@
|
||||
"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": {
|
||||
"version": "1.11.18",
|
||||
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.18.tgz",
|
||||
|
||||
@ -13,6 +13,7 @@
|
||||
"dependencies": {
|
||||
"bcryptjs": "^3.0.2",
|
||||
"cors": "^2.8.5",
|
||||
"csv-parser": "^3.2.0",
|
||||
"dotenv": "^17.2.3",
|
||||
"exceljs": "^4.4.0",
|
||||
"express": "^5.1.0",
|
||||
|
||||
Loading…
Reference in New Issue
Block a user