fcsc_ipi_backend/app/controllers/manufacturingIPI.controller.js
2026-04-29 11:09:06 +05:30

204 lines
7.2 KiB
JavaScript

const db = require("../models");
const ManufacturingIpi = db.ManufacturingIpi;
const Isic2DigitIndices = db.Isic2DigitIndices;
const Isic3DigitIndices = db.Isic3DigitIndices;
const Isic4DigitIndices = db.Isic4DigitIndices;
const QuarterlyWindowsConfiguration = db.QuarterlyWindowsConfiguration;
const logger = require("../services/logger");
const formatDecimal = (value) => {
if (value === null || value === undefined || value === '' || value === 0) {
return "0.00";
}
return parseFloat(value).toFixed(2);
};
exports.getAllManufacturingIndexDetails = async (req, res) => {
try {
const latestWindow = await QuarterlyWindowsConfiguration.findOne({
order: [["created_at", "DESC"]],
});
let nextScheduleDate = null;
if (latestWindow && latestWindow.end_date && latestWindow.grace_periods_days !== null) {
const endDate = new Date(latestWindow.end_date);
endDate.setDate(endDate.getDate()+ 1 + latestWindow.grace_periods_days);
nextScheduleDate = endDate.toISOString().split("T")[0]; // YYYY-MM-DD
}
const rawData = await ManufacturingIpi.findAll({
order: [["created_at", "DESC"]],
});
// Format decimal fields
const data = rawData.map(item => {
const plainItem = item.get({ plain: true });
return {
...plainItem,
total_weight: formatDecimal(plainItem.total_weight),
weighted_index_sum: formatDecimal(plainItem.weighted_index_sum),
manufacturing_index: formatDecimal(plainItem.manufacturing_index),
mom_change: formatDecimal(plainItem.mom_change),
yoy_change: formatDecimal(plainItem.yoy_change),
};
});
logger.info(`getAllManufacturingIndexDetails API: Fetched ${data.length} manufacturing index records successfully`);
res.status(200).send({
status: "success",
message: "Fetched successfully",
data: data,
nextScheduleDate: nextScheduleDate
});
} catch (error) {
logger.error(`getAllManufacturingIndexDetails API: ${error.message}`);
logger.error(`Stack trace: ${error.stack}`);
res.status(500).send({ status: "failed", message: "Internal server error" });
}
};
exports.getManufacturingMonthlyOverviewByYearMonth = async (req, res) => {
try {
const { year, quarter } = req.query;
// Validate parameters exist
if (!year || !quarter) {
logger.warn('getManufacturingMonthlyOverview API: Missing required parameters');
return res.status(400).send({
status: "failed",
message: "Year and quarter are required"
});
}
// Sanitize and validate input - prevent SQL injection
const yearInt = parseInt(year, 10);
// Validate that parsing was successful
if (isNaN(yearInt)) {
logger.warn(`getManufacturingMonthlyOverview API: Invalid input - year: ${year}, quarter: ${quarter}`);
return res.status(400).send({
status: "failed",
message: "Year must be a valid number"
});
}
// Validate year range (reasonable bounds)
if (yearInt < 2000 || yearInt > 2100) {
return res.status(400).send({
status: "failed",
message: "Year must be between 2000 and 2100"
});
}
if (!["Q1", "Q2", "Q3", "Q4"].includes(quarter)) {
return res.status(400).send({
status: "failed",
message: "Quarter must be one of Q1, Q2, Q3, Q4"
});
}
// Common where clause
const whereClause = {
year: yearInt,
quarter
};
// Fetch data from all tables in parallel
const [manufacturingData, isic2DigitData, isic3DigitData, isic4DigitData] = await Promise.all([
ManufacturingIpi.findOne({
attributes: ['manufacturing_index', 'mom_change', 'yoy_change'],
where: whereClause
}),
Isic2DigitIndices.findAll({
attributes: ['isic_2digit_code', 'isic_description', 'total_weight', 'weighted_index_sum', 'isic_2digit_index'],
where: whereClause,
order: [['isic_2digit_code', 'ASC']]
}),
Isic3DigitIndices.findAll({
attributes: ['isic_3digit_code', 'isic_description', 'total_weight', 'weighted_index_sum', 'isic_3digit_index'],
where: whereClause,
order: [['isic_3digit_code', 'ASC']]
}),
Isic4DigitIndices.findAll({
attributes: ['isic_4digit_code', 'isic_description', 'total_weight', 'weighted_index_sum', 'isic_4digit_index'],
where: whereClause,
order: [['isic_4digit_code', 'ASC']]
})
]);
// Check if manufacturing data exists (main data)
if (!manufacturingData) {
logger.info(`getManufacturingMonthlyOverview API: No data found for year ${yearInt}, quarter ${derivedQuarter}`);
return res.status(404).send({
status: "failed",
message: "No data found for the specified period"
});
}
// Format Manufacturing IPI data
const plainManufacturing = manufacturingData.get({ plain: true });
const formattedManufacturing = {
manufacturing_index: formatDecimal(plainManufacturing.manufacturing_index),
mom_change: formatDecimal(plainManufacturing.mom_change),
yoy_change: formatDecimal(plainManufacturing.yoy_change),
};
// Format ISIC 2-digit data
const formattedIsic2Digit = isic2DigitData.map(item => {
const plainItem = item.get({ plain: true });
return {
isic_2digit_code: plainItem.isic_2digit_code,
isic_description: plainItem.isic_description,
total_weight: formatDecimal(plainItem.total_weight),
weighted_index_sum: formatDecimal(plainItem.weighted_index_sum),
isic_2digit_index: formatDecimal(plainItem.isic_2digit_index),
};
});
// Format ISIC 3-digit data
const formattedIsic3Digit = isic3DigitData.map(item => {
const plainItem = item.get({ plain: true });
return {
isic_3digit_code: plainItem.isic_3digit_code,
isic_description: plainItem.isic_description,
total_weight: formatDecimal(plainItem.total_weight),
weighted_index_sum: formatDecimal(plainItem.weighted_index_sum),
isic_3digit_index: formatDecimal(plainItem.isic_3digit_index),
};
});
// Format ISIC 4-digit data
const formattedIsic4Digit = isic4DigitData.map(item => {
const plainItem = item.get({ plain: true });
return {
isic_4digit_code: plainItem.isic_4digit_code,
isic_description: plainItem.isic_description,
total_weight: formatDecimal(plainItem.total_weight),
weighted_index_sum: formatDecimal(plainItem.weighted_index_sum),
isic_4digit_index: formatDecimal(plainItem.isic_4digit_index),
};
});
logger.info(`getManufacturingMonthlyOverview API: Successfully fetched data for year ${yearInt}, quarter ${quarter}`);
res.status(200).send({
status: "success",
message: "Fetched successfully",
manufacturing_total: formattedManufacturing,
isic_2digit: formattedIsic2Digit,
isic_3digit: formattedIsic3Digit,
isic_4digit: formattedIsic4Digit
});
} catch (error) {
logger.error(`getManufacturingMonthlyOverview API Error: ${error.message}`);
logger.error(`Stack trace: ${error.stack}`);
res.status(500).send({
status: "failed",
message: "Internal server error"
});
}
};