Merge Staging in Prepod
This commit is contained in:
commit
9b493dd075
@ -1,9 +0,0 @@
|
||||
const {join} = require('path');
|
||||
|
||||
/**
|
||||
* @type {import("puppeteer").Configuration}
|
||||
*/
|
||||
module.exports = {
|
||||
// Changes the cache location for Puppeteer.
|
||||
cacheDirectory: join(__dirname, '.cache', 'puppeteer'),
|
||||
};
|
27
Dockerfile
27
Dockerfile
@ -1,14 +1,19 @@
|
||||
# Install dependencies only when needed
|
||||
FROM node:19-alpine AS deps
|
||||
FROM node:18-bullseye-slim AS deps
|
||||
|
||||
WORKDIR leCoffre
|
||||
|
||||
RUN npm install -D prisma@4.11.0
|
||||
COPY package.json ./
|
||||
|
||||
RUN apk update && apk add openssh-client git
|
||||
# ENV PUPPETEER_CACHE_DIR=~/leCoffre/.cache/puppeteer
|
||||
# ENV PUPPETEER_SKIP_DOWNLOAD=false
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y wget gnupg \
|
||||
&& wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | gpg --dearmor -o /usr/share/keyrings/googlechrome-linux-keyring.gpg \
|
||||
&& sh -c 'echo "deb [arch=amd64 signed-by=/usr/share/keyrings/googlechrome-linux-keyring.gpg] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list' \
|
||||
&& apt-get update \
|
||||
&& apt-get install -y google-chrome-stable chromium fonts-ipafont-gothic fonts-wqy-zenhei fonts-thai-tlwg fonts-khmeros fonts-kacst fonts-freefont-ttf libxss1 openssh-client git \
|
||||
--no-install-recommends \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
COPY id_rsa /root/.ssh/id_rsa
|
||||
RUN chmod 600 ~/.ssh/id_rsa
|
||||
@ -18,13 +23,12 @@ RUN ssh-keyscan github.com smart-chain-fr/leCoffre-resources.git >> /root/.ssh/k
|
||||
RUN npm install --frozen-lockfile
|
||||
|
||||
# Rebuild the source code only when needed
|
||||
FROM node:19-alpine AS builder
|
||||
FROM node:18-bullseye-slim AS builder
|
||||
|
||||
WORKDIR leCoffre
|
||||
|
||||
COPY --from=deps leCoffre/node_modules ./node_modules
|
||||
COPY --from=deps leCoffre/package.json package.json
|
||||
#COPY --from=deps leCoffre/.cache ./.cache
|
||||
|
||||
COPY tsconfig.json tsconfig.json
|
||||
COPY src src
|
||||
@ -33,19 +37,24 @@ RUN npx prisma generate
|
||||
RUN npm run build
|
||||
|
||||
# Production image, copy all the files and run next
|
||||
FROM node:19-alpine AS production
|
||||
FROM node:18-bullseye-slim AS production
|
||||
|
||||
WORKDIR leCoffre
|
||||
|
||||
RUN adduser -D lecoffreuser --uid 10000 && chown -R lecoffreuser .
|
||||
RUN adduser --disabled-password lecoffreuser --uid 10000 && chown -R lecoffreuser .
|
||||
|
||||
RUN mkdir -p /home/lecoffreuser/Downloads \
|
||||
&& mkdir -p /home/lecoffreuser/Downloads \
|
||||
&& chown -R lecoffreuser:lecoffreuser /home/lecoffreuser
|
||||
|
||||
COPY --from=builder --chown=lecoffreuser leCoffre/node_modules ./node_modules
|
||||
COPY --from=builder --chown=lecoffreuser leCoffre/dist dist
|
||||
COPY --from=builder --chown=lecoffreuser leCoffre/package.json ./package.json
|
||||
COPY --from=builder --chown=lecoffreuser leCoffre/src/common/databases ./src/common/databases
|
||||
#COPY --from=builder --chown=lecoffreuser leCoffre/.cache ./.cache
|
||||
|
||||
USER lecoffreuser
|
||||
|
||||
CMD ["npm", "run", "start"]
|
||||
EXPOSE 3001
|
||||
|
||||
|
||||
|
@ -28,6 +28,9 @@ lecoffreBack:
|
||||
cert-manager.io/cluster-issuer: letsencrypt-prod
|
||||
nginx.ingress.kubernetes.io/from-to-www-redirect: "true"
|
||||
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
|
||||
nginx.ingress.kubernetes.io/client_max_body_size: 200m
|
||||
nginx.ingress.kubernetes.io/client-body-buffer-size: 2M
|
||||
nginx.ingress.kubernetes.io/proxy-body-size: 200m
|
||||
env:
|
||||
- key: .env
|
||||
scwID: "id:430001f8-68ab-47b2-92e8-38024c35a80d"
|
||||
|
@ -28,6 +28,9 @@ lecoffreBack:
|
||||
cert-manager.io/cluster-issuer: letsencrypt-prod
|
||||
nginx.ingress.kubernetes.io/from-to-www-redirect: "true"
|
||||
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
|
||||
nginx.ingress.kubernetes.io/client_max_body_size: 200m
|
||||
nginx.ingress.kubernetes.io/client-body-buffer-size: 2M
|
||||
nginx.ingress.kubernetes.io/proxy-body-size: 200m
|
||||
env:
|
||||
- key: .env
|
||||
scwID: "id:8f66af26-2481-4ef2-b4f0-7f076f9ee18b"
|
||||
|
@ -28,6 +28,9 @@ lecoffreBack:
|
||||
cert-manager.io/cluster-issuer: letsencrypt-prod
|
||||
nginx.ingress.kubernetes.io/from-to-www-redirect: "true"
|
||||
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
|
||||
nginx.ingress.kubernetes.io/client_max_body_size: 200m
|
||||
nginx.ingress.kubernetes.io/client-body-buffer-size: 2M
|
||||
nginx.ingress.kubernetes.io/proxy-body-size: 200m
|
||||
# key is name of the environment variable, scwID is the secret ID in SCW with "id:" in front
|
||||
env:
|
||||
- key: .env
|
||||
|
@ -53,7 +53,7 @@
|
||||
"express": "^4.18.2",
|
||||
"fp-ts": "^2.16.1",
|
||||
"jsonwebtoken": "^9.0.0",
|
||||
"le-coffre-resources": "git@github.com:smart-chain-fr/leCoffre-resources.git#v2.89",
|
||||
"le-coffre-resources": "git@github.com:smart-chain-fr/leCoffre-resources.git#v2.90",
|
||||
"module-alias": "^2.2.2",
|
||||
"monocle-ts": "^2.3.13",
|
||||
"multer": "^1.4.5-lts.1",
|
||||
|
@ -9,6 +9,7 @@ import authHandler from "@App/middlewares/AuthHandler";
|
||||
import ruleHandler from "@App/middlewares/RulesHandler";
|
||||
import roleHandler from "@App/middlewares/RolesHandler";
|
||||
import { Prisma } from "@prisma/client";
|
||||
import customerHandler from "@App/middlewares/OfficeMembershipHandlers/CustomerHandler";
|
||||
|
||||
@Controller()
|
||||
@Service()
|
||||
@ -78,7 +79,7 @@ export default class CustomersController extends ApiController {
|
||||
/**
|
||||
* @description Modify a specific customer by uid
|
||||
*/
|
||||
@Put("/api/v1/admin/customers/:uid", [authHandler, roleHandler, ruleHandler])
|
||||
@Put("/api/v1/admin/customers/:uid", [authHandler, roleHandler, ruleHandler, customerHandler])
|
||||
protected async put(req: Request, response: Response) {
|
||||
try {
|
||||
const uid = req.params["uid"];
|
||||
@ -119,7 +120,7 @@ export default class CustomersController extends ApiController {
|
||||
/**
|
||||
* @description Get a specific customer by uid
|
||||
*/
|
||||
@Get("/api/v1/admin/customers/:uid", [authHandler, roleHandler, ruleHandler])
|
||||
@Get("/api/v1/admin/customers/:uid", [authHandler, roleHandler, ruleHandler, customerHandler])
|
||||
protected async getOneByUid(req: Request, response: Response) {
|
||||
try {
|
||||
const uid = req.params["uid"];
|
||||
|
@ -3,7 +3,7 @@ import { Controller, Delete, Get, Post, Put } from "@ControllerPattern/index";
|
||||
import ApiController from "@Common/system/controller-pattern/ApiController";
|
||||
import { Service } from "typedi";
|
||||
import DocumentsService from "@Services/admin/DocumentsService/DocumentsService";
|
||||
import { Documents, Prisma } from "@prisma/client";
|
||||
import { Documents, EDocumentStatus, Prisma } from "@prisma/client";
|
||||
import { Document } from "le-coffre-resources/dist/Admin";
|
||||
import { validateOrReject } from "class-validator";
|
||||
import authHandler from "@App/middlewares/AuthHandler";
|
||||
@ -104,7 +104,55 @@ export default class DocumentsController extends ApiController {
|
||||
await validateOrReject(documentEntity, { groups: ["updateDocument"] });
|
||||
|
||||
//call service to get prisma entity
|
||||
const documentEntityUpdated: Documents = await this.documentsService.update(uid, documentEntity, req.body.refused_reason);
|
||||
const documentEntityUpdated: Documents = await this.documentsService.update(uid, documentEntity);
|
||||
|
||||
//Hydrate ressource with prisma entity
|
||||
const document = Document.hydrate<Document>(documentEntityUpdated, { strategy: "excludeAll" });
|
||||
|
||||
//success
|
||||
this.httpSuccess(response, document);
|
||||
} catch (error) {
|
||||
this.httpInternalError(response, error);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Update a specific document
|
||||
*/
|
||||
@Put("/api/v1/notary/documents/:uid/refuse", [authHandler, ruleHandler, documentHandler])
|
||||
protected async refuseDocument(req: Request, response: Response) {
|
||||
try {
|
||||
const uid = req.params["uid"];
|
||||
if (!uid) {
|
||||
this.httpBadRequest(response, "No uid provided");
|
||||
return;
|
||||
}
|
||||
|
||||
const documentFound = await this.documentsService.getByUid(uid, {
|
||||
files: true,
|
||||
});
|
||||
|
||||
if (!documentFound) {
|
||||
this.httpNotFoundRequest(response, "document not found");
|
||||
return;
|
||||
}
|
||||
|
||||
//init Document resource with request body values
|
||||
const documentEntity = Document.hydrate<Document>(documentFound);
|
||||
|
||||
// Status to refuse
|
||||
documentEntity.document_status = EDocumentStatus.REFUSED;
|
||||
|
||||
//validate document
|
||||
await validateOrReject(documentEntity, { groups: ["updateDocument"] });
|
||||
|
||||
//call service to get prisma entity
|
||||
const documentEntityUpdated: Documents = await this.documentsService.refuse(uid, documentEntity, req.body.refused_reason);
|
||||
|
||||
//create email for asked document
|
||||
// this.emailBuilder.sendDocumentEmails(documentEntityUpdated);
|
||||
// this.notificationBuilder.sendDocumentAnchoredNotificatiom(documentEntityUpdated);
|
||||
|
||||
//Hydrate ressource with prisma entity
|
||||
const document = Document.hydrate<Document>(documentEntityUpdated, { strategy: "excludeAll" });
|
||||
|
@ -58,10 +58,10 @@ export default class OfficeFoldersController extends ApiController {
|
||||
};
|
||||
}
|
||||
|
||||
const officeId: string = req.body.user.office_Id;
|
||||
const officeWhereInput: Prisma.OfficesWhereInput = { uid: officeId } ;
|
||||
if(!query.where) query.where = { office: officeWhereInput};
|
||||
query.where.office = officeWhereInput;
|
||||
const userId: string = req.body.user.userId;
|
||||
if (query.where?.stakeholders) delete query.where.stakeholders;
|
||||
const officeFoldersWhereInput: Prisma.OfficeFoldersWhereInput = { ...query.where, stakeholders: { some: { uid: userId } } };
|
||||
query.where = officeFoldersWhereInput;
|
||||
|
||||
//call service to get prisma entity
|
||||
const officeFolderEntities: OfficeFolders[] = await this.officeFoldersService.get(query);
|
||||
|
@ -8,11 +8,13 @@ import { Document } from "le-coffre-resources/dist/Customer";
|
||||
import authHandler from "@App/middlewares/AuthHandler";
|
||||
import documentHandler from "@App/middlewares/CustomerHandler/DocumentHandler";
|
||||
import { validateOrReject } from "class-validator";
|
||||
import OfficeFoldersService from "@Services/super-admin/OfficeFoldersService/OfficeFoldersService";
|
||||
import { OfficeFolder } from "le-coffre-resources/dist/Notary";
|
||||
|
||||
@Controller()
|
||||
@Service()
|
||||
export default class DocumentsController extends ApiController {
|
||||
constructor(private documentsService: DocumentsService) {
|
||||
constructor(private documentsService: DocumentsService, private officeFoldersService: OfficeFoldersService) {
|
||||
super();
|
||||
}
|
||||
|
||||
@ -94,7 +96,22 @@ export default class DocumentsController extends ApiController {
|
||||
try {
|
||||
//init Document resource with request body values
|
||||
const documentEntity = Document.hydrate<Document>(req.body);
|
||||
if(!documentEntity.folder?.uid) {
|
||||
this.httpBadRequest(response, "No folder uid provided");
|
||||
return;
|
||||
}
|
||||
|
||||
const folder = await this.officeFoldersService.getByUid(documentEntity.folder.uid, {folder_anchor: true});
|
||||
if(!folder) {
|
||||
this.httpBadRequest(response, "Folder not found");
|
||||
return;
|
||||
}
|
||||
|
||||
const folderEntity = OfficeFolder.hydrate<OfficeFolder>(folder);
|
||||
if (folderEntity.folder_anchor?.status === "VERIFIED_ON_CHAIN") {
|
||||
this.httpBadRequest(response, "Cannot update a verified folder");
|
||||
return;
|
||||
}
|
||||
//validate document
|
||||
await validateOrReject(documentEntity, { groups: ["createDocument"], forbidUnknownValues: false });
|
||||
|
||||
|
@ -6,19 +6,16 @@ import FilesService from "@Services/common/FilesService/FilesService";
|
||||
import { Files, Prisma } from "@prisma/client";
|
||||
import { File } from "le-coffre-resources/dist/Customer";
|
||||
import { Document } from "le-coffre-resources/dist/Customer";
|
||||
import { validateOrReject } from "class-validator";
|
||||
import DocumentsService from "@Services/customer/DocumentsService/DocumentsService";
|
||||
import authHandler from "@App/middlewares/AuthHandler";
|
||||
import fileHandler from "@App/middlewares/CustomerHandler/FileHandler";
|
||||
import DocumentTypesService from "@Services/super-admin/DocumentTypesService/DocumentTypesService";
|
||||
import { DocumentType } from "le-coffre-resources/dist/SuperAdmin";
|
||||
import ObjectHydrate from "@Common/helpers/ObjectHydrate";
|
||||
import NotificationBuilder from "@Common/notifications/NotificationBuilder";
|
||||
import { validateOrReject } from "class-validator";
|
||||
|
||||
@Controller()
|
||||
@Service()
|
||||
export default class FilesController extends ApiController {
|
||||
constructor(private filesService: FilesService, private documentService: DocumentsService, private documentTypesService : DocumentTypesService, private notificationBuilder : NotificationBuilder) {
|
||||
constructor(private filesService: FilesService, private documentService: DocumentsService, private notificationBuilder : NotificationBuilder) {
|
||||
super();
|
||||
}
|
||||
|
||||
@ -93,7 +90,12 @@ export default class FilesController extends ApiController {
|
||||
const fileEntity = File.hydrate<File>(JSON.parse(req.body["q"]));
|
||||
|
||||
//validate File
|
||||
// await validateOrReject(fileEntity, { groups: ["createFile"] });
|
||||
try {
|
||||
await validateOrReject(fileEntity, { groups: ["createFile"] });
|
||||
} catch (error) {
|
||||
this.httpBadRequest(response, error);
|
||||
return;
|
||||
}
|
||||
|
||||
//call service to get prisma entity
|
||||
const fileEntityCreated = await this.filesService.create(fileEntity, req.file);
|
||||
@ -111,6 +113,7 @@ export default class FilesController extends ApiController {
|
||||
strategy: "excludeAll",
|
||||
});
|
||||
|
||||
|
||||
//success
|
||||
this.httpCreated(response, fileEntityHydrated);
|
||||
} catch (error) {
|
||||
@ -226,52 +229,4 @@ export default class FilesController extends ApiController {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Create a new File
|
||||
* @returns File created
|
||||
*/
|
||||
@Post("/api/v1/customer/addPersonalFile", [authHandler, fileHandler])
|
||||
protected async addPersonalFile(req: Request, response: Response) {
|
||||
try {
|
||||
//get file
|
||||
if (!req.file) throw new Error("No file provided");
|
||||
|
||||
//init File resource with request body values
|
||||
const fileEntity = File.hydrate<File>(JSON.parse(req.body["q"]));
|
||||
|
||||
const documentTypeEntities = await this.documentTypesService.get({ where: { name: "Other"} });
|
||||
const documentTypeEntity = documentTypeEntities[0];
|
||||
const documentType = ObjectHydrate.hydrate<DocumentType>(new DocumentType(), documentTypeEntity!, { strategy: "excludeAll" });
|
||||
|
||||
const documentEntity = Document.hydrate<Document>({document_type: documentType});
|
||||
await validateOrReject(documentEntity, { groups: ["createDocument"], forbidUnknownValues: false });
|
||||
const documentEntityCreated = await this.documentService.create(documentEntity);
|
||||
|
||||
const document = Document.hydrate<Document>(documentEntityCreated, {
|
||||
strategy: "excludeAll",
|
||||
});
|
||||
|
||||
fileEntity.document = document;
|
||||
|
||||
const fileEntityCreated = await this.filesService.create(fileEntity, req.file);
|
||||
|
||||
const documentToUpdate = Document.hydrate<Document>(document!);
|
||||
|
||||
documentToUpdate!.document_status = "DEPOSITED";
|
||||
await this.documentService.update(document!.uid!, documentToUpdate);
|
||||
|
||||
//Hydrate ressource with prisma entity
|
||||
const fileEntityHydrated = File.hydrate<File>(fileEntityCreated, {
|
||||
strategy: "excludeAll",
|
||||
});
|
||||
|
||||
//success
|
||||
this.httpCreated(response, fileEntityHydrated);
|
||||
|
||||
} catch (error) {
|
||||
this.httpBadRequest(response, error);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ import { Response, Request } from "express";
|
||||
import { Controller, Post } from "@ControllerPattern/index";
|
||||
import ApiController from "@Common/system/controller-pattern/ApiController";
|
||||
import { Service } from "typedi";
|
||||
import Id360Service from "@Services/common/Id360Service/Id360Service";
|
||||
import Id360Service, { EnrollmentResponse } from "@Services/common/Id360Service/Id360Service";
|
||||
import CustomersService from "@Services/customer/CustomersService/CustomersService";
|
||||
import AuthService from "@Services/common/AuthService/AuthService";
|
||||
import { Customer } from "le-coffre-resources/dist/SuperAdmin";
|
||||
@ -34,7 +34,11 @@ export default class CustomerController extends ApiController {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const enrollment = await this.id360Service.getEnrollment(callbackToken);
|
||||
const res = await this.id360Service.getEnrollment(callbackToken);
|
||||
const enrollment = await res.json() as EnrollmentResponse;
|
||||
if(enrollment.status === "STARTED") {
|
||||
this.loginCallback(req, response);
|
||||
}
|
||||
if (enrollment.status !== "OK") {
|
||||
this.httpUnauthorized(response, "Enrollment status is not OK");
|
||||
return;
|
||||
|
@ -20,7 +20,6 @@ export default class DocumentController extends ApiController {
|
||||
protected async getDocumentVerificationFromId360(req: Request, response: Response) {
|
||||
|
||||
try {
|
||||
console.log("document callback", req, response)
|
||||
this.httpSuccess(response);
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
@ -33,7 +32,6 @@ export default class DocumentController extends ApiController {
|
||||
protected async getCustomerVerificationFromId360(req: Request, response: Response) {
|
||||
|
||||
try {
|
||||
console.log("customer callback", req, response)
|
||||
this.httpSuccess(response);
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
|
@ -25,6 +25,10 @@ export default class UserController extends ApiController {
|
||||
if (!code) throw new Error("code is required");
|
||||
|
||||
const idNotToken = await this.idNotService.getIdNotToken(code);
|
||||
if(!idNotToken) {
|
||||
this.httpValidationError(response, "IdNot token undefined");
|
||||
return;
|
||||
}
|
||||
const user = await this.idNotService.getOrCreateUser(idNotToken);
|
||||
|
||||
if(!user) {
|
||||
|
@ -8,6 +8,7 @@ import { validateOrReject } from "class-validator";
|
||||
import authHandler from "@App/middlewares/AuthHandler";
|
||||
import ruleHandler from "@App/middlewares/RulesHandler";
|
||||
import { Prisma } from "@prisma/client";
|
||||
import customerHandler from "@App/middlewares/OfficeMembershipHandlers/CustomerHandler";
|
||||
|
||||
@Controller()
|
||||
@Service()
|
||||
@ -76,7 +77,7 @@ export default class CustomersController extends ApiController {
|
||||
/**
|
||||
* @description Modify a specific customer by uid
|
||||
*/
|
||||
@Put("/api/v1/notary/customers/:uid", [authHandler, ruleHandler])
|
||||
@Put("/api/v1/notary/customers/:uid", [authHandler, ruleHandler, customerHandler])
|
||||
protected async put(req: Request, response: Response) {
|
||||
try {
|
||||
const uid = req.params["uid"];
|
||||
@ -117,7 +118,7 @@ export default class CustomersController extends ApiController {
|
||||
/**
|
||||
* @description Get a specific customer by uid
|
||||
*/
|
||||
@Get("/api/v1/notary/customers/:uid", [authHandler, ruleHandler])
|
||||
@Get("/api/v1/notary/customers/:uid", [authHandler, ruleHandler, customerHandler])
|
||||
protected async getOneByUid(req: Request, response: Response) {
|
||||
try {
|
||||
const uid = req.params["uid"];
|
||||
|
@ -3,19 +3,24 @@ import { Controller, Delete, Get, Post, Put } from "@ControllerPattern/index";
|
||||
import ApiController from "@Common/system/controller-pattern/ApiController";
|
||||
import { Service } from "typedi";
|
||||
import DocumentsService from "@Services/notary/DocumentsService/DocumentsService";
|
||||
import { Documents, Prisma } from "@prisma/client";
|
||||
import { Document } from "le-coffre-resources/dist/Notary";
|
||||
import { Documents, EDocumentStatus, Prisma } from "@prisma/client";
|
||||
import { Document, OfficeFolder } from "le-coffre-resources/dist/Notary";
|
||||
import { validateOrReject } from "class-validator";
|
||||
import authHandler from "@App/middlewares/AuthHandler";
|
||||
import ruleHandler from "@App/middlewares/RulesHandler";
|
||||
import documentHandler from "@App/middlewares/OfficeMembershipHandlers/DocumentHandler";
|
||||
import EmailBuilder from "@Common/emails/EmailBuilder";
|
||||
import OfficeFoldersService from "@Services/notary/OfficeFoldersService/OfficeFoldersService";
|
||||
// import NotificationBuilder from "@Common/notifications/NotificationBuilder";
|
||||
|
||||
@Controller()
|
||||
@Service()
|
||||
export default class DocumentsController extends ApiController {
|
||||
constructor(private documentsService: DocumentsService, private emailBuilder: EmailBuilder) {
|
||||
constructor(
|
||||
private documentsService: DocumentsService,
|
||||
private emailBuilder: EmailBuilder,
|
||||
private officeFoldersService: OfficeFoldersService,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
@ -60,6 +65,20 @@ export default class DocumentsController extends ApiController {
|
||||
//init Document resource with request body values
|
||||
const documentEntity = Document.hydrate<Document>(req.body);
|
||||
|
||||
const folder = await this.officeFoldersService.getByUid(documentEntity.folder?.uid!, {
|
||||
folder_anchor: true,
|
||||
});
|
||||
if (!folder) {
|
||||
this.httpBadRequest(response, "Folder not found");
|
||||
return;
|
||||
}
|
||||
|
||||
const folderRessource = OfficeFolder.hydrate<OfficeFolder>(folder);
|
||||
if (folderRessource.folder_anchor) {
|
||||
this.httpBadRequest(response, "Cannot ask document on an anchored or anchoring folder");
|
||||
return;
|
||||
}
|
||||
|
||||
//validate document
|
||||
await validateOrReject(documentEntity, { groups: ["createDocument"], forbidUnknownValues: false });
|
||||
|
||||
@ -104,13 +123,59 @@ export default class DocumentsController extends ApiController {
|
||||
//init Document resource with request body values
|
||||
const documentEntity = Document.hydrate<Document>(req.body);
|
||||
|
||||
//validate document
|
||||
await validateOrReject(documentEntity, { groups: ["updateDocument"] });
|
||||
|
||||
//call service to get prisma entity
|
||||
const documentEntityUpdated: Documents = await this.documentsService.update(uid, documentEntity);
|
||||
|
||||
//create email for asked document
|
||||
// this.emailBuilder.sendDocumentEmails(documentEntityUpdated);
|
||||
// this.notificationBuilder.sendDocumentAnchoredNotificatiom(documentEntityUpdated);
|
||||
|
||||
//Hydrate ressource with prisma entity
|
||||
const document = Document.hydrate<Document>(documentEntityUpdated, { strategy: "excludeAll" });
|
||||
|
||||
//success
|
||||
this.httpSuccess(response, document);
|
||||
} catch (error) {
|
||||
this.httpInternalError(response, error);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Update a specific document
|
||||
*/
|
||||
@Put("/api/v1/notary/documents/:uid/refuse", [authHandler, ruleHandler, documentHandler])
|
||||
protected async refuseDocument(req: Request, response: Response) {
|
||||
try {
|
||||
const uid = req.params["uid"];
|
||||
if (!uid) {
|
||||
this.httpBadRequest(response, "No uid provided");
|
||||
return;
|
||||
}
|
||||
|
||||
const documentFound = await this.documentsService.getByUid(uid, {
|
||||
files: true,
|
||||
});
|
||||
|
||||
if (!documentFound) {
|
||||
this.httpNotFoundRequest(response, "document not found");
|
||||
return;
|
||||
}
|
||||
|
||||
//init Document resource with request body values
|
||||
const documentEntity = Document.hydrate<Document>(documentFound);
|
||||
|
||||
// Status to refuse
|
||||
documentEntity.document_status = EDocumentStatus.REFUSED;
|
||||
|
||||
//validate document
|
||||
await validateOrReject(documentEntity, { groups: ["updateDocument"] });
|
||||
|
||||
//call service to get prisma entity
|
||||
const documentEntityUpdated: Documents = await this.documentsService.update(uid, documentEntity, req.body.refused_reason);
|
||||
const documentEntityUpdated: Documents = await this.documentsService.refuse(uid, documentEntity, req.body.refused_reason);
|
||||
|
||||
//create email for asked document
|
||||
// this.emailBuilder.sendDocumentEmails(documentEntityUpdated);
|
||||
|
@ -2,7 +2,7 @@ import { Response, Request } from "express";
|
||||
import { Controller, Get, Post } from "@ControllerPattern/index";
|
||||
import ApiController from "@Common/system/controller-pattern/ApiController";
|
||||
import { Service } from "typedi";
|
||||
import { OfficeFolder } from "le-coffre-resources/dist/Notary";
|
||||
import { Document, OfficeFolder } from "le-coffre-resources/dist/Notary";
|
||||
import { getFolderHashes } from "@Common/optics/notary";
|
||||
import OfficeFoldersService from "@Services/notary/OfficeFoldersService/OfficeFoldersService";
|
||||
import OfficeFolderAnchorsRepository from "@Repositories/OfficeFolderAnchorsRepository";
|
||||
@ -136,6 +136,18 @@ export default class OfficeFoldersController extends ApiController {
|
||||
|
||||
const officeFolder = OfficeFolder.hydrate<OfficeFolder>(officeFolderFound, { strategy: "excludeAll" });
|
||||
|
||||
// Check if every document is validated in a folder
|
||||
const documents = officeFolder.documents ?? [];
|
||||
const documentsValidated = documents.filter((document) => {
|
||||
let documentHydrated = Document.hydrate<Document>(document, { strategy: "excludeAll" });
|
||||
return documentHydrated.document_status === "VALIDATED";
|
||||
});
|
||||
|
||||
if (documentsValidated.length !== documents.length && documents.length !== 0) {
|
||||
this.httpBadRequest(response, "Cannot anchor a folder with non validated documents");
|
||||
return;
|
||||
}
|
||||
|
||||
const folderHashes = getFolderHashes(officeFolder);
|
||||
|
||||
if (folderHashes.length === 0) {
|
||||
|
@ -46,7 +46,7 @@ export default class OfficeFoldersController extends ApiController {
|
||||
OR: [
|
||||
{ contact: { first_name: { contains: filter, mode: "insensitive" } } },
|
||||
{ contact: { last_name: { contains: filter, mode: "insensitive" } } },
|
||||
]
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -111,7 +111,9 @@ export default class OfficeFoldersController extends ApiController {
|
||||
return;
|
||||
}
|
||||
|
||||
const officeFolderFound = await this.officeFoldersService.getByUid(uid);
|
||||
const officeFolderFound = await this.officeFoldersService.getByUid(uid, {
|
||||
folder_anchor: true,
|
||||
});
|
||||
|
||||
if (!officeFolderFound) {
|
||||
this.httpNotFoundRequest(response, "office folder not found");
|
||||
@ -119,13 +121,17 @@ export default class OfficeFoldersController extends ApiController {
|
||||
}
|
||||
|
||||
//init OfficeFolder resource with request body values
|
||||
const officeFolderEntity = OfficeFolder.hydrate<OfficeFolder>(req.body);
|
||||
|
||||
const officefolderToUpdate = OfficeFolder.hydrate<OfficeFolder>(req.body);
|
||||
const officeFolderFoundEntity = OfficeFolder.hydrate<OfficeFolder>(officeFolderFound);
|
||||
//validate folder
|
||||
await validateOrReject(officeFolderEntity, { groups: ["updateFolder"], forbidUnknownValues: false });
|
||||
await validateOrReject(officefolderToUpdate, { groups: ["updateFolder"], forbidUnknownValues: false });
|
||||
|
||||
if (officeFolderFoundEntity.folder_anchor?.status === "VERIFIED_ON_CHAIN") {
|
||||
this.httpBadRequest(response, "Cannot update a verified folder");
|
||||
return;
|
||||
}
|
||||
//call service to get prisma entity
|
||||
const officeFolderEntityUpdated = await this.officeFoldersService.update(uid, officeFolderEntity);
|
||||
const officeFolderEntityUpdated = await this.officeFoldersService.update(uid, officefolderToUpdate);
|
||||
|
||||
//Hydrate ressource with prisma entity
|
||||
const officeFolders = OfficeFolder.hydrate<OfficeFolder>(officeFolderEntityUpdated, {
|
||||
@ -140,6 +146,102 @@ export default class OfficeFoldersController extends ApiController {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Modify a specific folder by uid
|
||||
*/
|
||||
@Put("/api/v1/notary/folders/:uid/archive", [authHandler, ruleHandler, folderHandler])
|
||||
protected async archive(req: Request, response: Response) {
|
||||
try {
|
||||
const uid = req.params["uid"];
|
||||
if (!uid) {
|
||||
this.httpBadRequest(response, "No uid provided");
|
||||
return;
|
||||
}
|
||||
|
||||
const officeFolderFound = await this.officeFoldersService.getByUid(uid, {
|
||||
folder_anchor: true,
|
||||
});
|
||||
|
||||
if (!officeFolderFound) {
|
||||
this.httpNotFoundRequest(response, "office folder not found");
|
||||
return;
|
||||
}
|
||||
|
||||
//init OfficeFolder resource with request body values
|
||||
const officefolderToUpdate = OfficeFolder.hydrate<OfficeFolder>(officeFolderFound);
|
||||
|
||||
officefolderToUpdate.status = "ARCHIVED";
|
||||
officefolderToUpdate.archived_description = req.body.archived_description ?? "";
|
||||
|
||||
//validate folder
|
||||
await validateOrReject(officefolderToUpdate, { groups: ["updateFolder"], forbidUnknownValues: false });
|
||||
|
||||
if ((officeFolderFound as any).folder_anchor?.status !== "VERIFIED_ON_CHAIN") {
|
||||
this.httpBadRequest(response, "Cannot archive a not anchored folder");
|
||||
return;
|
||||
}
|
||||
|
||||
//call service to get prisma entity
|
||||
const officeFolderEntityUpdated = await this.officeFoldersService.update(uid, officefolderToUpdate);
|
||||
|
||||
//Hydrate ressource with prisma entity
|
||||
const officeFolders = OfficeFolder.hydrate<OfficeFolder>(officeFolderEntityUpdated, {
|
||||
strategy: "excludeAll",
|
||||
});
|
||||
|
||||
//success
|
||||
this.httpSuccess(response, officeFolders);
|
||||
} catch (error) {
|
||||
this.httpInternalError(response, error);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Modify a specific folder by uid
|
||||
*/
|
||||
@Put("/api/v1/notary/folders/:uid/restore", [authHandler, ruleHandler, folderHandler])
|
||||
protected async restore(req: Request, response: Response) {
|
||||
try {
|
||||
const uid = req.params["uid"];
|
||||
if (!uid) {
|
||||
this.httpBadRequest(response, "No uid provided");
|
||||
return;
|
||||
}
|
||||
|
||||
const officeFolderFound = await this.officeFoldersService.getByUid(uid, {
|
||||
folder_anchor: true,
|
||||
});
|
||||
|
||||
if (!officeFolderFound) {
|
||||
this.httpNotFoundRequest(response, "office folder not found");
|
||||
return;
|
||||
}
|
||||
|
||||
//init OfficeFolder resource with request body values
|
||||
const officefolderToUpdate = OfficeFolder.hydrate<OfficeFolder>(officeFolderFound);
|
||||
|
||||
officefolderToUpdate.status = "LIVE";
|
||||
officefolderToUpdate.archived_description = "";
|
||||
|
||||
//validate folder
|
||||
await validateOrReject(officefolderToUpdate, { groups: ["updateFolder"], forbidUnknownValues: false });
|
||||
|
||||
//call service to get prisma entity
|
||||
const officeFolderEntityUpdated = await this.officeFoldersService.update(uid, officefolderToUpdate);
|
||||
|
||||
//Hydrate ressource with prisma entity
|
||||
const officeFolders = OfficeFolder.hydrate<OfficeFolder>(officeFolderEntityUpdated, {
|
||||
strategy: "excludeAll",
|
||||
});
|
||||
|
||||
//success
|
||||
this.httpSuccess(response, officeFolders);
|
||||
} catch (error) {
|
||||
this.httpInternalError(response, error);
|
||||
return;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @description Get a specific folder by uid
|
||||
* @returns IFolder
|
||||
|
@ -9,6 +9,7 @@ import authHandler from "@App/middlewares/AuthHandler";
|
||||
import ruleHandler from "@App/middlewares/RulesHandler";
|
||||
import roleHandler from "@App/middlewares/RolesHandler";
|
||||
import { Prisma } from "@prisma/client";
|
||||
import customerHandler from "@App/middlewares/OfficeMembershipHandlers/CustomerHandler";
|
||||
|
||||
@Controller()
|
||||
@Service()
|
||||
@ -78,7 +79,7 @@ export default class CustomersController extends ApiController {
|
||||
/**
|
||||
* @description Modify a specific customer by uid
|
||||
*/
|
||||
@Put("/api/v1/super-admin/customers/:uid", [authHandler, roleHandler, ruleHandler])
|
||||
@Put("/api/v1/super-admin/customers/:uid", [authHandler, roleHandler, ruleHandler, customerHandler])
|
||||
protected async put(req: Request, response: Response) {
|
||||
try {
|
||||
const uid = req.params["uid"];
|
||||
@ -119,7 +120,7 @@ export default class CustomersController extends ApiController {
|
||||
/**
|
||||
* @description Get a specific customer by uid
|
||||
*/
|
||||
@Get("/api/v1/super-admin/customers/:uid", [authHandler, roleHandler, ruleHandler])
|
||||
@Get("/api/v1/super-admin/customers/:uid", [authHandler, roleHandler, ruleHandler, customerHandler])
|
||||
protected async getOneByUid(req: Request, response: Response) {
|
||||
try {
|
||||
const uid = req.params["uid"];
|
||||
|
@ -4,7 +4,7 @@ import roleHandler from "@App/middlewares/RolesHandler";
|
||||
import ruleHandler from "@App/middlewares/RulesHandler";
|
||||
import ApiController from "@Common/system/controller-pattern/ApiController";
|
||||
import { Controller, Delete, Get, Post, Put } from "@ControllerPattern/index";
|
||||
import { Documents, Prisma } from "@prisma/client";
|
||||
import { Documents, EDocumentStatus, Prisma } from "@prisma/client";
|
||||
import DocumentsService from "@Services/super-admin/DocumentsService/DocumentsService";
|
||||
import { validateOrReject } from "class-validator";
|
||||
import { Request, Response } from "express";
|
||||
@ -108,7 +108,55 @@ export default class DocumentsController extends ApiController {
|
||||
await validateOrReject(documentEntity, { groups: ["updateDocument"] });
|
||||
|
||||
//call service to get prisma entity
|
||||
const documentEntityUpdated: Documents = await this.documentsService.update(uid, documentEntity, req.body.refused_reason);
|
||||
const documentEntityUpdated: Documents = await this.documentsService.update(uid, documentEntity);
|
||||
|
||||
//Hydrate ressource with prisma entity
|
||||
const document = Document.hydrate<Document>(documentEntityUpdated, { strategy: "excludeAll" });
|
||||
|
||||
//success
|
||||
this.httpSuccess(response, document);
|
||||
} catch (error) {
|
||||
this.httpInternalError(response, error);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Update a specific document
|
||||
*/
|
||||
@Put("/api/v1/notary/documents/:uid/refuse", [authHandler, ruleHandler, documentHandler])
|
||||
protected async refuseDocument(req: Request, response: Response) {
|
||||
try {
|
||||
const uid = req.params["uid"];
|
||||
if (!uid) {
|
||||
this.httpBadRequest(response, "No uid provided");
|
||||
return;
|
||||
}
|
||||
|
||||
const documentFound = await this.documentsService.getByUid(uid, {
|
||||
files: true,
|
||||
});
|
||||
|
||||
if (!documentFound) {
|
||||
this.httpNotFoundRequest(response, "document not found");
|
||||
return;
|
||||
}
|
||||
|
||||
//init Document resource with request body values
|
||||
const documentEntity = Document.hydrate<Document>(documentFound);
|
||||
|
||||
// Status to refuse
|
||||
documentEntity.document_status = EDocumentStatus.REFUSED;
|
||||
|
||||
//validate document
|
||||
await validateOrReject(documentEntity, { groups: ["updateDocument"] });
|
||||
|
||||
//call service to get prisma entity
|
||||
const documentEntityUpdated: Documents = await this.documentsService.refuse(uid, documentEntity, req.body.refused_reason);
|
||||
|
||||
//create email for asked document
|
||||
// this.emailBuilder.sendDocumentEmails(documentEntityUpdated);
|
||||
// this.notificationBuilder.sendDocumentAnchoredNotificatiom(documentEntityUpdated);
|
||||
|
||||
//Hydrate ressource with prisma entity
|
||||
const document = Document.hydrate<Document>(documentEntityUpdated, { strategy: "excludeAll" });
|
||||
|
@ -1,6 +1,5 @@
|
||||
import authHandler from "@App/middlewares/AuthHandler";
|
||||
import roleHandler from "@App/middlewares/RolesHandler";
|
||||
import NotificationBuilder from "@Common/notifications/NotificationBuilder";
|
||||
import ApiController from "@Common/system/controller-pattern/ApiController";
|
||||
import { Controller, Delete, Post } from "@ControllerPattern/index";
|
||||
import { EAppointmentStatus, Votes } from "@prisma/client";
|
||||
@ -17,7 +16,6 @@ export default class LiveVoteController extends ApiController {
|
||||
constructor(
|
||||
private liveVoteService: LiveVoteService,
|
||||
private usersService: UsersService,
|
||||
private notificationBuilder: NotificationBuilder,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
@ -30,7 +28,7 @@ export default class LiveVoteController extends ApiController {
|
||||
try {
|
||||
const userId = req.body.user.userId;
|
||||
//init IUser resource with request body values
|
||||
const voteEntity = Vote.hydrate<Vote>(req.body);
|
||||
const voteEntity = Vote.hydrate<Vote>(req.body, { strategy: "excludeAll" });
|
||||
//validate user
|
||||
await validateOrReject(voteEntity, { groups: ["createVote"] });
|
||||
|
||||
@ -54,7 +52,7 @@ export default class LiveVoteController extends ApiController {
|
||||
AND: [
|
||||
{
|
||||
appointment: {
|
||||
AND: [{ user_uid: voteEntity.appointment.targeted_user.uid }, { status: EAppointmentStatus.OPEN }],
|
||||
AND: [{ user_uid: voteEntity.appointment.user.uid }, { status: EAppointmentStatus.OPEN }],
|
||||
},
|
||||
},
|
||||
{ voter: { uid: userId } },
|
||||
@ -79,11 +77,7 @@ export default class LiveVoteController extends ApiController {
|
||||
return;
|
||||
}
|
||||
//Hydrate ressource with prisma entity
|
||||
const vote = Vote.hydrate<Vote>(voteEntityCreated, {
|
||||
strategy: "excludeAll",
|
||||
});
|
||||
|
||||
await this.notificationBuilder.sendVoteNotification(vote);
|
||||
const vote = Vote.hydrate<Vote>(voteEntityCreated, { strategy: "excludeAll" });
|
||||
|
||||
//success
|
||||
this.httpCreated(response, vote);
|
||||
|
@ -44,23 +44,22 @@ export default class OfficeFoldersController extends ApiController {
|
||||
{
|
||||
customers: {
|
||||
some: {
|
||||
contact: {
|
||||
OR: [
|
||||
{ first_name: { contains: filter, mode: "insensitive" } },
|
||||
{ last_name: { contains: filter, mode: "insensitive" } },
|
||||
{ contact: { first_name: { contains: filter, mode: "insensitive" } } },
|
||||
{ contact: { last_name: { contains: filter, mode: "insensitive" } } },
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
}
|
||||
const officeId: string = req.body.user.office_Id;
|
||||
const officeWhereInput: Prisma.OfficesWhereInput = { uid: officeId };
|
||||
if (!query.where) query.where = { office: officeWhereInput };
|
||||
query.where.office = officeWhereInput;
|
||||
|
||||
const userId: string = req.body.user.userId;
|
||||
if (query.where?.stakeholders) delete query.where.stakeholders;
|
||||
const officeFoldersWhereInput: Prisma.OfficeFoldersWhereInput = { ...query.where, stakeholders: { some: { uid: userId } } };
|
||||
query.where = officeFoldersWhereInput;
|
||||
|
||||
//call service to get prisma entity
|
||||
const officeFolderEntities: OfficeFolders[] = await this.officeFoldersService.get(query);
|
||||
|
@ -127,6 +127,7 @@ export default class UsersController extends ApiController {
|
||||
this.httpBadRequest(response, "Office role not found");
|
||||
return;
|
||||
}
|
||||
|
||||
if (officeRole.office_uid != userFound.office_uid) {
|
||||
this.httpBadRequest(response, "Cannot assign an office role from another office");
|
||||
return;
|
||||
|
@ -1,5 +1,6 @@
|
||||
import HttpCodes from "@Common/system/controller-pattern/HttpCodes";
|
||||
import DocumentsService from "@Services/customer/DocumentsService/DocumentsService";
|
||||
import Document from "le-coffre-resources/dist/SuperAdmin/Document";
|
||||
import { NextFunction, Request, Response } from "express";
|
||||
import Container from "typedi";
|
||||
|
||||
@ -14,15 +15,27 @@ export default async function documentHandler(req: Request, response: Response,
|
||||
}
|
||||
|
||||
const documentService = Container.get(DocumentsService);
|
||||
const document = await documentService.getByUid(uid);
|
||||
const document = await documentService.getByUid(uid, { folder: { include: { folder_anchor: true } } });
|
||||
|
||||
if (!document) {
|
||||
response.status(HttpCodes.NOT_FOUND).send("Document not found");
|
||||
return;
|
||||
}
|
||||
|
||||
if (document?.depositor_uid != customerId) {
|
||||
response.status(HttpCodes.UNAUTHORIZED).send("Not authorized with this depositor");
|
||||
return;
|
||||
}
|
||||
|
||||
next();
|
||||
if (req.method === "POST" || req.method === "PUT") {
|
||||
const documentEntity = Document.hydrate<Document>(document);
|
||||
if (documentEntity.folder?.folder_anchor?.status === "VERIFIED_ON_CHAIN") {
|
||||
response.status(HttpCodes.BAD_REQUEST).send("Cannot update a verified folder");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
next();
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
response.status(HttpCodes.INTERNAL_ERROR).send("Internal server error");
|
||||
|
@ -1,13 +1,20 @@
|
||||
import HttpCodes from "@Common/system/controller-pattern/HttpCodes";
|
||||
import FilesService from "@Services/common/FilesService/FilesService";
|
||||
import DocumentsService from "@Services/customer/DocumentsService/DocumentsService";
|
||||
import File from "le-coffre-resources/dist/SuperAdmin/File";
|
||||
import { NextFunction, Request, Response } from "express";
|
||||
import Container from "typedi";
|
||||
import { EDocumentStatus } from "@prisma/client";
|
||||
|
||||
export default async function fileHandler(req: Request, response: Response, next: NextFunction) {
|
||||
const customerId = req.body.user.customerId;
|
||||
const uid = req.path && req.path.split("/")[5];
|
||||
const document = req.body.document;
|
||||
const file: string | undefined = req.body["q"];
|
||||
|
||||
if (req.file && req.file.mimetype !== "application/pdf" && req.file.mimetype !== "image/png" && req.file.mimetype !== "image/jpeg") {
|
||||
response.status(HttpCodes.BAD_REQUEST).send("File type not supported");
|
||||
return;
|
||||
}
|
||||
|
||||
if (uid) {
|
||||
const fileService = Container.get(FilesService);
|
||||
@ -20,11 +27,17 @@ export default async function fileHandler(req: Request, response: Response, next
|
||||
response.status(HttpCodes.UNAUTHORIZED).send("Not authorized with this depositor");
|
||||
return;
|
||||
}
|
||||
if (req.method === "PUT") {
|
||||
if (file.document.document_status === EDocumentStatus.VALIDATED) {
|
||||
response.status(HttpCodes.BAD_REQUEST).send("Cannot update a validated document");
|
||||
return;
|
||||
}
|
||||
|
||||
if (document) {
|
||||
}
|
||||
}
|
||||
if (file) {
|
||||
const fileEntity = File.hydrate<File>(JSON.parse(file));
|
||||
const documentService = Container.get(DocumentsService);
|
||||
const documentFound = await documentService.getByUid(document.uid!);
|
||||
const documentFound = await documentService.getByUid(fileEntity.document?.uid!, { folder: { include: { folder_anchor: true } } });
|
||||
if (!documentFound) {
|
||||
response.status(HttpCodes.NOT_FOUND).send("Document not found");
|
||||
return;
|
||||
@ -33,6 +46,10 @@ export default async function fileHandler(req: Request, response: Response, next
|
||||
response.status(HttpCodes.UNAUTHORIZED).send("Not authorized with this depositor");
|
||||
return;
|
||||
}
|
||||
if (documentFound.document_status === EDocumentStatus.VALIDATED) {
|
||||
response.status(HttpCodes.BAD_REQUEST).send("Cannot update a validated document");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
next();
|
||||
|
@ -0,0 +1,28 @@
|
||||
import HttpCodes from "@Common/system/controller-pattern/HttpCodes";
|
||||
import { NextFunction, Request, Response } from "express";
|
||||
import Container from "typedi";
|
||||
import CustomersService from "@Services/super-admin/CustomersService/CustomersService";
|
||||
|
||||
export default async function customerHandler(req: Request, response: Response, next: NextFunction) {
|
||||
try {
|
||||
const officeId = req.body.user.office_Id;
|
||||
const uid = req.path && req.path.split("/")[5];
|
||||
|
||||
if (uid) {
|
||||
const customerService = Container.get(CustomersService);
|
||||
const customer = await customerService.get({where:{AND: [{uid: uid}, {office_folders: {some: {office_uid: officeId}}}]}});
|
||||
|
||||
if (!customer[0]) {
|
||||
response.status(HttpCodes.NOT_FOUND).send("Customer not found");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
next();
|
||||
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
response.status(HttpCodes.INTERNAL_ERROR).send("Internal server error");
|
||||
return;
|
||||
}
|
||||
}
|
@ -17,6 +17,11 @@ export default class EmailBuilder {
|
||||
const documentPrisma = await this.documentsService.getByUid(documentEntity.uid, { depositor: {include: {contact: true}}, folder:{include:{ office: true}} });
|
||||
if(!documentPrisma) throw new Error("Document not found");
|
||||
const document = Document.hydrate<Document>(documentPrisma);
|
||||
|
||||
//Use mailchimpService.get get if an email was sent to the user in the lst hour
|
||||
const lastEmail = await this.mailchimpService.get({ where: { to: document.depositor!.contact!.email, sentAt: { gte: new Date(Date.now() - 3600000) } } });
|
||||
if(lastEmail.length > 0) return;
|
||||
|
||||
const to = document.depositor!.contact!.email;
|
||||
const civility = this.getCivility(document.depositor!.contact!.civility);
|
||||
const templateVariables = {
|
||||
|
@ -14,7 +14,7 @@ export default class NotificationBuilder {
|
||||
private documentsService: DocumentsService,
|
||||
private usersService: UsersService,
|
||||
private foldersService: OfficeFoldersService,
|
||||
private backendVariables: BackendVariables
|
||||
private backendVariables: BackendVariables,
|
||||
) {}
|
||||
|
||||
public async sendDocumentDepositedNotification(documentEntity: Documents) {
|
||||
@ -43,9 +43,11 @@ export default class NotificationBuilder {
|
||||
|
||||
public async sendFolderAnchoredNotification(folderEntity: OfficeFolders) {
|
||||
if (!folderEntity.uid) return;
|
||||
const officeFolderPrisma = await this.foldersService.getByUid(folderEntity.uid,
|
||||
{ folder_anchor: true, office: true, stakeholders: true }
|
||||
);
|
||||
const officeFolderPrisma = await this.foldersService.getByUid(folderEntity.uid, {
|
||||
folder_anchor: true,
|
||||
office: true,
|
||||
stakeholders: true,
|
||||
});
|
||||
if (!officeFolderPrisma) throw new Error("Folder not found");
|
||||
const folder = OfficeFolder.hydrate<OfficeFolder>(officeFolderPrisma);
|
||||
if (folder.folder_anchor?.status !== "VERIFIED_ON_CHAIN") return;
|
||||
@ -66,26 +68,24 @@ export default class NotificationBuilder {
|
||||
|
||||
public async sendVoteNotification(vote: Vote) {
|
||||
if (vote.appointment.status !== "OPEN") return;
|
||||
const superAdminList = await this.usersService.get({ where: { role: { label: "super-admin" } } });
|
||||
const superAdminList = await this.usersService.get({ where: { role: { name: "super-admin" } } });
|
||||
const voterIndex = superAdminList.findIndex((user) => user.uid === vote.voter.uid);
|
||||
superAdminList.splice(voterIndex, 1);
|
||||
const userTargeted = await this.usersService.getByUid(vote.appointment.user.uid!, { contact: true });
|
||||
const userTargetedEntity = User.hydrate<User>(userTargeted!, { strategy: "excludeAll" });
|
||||
let message = "";
|
||||
if (vote.appointment.choice === "NOMINATE") {
|
||||
message =
|
||||
"Un collaborateur souhaite attribuer le titre de Super Administrateur à " +
|
||||
vote.appointment.targeted_user +
|
||||
". Cliquez ici pour voter.";
|
||||
message = `Un collaborateur souhaite attribuer le titre de Super Administrateur à ${userTargetedEntity.contact?.first_name} ${userTargetedEntity.contact?.last_name}. Cliquez ici pour voter.`;
|
||||
} else if (vote.appointment.choice === "DISMISS") {
|
||||
message =
|
||||
"Un collaborateur souhaite retirer le titre de Super Administrateur à " +
|
||||
vote.appointment.targeted_user +
|
||||
". Cliquez ici pour voter.";
|
||||
message = `Un collaborateur souhaite retirer le titre de Super Administrateur à ${userTargetedEntity.contact?.first_name} ${userTargetedEntity.contact?.last_name}. Cliquez ici pour voter.`;
|
||||
}
|
||||
|
||||
this.notificationsService.create({
|
||||
message: message,
|
||||
redirection_url: `${this.backendVariables.APP_HOST}/users/${vote.appointment.targeted_user.uid}`,
|
||||
redirection_url: `${this.backendVariables.APP_HOST}/users/${vote.appointment.user.uid}`,
|
||||
created_at: new Date(),
|
||||
updated_at: new Date(),
|
||||
user: superAdminList || [],
|
||||
user: superAdminList,
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
import Database from "@Common/databases/database";
|
||||
import BaseRepository from "@Repositories/BaseRepository";
|
||||
import { Service } from "typedi";
|
||||
import { Appointments, EAppointmentStatus, Prisma } from "@prisma/client";
|
||||
import { Appointments, EAppointmentStatus, EVote, Prisma, Users, Votes } from "@prisma/client";
|
||||
|
||||
@Service()
|
||||
export default class AppointmentsRepository extends BaseRepository {
|
||||
@ -39,6 +39,18 @@ export default class AppointmentsRepository extends BaseRepository {
|
||||
return this.model.update(updateArgs);
|
||||
}
|
||||
|
||||
public async findOneByStatusUserAndChoice(userUid: string, choice: EVote, status: EAppointmentStatus): Promise<Appointments | null> {
|
||||
return this.model.findUnique({
|
||||
where: {
|
||||
user_uid_choice_status: {
|
||||
user_uid: userUid,
|
||||
choice: choice,
|
||||
status: status,
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @description : Find one appointment
|
||||
*/
|
||||
@ -54,12 +66,12 @@ export default class AppointmentsRepository extends BaseRepository {
|
||||
/**
|
||||
* @description : Find one appointment with votes
|
||||
*/
|
||||
public async findOneByUidWithVotes(uid: string) {
|
||||
public async findOneByUidWithVotes(uid: string): Promise<(Appointments & {votes: Votes[], user: Users}) | null> {
|
||||
return this.model.findUnique({
|
||||
where: {
|
||||
uid: uid,
|
||||
},
|
||||
include: {votes: true},
|
||||
include: {votes: true, user: true},
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -21,7 +21,6 @@ export default class DocumentsRepository extends BaseRepository {
|
||||
* @description : Find many documents
|
||||
*/
|
||||
public async findMany(query: Prisma.DocumentsFindManyArgs) {
|
||||
|
||||
query.take = Math.min(query.take || this.defaultFetchRows, this.maxFetchRows);
|
||||
return this.model.findMany(query);
|
||||
}
|
||||
@ -96,7 +95,26 @@ export default class DocumentsRepository extends BaseRepository {
|
||||
/**
|
||||
* @description : Update data of a document
|
||||
*/
|
||||
public async update(uid: string, document: Partial<DocumentCustomer>, refusedReason?: string): Promise<Documents> {
|
||||
public async update(uid: string, document: Partial<DocumentCustomer>): Promise<Documents> {
|
||||
return this.model.update({
|
||||
where: {
|
||||
uid: uid,
|
||||
},
|
||||
data: {
|
||||
document_status: EDocumentStatus[document.document_status as keyof typeof EDocumentStatus],
|
||||
document_history: {
|
||||
create: {
|
||||
document_status: EDocumentStatus[document.document_status as keyof typeof EDocumentStatus],
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @description : Update data of a document
|
||||
*/
|
||||
public async refuse(uid: string, document: Partial<DocumentCustomer>, refusedReason?: string): Promise<Documents> {
|
||||
return this.model.update({
|
||||
where: {
|
||||
uid: uid,
|
||||
|
@ -29,10 +29,10 @@ export default class VotesRepository extends BaseRepository {
|
||||
*/
|
||||
public async create(vote: Vote): Promise<Votes> {
|
||||
let whereArg: Prisma.AppointmentsWhereUniqueInput;
|
||||
if(vote.appointment.targeted_user.uid) {
|
||||
if(vote.appointment.user.uid) {
|
||||
whereArg = {
|
||||
user_uid_choice_status: {
|
||||
user_uid: vote.appointment.targeted_user.uid,
|
||||
user_uid: vote.appointment.user.uid,
|
||||
choice: EVote[vote.appointment.choice as keyof typeof EVote],
|
||||
status: EAppointmentStatus.OPEN,
|
||||
}
|
||||
@ -49,7 +49,7 @@ export default class VotesRepository extends BaseRepository {
|
||||
where: whereArg,
|
||||
create: {
|
||||
choice: EVote[vote.appointment.choice as keyof typeof EVote],
|
||||
user_uid: vote.appointment.targeted_user.uid!,
|
||||
user_uid: vote.appointment.user.uid!,
|
||||
}
|
||||
},
|
||||
},
|
||||
@ -61,7 +61,7 @@ export default class VotesRepository extends BaseRepository {
|
||||
}
|
||||
};
|
||||
|
||||
return this.model.create({...createArgs, include: {appointment: {include: {votes: true}}}});
|
||||
return this.model.create({...createArgs, include: {voter: true, appointment: {include: {votes: true, user: true}}}});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -25,8 +25,8 @@ const storage = multer.memoryStorage();
|
||||
middlwares: [
|
||||
cors({ origin: "*" }),
|
||||
multer({ storage: storage, limits: { fileSize: 32000000 } }).single("file"), //32 MB maximum
|
||||
bodyParser.urlencoded({ extended: true }),
|
||||
bodyParser.json(),
|
||||
bodyParser.json({ limit: "35mb"}),
|
||||
bodyParser.urlencoded({ extended: true, limit: "35mb", parameterLimit: 50000 }),
|
||||
],
|
||||
errorHandler,
|
||||
});
|
||||
|
@ -3,10 +3,11 @@ import { Document } from "le-coffre-resources/dist/Admin";
|
||||
import DocumentsRepository from "@Repositories/DocumentsRepository";
|
||||
import BaseService from "@Services/BaseService";
|
||||
import { Service } from "typedi";
|
||||
import FilesRepository from "@Repositories/FilesRepository";
|
||||
|
||||
@Service()
|
||||
export default class DocumentsService extends BaseService {
|
||||
constructor(private documentsRepository: DocumentsRepository) {
|
||||
constructor(private documentsRepository: DocumentsRepository, private filesRepository: FilesRepository) {
|
||||
super();
|
||||
}
|
||||
|
||||
@ -38,8 +39,19 @@ export default class DocumentsService extends BaseService {
|
||||
* @description : Modify a document
|
||||
* @throws {Error} If document cannot be modified
|
||||
*/
|
||||
public async update(uid: string, document: Partial<Document>, refused_reason?: string): Promise<Documents> {
|
||||
return this.documentsRepository.update(uid, document, refused_reason);
|
||||
public async update(uid: string, document: Partial<Document>): Promise<Documents> {
|
||||
return this.documentsRepository.update(uid, document);
|
||||
}
|
||||
|
||||
public async refuse(uid: string, document: Partial<Document>, refused_reason: string): Promise<Documents> {
|
||||
if (document.files) {
|
||||
for (let i = 0; i < document.files.length; i++) {
|
||||
console.log("archiving file", document.files[i]?.uid);
|
||||
await this.filesRepository.deleteKeyAndArchive(document.files[i]?.uid as string);
|
||||
}
|
||||
}
|
||||
|
||||
return this.documentsRepository.refuse(uid, document, refused_reason);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -72,8 +72,7 @@ export default class AnchoringProofService extends BaseService {
|
||||
*/
|
||||
public async generate(data: AnchoringProofData): Promise<Buffer> {
|
||||
const browser = await puppeteer.launch({
|
||||
headless: "new",
|
||||
executablePath: process.env['PUPPETEER_EXECUTABLE_PATH'],
|
||||
headless: 'new',
|
||||
args: ["--no-sandbox", "--disable-setuid-sandbox"],
|
||||
});
|
||||
const page = await browser.newPage();
|
||||
|
@ -4,7 +4,7 @@ import { BackendVariables } from "@Common/config/variables/Variables";
|
||||
import DocumentsService from "@Services/super-admin/DocumentsService/DocumentsService";
|
||||
import FilesService from "../FilesService/FilesService";
|
||||
|
||||
type EnrollmentResponse = {
|
||||
export type EnrollmentResponse = {
|
||||
url: string;
|
||||
id: number;
|
||||
api_key: string;
|
||||
@ -196,13 +196,12 @@ export default class Id360Service extends BaseService {
|
||||
}
|
||||
|
||||
public async getEnrollment(token: string) {
|
||||
const res = await fetch(
|
||||
return await fetch(
|
||||
`${
|
||||
this.variables.DOCAPOST_BASE_URL + this.variables.DOCAPOST_ROOT + this.variables.DOCAPOST_VERSION
|
||||
}/enrollment/status/${token}`,
|
||||
{ method: "GET" },
|
||||
);
|
||||
return (await res.json()) as EnrollmentResponse;
|
||||
}
|
||||
|
||||
public async finalizeEnrollment(apiKey: string) {
|
||||
|
@ -1,6 +1,6 @@
|
||||
import EmailRepository from "@Repositories/EmailRepository";
|
||||
import BaseService from "@Services/BaseService";
|
||||
import { Emails } from "@prisma/client";
|
||||
import { Emails, Prisma } from "@prisma/client";
|
||||
import { Service } from "typedi";
|
||||
import MailchimpClient from "@mailchimp/mailchimp_transactional";
|
||||
import { BackendVariables } from "@Common/config/variables/Variables";
|
||||
@ -24,7 +24,7 @@ export default class MailchimpService extends BaseService {
|
||||
* @description : Get all emails
|
||||
* @throws {Error} If emails cannot be get
|
||||
*/
|
||||
public async get(query: any): Promise<Emails[]> {
|
||||
public async get(query: Prisma.EmailsFindManyArgs): Promise<Emails[]> {
|
||||
return this.emailRepository.findMany(query);
|
||||
}
|
||||
|
||||
|
@ -3,10 +3,11 @@ import { Document } from "le-coffre-resources/dist/Notary";
|
||||
import DocumentsRepository from "@Repositories/DocumentsRepository";
|
||||
import BaseService from "@Services/BaseService";
|
||||
import { Service } from "typedi";
|
||||
import FilesRepository from "@Repositories/FilesRepository";
|
||||
|
||||
@Service()
|
||||
export default class DocumentsService extends BaseService {
|
||||
constructor(private documentsRepository: DocumentsRepository) {
|
||||
constructor(private documentsRepository: DocumentsRepository, private filesRepository: FilesRepository) {
|
||||
super();
|
||||
}
|
||||
|
||||
@ -38,8 +39,19 @@ export default class DocumentsService extends BaseService {
|
||||
* @description : Modify a document
|
||||
* @throws {Error} If document cannot be modified
|
||||
*/
|
||||
public async update(uid: string, document: Partial<Document>, refused_reason?: string): Promise<Documents> {
|
||||
return this.documentsRepository.update(uid, document, refused_reason);
|
||||
public async update(uid: string, document: Partial<Document>): Promise<Documents> {
|
||||
return this.documentsRepository.update(uid, document);
|
||||
}
|
||||
|
||||
public async refuse(uid: string, document: Partial<Document>, refused_reason: string): Promise<Documents> {
|
||||
if (document.files) {
|
||||
for (let i = 0; i < document.files.length; i++) {
|
||||
console.log("archiving file", document.files[i]?.uid);
|
||||
await this.filesRepository.deleteKeyAndArchive(document.files[i]?.uid as string);
|
||||
}
|
||||
}
|
||||
|
||||
return this.documentsRepository.refuse(uid, document, refused_reason);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -3,10 +3,11 @@ import { Document } from "le-coffre-resources/dist/SuperAdmin";
|
||||
import DocumentsRepository from "@Repositories/DocumentsRepository";
|
||||
import BaseService from "@Services/BaseService";
|
||||
import { Service } from "typedi";
|
||||
import FilesRepository from "@Repositories/FilesRepository";
|
||||
|
||||
@Service()
|
||||
export default class DocumentsService extends BaseService {
|
||||
constructor(private documentsRepository: DocumentsRepository) {
|
||||
constructor(private documentsRepository: DocumentsRepository, private filesRepository: FilesRepository) {
|
||||
super();
|
||||
}
|
||||
|
||||
@ -38,8 +39,19 @@ export default class DocumentsService extends BaseService {
|
||||
* @description : Modify a document
|
||||
* @throws {Error} If document cannot be modified
|
||||
*/
|
||||
public async update(uid: string, document: Partial<Document>, refused_reason?: string): Promise<Documents> {
|
||||
return this.documentsRepository.update(uid, document, refused_reason);
|
||||
public async update(uid: string, document: Partial<Document>): Promise<Documents> {
|
||||
return this.documentsRepository.update(uid, document);
|
||||
}
|
||||
|
||||
public async refuse(uid: string, document: Partial<Document>, refused_reason: string): Promise<Documents> {
|
||||
if (document.files) {
|
||||
for (let i = 0; i < document.files.length; i++) {
|
||||
console.log("archiving file", document.files[i]?.uid);
|
||||
await this.filesRepository.deleteKeyAndArchive(document.files[i]?.uid as string);
|
||||
}
|
||||
}
|
||||
|
||||
return this.documentsRepository.refuse(uid, document, refused_reason);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -69,7 +81,7 @@ export default class DocumentsService extends BaseService {
|
||||
* @description : Get a document by uid
|
||||
* @throws {Error} If document cannot be get by uid
|
||||
*/
|
||||
public async getByUidWithFiles(uid: string): Promise<Documents & {files: Files[] | null} | null> {
|
||||
public async getByUidWithFiles(uid: string): Promise<(Documents & { files: Files[] | null }) | null> {
|
||||
return this.documentsRepository.findOneByUidWithFiles(uid);
|
||||
}
|
||||
|
||||
|
@ -2,10 +2,11 @@ import BaseService from "@Services/BaseService";
|
||||
import { Service } from "typedi";
|
||||
import User, { Appointment, Role, Vote } from "le-coffre-resources/dist/SuperAdmin";
|
||||
import VotesRepository from "@Repositories/VotesRepository";
|
||||
import { Appointments, EAppointmentStatus, EVote, Prisma, Votes } from "@prisma/client";
|
||||
import { Appointments, EAppointmentStatus, EVote, Prisma, Users, Votes } from "@prisma/client";
|
||||
import UsersService from "../UsersService/UsersService";
|
||||
import RolesService from "../RolesService/RolesService";
|
||||
import AppointmentsRepository from "@Repositories/AppointmentsRepository";
|
||||
import NotificationBuilder from "@Common/notifications/NotificationBuilder";
|
||||
|
||||
@Service()
|
||||
export default class LiveVoteService extends BaseService {
|
||||
@ -14,12 +15,13 @@ export default class LiveVoteService extends BaseService {
|
||||
private appointmentRepository: AppointmentsRepository,
|
||||
private userService: UsersService,
|
||||
private roleService: RolesService,
|
||||
private notificationBuilder: NotificationBuilder,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
public async verifyVoterChoice(vote: Vote): Promise<boolean> {
|
||||
const userWithRole = await this.userService.getByUidWithRole(vote.appointment.targeted_user.uid!);
|
||||
const userWithRole = await this.userService.getByUidWithRole(vote.appointment.user.uid!);
|
||||
if (userWithRole!.role.name === "super-admin" && vote.appointment.choice === EVote.DISMISS) {
|
||||
return true;
|
||||
}
|
||||
@ -65,27 +67,35 @@ export default class LiveVoteService extends BaseService {
|
||||
return this.appointmentRepository.findOneByUid(uid, query);
|
||||
}
|
||||
|
||||
public async getAppointmentWithVotes(vote: Vote): Promise<Appointments | null> {
|
||||
public async getAppointmentWithVotes(vote: Vote): Promise<(Appointments & { votes: Votes[]; user: Users }) | null> {
|
||||
if (vote.appointment.uid) {
|
||||
return this.appointmentRepository.findOneByUid(vote.appointment.uid);
|
||||
return this.appointmentRepository.findOneByUidWithVotes(vote.appointment.uid);
|
||||
}
|
||||
const appointmentByUser = await this.appointmentRepository.findMany({
|
||||
where: {
|
||||
AND: [
|
||||
{ user_uid: vote.appointment.targeted_user.uid },
|
||||
{ user_uid: vote.appointment.user.uid },
|
||||
{ status: EAppointmentStatus.OPEN },
|
||||
{ choice: EVote[vote.appointment.choice as keyof typeof EVote] },
|
||||
],
|
||||
},
|
||||
include: { votes: true },
|
||||
include: { votes: true, user: true },
|
||||
});
|
||||
if (appointmentByUser.length >= 1) {
|
||||
if (appointmentByUser.length != 0) {
|
||||
return this.appointmentRepository.findOneByUidWithVotes(appointmentByUser[0]!.uid);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private async closeVote(appointment: Appointments, vote: Votes) {
|
||||
const apointmentFound = await this.appointmentRepository.findOneByStatusUserAndChoice(
|
||||
appointment.user_uid,
|
||||
EVote[appointment.choice as keyof typeof EVote],
|
||||
EAppointmentStatus.CLOSED,
|
||||
);
|
||||
if (apointmentFound) {
|
||||
await this.appointmentRepository.delete(apointmentFound.uid);
|
||||
}
|
||||
await this.appointmentRepository.update(vote.appointment_uid, EAppointmentStatus.CLOSED);
|
||||
const user = await this.userService.getByUid(appointment.user_uid, { role: true });
|
||||
const userEntity = User.hydrate<User>(user!, { strategy: "excludeAll" });
|
||||
@ -98,12 +108,14 @@ export default class LiveVoteService extends BaseService {
|
||||
const roles = await this.roleService.get({ where: { name: "default" } });
|
||||
const roleEntity = Role.hydrate<Role>(roles[0]!, { strategy: "excludeAll" });
|
||||
userEntity.role = roleEntity;
|
||||
await this.notificationBuilder.sendDismissNotification(userEntity);
|
||||
await this.userService.update(appointment!.user_uid, userEntity);
|
||||
return vote;
|
||||
} else if (appointment.choice === EVote.NOMINATE) {
|
||||
const roles = await this.roleService.get({ where: { name: "super-admin" } });
|
||||
const roleEntity = Role.hydrate<Role>(roles[0]!, { strategy: "excludeAll" });
|
||||
userEntity!.role = roleEntity;
|
||||
await this.notificationBuilder.sendNominateNotification(userEntity);
|
||||
await this.userService.update(appointment!.user_uid, userEntity);
|
||||
return vote;
|
||||
}
|
||||
@ -118,8 +130,10 @@ export default class LiveVoteService extends BaseService {
|
||||
const appointment = await this.getAppointmentWithVotes(vote);
|
||||
|
||||
if (appointment) {
|
||||
const appointmentEntity = Appointment.hydrate<Appointment>(appointment, { strategy: "excludeAll" });
|
||||
if (appointmentEntity?.votes && appointmentEntity.votes.length >= 2) {
|
||||
const voteEntity = Vote.hydrateArray<Vote>(appointment.votes, { strategy: "excludeAll" });
|
||||
const appointementWithVotesHydrated = { ...appointment, votes: voteEntity };
|
||||
const appointmentEntity = Appointment.hydrate<Appointment>(appointementWithVotesHydrated, { strategy: "excludeAll" });
|
||||
if (appointmentEntity.votes && appointmentEntity.votes.length >= 2) {
|
||||
const voteCreated = await this.voteRepository.create(vote);
|
||||
return this.closeVote(appointment, voteCreated);
|
||||
}
|
||||
@ -127,7 +141,9 @@ export default class LiveVoteService extends BaseService {
|
||||
|
||||
const approvedChoice = await this.verifyVoterChoice(vote);
|
||||
if (!approvedChoice) return null;
|
||||
|
||||
return this.voteRepository.create(vote);
|
||||
const voteCreated = await this.voteRepository.create(vote);
|
||||
const voteEntity = Vote.hydrate<Vote>(voteCreated, { strategy: "excludeAll" });
|
||||
await this.notificationBuilder.sendVoteNotification(voteEntity);
|
||||
return voteCreated;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user