synt_backend
Version:
Synt light-weight node backend service
488 lines (451 loc) • 13.5 kB
JavaScript
const express = require("express");
const router = express.Router();
const db = require("./../mysql/models/index");
import * as ValidationHelper from "./../helpers/validations";
const userHelper = require("./../helpers/user");
var keypoint = require("./../helpers/keypoint");
import { attachUploadedFiles } from "./../helpers/db-storage";
const notifier = require("./../helpers/notifier");
// routes
router.get("/", getIncidents);
router.get("/:IncidentId", getIncident);
router.post("/", postIncident);
router.post("/:IncidentId/comment", postIncidentComment);
module.exports = router;
async function getIncident(req, res) {
const { t } = req;
let user = await userHelper.getAuthUser(req);
const { IncidentId } = req.params;
if (user) {
let VmeValidation = await ValidationHelper.validateVme(t, user.VMEId);
if (!VmeValidation.success) {
return res.json(VmeValidation);
}
const { VME } = VmeValidation;
db.Incident.findOne({
where: { id: IncidentId },
include: [
{ model: db.ReportType },
{ model: db.Supplier, include: [{ model: db.Company }] },
{ model: db.Image },
{
model: db.IncidentComment,
include: [
{
model: db.User,
attributes: {
exclude: [
"email",
"phone",
"email_verified_at",
"phone_verified_at",
],
},
},
],
},
],
}).then(async (Incident) => {
//FIXME: TypeError: Cannot read property 'VMEId' of null
if (Incident.VMEId !== VME.id) {
return res.json({
success: false,
error: t(
"api.incidents.errors.notYourVme",
"This message does not belong to your VME."
),
});
} else if (Incident) {
// return results
if (Incident.ReportType?.category === "other") {
if (Incident.Supplier) {
Incident.setDataValue("new_supplier", true);
if (Incident.Supplier.CompanyId) {
Incident.Supplier.setDataValue("has_vat_number", true);
} else {
Incident.Supplier.setDataValue("has_vat_number", false);
}
} else {
Incident.setDataValue("new_supplier", false);
}
}
await Promise.all(
Incident.Images.map(async (I) => {
I.setDataValue("presignedUrl", await I.getPresignedUrl());
})
);
return res.json({
success: true,
Incident,
});
} else {
return res.json({
success: false,
error: t(
"api.incidents.errors.missingMessage",
"This message does not exist. Contact support"
),
});
}
});
}
}
async function getIncidents(req, res) {
const { t } = req;
try {
// verify vme and get vme
let user = await userHelper.getAuthUser(req);
let VmeValidation = await ValidationHelper.validateVme(t, user.VMEId);
if (!VmeValidation.success) {
return res.json(VmeValidation);
}
const { VME } = VmeValidation;
if (VME) {
VME.getIncidents({
include: [
{ model: db.ReportType },
{
model: db.User,
attributes: {
exclude: ["email_verified_at", "phone_verified_at"],
},
},
{ model: db.Image },
{
model: db.IncidentComment,
include: [
{
model: db.User,
attributes: {
exclude: [
"email",
"phone",
"email_verified_at",
"phone_verified_at",
],
},
},
],
},
],
}).then((Incidents) => {
return res.json({
success: true,
Incidents: Incidents.sort(
(a, b) => new Date(b.createdAt) - new Date(a.createdAt)
),
});
});
} else {
return res.json({
success: false,
error: t("api.incidents.errors.noVmeSelected", "No VME selected yet."),
});
}
} catch (error) {
return res.json({ success: false, error });
}
}
async function postIncident(req, res) {
const { t } = req;
let User = await userHelper.getAuthUser(req);
if (User) {
// verify vme and get vme
let VmeValidation = await ValidationHelper.validateVme(t, User.VMEId); //TODO: Validate user roles
if (!VmeValidation.success) {
return res.json(VmeValidation);
}
const { VME } = VmeValidation;
const {
id,
report_description,
is_urgent,
has_tried_to_call,
has_called,
is_covered,
ReportType,
call_description,
solved_at,
Images,
new_supplier,
Supplier, // new supplier/ aannemer
} = req.body;
//const { IncidentId } = req.params; //TODO: Check which user wants to change (roles / reporter)
const IncidentData = {
UserId: User.id,
ReportTypeId: ReportType.id || null,
VMEId: VME.id,
report_description,
is_urgent,
has_tried_to_call,
has_called,
is_covered,
call_description,
solved_at,
};
let errors = {};
if (
ReportType.category === "other" &&
!Supplier &&
typeof new_supplier === "undefined"
) {
errors["new_supplier"] = t(
"api.incidents.errors.newSupplier",
"You must indicate whether you know a contractor."
);
}
if (ReportType.category === "other" && new_supplier) {
let temp = {};
if (Supplier.has_vat_number) {
if (!Supplier.vat_number) {
temp["vat_number"] = t(
"api.incidents.errors.vatNumber",
"Enter the company number."
);
}
} else {
if (!Supplier.alias) {
temp["alias"] = t(
"api.incidents.errors.alias",
"Enter the company alias/name."
);
}
if (!Supplier.email) {
temp["email"] = t(
"api.incidents.errors.email",
"Company email is required."
);
}
/*
if (!Supplier.phone) {
temp["phone"] = t(
"api.incidents.errors.phone",
"Company phone number is required."
);
}
*/
}
if (Object.keys(temp).length) {
errors["Supplier"] = temp;
}
}
if (!ReportType.name) {
errors["ReportTypeId"] = t(
"api.incidents.errors.reportType",
"Selection of notification type is required."
);
}
if (!report_description || report_description === "") {
errors["report_description"] = t(
"api.incidents.errors.reportDescription",
"A description of the notification is required."
);
}
if (typeof is_urgent === "undefined") {
errors["is_urgent"] = t(
"api.incidents.errors.isUrgent",
"You must indicate whether it is urgent."
);
}
if (has_called && (!call_description || call_description === "")) {
errors["call_description"] = t(
"api.incidents.errors.callDescription",
"A description of the phone call is required."
);
}
// return errors if there are any
if (Object.keys(errors).length) {
return res.json({
success: false,
errors,
});
}
if (id) {
// update exisiting incident
// TODO: Check other details editable?
db.Incident.findOne({ where: { id }, include: db.IncidentComment }).then(
(Incident) => {
Incident.update(IncidentData);
if (solved_at) {
/*
sendRemarkToKeypoint(
Incident,
"Synt gebruiker sluit de melding af: " + solved_at
);
*/
}
attachUploadedFiles("Incident", Incident, Images, "Image"); // only images can be added
keypoint.createClient("demo").then(async (client) => {
// send images to kp
for (const File of Images) {
console.log("hello");
client.postCaseFile(Incident.case_id, File);
}
});
return res.json({ success: true, Incident: IncidentData });
}
);
} else {
let NewSupplier;
if (ReportType.category === "other" && new_supplier) {
let Company;
if (Supplier.has_vat_number) {
Company = await db.Company.findOne({
where: {
company_number: Supplier.company_number,
country_code: Supplier.country_code,
},
});
if (!Company) {
Company = await db.Company.create({ ...Supplier });
}
}
// find or add new supplier
// FIXME: existing supplier
NewSupplier = await db.Supplier.create({
alias: Supplier.alias || null,
CompanyId: Company?.id || null,
ReportTypeId: null,
VMEId: VME.id,
});
}
db.Incident.create({
...IncidentData,
SupplierId: NewSupplier?.id || null,
}).then((newItem) => {
// handle images
attachUploadedFiles("Incident", newItem, Images, "Image");
//notify //FIXME: limit user
VME.getUsers().then((Users) => {
Users.forEach((U) => {
notifier.notify(U, "new_incident", {
Incident: newItem,
VME,
Notifier: User,
});
});
});
if (ReportType.category === "other" && !new_supplier) {
// only sending other incident without new supplier to keypoint
keypoint
.createClient("demo")
.then(async (client) => {
// save the initial object send to kp (in case something fails, we have backup)
newItem.declaration = JSON.stringify({
ReportType,
...IncidentData,
id: newItem.id,
});
// send incident to keypoint
let result = await client.postDeclaration(
{ ReportType, ...IncidentData, id: newItem.id },
VME,
User
);
if (typeof result === "number") {
// newItem.case = JSON.stringify(result);
newItem.case_id = result;
newItem.save();
}
console.log(result);
// send images to kp
if (Images) {
for (const File of Images) {
let result = await client.postCaseFile(newItem.case_id, File);
console.log(result);
}
}
})
.catch((error) => {
console.log(error);
});
} else {
// notify supplier (if not to keypoint)
// if a supplier is selected
if (Supplier) {
notifier.sendMail(Supplier.email, "new_incident_to_supplier", {
Incident: newItem,
Supplier,
VME,
Notifier: User,
});
}
}
return res.json({ success: true, Incident: newItem });
});
}
}
}
// function sendRemarkToKeypoint(Incident, message) {
// // send incident remark to keypoint
// // last incident comment is message
// keypoint
// .createClient("demo")
// .then(async (client) => {
// let remark =
// Incident.createdAt + ": " + Incident.report_description || "";
// for (const comment of Incident.IncidentComments) {
// remark =
// remark + " " + comment.createdAt + ": " + comment.message;
// }
// let result = await client.postDeclarationRemark(
// Incident.declaration_id,
// remark
// );
// console.log(result);
// })
// .catch((error) => {
// console.log(error);
// });
// }
async function postIncidentComment(req, res) {
const { t } = req;
let user = await userHelper.getAuthUser(req);
if (user) {
const { message } = req.body;
const { IncidentId } = req.params; //TODO: Check which user wants to change (roles / reporter)
const IncidentComment = {
UserId: user.id,
IncidentId,
message,
};
if (!IncidentId) {
return res.json({
success: false,
errors: {
message: t(
"api.incidents.errors.notificationRequired",
"An existing notification is required."
),
},
});
}
if (!message || message === "") {
return res.json({
success: false,
errors: {
message: t(
"api.incidents.errors.messageRequired",
"Message is required."
),
},
});
}
db.IncidentComment.create(IncidentComment)
.then((response) => {
/*
db.Incident.findOne({
where: { id: IncidentId },
include: db.IncidentComment,
}).then((Incident) => {
sendRemarkToKeypoint(Incident, message);
});
*/
console.log(response);
})
.catch((err) => {
console.log(err);
});
return res.json({ success: true });
}
}