GWM : submission data updated

This commit is contained in:
Gowtham M 2025-10-28 12:29:13 +05:30
parent 55787d3cbd
commit 0df0d647dd
4 changed files with 373 additions and 48 deletions

View File

@ -10,6 +10,7 @@ const Product = db.Product;
const { Op } = require("sequelize");
const { Sequelize } = require("sequelize");
const { sendEmail } = require("../services/email.service");
const { getQuarterPeriods } = require("../services/quarterService");
@ -23,8 +24,59 @@ exports.createSubmission = async (req, res) => {
const submission = await Submission.create(submissionData);
if (products.length) {
products.forEach((p) => (p.submission_id = submission.id));
await SubmissionProduct.bulkCreate(products);
// products.forEach((p) => (p.submission_id = submission.id));
// await SubmissionProduct.bulkCreate(products);
// Process products before insert
const processedProducts = products.map((p) => {
const num = (v) => (isNaN(parseFloat(v)) ? 0 : parseFloat(v)); // safe number conversion
// Calculate totals for each section
const previous_quantity =
num(p.previous_quantity_period_one) +
num(p.previous_quantity_period_two) +
num(p.previous_quantity_period_three);
const previous_cost =
num(p.previous_cost_period_one) +
num(p.previous_cost_period_two) +
num(p.previous_cost_period_three);
const current_quantity =
num(p.current_quantity_period_one) +
num(p.current_quantity_period_two) +
num(p.current_quantity_period_three);
const current_cost =
num(p.current_cost_period_one) +
num(p.current_cost_period_two) +
num(p.current_cost_period_three);
const forecast_quantity =
num(p.forecast_quantity_period_one) +
num(p.forecast_quantity_period_two) +
num(p.forecast_quantity_period_three);
const forecast_cost =
num(p.forecast_cost_period_one) +
num(p.forecast_cost_period_two) +
num(p.forecast_cost_period_three);
return {
...p,
submission_id: submission.id,
previous_quantity: previous_quantity.toString(),
previous_cost: previous_cost.toString(),
current_quantity: current_quantity.toString(),
current_cost: current_cost.toString(),
forecast_quantity: forecast_quantity.toString(),
forecast_cost: forecast_cost.toString(),
};
});
// Bulk insert products
await SubmissionProduct.bulkCreate(processedProducts);
}
const result = await Submission.findByPk(submission.id, {
@ -38,58 +90,150 @@ exports.createSubmission = async (req, res) => {
}
};
exports.updateSubmission = async (req, res) => {
try {
const { id } = req.params;
const { products = [], ...submissionData } = req.body;
// exports.updateSubmission = async (req, res) => {
// try {
// const { id } = req.params;
// const { products = [], ...submissionData } = req.body;
// Check submission exists
const submission = await Submission.findByPk(id);
if (!submission)
return res.status(404).json({ status: "failed", message: "Submission not found" });
// // Check submission exists
// const submission = await Submission.findByPk(id);
// if (!submission)
// return res.status(404).json({ status: "failed", message: "Submission not found" });
// Update submission main data
await submission.update(submissionData);
// // Update submission main data
// await submission.update(submissionData);
// Process products
for (const product of products) {
if (product.id) {
// If product ID exists, update
const existingProduct = await SubmissionProduct.findOne({
where: { id: product.id, submission_id: id },
});
// // Process products
// for (const product of products) {
// if (product.id) {
// // If product ID exists, update
// const existingProduct = await SubmissionProduct.findOne({
// where: { id: product.id, submission_id: id },
// });
if (existingProduct) {
await existingProduct.update(product);
} else {
// fallback: if given ID not found, create new
product.submission_id = id;
await SubmissionProduct.create(product);
}
} else {
// If product has no ID → create new record
product.submission_id = id;
await SubmissionProduct.create(product);
}
}
// if (existingProduct) {
// await existingProduct.update(product);
// } else {
// // fallback: if given ID not found, create new
// product.submission_id = id;
// await SubmissionProduct.create(product);
// }
// } else {
// // If product has no ID → create new record
// product.submission_id = id;
// await SubmissionProduct.create(product);
// }
// }
// Get updated full record
const updatedSubmission = await Submission.findByPk(id, {
include: [{ model: SubmissionProduct, as: "products" }],
});
// // Get updated full record
// const updatedSubmission = await Submission.findByPk(id, {
// include: [{ model: SubmissionProduct, as: "products" }],
// });
res.status(200).json({
status: "success",
message: "Submission updated successfully",
data: updatedSubmission,
});
// res.status(200).json({
// status: "success",
// message: "Submission updated successfully",
// data: updatedSubmission,
// });
} catch (err) {
console.error(err);
res.status(500).json({ status: "failed", message: err.message });
}
};
// } catch (err) {
// console.error(err);
// res.status(500).json({ status: "failed", message: err.message });
// }
// };
exports.updateSubmission = async (req, res) => {
try {
const { id } = req.params;
const { products = [], ...submissionData } = req.body;
// Check if submission exists
const submission = await Submission.findByPk(id);
if (!submission)
return res.status(404).json({ status: "failed", message: "Submission not found" });
// Update main submission record
await submission.update(submissionData);
// Helper: safe numeric conversion
const num = (v) => (isNaN(parseFloat(v)) ? 0 : parseFloat(v));
// Loop through products
for (const p of products) {
// --- Auto-calculate totals ---
const previous_quantity =
num(p.previous_quantity_period_one) +
num(p.previous_quantity_period_two) +
num(p.previous_quantity_period_three);
const previous_cost =
num(p.previous_cost_period_one) +
num(p.previous_cost_period_two) +
num(p.previous_cost_period_three);
const current_quantity =
num(p.current_quantity_period_one) +
num(p.current_quantity_period_two) +
num(p.current_quantity_period_three);
const current_cost =
num(p.current_cost_period_one) +
num(p.current_cost_period_two) +
num(p.current_cost_period_three);
const forecast_quantity =
num(p.forecast_quantity_period_one) +
num(p.forecast_quantity_period_two) +
num(p.forecast_quantity_period_three);
const forecast_cost =
num(p.forecast_cost_period_one) +
num(p.forecast_cost_period_two) +
num(p.forecast_cost_period_three);
// Attach calculated fields
const updatedProductData = {
...p,
submission_id: id,
previous_quantity: previous_quantity.toString(),
previous_cost: previous_cost.toString(),
current_quantity: current_quantity.toString(),
current_cost: current_cost.toString(),
forecast_quantity: forecast_quantity.toString(),
forecast_cost: forecast_cost.toString(),
};
// --- Update or Create ---
if (p.id) {
const existingProduct = await SubmissionProduct.findOne({
where: { id: p.id, submission_id: id },
});
if (existingProduct) {
await existingProduct.update(updatedProductData);
} else {
await SubmissionProduct.create(updatedProductData);
}
} else {
await SubmissionProduct.create(updatedProductData);
}
}
// Fetch updated data with associations
const updatedSubmission = await Submission.findByPk(id, {
include: [{ model: SubmissionProduct, as: "products" }],
});
res.status(200).json({
status: "success",
message: "Submission updated successfully",
data: updatedSubmission,
});
} catch (err) {
console.error(err);
res.status(500).json({ status: "failed", message: err.message });
}
};
exports.submissionHistory = async (req, res) => {
@ -185,10 +329,12 @@ exports.viewSubmissionDetails = async (req, res) => {
],
});
const quarter_periods = getQuarterPeriods(Number(data.year), data.quarter);
if (!data) return res.status(404).json({ status: "failed", message: "Not found" });
res.status(200).json({ status: "success", data });
res.status(200).json({ status: "success", data , quarter_periods });
} catch (err) {
res.status(500).json({ status: "failed", message: err.message });
@ -281,3 +427,23 @@ exports.approveOrRejectSubmission = async (req, res) => {
res.status(500).json({ status: "failed", message: err.message });
}
};
exports.getQuarterPeriods = async (req, res) => {
try {
const { current_year, current_quarter } = req.body;
if (!current_year || !current_quarter) {
return res
.status(400)
.json({ status: "failed", message: "current_year and current_quarter are required" });
}
const quarter_periods = getQuarterPeriods(Number(current_year), current_quarter);
return res.status(200).json({ status: "success", data: quarter_periods });
} catch (err) {
return res.status(500).json({ status: "failed", message: err.message });
}
};

View File

@ -12,6 +12,34 @@ module.exports = (sequelize, DataTypes) => {
product_id: DataTypes.INTEGER,
unit_id: DataTypes.INTEGER,
annual_installed_capacity: DataTypes.STRING(100),
// --- Previous Periods ---
previous_quantity_period_one: { type: DataTypes.STRING(100), allowNull: true },
previous_quantity_period_two: { type: DataTypes.STRING(100), allowNull: true },
previous_quantity_period_three: { type: DataTypes.STRING(100), allowNull: true },
previous_cost_period_one: { type: DataTypes.STRING(100), allowNull: true },
previous_cost_period_two: { type: DataTypes.STRING(100), allowNull: true },
previous_cost_period_three: { type: DataTypes.STRING(100), allowNull: true },
// --- Current Periods ---
current_quantity_period_one: { type: DataTypes.STRING(100), allowNull: true },
current_quantity_period_two: { type: DataTypes.STRING(100), allowNull: true },
current_quantity_period_three: { type: DataTypes.STRING(100), allowNull: true },
current_cost_period_one: { type: DataTypes.STRING(100), allowNull: true },
current_cost_period_two: { type: DataTypes.STRING(100), allowNull: true },
current_cost_period_three: { type: DataTypes.STRING(100), allowNull: true },
// --- Forecast Periods ---
forecast_quantity_period_one: { type: DataTypes.STRING(100), allowNull: true },
forecast_quantity_period_two: { type: DataTypes.STRING(100), allowNull: true },
forecast_quantity_period_three: { type: DataTypes.STRING(100), allowNull: true },
forecast_cost_period_one: { type: DataTypes.STRING(100), allowNull: true },
forecast_cost_period_two: { type: DataTypes.STRING(100), allowNull: true },
forecast_cost_period_three: { type: DataTypes.STRING(100), allowNull: true },
previous_quantity: DataTypes.STRING(100),
previous_cost: DataTypes.STRING(100),
current_quantity: DataTypes.STRING(100),

View File

@ -1545,6 +1545,24 @@ router.delete("/unit_master/:id",[verifySignature, verifyToken], unitMasterContr
* product_id: { type: integer }
* unit_id: { type: integer }
* annual_installed_capacity: { type: string }
* previous_quantity_period_one: { type: string }
* previous_quantity_period_two: { type: string }
* previous_quantity_period_three: { type: string }
* previous_cost_period_one: { type: string }
* previous_cost_period_two: { type: string }
* previous_cost_period_three: { type: string }
* current_quantity_period_one: { type: string }
* current_quantity_period_two: { type: string }
* current_quantity_period_three: { type: string }
* current_cost_period_one: { type: string }
* current_cost_period_two: { type: string }
* current_cost_period_three: { type: string }
* forecast_quantity_period_one: { type: string }
* forecast_quantity_period_two: { type: string }
* forecast_quantity_period_three: { type: string }
* forecast_cost_period_one: { type: string }
* forecast_cost_period_two: { type: string }
* forecast_cost_period_three: { type: string }
* previous_quantity: { type: string }
* previous_cost: { type: string }
* current_quantity: { type: string }
@ -1600,6 +1618,24 @@ router.post("/submissions",[verifySignature, verifyToken], submissionController.
* product_id: { type: integer }
* unit_id: { type: integer }
* annual_installed_capacity: { type: string }
* previous_quantity_period_one: { type: string }
* previous_quantity_period_two: { type: string }
* previous_quantity_period_three: { type: string }
* previous_cost_period_one: { type: string }
* previous_cost_period_two: { type: string }
* previous_cost_period_three: { type: string }
* current_quantity_period_one: { type: string }
* current_quantity_period_two: { type: string }
* current_quantity_period_three: { type: string }
* current_cost_period_one: { type: string }
* current_cost_period_two: { type: string }
* current_cost_period_three: { type: string }
* forecast_quantity_period_one: { type: string }
* forecast_quantity_period_two: { type: string }
* forecast_quantity_period_three: { type: string }
* forecast_cost_period_one: { type: string }
* forecast_cost_period_two: { type: string }
* forecast_cost_period_three: { type: string }
* previous_quantity: { type: string }
* previous_cost: { type: string }
* current_quantity: { type: string }
@ -1760,7 +1796,29 @@ router.put("/enableOrDisableSubmissionEditAccess/:id",[verifySignature, verifyTo
router.put("/approveOrRejectSubmission/:id",[verifySignature, verifyToken], submissionController.approveOrRejectSubmission);
/**
* @swagger
* /api/getQuarterPeriods:
* post:
* summary: get Quarter Periods based on current quarter and year
* tags: [Submissions]
* security:
* - appSignature: []
* - bearerAuth: []
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* properties:
* current_year: { type: integer }
* current_quarter: { type: string }
* responses:
* 200:
* description: Updated successfully
*/
router.post("/getQuarterPeriods",[verifySignature, verifyToken], submissionController.getQuarterPeriods);

View File

@ -0,0 +1,73 @@
// services/quarterService.js
/**
* Get Quarter and Month details based on current quarter and financial year
* @param {number} currentYear - e.g. 2025
* @param {string} currentQuarter - e.g. 'Q4'
* @returns {object} - structured period data
*/
exports.getQuarterPeriods = (currentYear, currentQuarter) => {
// Define quarters based on financial year (AprMar)
const quarters = {
Q1: ["Apr", "May", "Jun"],
Q2: ["Jul", "Aug", "Sep"],
Q3: ["Oct", "Nov", "Dec"],
Q4: ["Jan", "Feb", "Mar"],
};
const allQuarters = ["Q1", "Q2", "Q3", "Q4"];
const currentIndex = allQuarters.indexOf(currentQuarter);
if (currentIndex === -1) {
throw new Error("Invalid quarter. Use one of: Q1, Q2, Q3, Q4");
}
// --- Previous Quarter ---
let previousQuarter = allQuarters[(currentIndex - 1 + 4) % 4];
let previousYear = currentYear;
// If current quarter is Q1, previous year is same financial year → currentYear
// But Q1 (Apr-Jun) comes after Mar, so same financial year
if (currentQuarter === "Q1") {
previousYear = currentYear - 1;
} else if (currentQuarter === "Q4") {
previousYear = currentYear; // Q4 (JanMar) belongs to same financial year end
}
// --- Forecast Quarter ---
let forecastQuarter = allQuarters[(currentIndex + 1) % 4];
let forecastYear = currentYear;
// If next quarter is Q1, then financial year increments
if (forecastQuarter === "Q1") {
forecastYear = currentYear + 1;
}
// Construct Output Object
const output = {
previous_month: {
previous_period_one: quarters[previousQuarter][0],
previous_period_two: quarters[previousQuarter][1],
previous_period_three: quarters[previousQuarter][2],
},
previous_year: previousYear,
previous_quarter: previousQuarter,
current_month: {
current_period_one: quarters[currentQuarter][0],
current_period_two: quarters[currentQuarter][1],
current_period_three: quarters[currentQuarter][2],
},
current_year: currentYear,
current_quarter: currentQuarter,
forecast_month: {
forecast_period_one: quarters[forecastQuarter][0],
forecast_period_two: quarters[forecastQuarter][1],
forecast_period_three: quarters[forecastQuarter][2],
},
forecast_year: forecastYear,
forecast_quarter: forecastQuarter,
};
return output;
};