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,
|
||||
allowNull: true,
|
||||
},
|
||||
isic_code: {
|
||||
type: DataTypes.INTEGER,
|
||||
allowNull: true,
|
||||
},
|
||||
is_active: {
|
||||
type: DataTypes.BOOLEAN,
|
||||
defaultValue: true,
|
||||
|
||||
@ -19,6 +19,7 @@ const notificationTemplateController = require("../controllers/notificationTempl
|
||||
const quarterlyWindowsController = require("../controllers/quarterlyWindowsConfiguration.controller");
|
||||
const calculationController = require("../controllers/calculation.controller");
|
||||
const ManufacturingIpiController = require("../controllers/manufacturingIPI.controller")
|
||||
const testController = require("../controllers/test.controller");
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
const multer = require("multer");
|
||||
@ -530,6 +531,101 @@ router.put("/admin_users/:id/change-password",[verifySignature, verifyToken], ad
|
||||
|
||||
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'];
|
||||
|
||||
// Aggregate by establishment ISIC4 for the target month-period.
|
||||
// This keeps grouping driven by establishment isic_code as requested.
|
||||
// ISIC mapping source is now products.isic_code.
|
||||
// Aggregate weighted item indices to ISIC 4-digit using product master mapping.
|
||||
const query = `
|
||||
WITH submission_period AS (
|
||||
SELECT
|
||||
s.establishment_id,
|
||||
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,
|
||||
LEFT(CAST(p.isic_code AS CHAR), 4) AS isic_4digit_code,
|
||||
SUM(COALESCE(p.weight_in_ib, 0)) AS total_weight,
|
||||
SUM(
|
||||
COALESCE(p.weight_in_ib, 0) *
|
||||
((spd.current_production / byp.avg_by_production) * 100)
|
||||
ili.item_index
|
||||
) AS weighted_index_sum,
|
||||
(
|
||||
SUM(
|
||||
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)
|
||||
) AS isic_4digit_index
|
||||
FROM submission_period spd
|
||||
JOIN products p ON p.id = spd.product_id
|
||||
JOIN base_year_production byp ON byp.product_id = spd.product_id
|
||||
WHERE byp.avg_by_production > 0
|
||||
FROM item_level_indices ili
|
||||
JOIN products p ON p.id = ili.product_id
|
||||
WHERE ili.year = ?
|
||||
AND ili.month = ?
|
||||
AND p.isic_code IS NOT NULL
|
||||
AND p.weight_in_ib IS NOT NULL
|
||||
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, [
|
||||
month, month, month, month, month, month, month, month, month, month, month,
|
||||
year, month, month, month
|
||||
]);
|
||||
const [isic4Results] = await connection.query(query, [year, month]);
|
||||
|
||||
for (const result of isic4Results) {
|
||||
await connection.query(
|
||||
|
||||
Loading…
Reference in New Issue
Block a user