Added some api's : GWM
This commit is contained in:
parent
d96e82f150
commit
0915843ef4
52
app/controllers/config.controller.js
Normal file
52
app/controllers/config.controller.js
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
const db = require("../models");
|
||||||
|
const SubmissionDeadline = db.SubmissionDeadline;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// POST /api/submission-deadlines
|
||||||
|
exports.updateDeadlineData = async (req, res) => {
|
||||||
|
try {
|
||||||
|
const {
|
||||||
|
deadline_days_after_quarter_end,
|
||||||
|
grace_periods_days_after_deadline,
|
||||||
|
first_reminder_days_before_deadline,
|
||||||
|
second_reminder_days_before_deadline,
|
||||||
|
created_by,
|
||||||
|
updated_by,
|
||||||
|
} = req.body;
|
||||||
|
|
||||||
|
// Try to find existing record (id=1)
|
||||||
|
let existing = await SubmissionDeadline.findByPk(1);
|
||||||
|
|
||||||
|
if (existing) {
|
||||||
|
// Update
|
||||||
|
await existing.update({
|
||||||
|
deadline_days_after_quarter_end,
|
||||||
|
grace_periods_days_after_deadline,
|
||||||
|
first_reminder_days_before_deadline,
|
||||||
|
second_reminder_days_before_deadline,
|
||||||
|
updated_at: new Date(),
|
||||||
|
updated_by,
|
||||||
|
});
|
||||||
|
|
||||||
|
res.status(200).json({ status: "success", message: "Deadline updated successfully", data: existing });
|
||||||
|
} else {
|
||||||
|
// Create new (set id = 1 manually)
|
||||||
|
const newRecord = await SubmissionDeadline.create({
|
||||||
|
id: 1,
|
||||||
|
deadline_days_after_quarter_end,
|
||||||
|
grace_periods_days_after_deadline,
|
||||||
|
first_reminder_days_before_deadline,
|
||||||
|
second_reminder_days_before_deadline,
|
||||||
|
created_at: new Date(),
|
||||||
|
created_by,
|
||||||
|
});
|
||||||
|
|
||||||
|
res.status(201).json({ status: "success", message: "Deadline created successfully", data: newRecord });
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
res.status(500).json({ status: "failed", message: err.message });
|
||||||
|
}
|
||||||
|
};
|
||||||
140
app/controllers/dashboard.controller.js
Normal file
140
app/controllers/dashboard.controller.js
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
const db = require("../models");
|
||||||
|
const { Op } = require("sequelize");
|
||||||
|
|
||||||
|
const Submission = db.Submission;
|
||||||
|
const SubmissionDeadline = db.SubmissionDeadline;
|
||||||
|
|
||||||
|
function getQuarter(date) {
|
||||||
|
const month = date.getMonth() + 1;
|
||||||
|
if (month >= 4 && month <= 6) return "Q1";
|
||||||
|
if (month >= 7 && month <= 9) return "Q2";
|
||||||
|
if (month >= 10 && month <= 12) return "Q3";
|
||||||
|
return "Q4"; // Jan-Mar
|
||||||
|
}
|
||||||
|
|
||||||
|
function getQuarterDates(quarter, year) {
|
||||||
|
switch (quarter) {
|
||||||
|
case "Q1":
|
||||||
|
return { start: new Date(year, 3, 1), end: new Date(year, 5, 30) };
|
||||||
|
case "Q2":
|
||||||
|
return { start: new Date(year, 6, 1), end: new Date(year, 8, 30) };
|
||||||
|
case "Q3":
|
||||||
|
return { start: new Date(year, 9, 1), end: new Date(year, 11, 31) };
|
||||||
|
case "Q4":
|
||||||
|
return { start: new Date(year, 0, 1), end: new Date(year, 2, 31) };
|
||||||
|
default:
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getPrevCurrNextQuarter(date) {
|
||||||
|
const month = date.getMonth() + 1; // 1-12
|
||||||
|
const year = date.getFullYear();
|
||||||
|
const quarters = ["Q1", "Q2", "Q3", "Q4"];
|
||||||
|
|
||||||
|
// map month -> index: 0=Q1(Apr-Jun),1=Q2(Jul-Sep),2=Q3(Oct-Dec),3=Q4(Jan-Mar)
|
||||||
|
const getQuarterIndex = (m) => {
|
||||||
|
if (m >= 4 && m <= 6) return 0; // Apr-Jun -> Q1
|
||||||
|
if (m >= 7 && m <= 9) return 1; // Jul-Sep -> Q2
|
||||||
|
if (m >= 10 && m <= 12) return 2; // Oct-Dec -> Q3
|
||||||
|
return 3; // Jan-Mar -> Q4
|
||||||
|
};
|
||||||
|
|
||||||
|
const currentIndex = getQuarterIndex(month);
|
||||||
|
const currentQuarter = quarters[currentIndex];
|
||||||
|
|
||||||
|
const previousIndex = (currentIndex - 1 + 4) % 4;
|
||||||
|
const nextIndex = (currentIndex + 1) % 4;
|
||||||
|
|
||||||
|
const previousQuarter = quarters[previousIndex];
|
||||||
|
const nextQuarter = quarters[nextIndex];
|
||||||
|
|
||||||
|
const previousQuarterYear = (currentIndex === 3) ? year - 1 : year;
|
||||||
|
const nextQuarterYear = (currentIndex === 2) ? year + 1 : year;
|
||||||
|
|
||||||
|
return {
|
||||||
|
previous_quarter: previousQuarter,
|
||||||
|
previous_quarter_year: previousQuarterYear,
|
||||||
|
current_quarter: currentQuarter,
|
||||||
|
current_quarter_year: year,
|
||||||
|
next_quarter: nextQuarter,
|
||||||
|
next_quarter_year: nextQuarterYear,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
exports.getEstablishmentDashboard = async (req, res) => {
|
||||||
|
try {
|
||||||
|
const establishment_id = req.query.establishment_id;
|
||||||
|
if (!establishment_id) {
|
||||||
|
return res.status(400).json({ status: "failed", message: "establishment_id required" });
|
||||||
|
}
|
||||||
|
|
||||||
|
const today = new Date();
|
||||||
|
const quarters = getPrevCurrNextQuarter(today);
|
||||||
|
|
||||||
|
// Last 5 submissions
|
||||||
|
const submission_history = await Submission.findAll({
|
||||||
|
where: { establishment_id },
|
||||||
|
order: [["created_at", "DESC"]],
|
||||||
|
limit: 5,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Submission status for current quarter
|
||||||
|
const currentQuarterDates = getQuarterDates(quarters.current_quarter, quarters.current_quarter_year);
|
||||||
|
|
||||||
|
const currentSubmission = await Submission.findOne({
|
||||||
|
where: {
|
||||||
|
establishment_id,
|
||||||
|
quarter: quarters.current_quarter,
|
||||||
|
year: quarters.current_quarter_year,
|
||||||
|
},
|
||||||
|
order: [["created_at", "DESC"]],
|
||||||
|
});
|
||||||
|
|
||||||
|
// Get submission deadline (assuming only one row)
|
||||||
|
const deadline = await SubmissionDeadline.findByPk(1);
|
||||||
|
|
||||||
|
let nextDeadline = null;
|
||||||
|
let submissionStatus = "Pending";
|
||||||
|
|
||||||
|
if (deadline) {
|
||||||
|
const quarterEnd = currentQuarterDates.end;
|
||||||
|
const deadlineDate = new Date(quarterEnd);
|
||||||
|
deadlineDate.setDate(deadlineDate.getDate() + deadline.deadline_days_after_quarter_end);
|
||||||
|
|
||||||
|
nextDeadline = deadlineDate;
|
||||||
|
|
||||||
|
if (currentSubmission) {
|
||||||
|
submissionStatus = "Submitted";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let lastSubmissionInfo = null;
|
||||||
|
if (submission_history.length > 0) {
|
||||||
|
const last = submission_history[0];
|
||||||
|
lastSubmissionInfo = {
|
||||||
|
quarter: last.quarter,
|
||||||
|
year: last.year,
|
||||||
|
submitted_on: last.created_at,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
res.status(200).json({
|
||||||
|
status: "success",
|
||||||
|
data: {
|
||||||
|
...quarters,
|
||||||
|
submission_status: submissionStatus,
|
||||||
|
next_deadline: nextDeadline,
|
||||||
|
last_submission: lastSubmissionInfo,
|
||||||
|
submission_history,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
res.status(500).json({ status: "failed", message: err.message });
|
||||||
|
}
|
||||||
|
};
|
||||||
@ -6,13 +6,13 @@ const EstablishmentUser = db.establishment_user;
|
|||||||
// Create Establishment + linked user
|
// Create Establishment + linked user
|
||||||
exports.createEstablishment = async (req, res) => {
|
exports.createEstablishment = async (req, res) => {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
const { establishment_code, factory_name, email, permanent_factory_code, industry_code, license_number, isic_code, emirate, total_employment, establishment_user, } = req.body;
|
const { establishment_code, factory_name, email, permanent_factory_code, industry_code, license_number, isic_code, emirate, emirati_male,emirati_female,non_emirati_male,non_emirati_female,total_emirati,total_employees, establishment_user, } = req.body;
|
||||||
|
|
||||||
if ( !establishment_code || !factory_name || !email || !establishment_user?.name || !establishment_user?.email || !establishment_user?.password )
|
// if ( !establishment_code || !factory_name || !email || !establishment_user?.name || !establishment_user?.email || !establishment_user?.password )
|
||||||
{
|
// {
|
||||||
res.status(400).send({'status':"failed",'message':"Missing required fields",'data': "" });
|
// res.status(400).send({'status':"failed",'message':"Missing required fields",'data': "" });
|
||||||
}
|
// }
|
||||||
|
|
||||||
// Create Establishment
|
// Create Establishment
|
||||||
const establishment = await Establishment.create({
|
const establishment = await Establishment.create({
|
||||||
@ -24,22 +24,22 @@ exports.createEstablishment = async (req, res) => {
|
|||||||
license_number,
|
license_number,
|
||||||
isic_code,
|
isic_code,
|
||||||
emirate,
|
emirate,
|
||||||
total_employment,
|
emirati_male,emirati_female,non_emirati_male,non_emirati_female,total_emirati,total_employees,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Hash password for user
|
// Hash password for user
|
||||||
const hashedPassword = await bcrypt.hash(establishment_user.password, 10);
|
// const hashedPassword = await bcrypt.hash(establishment_user.password, 10);
|
||||||
|
|
||||||
// Create related Establishment User
|
// Create related Establishment User
|
||||||
const user = await EstablishmentUser.create({
|
// const user = await EstablishmentUser.create({
|
||||||
establishment_id: establishment.id,
|
// establishment_id: establishment.id,
|
||||||
name: establishment_user.name,
|
// name: establishment_user.name,
|
||||||
email: establishment_user.email,
|
// email: establishment_user.email,
|
||||||
password: hashedPassword,
|
// password: hashedPassword,
|
||||||
});
|
// });
|
||||||
|
|
||||||
|
|
||||||
res.status(201).send({'status':"success",'message':"Establishment and linked user created successfully",'data': { establishment, user } });
|
res.status(201).send({'status':"success",'message':"Establishment and linked user created successfully",'data': { establishment } });
|
||||||
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
res.status(500).send({'status':"failed",'message':err.message });
|
res.status(500).send({'status':"failed",'message':err.message });
|
||||||
|
|||||||
@ -22,6 +22,7 @@ db.ZeroTargetReasonMaster = require("./zeroTargetReason.model")(sequelize, DataT
|
|||||||
db.Submission = require("./submission.model")(sequelize, DataTypes);
|
db.Submission = require("./submission.model")(sequelize, DataTypes);
|
||||||
db.SubmissionProduct = require("./submissionProduct.model")(sequelize, DataTypes);
|
db.SubmissionProduct = require("./submissionProduct.model")(sequelize, DataTypes);
|
||||||
db.UnitMaster = require("./UnitMaster.model")(sequelize, DataTypes);
|
db.UnitMaster = require("./UnitMaster.model")(sequelize, DataTypes);
|
||||||
|
db.SubmissionDeadline = require("./submissionDeadline.model")(sequelize, DataTypes);
|
||||||
|
|
||||||
|
|
||||||
// Associations
|
// Associations
|
||||||
|
|||||||
@ -17,12 +17,6 @@ module.exports = (sequelize, DataTypes) => {
|
|||||||
type: DataTypes.INTEGER,
|
type: DataTypes.INTEGER,
|
||||||
allowNull: false,
|
allowNull: false,
|
||||||
},
|
},
|
||||||
emirati_male: DataTypes.INTEGER,
|
|
||||||
emirati_female: DataTypes.INTEGER,
|
|
||||||
non_emirati_male: DataTypes.INTEGER,
|
|
||||||
non_emirati_female: DataTypes.INTEGER,
|
|
||||||
total_emirati: DataTypes.INTEGER,
|
|
||||||
total_employees: DataTypes.INTEGER,
|
|
||||||
edit_request: {
|
edit_request: {
|
||||||
type: DataTypes.BOOLEAN,
|
type: DataTypes.BOOLEAN,
|
||||||
defaultValue: false,
|
defaultValue: false,
|
||||||
|
|||||||
51
app/models/submissionDeadline.model.js
Normal file
51
app/models/submissionDeadline.model.js
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
module.exports = (sequelize, DataTypes) => {
|
||||||
|
const SubmissionDeadline = sequelize.define(
|
||||||
|
"submission_deadlines",
|
||||||
|
{
|
||||||
|
id: {
|
||||||
|
type: DataTypes.INTEGER,
|
||||||
|
autoIncrement: true,
|
||||||
|
primaryKey: true,
|
||||||
|
},
|
||||||
|
deadline_days_after_quarter_end: {
|
||||||
|
type: DataTypes.INTEGER,
|
||||||
|
allowNull: false,
|
||||||
|
},
|
||||||
|
grace_periods_days_after_deadline: {
|
||||||
|
type: DataTypes.INTEGER,
|
||||||
|
allowNull: false,
|
||||||
|
},
|
||||||
|
first_reminder_days_before_deadline: {
|
||||||
|
type: DataTypes.INTEGER,
|
||||||
|
allowNull: false,
|
||||||
|
},
|
||||||
|
second_reminder_days_before_deadline: {
|
||||||
|
type: DataTypes.INTEGER,
|
||||||
|
allowNull: false,
|
||||||
|
},
|
||||||
|
created_at: {
|
||||||
|
type: DataTypes.DATE,
|
||||||
|
defaultValue: DataTypes.NOW,
|
||||||
|
},
|
||||||
|
updated_at: {
|
||||||
|
type: DataTypes.DATE,
|
||||||
|
allowNull: true,
|
||||||
|
},
|
||||||
|
created_by: {
|
||||||
|
type: DataTypes.INTEGER,
|
||||||
|
allowNull: true,
|
||||||
|
},
|
||||||
|
updated_by: {
|
||||||
|
type: DataTypes.INTEGER,
|
||||||
|
allowNull: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
tableName: "submission_deadlines",
|
||||||
|
timestamps: false,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return SubmissionDeadline;
|
||||||
|
};
|
||||||
|
|
||||||
@ -13,6 +13,8 @@ const variationReasonMasterController = require("../controllers/variationReasonM
|
|||||||
const zeroTargetReasonMasterController = require("../controllers/zeroTargetReasonMaster.controller");
|
const zeroTargetReasonMasterController = require("../controllers/zeroTargetReasonMaster.controller");
|
||||||
const unitMasterController = require("../controllers/unitMasterController");
|
const unitMasterController = require("../controllers/unitMasterController");
|
||||||
const submissionController = require("../controllers/submission.controller");
|
const submissionController = require("../controllers/submission.controller");
|
||||||
|
const ConfigController = require("../controllers/config.controller");
|
||||||
|
const dashboardController = require("../controllers/dashboard.controller");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -41,6 +43,10 @@ const submissionController = require("../controllers/submission.controller");
|
|||||||
* description: Manage Unit Master entries
|
* description: Manage Unit Master entries
|
||||||
* - name: Submissions
|
* - name: Submissions
|
||||||
* description: Manage establishment submissions
|
* description: Manage establishment submissions
|
||||||
|
* - name: Config
|
||||||
|
* description: Sumbission config
|
||||||
|
* - name: Dashboard
|
||||||
|
* description:
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@ -1664,4 +1670,110 @@ router.put("/approveOrRejectSubmission/:id",[verifySignature, verifyToken], subm
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @swagger
|
||||||
|
* /api/submission_deadlines:
|
||||||
|
* post:
|
||||||
|
* summary: Create or update submission deadline configuration (only one record allowed)
|
||||||
|
* tags: [Config]
|
||||||
|
* security:
|
||||||
|
* - appSignature: []
|
||||||
|
* - bearerAuth: []
|
||||||
|
* requestBody:
|
||||||
|
* required: true
|
||||||
|
* content:
|
||||||
|
* application/json:
|
||||||
|
* schema:
|
||||||
|
* type: object
|
||||||
|
* properties:
|
||||||
|
* deadline_days_after_quarter_end:
|
||||||
|
* type: integer
|
||||||
|
* example: 30
|
||||||
|
* grace_periods_days_after_deadline:
|
||||||
|
* type: integer
|
||||||
|
* example: 7
|
||||||
|
* first_reminder_days_before_deadline:
|
||||||
|
* type: integer
|
||||||
|
* example: 5
|
||||||
|
* second_reminder_days_before_deadline:
|
||||||
|
* type: integer
|
||||||
|
* example: 2
|
||||||
|
* created_by:
|
||||||
|
* type: integer
|
||||||
|
* example: 1
|
||||||
|
* updated_by:
|
||||||
|
* type: integer
|
||||||
|
* example: 1
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: Deadline data updated successfully
|
||||||
|
* 201:
|
||||||
|
* description: Deadline data created successfully
|
||||||
|
* 500:
|
||||||
|
* description: Server error
|
||||||
|
*/
|
||||||
|
router.post("/submission_deadlines",[verifySignature, verifyToken], ConfigController.updateDeadlineData);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @swagger
|
||||||
|
* /api/establishment_dashboard:
|
||||||
|
* get:
|
||||||
|
* summary: Get dashboard data for establishment user
|
||||||
|
* tags: [Dashboard]
|
||||||
|
* parameters:
|
||||||
|
* - in: query
|
||||||
|
* name: establishment_id
|
||||||
|
* required: true
|
||||||
|
* schema:
|
||||||
|
* type: integer
|
||||||
|
* description: ID of the establishment
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: Dashboard data fetched successfully
|
||||||
|
* 400:
|
||||||
|
* description: Bad request
|
||||||
|
* 403:
|
||||||
|
* description: Invalid signature
|
||||||
|
* 401:
|
||||||
|
* description: Unauthorized
|
||||||
|
* 500:
|
||||||
|
* description: Server error
|
||||||
|
*/
|
||||||
|
router.get("/establishment_dashboard",dashboardController.getEstablishmentDashboard);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
module.exports = router;
|
module.exports = router;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user