fcsc_ipi_backend/app/controllers/test.controller.js

244 lines
6.1 KiB
JavaScript

const db = require("../models");
const VALID_QUARTERS = ["Q1", "Q2", "Q3", "Q4"];
async function createSubmissionWithProducts(transaction, payload) {
const { year, establishment_id, product_id, data } = payload;
for (const row of data) {
const { quarter, qty, cost } = row;
await db.sequelize.query(
`
INSERT INTO submission (
establishment_id, quarter, year,
edit_request, edit_access, status,
created_by, created_at, updated_at,
approve_reject_status
)
SELECT ?, ?, ?, 0, 0, 'Approved', 1,
CASE ?
WHEN 'Q1' THEN CONCAT(?, '-03-15 10:00:00')
WHEN 'Q2' THEN CONCAT(?, '-06-15 10:00:00')
WHEN 'Q3' THEN CONCAT(?, '-09-15 10:00:00')
WHEN 'Q4' THEN CONCAT(?, '-12-15 10:00:00')
END,
CASE ?
WHEN 'Q1' THEN CONCAT(?, '-03-15 10:00:00')
WHEN 'Q2' THEN CONCAT(?, '-06-15 10:00:00')
WHEN 'Q3' THEN CONCAT(?, '-09-15 10:00:00')
WHEN 'Q4' THEN CONCAT(?, '-12-15 10:00:00')
END,
1
WHERE NOT EXISTS (
SELECT 1
FROM submission
WHERE establishment_id = ?
AND quarter = ?
AND year = ?
)
`,
{
replacements: [
establishment_id,
quarter,
year,
quarter,
year,
year,
year,
year,
quarter,
year,
year,
year,
year,
establishment_id,
quarter,
year,
],
transaction,
}
);
const submissionRows = await db.sequelize.query(
`
SELECT id
FROM submission
WHERE establishment_id = ?
AND quarter = ?
AND year = ?
LIMIT 1
`,
{
replacements: [establishment_id, quarter, year],
type: db.Sequelize.QueryTypes.SELECT,
transaction,
}
);
if (!submissionRows.length) {
throw new Error(`Submission not found for ${quarter}-${year}`);
}
const submission_id = submissionRows[0].id;
await db.sequelize.query(
`
INSERT INTO submission_products (
submission_id, product_id, unit_id,
annual_installed_capacity,
previous_quantity_period_one,
previous_quantity_period_two,
previous_quantity_period_three,
previous_cost_period_one,
previous_cost_period_two,
previous_cost_period_three,
current_quantity_period_one,
current_quantity_period_two,
current_quantity_period_three,
current_cost_period_one,
current_cost_period_two,
current_cost_period_three,
forecast_quantity_period_one,
forecast_quantity_period_two,
forecast_quantity_period_three,
forecast_cost_period_one,
forecast_cost_period_two,
forecast_cost_period_three,
previous_quantity, previous_cost,
current_quantity, current_cost,
forecast_quantity, forecast_cost,
remarks, created_by, created_at, updated_at, is_active
)
SELECT ?, ?, 1, 50000,
0, 0, 0,
0, 0, 0,
?, ?, ?,
?, ?, ?,
0, 0, 0,
0, 0, 0,
0, 0,
?, ?,
0, 0,
CONCAT(?, ' current only'),
1, NOW(), NOW(), 1
WHERE NOT EXISTS (
SELECT 1
FROM submission_products
WHERE submission_id = ?
AND product_id = ?
)
`,
{
replacements: [
submission_id,
product_id,
qty / 3,
qty / 3,
qty / 3,
cost / 3,
cost / 3,
cost / 3,
qty,
cost,
quarter,
submission_id,
product_id,
],
transaction,
}
);
}
}
exports.createSubmissionWithProducts = async (req, res) => {
const payloadList = Array.isArray(req.body) ? req.body : [req.body];
if (!payloadList.length) {
return res.status(400).json({
success: false,
message: "Request body must be a non-empty array",
});
}
const invalidItem = payloadList.find(
(item) =>
!item ||
!item.year ||
!item.establishment_id ||
!item.product_id ||
!Array.isArray(item.data) ||
item.data.length === 0
);
if (invalidItem) {
return res.status(400).json({
success: false,
message:
"Each payload item must contain year, establishment_id, product_id and non-empty data array",
});
}
const invalidQuarterItem = payloadList.find((item) =>
item.data.some((row) => !VALID_QUARTERS.includes(row?.quarter))
);
if (invalidQuarterItem) {
const invalidQuarterRow = invalidQuarterItem.data.find(
(row) => !VALID_QUARTERS.includes(row?.quarter)
);
return res.status(400).json({
success: false,
message: `Invalid quarter '${invalidQuarterRow.quarter}'. Allowed: Q1, Q2, Q3, Q4`,
});
}
const invalidNumberItem = payloadList.find((item) =>
item.data.some((row) => Number.isNaN(Number(row?.qty)) || Number.isNaN(Number(row?.cost)))
);
if (invalidNumberItem) {
return res.status(400).json({
success: false,
message: "Each data row in each payload item must contain numeric qty and cost values",
});
}
const transaction = await db.sequelize.transaction();
try {
for (const item of payloadList) {
await createSubmissionWithProducts(transaction, {
year: Number(item.year),
establishment_id: Number(item.establishment_id),
product_id: Number(item.product_id),
data: item.data.map((row) => ({
quarter: row.quarter,
qty: Number(row.qty),
cost: Number(row.cost),
})),
});
}
await transaction.commit();
return res.status(201).json({
success: true,
message: "Submission and submission products processed successfully",
total_payload_items: payloadList.length,
});
} catch (error) {
await transaction.rollback();
return res.status(500).json({
success: false,
message: "Failed to process submission data",
error: error.message,
});
}
};