synt_backend
Version:
Synt light-weight node backend service
547 lines (484 loc) • 15.7 kB
JavaScript
const express = require("express");
const router = express.Router();
const db = require("./../mysql/models/index");
const userHelper = require("./../helpers/user");
import * as ValidationHelper from "./../helpers/validations";
import { attachUploadedFiles } from "./../helpers/db-storage";
const notifier = require("./../helpers/notifier");
import { findCommissioners } from "../helpers/format";
import {
getGLAPurchasesDB,
getOwnersDB,
getSuppliersDB,
getVmePurchases,
} from "../database/documents";
// routes
router.get("/owners/:vmeId/:start_date/:end_date", getOwners);
router.get("/suppliers/:vmeId/:start_date/:end_date", getSuppliers);
router.get("/globalSettlement/:vmeId/:start_date/:end_date", getGLAPurchases);
router.get("/budgets/:vmeId/:start_date/:end_date", getBudgets);
router.get("/purchases/:vmeId/:start_date/:end_date", getPurchases);
router.get("/:DocumentId", getDocument);
router.get("/", getDocuments);
router.post("/", postDocument);
module.exports = router;
async function getDocument(req, res) {
const { t } = req;
let user = await userHelper.getAuthUser(req);
const { DocumentId } = req.params;
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;
db.Document.findOne({
where: { id: DocumentId },
include: [
{ model: db.DocumentType },
{ model: db.DocumentFile },
{ model: db.User },
],
}).then(async (Document) => {
if (Document.VMEId !== VME.id) {
return res.json({
success: false,
error: t("api.documents.errors.notYourVme"),
});
} else {
await Promise.all(
Document.DocumentFiles.map(async (DF) => {
DF.setDataValue("presignedUrl", await DF.getPresignedUrl());
})
);
return res.json({ success: true, Document });
}
});
}
}
async function getSuppliers(req, res) {
const { t } = req;
try {
let User = await userHelper.getAuthUser(req);
const { vmeId, start_date, end_date } = req.params;
if (!User) {
return res.json({ success: false, error: "No user" });
}
const vme = await db.VME.findOne({
where: { id: vmeId },
include: [{ model: db.Company }],
});
// 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 result = await getSuppliersDB({ vme, start_date, end_date });
return res.json(result);
} catch (error) {
return res.json({ success: false, error: error.stack });
}
}
async function getOwners(req, res) {
const { t } = req;
try {
let User = await userHelper.getAuthUser(req);
const { vmeId, start_date, end_date } = req.params;
if (!User) {
return res.json({ success: false, error: "No user" });
}
const vme = await db.VME.findOne({
where: { id: vmeId },
include: [{ model: db.Company }],
});
// 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 result = await getOwnersDB({
vme,
include_past: true,
start_date,
end_date,
});
return res.json(result);
} catch (error) {
return res.json({ success: false, error: error.stack });
}
}
async function getGLAPurchases(req, res) {
const { t } = req;
try {
let User = await userHelper.getAuthUser(req);
const { vmeId, start_date, end_date } = req.params;
if (!User) {
return res.json({ success: false, error: "No user" });
}
const vme = await db.VME.findOne({
where: { id: vmeId },
include: [{ model: db.Company }],
});
// 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 result = await getGLAPurchasesDB({
vme,
start_date,
end_date,
});
return res.json(result);
} catch (error) {
return res.json({ success: false, error: error.stack });
}
}
async function getPurchases(req, res) {
const { t } = req;
try {
let User = await userHelper.getAuthUser(req);
const { vmeId, start_date, end_date } = req.params;
if (!User) {
return res.json({ success: false, error: "No user" });
}
const vme = await db.VME.findOne({
where: { id: vmeId },
include: [{ model: db.Company }],
});
// 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 purchases = await getVmePurchases({
vme,
start_date,
end_date,
});
return res.json({
vme,
start_date,
end_date,
purchases,
success: true,
});
} catch (error) {
return res.json({ success: false, error: error.stack });
}
}
async function getBudgets(req, res) {
const { t } = req;
try {
let User = await userHelper.getAuthUser(req);
const { vmeId, start_date, end_date } = req.params;
if (!User) {
return res.json({ success: false, error: "No user" });
}
const vme = await db.VME.findOne({
where: { id: vmeId },
include: [{ model: db.Company }],
});
// 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 result = await getGLAPurchasesDB({
vme,
start_date,
end_date,
});
const financialYears = await vme.getFinancialYears();
return res.json({ ...result, financialYears });
} catch (error) {
return res.json({ success: false, error: error.stack });
}
}
async function getDocuments(req, res) {
const { t } = req;
try {
let User = await userHelper.getAuthUser(req);
let { type } = req.query;
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, role } = VmeValidation;
if (VME) {
try {
// check whether owner
let Lots = await VME.getLots({
include: {
model: db.LotPhase,
include: { model: db.User, where: { id: User.id } },
},
});
let is_owner = false;
for (const Lot of Lots) {
// FIXME: document visibility depending on create date and phase date
let U = Lot.LotPhases.find((LP) => !LP.ends_at)?.Users.find(
(U) => U.id === User.id
);
if (U?.LotPhaseUser.type === ("owner" || "bare_owner")) {
is_owner = true;
break;
}
}
// general documents (opstart en andere)
const getDocuments = VME.getDocuments({
include: [
{ model: db.DocumentType },
{ model: db.DocumentFile },
{ model: db.User },
],
});
let getSupplierFiles,
getPurchaseFiles = null;
let is_super = User.is_admin == true;
let is_synt = role === "synt_authoriser" || role === "synt_viewer";
if (is_super) {
// supplier files
getSupplierFiles = db.SupplierFile.findAll({
include: [{ model: db.Supplier, where: { VMEId: VME.id } }],
});
}
// purchase files
getPurchaseFiles = db.PurchaseFile.findAll({
include: [{ model: db.Purchase, where: { VMEId: VME.id } }],
});
// settlement files
const getSettlementFiles = db.SettlementFile.findAll({
include: [
{
model: db.Settlement,
include: [
{ model: db.FinancialYear, where: { VMEId: VME.id } },
],
},
{
model: db.User,
...(!is_super ? { where: { id: User.id } } : {}),
},
],
});
// settlement files
const getProvisionFiles = db.ProvisionFile.findAll({
include: [
{
model: db.Provision,
include: [
{ model: db.Lot },
{
model: db.User,
...(!is_super ? { where: { id: User.id } } : {}),
},
],
where: { VMEId: VME.id },
},
],
});
// call all in parallel
const [
Documents,
SupplierFiles,
SettlementFiles,
PurchaseFiles,
ProvisionFiles,
] = await Promise.all([
getDocuments,
getSupplierFiles || [],
getSettlementFiles,
getPurchaseFiles || [],
getProvisionFiles,
]);
// Get all signed urls
await Promise.all([
...SupplierFiles.map(async (SF) => {
SF.setDataValue("presignedUrl", await SF.getPresignedUrl());
}),
...ProvisionFiles.map(async (PF) => {
PF.setDataValue("presignedUrl", await PF.getPresignedUrl());
}),
...SettlementFiles.map(async (SF) => {
SF.setDataValue("presignedUrl", await SF.getPresignedUrl());
}),
...PurchaseFiles.map(async (PF) => {
PF.setDataValue("presignedUrl", await PF.getPresignedUrl());
}),
]);
return res.json({
success: true,
Documents: Documents.filter((D) => {
if (
D.visibility === "custom" &&
D.Users.map((U) => U.id).includes(User.id)
) {
// custom visibility and user included
return true;
} else {
// not custom
return (
is_super ||
D.visibility === "everyone" ||
(is_owner && D.visibility === "owners") ||
(is_synt && D.visibility === "synt")
);
}
}).map((D) => ({ ...D.toJSON(), is_file: false })),
SupplierFiles: SupplierFiles.map((F) => {
F = F.toJSON();
F.DocumentType = {
name: t("api.documents.documentType.names.supplier"),
};
F.is_file = true;
return F;
}),
SettlementFiles: SettlementFiles.map((F) => {
F = F.toJSON();
F.DocumentType = {
name: t("api.documents.documentType.names.settlement"),
};
F.name = "S" + F.Settlement.FinancialYear.year + "/" + F.UserId;
F.visibility = F.User.full_name;
F.is_file = true;
return F;
}),
PurchaseFiles: PurchaseFiles.map((F) => {
F = F.toJSON();
F.DocumentType = {
name: t("api.documents.documentType.names.purchaseInvoice"),
};
F.name = F.Purchase.reference;
F.visibility = "everyone";
F.is_file = true;
return F;
}),
ProvisionFiles: ProvisionFiles.map((F) => {
F = F.toJSON();
F.DocumentType = {
name: t("api.documents.documentType.names.contribution"),
};
F.name = F.original_name;
F.visibility = F.Provision.Lot.name;
F.is_file = true;
return F;
}),
});
} catch (error) {
console.log(error);
}
} else {
return res.json({
success: false,
error: t("api.documents.errors.noVmeSelected"),
});
}
}
} catch (error) {
return res.json({
success: false,
error,
});
}
}
async function postDocument(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, name, visibility, DocumentTypeId, DocumentFiles } = req.body;
let { Users } = req.body;
const Data = {
name,
visibility,
DocumentTypeId,
VMEId: VME.id,
UserId: User.id,
Users,
};
let errors = {};
if (!name) {
errors.name = t("api.documents.errors.nameRequired");
}
if (!id && !DocumentFiles) {
errors.DocumentFiles = t("api.documents.errors.filesRequired");
}
if (!visibility) {
errors.visibility = t("api.documents.errors.visibilityRequired");
}
if (visibility === "custom" && (!Users || Users?.length === 0)) {
errors.Users = t("api.documents.errors.residentsRequired");
}
if (!DocumentTypeId) {
errors.DocumentType = t("api.documents.errors.typeRequired");
}
let exists = await db.Document.findOne({ where: { VMEId: VME.id, name } });
if (exists) {
errors.name = t("api.documents.errors.alreadyExists", { name });
}
if (Object.keys(errors).length > 0) {
return res.json({
success: false,
errors,
});
}
//Set Users based on visibility
if (typeof Users === "undefined") {
Users = await VME.getUsers();
if (visibility === "synt") {
Users = Users.filter(
(U) =>
U.UserVME.type === "synt_viewer" ||
U.UserVME.type === "synt_authoriser"
);
} else if (visibility === "owners") {
Users = await findCommissioners(VME);
} else if (visibility === "everyone") {
// all users
}
}
if (id) {
// update exisiting document
db.Document.findOne({ where: { id } }).then((Document) => {
attachUploadedFiles("Document", Document, DocumentFiles);
const update = { name, visibility, DocumentTypeId };
Document.update(update);
if (Users) {
// custom visibility
Document.setUsers(Users.map((U) => U.id)); // who has access
Users.forEach((U) => {
notifier.notify(U, "update_document", {
Document,
VME,
});
});
}
return res.json({ success: true, Document });
});
} else {
db.Document.create(Data).then((newItem) => {
attachUploadedFiles("Document", newItem, DocumentFiles);
if (Users) {
// custom visibility
newItem.setUsers(Users.map((U) => U.id)); // who has access
Users.forEach((U) => {
notifier.notify(U, "new_document", {
Document: newItem,
VME,
});
});
}
return res.json({ success: true, Document: newItem });
});
}
}
}