GWM : index calculation demo changes.
This commit is contained in:
parent
466fcecda8
commit
5ffb872c3a
243
app/controllers/test.controller.js
Normal file
243
app/controllers/test.controller.js
Normal file
@ -0,0 +1,243 @@
|
|||||||
|
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,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
@ -42,6 +42,10 @@ module.exports = (sequelize, DataTypes) => {
|
|||||||
type: DataTypes.INTEGER,
|
type: DataTypes.INTEGER,
|
||||||
allowNull: true,
|
allowNull: true,
|
||||||
},
|
},
|
||||||
|
isic_code: {
|
||||||
|
type: DataTypes.INTEGER,
|
||||||
|
allowNull: true,
|
||||||
|
},
|
||||||
is_active: {
|
is_active: {
|
||||||
type: DataTypes.BOOLEAN,
|
type: DataTypes.BOOLEAN,
|
||||||
defaultValue: true,
|
defaultValue: true,
|
||||||
|
|||||||
@ -19,6 +19,7 @@ const notificationTemplateController = require("../controllers/notificationTempl
|
|||||||
const quarterlyWindowsController = require("../controllers/quarterlyWindowsConfiguration.controller");
|
const quarterlyWindowsController = require("../controllers/quarterlyWindowsConfiguration.controller");
|
||||||
const calculationController = require("../controllers/calculation.controller");
|
const calculationController = require("../controllers/calculation.controller");
|
||||||
const ManufacturingIpiController = require("../controllers/manufacturingIPI.controller")
|
const ManufacturingIpiController = require("../controllers/manufacturingIPI.controller")
|
||||||
|
const testController = require("../controllers/test.controller");
|
||||||
const fs = require("fs");
|
const fs = require("fs");
|
||||||
const path = require("path");
|
const path = require("path");
|
||||||
const multer = require("multer");
|
const multer = require("multer");
|
||||||
@ -530,6 +531,101 @@ router.put("/admin_users/:id/change-password",[verifySignature, verifyToken], ad
|
|||||||
|
|
||||||
router.get("/testEmail", establishmentController.testEmail);
|
router.get("/testEmail", establishmentController.testEmail);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @swagger
|
||||||
|
* /api/test/submissions-with-products:
|
||||||
|
* post:
|
||||||
|
* summary: Create test submission and submission-products for multiple quarters
|
||||||
|
* tags: [Submissions]
|
||||||
|
* security:
|
||||||
|
* - appSignature: []
|
||||||
|
* - CSRF: []
|
||||||
|
* cookieAuth: []
|
||||||
|
* requestBody:
|
||||||
|
* required: true
|
||||||
|
* content:
|
||||||
|
* application/json:
|
||||||
|
* schema:
|
||||||
|
* type: array
|
||||||
|
* items:
|
||||||
|
* type: object
|
||||||
|
* required:
|
||||||
|
* - year
|
||||||
|
* - establishment_id
|
||||||
|
* - product_id
|
||||||
|
* - data
|
||||||
|
* properties:
|
||||||
|
* year:
|
||||||
|
* type: integer
|
||||||
|
* example: 2022
|
||||||
|
* establishment_id:
|
||||||
|
* type: integer
|
||||||
|
* example: 2
|
||||||
|
* product_id:
|
||||||
|
* type: integer
|
||||||
|
* example: 3
|
||||||
|
* data:
|
||||||
|
* type: array
|
||||||
|
* items:
|
||||||
|
* type: object
|
||||||
|
* required:
|
||||||
|
* - quarter
|
||||||
|
* - qty
|
||||||
|
* - cost
|
||||||
|
* properties:
|
||||||
|
* quarter:
|
||||||
|
* type: string
|
||||||
|
* enum: [Q1, Q2, Q3, Q4]
|
||||||
|
* example: Q1
|
||||||
|
* qty:
|
||||||
|
* type: number
|
||||||
|
* example: 456573559
|
||||||
|
* cost:
|
||||||
|
* type: number
|
||||||
|
* example: 40566560717
|
||||||
|
* example:
|
||||||
|
* - year: 2022
|
||||||
|
* establishment_id: 2
|
||||||
|
* product_id: 3
|
||||||
|
* data:
|
||||||
|
* - quarter: Q1
|
||||||
|
* qty: 456573559
|
||||||
|
* cost: 40566560717
|
||||||
|
* - quarter: Q2
|
||||||
|
* qty: 8755776
|
||||||
|
* cost: 7654656
|
||||||
|
* - quarter: Q3
|
||||||
|
* qty: 7465465
|
||||||
|
* cost: 865454
|
||||||
|
* - quarter: Q4
|
||||||
|
* qty: 656465465
|
||||||
|
* cost: 98776
|
||||||
|
* - year: 2022
|
||||||
|
* establishment_id: 2
|
||||||
|
* product_id: 3
|
||||||
|
* data:
|
||||||
|
* - quarter: Q1
|
||||||
|
* qty: 456573559
|
||||||
|
* cost: 40566560717
|
||||||
|
* - quarter: Q2
|
||||||
|
* qty: 8755776
|
||||||
|
* cost: 7654656
|
||||||
|
* - quarter: Q3
|
||||||
|
* qty: 7465465
|
||||||
|
* cost: 865454
|
||||||
|
* - quarter: Q4
|
||||||
|
* qty: 656465465
|
||||||
|
* cost: 98776
|
||||||
|
* responses:
|
||||||
|
* 201:
|
||||||
|
* description: Submission and products processed successfully
|
||||||
|
* 400:
|
||||||
|
* description: Validation error
|
||||||
|
* 500:
|
||||||
|
* description: Server error
|
||||||
|
*/
|
||||||
|
router.post("/test/submissions-with-products",[verifySignature], testController.createSubmissionWithProducts);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -309,85 +309,34 @@ class IPICalculationService {
|
|||||||
|
|
||||||
const monthNames = ['', 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
|
const monthNames = ['', 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
|
||||||
|
|
||||||
// Aggregate by establishment ISIC4 for the target month-period.
|
// ISIC mapping source is now products.isic_code.
|
||||||
// This keeps grouping driven by establishment isic_code as requested.
|
// Aggregate weighted item indices to ISIC 4-digit using product master mapping.
|
||||||
const query = `
|
const query = `
|
||||||
WITH submission_period AS (
|
|
||||||
SELECT
|
SELECT
|
||||||
s.establishment_id,
|
LEFT(CAST(p.isic_code AS CHAR), 4) AS isic_4digit_code,
|
||||||
sp.product_id,
|
|
||||||
LEFT(e.isic_code, 4) AS isic_4digit_code,
|
|
||||||
SUM(
|
|
||||||
CASE
|
|
||||||
WHEN ? BETWEEN 1 AND 3 THEN
|
|
||||||
CASE
|
|
||||||
WHEN ? = 1 THEN COALESCE(sp.current_quantity_period_one, 0)
|
|
||||||
WHEN ? = 2 THEN COALESCE(sp.current_quantity_period_two, 0)
|
|
||||||
ELSE COALESCE(sp.current_quantity_period_three, 0)
|
|
||||||
END
|
|
||||||
WHEN ? BETWEEN 4 AND 6 THEN
|
|
||||||
CASE
|
|
||||||
WHEN ? = 4 THEN COALESCE(sp.current_quantity_period_one, 0)
|
|
||||||
WHEN ? = 5 THEN COALESCE(sp.current_quantity_period_two, 0)
|
|
||||||
ELSE COALESCE(sp.current_quantity_period_three, 0)
|
|
||||||
END
|
|
||||||
WHEN ? BETWEEN 7 AND 9 THEN
|
|
||||||
CASE
|
|
||||||
WHEN ? = 7 THEN COALESCE(sp.current_quantity_period_one, 0)
|
|
||||||
WHEN ? = 8 THEN COALESCE(sp.current_quantity_period_two, 0)
|
|
||||||
ELSE COALESCE(sp.current_quantity_period_three, 0)
|
|
||||||
END
|
|
||||||
ELSE
|
|
||||||
CASE
|
|
||||||
WHEN ? = 10 THEN COALESCE(sp.current_quantity_period_one, 0)
|
|
||||||
WHEN ? = 11 THEN COALESCE(sp.current_quantity_period_two, 0)
|
|
||||||
ELSE COALESCE(sp.current_quantity_period_three, 0)
|
|
||||||
END
|
|
||||||
END
|
|
||||||
) AS current_production
|
|
||||||
FROM submission_products sp
|
|
||||||
JOIN submission s ON s.id = sp.submission_id
|
|
||||||
JOIN establishments e ON e.id = s.establishment_id
|
|
||||||
WHERE s.year = ?
|
|
||||||
AND s.quarter = CASE
|
|
||||||
WHEN ? BETWEEN 1 AND 3 THEN 'Q1'
|
|
||||||
WHEN ? BETWEEN 4 AND 6 THEN 'Q2'
|
|
||||||
WHEN ? BETWEEN 7 AND 9 THEN 'Q3'
|
|
||||||
ELSE 'Q4'
|
|
||||||
END
|
|
||||||
AND s.status = 'Approved'
|
|
||||||
AND sp.is_active = 1
|
|
||||||
AND e.isic_code IS NOT NULL
|
|
||||||
AND e.isic_code != ''
|
|
||||||
GROUP BY s.establishment_id, sp.product_id, LEFT(e.isic_code, 4)
|
|
||||||
)
|
|
||||||
SELECT
|
|
||||||
spd.isic_4digit_code,
|
|
||||||
SUM(COALESCE(p.weight_in_ib, 0)) AS total_weight,
|
SUM(COALESCE(p.weight_in_ib, 0)) AS total_weight,
|
||||||
SUM(
|
SUM(
|
||||||
COALESCE(p.weight_in_ib, 0) *
|
COALESCE(p.weight_in_ib, 0) *
|
||||||
((spd.current_production / byp.avg_by_production) * 100)
|
ili.item_index
|
||||||
) AS weighted_index_sum,
|
) AS weighted_index_sum,
|
||||||
(
|
(
|
||||||
SUM(
|
SUM(
|
||||||
COALESCE(p.weight_in_ib, 0) *
|
COALESCE(p.weight_in_ib, 0) *
|
||||||
((spd.current_production / byp.avg_by_production) * 100)
|
ili.item_index
|
||||||
) /
|
) /
|
||||||
NULLIF(SUM(COALESCE(p.weight_in_ib, 0)), 0)
|
NULLIF(SUM(COALESCE(p.weight_in_ib, 0)), 0)
|
||||||
) AS isic_4digit_index
|
) AS isic_4digit_index
|
||||||
FROM submission_period spd
|
FROM item_level_indices ili
|
||||||
JOIN products p ON p.id = spd.product_id
|
JOIN products p ON p.id = ili.product_id
|
||||||
JOIN base_year_production byp ON byp.product_id = spd.product_id
|
WHERE ili.year = ?
|
||||||
WHERE byp.avg_by_production > 0
|
AND ili.month = ?
|
||||||
|
AND p.isic_code IS NOT NULL
|
||||||
AND p.weight_in_ib IS NOT NULL
|
AND p.weight_in_ib IS NOT NULL
|
||||||
AND p.weight_in_ib > 0
|
AND p.weight_in_ib > 0
|
||||||
GROUP BY spd.isic_4digit_code
|
GROUP BY LEFT(CAST(p.isic_code AS CHAR), 4)
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const [isic4Results] = await connection.query(query, [
|
const [isic4Results] = await connection.query(query, [year, month]);
|
||||||
month, month, month, month, month, month, month, month, month, month, month,
|
|
||||||
year, month, month, month
|
|
||||||
]);
|
|
||||||
|
|
||||||
for (const result of isic4Results) {
|
for (const result of isic4Results) {
|
||||||
await connection.query(
|
await connection.query(
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user