Merge branch 'preprod'
This commit is contained in:
commit
9c013dc5ce
39
logfile
Normal file
39
logfile
Normal file
@ -0,0 +1,39 @@
|
||||
2024-07-16 10:29:09.983 CEST [21605] LOG: starting PostgreSQL 14.11 (Homebrew) on aarch64-apple-darwin22.6.0, compiled by Apple clang version 15.0.0 (clang-1500.1.0.2.5), 64-bit
|
||||
2024-07-16 10:29:09.985 CEST [21605] LOG: listening on IPv6 address "::1", port 5432
|
||||
2024-07-16 10:29:09.985 CEST [21605] LOG: listening on IPv4 address "127.0.0.1", port 5432
|
||||
2024-07-16 10:29:09.986 CEST [21605] LOG: listening on Unix socket "/tmp/.s.PGSQL.5432"
|
||||
2024-07-16 10:29:09.996 CEST [21606] LOG: database system was shut down at 2024-05-04 13:45:41 CEST
|
||||
2024-07-16 10:29:10.002 CEST [21605] LOG: database system is ready to accept connections
|
||||
2024-07-16 10:29:13.986 CEST [21782] ERROR: relation "public.notes" does not exist at character 58
|
||||
2024-07-16 10:29:13.986 CEST [21782] STATEMENT: SELECT COUNT(*) FROM (SELECT "public"."notes"."uid" FROM "public"."notes" WHERE 1=1 OFFSET $1) AS "sub"
|
||||
2024-07-16 10:29:14.132 CEST [21798] ERROR: column customers.office_uid does not exist at character 206
|
||||
2024-07-16 10:29:14.132 CEST [21798] STATEMENT: SELECT "public"."customers"."uid", "public"."customers"."status", "public"."customers"."contact_uid", "public"."customers"."created_at", "public"."customers"."updated_at", "public"."customers"."password", "public"."customers"."office_uid" FROM "public"."customers" WHERE "public"."customers"."contact_uid" IN ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$20) OFFSET $21
|
||||
2024-07-16 10:29:30.826 CEST [22049] ERROR: column customers.office_uid does not exist at character 206
|
||||
2024-07-16 10:29:30.826 CEST [22049] STATEMENT: SELECT "public"."customers"."uid", "public"."customers"."status", "public"."customers"."contact_uid", "public"."customers"."created_at", "public"."customers"."updated_at", "public"."customers"."password", "public"."customers"."office_uid" FROM "public"."customers" WHERE "public"."customers"."contact_uid" IN ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$20) OFFSET $21
|
||||
2024-07-16 10:29:49.261 CEST [22461] ERROR: relation "public.notes" does not exist at character 58
|
||||
2024-07-16 10:29:49.261 CEST [22461] STATEMENT: SELECT COUNT(*) FROM (SELECT "public"."notes"."uid" FROM "public"."notes" WHERE 1=1 OFFSET $1) AS "sub"
|
||||
2024-07-16 10:29:49.463 CEST [22463] ERROR: column customers.office_uid does not exist at character 206
|
||||
2024-07-16 10:29:49.463 CEST [22463] STATEMENT: SELECT "public"."customers"."uid", "public"."customers"."status", "public"."customers"."contact_uid", "public"."customers"."created_at", "public"."customers"."updated_at", "public"."customers"."password", "public"."customers"."office_uid" FROM "public"."customers" WHERE "public"."customers"."contact_uid" IN ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$20) OFFSET $21
|
||||
2024-07-16 10:32:09.636 CEST [24972] ERROR: relation "public.notes" does not exist at character 58
|
||||
2024-07-16 10:32:09.636 CEST [24972] STATEMENT: SELECT COUNT(*) FROM (SELECT "public"."notes"."uid" FROM "public"."notes" WHERE 1=1 OFFSET $1) AS "sub"
|
||||
2024-07-16 10:32:09.903 CEST [24974] ERROR: column customers.office_uid does not exist at character 206
|
||||
2024-07-16 10:32:09.903 CEST [24974] STATEMENT: SELECT "public"."customers"."uid", "public"."customers"."status", "public"."customers"."contact_uid", "public"."customers"."created_at", "public"."customers"."updated_at", "public"."customers"."password", "public"."customers"."office_uid" FROM "public"."customers" WHERE "public"."customers"."contact_uid" IN ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$20) OFFSET $21
|
||||
2024-07-16 10:32:13.659 CEST [25042] ERROR: relation "public.notes" does not exist at character 58
|
||||
2024-07-16 10:32:13.659 CEST [25042] STATEMENT: SELECT COUNT(*) FROM (SELECT "public"."notes"."uid" FROM "public"."notes" WHERE 1=1 OFFSET $1) AS "sub"
|
||||
2024-07-16 10:32:13.960 CEST [25044] ERROR: column customers.office_uid does not exist at character 206
|
||||
2024-07-16 10:32:13.960 CEST [25044] STATEMENT: SELECT "public"."customers"."uid", "public"."customers"."status", "public"."customers"."contact_uid", "public"."customers"."created_at", "public"."customers"."updated_at", "public"."customers"."password", "public"."customers"."office_uid" FROM "public"."customers" WHERE "public"."customers"."contact_uid" IN ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$20) OFFSET $21
|
||||
2024-07-16 10:32:26.772 CEST [25252] ERROR: column customers.office_uid does not exist at character 206
|
||||
2024-07-16 10:32:26.772 CEST [25252] STATEMENT: SELECT "public"."customers"."uid", "public"."customers"."status", "public"."customers"."contact_uid", "public"."customers"."created_at", "public"."customers"."updated_at", "public"."customers"."password", "public"."customers"."office_uid" FROM "public"."customers" WHERE "public"."customers"."contact_uid" IN ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$20) OFFSET $21
|
||||
2024-07-16 10:32:45.488 CEST [25549] ERROR: column customers.office_uid does not exist at character 206
|
||||
2024-07-16 10:32:45.488 CEST [25549] STATEMENT: SELECT "public"."customers"."uid", "public"."customers"."status", "public"."customers"."contact_uid", "public"."customers"."created_at", "public"."customers"."updated_at", "public"."customers"."password", "public"."customers"."office_uid" FROM "public"."customers" WHERE 1=1 ORDER BY "public"."customers"."uid" ASC LIMIT $1 OFFSET $2
|
||||
2024-07-16 10:33:22.589 CEST [26127] ERROR: column customers.office_uid does not exist at character 206
|
||||
2024-07-16 10:33:22.589 CEST [26127] STATEMENT: SELECT "public"."customers"."uid", "public"."customers"."status", "public"."customers"."contact_uid", "public"."customers"."created_at", "public"."customers"."updated_at", "public"."customers"."password", "public"."customers"."office_uid" FROM "public"."customers" WHERE "public"."customers"."contact_uid" IN ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$20) OFFSET $21
|
||||
2024-07-16 10:42:51.648 CEST [37340] ERROR: relation "public.notes" does not exist at character 58
|
||||
2024-07-16 10:42:51.648 CEST [37340] STATEMENT: SELECT COUNT(*) FROM (SELECT "public"."notes"."uid" FROM "public"."notes" WHERE 1=1 OFFSET $1) AS "sub"
|
||||
2024-07-16 10:42:51.859 CEST [37342] ERROR: column customers.office_uid does not exist at character 206
|
||||
2024-07-16 10:42:51.859 CEST [37342] STATEMENT: SELECT "public"."customers"."uid", "public"."customers"."status", "public"."customers"."contact_uid", "public"."customers"."created_at", "public"."customers"."updated_at", "public"."customers"."password", "public"."customers"."office_uid" FROM "public"."customers" WHERE "public"."customers"."contact_uid" IN ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$20,$21) OFFSET $22
|
||||
2024-07-16 10:42:56.305 CEST [37406] ERROR: column customers.office_uid does not exist at character 36
|
||||
2024-07-16 10:42:56.305 CEST [37406] STATEMENT: SELECT "public"."customers"."uid", "public"."customers"."office_uid" FROM "public"."customers" WHERE "public"."customers"."office_uid" IN ($1,$2) OFFSET $3
|
||||
2024-07-16 10:45:03.049 CEST [39643] LOG: could not receive data from client: Connection reset by peer
|
||||
2024-07-16 10:45:03.062 CEST [39645] ERROR: relation "_prisma_migrations" does not exist at character 126
|
||||
2024-07-16 10:45:03.062 CEST [39645] STATEMENT: SELECT "id", "checksum", "finished_at", "migration_name", "logs", "rolled_back_at", "started_at", "applied_steps_count" FROM "_prisma_migrations" ORDER BY "started_at" ASC
|
@ -59,7 +59,7 @@
|
||||
"file-type-checker": "^1.0.8",
|
||||
"fp-ts": "^2.16.1",
|
||||
"jsonwebtoken": "^9.0.0",
|
||||
"le-coffre-resources": "git@github.com:smart-chain-fr/leCoffre-resources.git#v2.151",
|
||||
"le-coffre-resources": "git@github.com:smart-chain-fr/leCoffre-resources.git#v2.160",
|
||||
"module-alias": "^2.2.2",
|
||||
"monocle-ts": "^2.3.13",
|
||||
"multer": "^1.4.5-lts.1",
|
||||
|
50
src/app/api/customer/DocumentsNotaryController.ts
Normal file
50
src/app/api/customer/DocumentsNotaryController.ts
Normal file
@ -0,0 +1,50 @@
|
||||
import { Response, Request } from "express";
|
||||
import { Controller, Get } from "@ControllerPattern/index";
|
||||
import ApiController from "@Common/system/controller-pattern/ApiController";
|
||||
import { Service } from "typedi";
|
||||
import DocumentsNotaryService from "@Services/notary/DocumentsNotaryService/DocumentsNotaryService";
|
||||
import { Prisma } from "@prisma/client";
|
||||
import { DocumentNotary } from "le-coffre-resources/dist/Notary";
|
||||
import authHandler from "@App/middlewares/AuthHandler";
|
||||
// import NotificationBuilder from "@Common/notifications/NotificationBuilder";
|
||||
|
||||
@Controller()
|
||||
@Service()
|
||||
export default class DocumentsNotaryController extends ApiController {
|
||||
constructor(
|
||||
private documentsNotaryService: DocumentsNotaryService,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Get all documents
|
||||
* @returns IDocument[] list of documents
|
||||
*/
|
||||
@Get("/api/v1/customer/documents_notary", [authHandler])
|
||||
protected async get(req: Request, response: Response) {
|
||||
try {
|
||||
//get query
|
||||
let query: Prisma.DocumentsNotaryFindManyArgs = {};
|
||||
if (req.query["q"]) {
|
||||
query = JSON.parse(req.query["q"] as string);
|
||||
if (query.where?.uid) {
|
||||
this.httpBadRequest(response, "You can't filter by uid");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//call service to get prisma entity
|
||||
const documentEntities = await this.documentsNotaryService.get(query);
|
||||
|
||||
//Hydrate ressource with prisma entity
|
||||
const documents = DocumentNotary.hydrateArray<DocumentNotary>(documentEntities, { strategy: "excludeAll" });
|
||||
|
||||
//success
|
||||
this.httpSuccess(response, documents);
|
||||
} catch (error) {
|
||||
this.httpInternalError(response, error);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
@ -7,13 +7,14 @@ import { Customer } from "le-coffre-resources/dist/Notary";
|
||||
import { validateOrReject } from "class-validator";
|
||||
import authHandler from "@App/middlewares/AuthHandler";
|
||||
import ruleHandler from "@App/middlewares/RulesHandler";
|
||||
import { Prisma } from "@prisma/client";
|
||||
import { Documents, Prisma } from "@prisma/client";
|
||||
import customerHandler from "@App/middlewares/OfficeMembershipHandlers/CustomerHandler";
|
||||
import DocumentsService from "@Services/notary/DocumentsService/DocumentsService";
|
||||
|
||||
@Controller()
|
||||
@Service()
|
||||
export default class CustomersController extends ApiController {
|
||||
constructor(private customersService: CustomersService) {
|
||||
constructor(private customersService: CustomersService, private documentsService: DocumentsService) {
|
||||
super();
|
||||
}
|
||||
|
||||
@ -215,4 +216,55 @@ export default class CustomersController extends ApiController {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Send a reminder to a specific customer by uid to signe specific documents
|
||||
*/
|
||||
@Post("/api/v1/notary/customers/:uid/send_reminder", [authHandler, ruleHandler, customerHandler])
|
||||
protected async sendReminder(req: Request, response: Response) {
|
||||
try {
|
||||
const uid = req.params["uid"];
|
||||
if (!uid) {
|
||||
this.httpBadRequest(response, "No uid provided");
|
||||
return;
|
||||
}
|
||||
|
||||
const documentsUid = req.body.documentsUid;
|
||||
if (!documentsUid || !Array.isArray(documentsUid)) {
|
||||
this.httpBadRequest(response, "Invalid or missing documents");
|
||||
return;
|
||||
}
|
||||
|
||||
const documentEntities: Documents[] = [];
|
||||
//For each document uid, use DocumentsService.getByUid to get the document entity and add it to the documents array
|
||||
for (const documentUid of documentsUid) {
|
||||
const documentEntity = await this.documentsService.getByUid(documentUid, { document_type: true, folder: true });
|
||||
|
||||
if (!documentEntity) {
|
||||
this.httpBadRequest(response, "Document not found");
|
||||
return;
|
||||
}
|
||||
documentEntities.push(documentEntity);
|
||||
}
|
||||
|
||||
const customerEntity = await this.customersService.getByUid(uid, { contact: true, office: true });
|
||||
|
||||
if (!customerEntity) {
|
||||
this.httpNotFoundRequest(response, "customer not found");
|
||||
return;
|
||||
}
|
||||
|
||||
//Hydrate ressource with prisma entity
|
||||
const customer = Customer.hydrate<Customer>(customerEntity, { strategy: "excludeAll" });
|
||||
|
||||
// Call service to send reminder with documents
|
||||
await this.customersService.sendDocumentsReminder(customer, documentEntities);
|
||||
|
||||
// Success
|
||||
this.httpSuccess(response, customer);
|
||||
} catch (error) {
|
||||
this.httpInternalError(response, error);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -35,15 +35,15 @@ export default class DocumentsController extends ApiController {
|
||||
let query: Prisma.DocumentsFindManyArgs = {};
|
||||
if (req.query["q"]) {
|
||||
query = JSON.parse(req.query["q"] as string);
|
||||
if(query.where?.uid) {
|
||||
if (query.where?.uid) {
|
||||
this.httpBadRequest(response, "You can't filter by uid");
|
||||
return;
|
||||
}
|
||||
}
|
||||
const officeId: string = req.body.user.office_Id;
|
||||
const officeWhereInput: Prisma.OfficesWhereInput = { uid: officeId };
|
||||
if (!query.where) query.where = { document_type: { office: officeWhereInput } };
|
||||
query.where.document_type!.office = officeWhereInput;
|
||||
|
||||
query.where = { ...query.where, document_type: { office: officeWhereInput } };
|
||||
|
||||
//call service to get prisma entity
|
||||
const documentEntities = await this.documentsService.get(query);
|
||||
@ -124,7 +124,7 @@ export default class DocumentsController extends ApiController {
|
||||
return;
|
||||
}
|
||||
|
||||
if(documentFound.document_status === EDocumentStatus.REFUSED || documentFound.document_status === EDocumentStatus.VALIDATED) {
|
||||
if (documentFound.document_status === EDocumentStatus.REFUSED || documentFound.document_status === EDocumentStatus.VALIDATED) {
|
||||
this.httpForbidden(response, "You are not allowed to update a VALIDATED or REFUSED document");
|
||||
return;
|
||||
}
|
||||
@ -186,11 +186,9 @@ export default class DocumentsController extends ApiController {
|
||||
//call service to get prisma entity
|
||||
const documentEntityUpdated: Documents = await this.documentsService.refuse(uid, documentEntity, req.body.refused_reason);
|
||||
|
||||
|
||||
//create email for asked document
|
||||
await this.emailBuilder.sendDocumentEmails(documentEntityUpdated);
|
||||
|
||||
|
||||
//Hydrate ressource with prisma entity
|
||||
const document = Document.hydrate<Document>(documentEntityUpdated, { strategy: "excludeAll" });
|
||||
|
||||
|
137
src/app/api/notary/DocumentsNotaryController.ts
Normal file
137
src/app/api/notary/DocumentsNotaryController.ts
Normal file
@ -0,0 +1,137 @@
|
||||
import authHandler from "@App/middlewares/AuthHandler";
|
||||
import ApiController from "@Common/system/controller-pattern/ApiController";
|
||||
import { Controller, Delete, Get, Post } from "@ControllerPattern/index";
|
||||
import { DocumentsNotary, Prisma } from "@prisma/client";
|
||||
import CustomersService from "@Services/admin/CustomersService/CustomersService";
|
||||
import FilesNotaryService from "@Services/common/FilesNotaryService/FilesNotaryService";
|
||||
import DocumentsNotaryService from "@Services/notary/DocumentsNotaryService/DocumentsNotaryService";
|
||||
import OfficeFoldersService from "@Services/notary/OfficeFoldersService/OfficeFoldersService";
|
||||
import UsersService from "@Services/notary/UsersService/UsersService";
|
||||
import { Request, Response } from "express";
|
||||
import { DocumentNotary, FileNotary } from "le-coffre-resources/dist/Notary";
|
||||
import { Service } from "typedi";
|
||||
|
||||
@Controller()
|
||||
@Service()
|
||||
export default class DocumentsNotaryController extends ApiController {
|
||||
constructor(
|
||||
private documentsNotaryService: DocumentsNotaryService,
|
||||
private officeFoldersService: OfficeFoldersService,
|
||||
private customerService: CustomersService,
|
||||
private userService: UsersService,
|
||||
private filesNotaryService: FilesNotaryService,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Get all documents
|
||||
* @returns IDocument[] list of documents
|
||||
*/
|
||||
@Get("/api/v1/notary/documents_notary", [authHandler])
|
||||
protected async get(req: Request, response: Response) {
|
||||
try {
|
||||
//get query
|
||||
let query: Prisma.DocumentsNotaryFindManyArgs = {};
|
||||
if (req.query["q"]) {
|
||||
query = JSON.parse(req.query["q"] as string);
|
||||
if (query.where?.uid) {
|
||||
this.httpBadRequest(response, "You can't filter by uid");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//call service to get prisma entity
|
||||
const documentEntities = await this.documentsNotaryService.get(query);
|
||||
|
||||
//Hydrate ressource with prisma entity
|
||||
const documents = DocumentNotary.hydrateArray<DocumentNotary>(documentEntities, { strategy: "excludeAll" });
|
||||
|
||||
//success
|
||||
this.httpSuccess(response, documents);
|
||||
} catch (error) {
|
||||
this.httpInternalError(response, error);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Create a new document
|
||||
* @returns IDocument created
|
||||
*/
|
||||
@Post("/api/v1/notary/documents_notary", [authHandler])
|
||||
protected async post(req: Request, response: Response) {
|
||||
try {
|
||||
if (!req.file) return;
|
||||
|
||||
const customer = await this.customerService.getByUid(req.body.customerUid);
|
||||
if (!customer) return;
|
||||
|
||||
const folder = await this.officeFoldersService.getByUid(req.body.folderUid);
|
||||
if (!folder) return;
|
||||
|
||||
const user = await this.userService.getByUid(req.body.user.userId);
|
||||
if (!user) return;
|
||||
|
||||
const documentNotaryEntity = DocumentNotary.hydrate<DocumentNotary>({
|
||||
customer: customer,
|
||||
folder: folder,
|
||||
depositor: user,
|
||||
});
|
||||
|
||||
const documentNotaryEntityCreated = await this.documentsNotaryService.create(documentNotaryEntity);
|
||||
|
||||
const query = JSON.stringify({ document: { uid: documentNotaryEntityCreated.uid } });
|
||||
|
||||
const fileEntity = FileNotary.hydrate<FileNotary>(JSON.parse(query));
|
||||
|
||||
const fileEntityCreated = await this.filesNotaryService.create(fileEntity, req.file!);
|
||||
if (!fileEntityCreated) {
|
||||
this.httpBadRequest(response, "File could not be created");
|
||||
return;
|
||||
}
|
||||
|
||||
const documentNotary = await this.documentsNotaryService.getByUid(documentNotaryEntityCreated.uid);
|
||||
|
||||
const document = DocumentNotary.hydrate<DocumentNotary>(documentNotary!);
|
||||
//success
|
||||
this.httpCreated(response, document);
|
||||
} catch (error) {
|
||||
this.httpInternalError(response, error);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Delete a specific document
|
||||
*/
|
||||
@Delete("/api/v1/notary/documents_notary/:uid", [authHandler])
|
||||
protected async delete(req: Request, response: Response) {
|
||||
try {
|
||||
const uid = req.params["uid"];
|
||||
if (!uid) {
|
||||
this.httpBadRequest(response, "No uid provided");
|
||||
return;
|
||||
}
|
||||
|
||||
const documentNotaryFound = await this.documentsNotaryService.getByUid(uid);
|
||||
|
||||
if (!documentNotaryFound) {
|
||||
this.httpNotFoundRequest(response, "document not found");
|
||||
return;
|
||||
}
|
||||
|
||||
//call service to get prisma entity
|
||||
const documentNotaryEntity: DocumentsNotary = await this.documentsNotaryService.delete(uid);
|
||||
|
||||
//Hydrate ressource with prisma entity
|
||||
const documentNotary = DocumentNotary.hydrate<DocumentNotary>(documentNotaryEntity, { strategy: "excludeAll" });
|
||||
|
||||
//success
|
||||
this.httpSuccess(response, documentNotary);
|
||||
} catch (error) {
|
||||
this.httpInternalError(response, error);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
87
src/app/api/notary/DocumentsReminderController.ts
Normal file
87
src/app/api/notary/DocumentsReminderController.ts
Normal file
@ -0,0 +1,87 @@
|
||||
import { Response, Request } from "express";
|
||||
import { Controller, Get } from "@ControllerPattern/index";
|
||||
import ApiController from "@Common/system/controller-pattern/ApiController";
|
||||
import { Service } from "typedi";
|
||||
import { Prisma } from "@prisma/client";
|
||||
import { DocumentReminder } from "le-coffre-resources/dist/Notary";
|
||||
|
||||
import authHandler from "@App/middlewares/AuthHandler";
|
||||
|
||||
import DocumentsReminderService from "@Services/notary/DocumentsReminder/DocumentsReminder";
|
||||
// import NotificationBuilder from "@Common/notifications/NotificationBuilder";
|
||||
|
||||
@Controller()
|
||||
@Service()
|
||||
export default class DocumentsReminderController extends ApiController {
|
||||
constructor(
|
||||
private documentsReminderService: DocumentsReminderService,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Get all documents
|
||||
* @returns IDocument[] list of documents
|
||||
*/
|
||||
@Get("/api/v1/notary/document_reminders", [authHandler])
|
||||
protected async get(req: Request, response: Response) {
|
||||
try {
|
||||
//get query
|
||||
let query: Prisma.DocumentsReminderFindManyArgs = {};
|
||||
if (req.query["q"]) {
|
||||
query = JSON.parse(req.query["q"] as string);
|
||||
if(query.where?.uid) {
|
||||
this.httpBadRequest(response, "You can't filter by uid");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//call service to get prisma entity
|
||||
const documentReminderEntities = await this.documentsReminderService.get(query);
|
||||
|
||||
//Hydrate ressource with prisma entity
|
||||
const documentReminders = DocumentReminder.hydrateArray<DocumentReminder>(documentReminderEntities, { strategy: "excludeAll" });
|
||||
|
||||
//success
|
||||
this.httpSuccess(response, documentReminders);
|
||||
} catch (error) {
|
||||
this.httpInternalError(response, error);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// /**
|
||||
// * @description Get a specific document by uid
|
||||
// */
|
||||
// @Get("/api/v1/notary/document_reminders/:uid", [authHandler, ruleHandler, documentHandler])
|
||||
// protected async getOneByUid(req: Request, response: Response) {
|
||||
// try {
|
||||
// const uid = req.params["uid"];
|
||||
// if (!uid) {
|
||||
// this.httpBadRequest(response, "No uid provided");
|
||||
// return;
|
||||
// }
|
||||
// //get query
|
||||
// let query;
|
||||
// if (req.query["q"]) {
|
||||
// query = JSON.parse(req.query["q"] as string);
|
||||
// }
|
||||
|
||||
// const documentEntity = await this.documentsNotaryService.getByUid(uid, query);
|
||||
|
||||
// if (!documentEntity) {
|
||||
// this.httpNotFoundRequest(response, "document not found");
|
||||
// return;
|
||||
// }
|
||||
|
||||
// //Hydrate ressource with prisma entity
|
||||
// const document = Document.hydrate<Document>(documentEntity, { strategy: "excludeAll" });
|
||||
|
||||
// //success
|
||||
// this.httpSuccess(response, document);
|
||||
// } catch (error) {
|
||||
// this.httpInternalError(response, error);
|
||||
// return;
|
||||
// }
|
||||
// }
|
||||
}
|
@ -27,14 +27,14 @@ export default class FilesController extends ApiController {
|
||||
let query: Prisma.FilesFindManyArgs = {};
|
||||
if (req.query["q"]) {
|
||||
query = JSON.parse(req.query["q"] as string);
|
||||
if(query.where?.uid) {
|
||||
if (query.where?.uid) {
|
||||
this.httpBadRequest(response, "You can't filter by uid");
|
||||
return;
|
||||
}
|
||||
}
|
||||
const officeId: string = req.body.user.office_Id;
|
||||
const officeWhereInput: Prisma.OfficesWhereInput = { uid: officeId } ;
|
||||
if(!query.where) query.where = { document: { folder: {office: officeWhereInput}}};
|
||||
const officeWhereInput: Prisma.OfficesWhereInput = { uid: officeId };
|
||||
if (!query.where) query.where = { document: { folder: { office: officeWhereInput } } };
|
||||
query.where.document!.folder!.office = officeWhereInput;
|
||||
//call service to get prisma entity
|
||||
const fileEntities = await this.filesService.get(query);
|
||||
|
109
src/app/api/notary/FilesNotaryController.ts
Normal file
109
src/app/api/notary/FilesNotaryController.ts
Normal file
@ -0,0 +1,109 @@
|
||||
import authHandler from "@App/middlewares/AuthHandler";
|
||||
import ApiController from "@Common/system/controller-pattern/ApiController";
|
||||
import { Controller, Get } from "@ControllerPattern/index";
|
||||
import { Prisma } from "@prisma/client";
|
||||
import FilesNotaryService from "@Services/common/FilesNotaryService/FilesNotaryService";
|
||||
|
||||
import { Request, Response } from "express";
|
||||
import { File } from "le-coffre-resources/dist/Notary";
|
||||
import { Service } from "typedi";
|
||||
|
||||
@Controller()
|
||||
@Service()
|
||||
export default class FilesNotaryController extends ApiController {
|
||||
constructor(private filesNotaryService: FilesNotaryService) {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Get all Files
|
||||
* @returns File[] list of Files
|
||||
*/
|
||||
@Get("/api/v1/notary/files-notary", [authHandler])
|
||||
protected async get(req: Request, response: Response) {
|
||||
try {
|
||||
//get query
|
||||
let query: Prisma.FilesFindManyArgs = {};
|
||||
if (req.query["q"]) {
|
||||
query = JSON.parse(req.query["q"] as string);
|
||||
if (query.where?.uid) {
|
||||
this.httpBadRequest(response, "You can't filter by uid");
|
||||
return;
|
||||
}
|
||||
}
|
||||
const officeId: string = req.body.user.office_Id;
|
||||
const officeWhereInput: Prisma.OfficesWhereInput = { uid: officeId };
|
||||
if (!query.where) query.where = { document: { folder: { office: officeWhereInput } } };
|
||||
query.where.document!.folder!.office = officeWhereInput;
|
||||
//call service to get prisma entity
|
||||
const fileEntities = await this.filesNotaryService.get(query);
|
||||
|
||||
//Hydrate ressource with prisma entity
|
||||
const files = File.hydrateArray<File>(fileEntities, { strategy: "excludeAll" });
|
||||
|
||||
//success
|
||||
this.httpSuccess(response, files);
|
||||
} catch (error) {
|
||||
this.httpBadRequest(response, error);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Get a specific File by uid
|
||||
*/
|
||||
@Get("/api/v1/notary/files-notary/download/:uid", [authHandler])
|
||||
protected async download(req: Request, response: Response) {
|
||||
const uid = req.params["uid"];
|
||||
if (!uid) {
|
||||
this.httpBadRequest(response, "uid not found");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const fileInfo = await this.filesNotaryService.download(uid);
|
||||
|
||||
if (!fileInfo) {
|
||||
this.httpNotFoundRequest(response, "file not found");
|
||||
return;
|
||||
}
|
||||
|
||||
response.setHeader("Content-Type", fileInfo.file.mimetype);
|
||||
response.setHeader("Content-Disposition", `inline; filename=${encodeURIComponent(fileInfo.file.file_name)}`);
|
||||
|
||||
this.httpSuccess(response, fileInfo.buffer);
|
||||
} catch (error) {
|
||||
this.httpInternalError(response, error);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Get a specific File by uid
|
||||
*/
|
||||
@Get("/api/v1/notary/files-notary/:uid", [authHandler])
|
||||
protected async getOneByUid(req: Request, response: Response) {
|
||||
try {
|
||||
const uid = req.params["uid"];
|
||||
if (!uid) {
|
||||
this.httpBadRequest(response, "No uid provided");
|
||||
return;
|
||||
}
|
||||
|
||||
const fileEntity = await this.filesNotaryService.getByUid(uid);
|
||||
|
||||
if (!fileEntity) {
|
||||
this.httpNotFoundRequest(response, "file not found");
|
||||
return;
|
||||
}
|
||||
|
||||
//Hydrate ressource with prisma entity
|
||||
const file = File.hydrate<File>(fileEntity, { strategy: "excludeAll" });
|
||||
|
||||
//success
|
||||
this.httpSuccess(response, file);
|
||||
} catch (error) {
|
||||
this.httpInternalError(response, error);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
@ -90,20 +90,20 @@ export default class OfficeFoldersController extends ApiController {
|
||||
const sortedHashes = [...folderHashes].sort();
|
||||
const anchoringProof = await this.secureService.download(sortedHashes, officeFolder.office!.name);
|
||||
|
||||
const addFileToZip = (zip: Zip) => (uid: string): Promise<void> =>
|
||||
(async () => {
|
||||
const data = await this.filesService.download(uid);
|
||||
if (!data?.buffer) return;
|
||||
zip.addFile(`Documents du client/${uid}-${data.file.file_name}`, data.buffer);
|
||||
})()
|
||||
const addFileToZip =
|
||||
(zip: Zip) =>
|
||||
(uid: string): Promise<void> =>
|
||||
(async () => {
|
||||
const data = await this.filesService.download(uid);
|
||||
if (!data?.buffer) return;
|
||||
zip.addFile(`Documents du client/${uid}-${data.file.file_name}`, data.buffer);
|
||||
})();
|
||||
|
||||
const uids: string[] = folderFilesUid.filter((uid): uid is string => uid !== undefined);
|
||||
|
||||
const zip = new Zip();
|
||||
zip.addFile("Certificat de dépôt du dossier.pdf", anchoringProof);
|
||||
await Promise.allSettled(
|
||||
uids.map(addFileToZip(zip))
|
||||
)
|
||||
await Promise.allSettled(uids.map(addFileToZip(zip)));
|
||||
|
||||
response.setHeader("Content-Type", "application/zip");
|
||||
this.httpSuccess(response, zip.toBuffer());
|
||||
@ -132,6 +132,11 @@ export default class OfficeFoldersController extends ApiController {
|
||||
files: true,
|
||||
},
|
||||
},
|
||||
documents_notary: {
|
||||
include: {
|
||||
files: true,
|
||||
},
|
||||
},
|
||||
folder_anchor: true,
|
||||
};
|
||||
|
||||
@ -276,7 +281,7 @@ export default class OfficeFoldersController extends ApiController {
|
||||
let query: Prisma.OfficeFolderAnchorsFindManyArgs = {};
|
||||
if (req.query["q"]) {
|
||||
query = JSON.parse(req.query["q"] as string);
|
||||
if(query.where?.uid) {
|
||||
if (query.where?.uid) {
|
||||
this.httpBadRequest(response, "You can't filter by uid");
|
||||
return;
|
||||
}
|
||||
|
@ -55,6 +55,9 @@ import StripeWebhooks from "@Common/webhooks/stripeWebhooks";
|
||||
import RulesGroupsController from "./api/admin/RulesGroupsController";
|
||||
import NotesController from "./api/customer/NotesController";
|
||||
import MailchimpController from "./api/notary/MailchimpController";
|
||||
import DocumentsReminderController from "./api/notary/DocumentsReminderController";
|
||||
import DocumentsNotaryController from "./api/notary/DocumentsNotaryController";
|
||||
import FilesNotaryController from "./api/notary/FilesNotaryController";
|
||||
|
||||
/**
|
||||
* @description This allow to declare all controllers used in the application
|
||||
@ -118,5 +121,8 @@ export default {
|
||||
Container.get(RulesGroupsController);
|
||||
Container.get(NotesController);
|
||||
Container.get(MailchimpController);
|
||||
Container.get(DocumentsReminderController);
|
||||
Container.get(DocumentsNotaryController);
|
||||
Container.get(FilesNotaryController);
|
||||
},
|
||||
};
|
||||
|
@ -0,0 +1,45 @@
|
||||
-- CreateTable
|
||||
CREATE TABLE "documents_notary" (
|
||||
"uid" TEXT NOT NULL,
|
||||
"folder_uid" VARCHAR(255) NOT NULL,
|
||||
"depositor_uid" VARCHAR(255) NOT NULL,
|
||||
"created_at" TIMESTAMP(3) DEFAULT CURRENT_TIMESTAMP,
|
||||
"updated_at" TIMESTAMP(3),
|
||||
|
||||
CONSTRAINT "documents_notary_pkey" PRIMARY KEY ("uid")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "files_notary" (
|
||||
"uid" TEXT NOT NULL,
|
||||
"document_uid" VARCHAR(255) NOT NULL,
|
||||
"file_path" VARCHAR(255) NOT NULL,
|
||||
"file_name" VARCHAR(255) NOT NULL,
|
||||
"mimetype" VARCHAR(255) NOT NULL,
|
||||
"hash" VARCHAR(255) NOT NULL,
|
||||
"size" INTEGER NOT NULL,
|
||||
"archived_at" TIMESTAMP(3),
|
||||
"key" VARCHAR(255),
|
||||
"created_at" TIMESTAMP(3) DEFAULT CURRENT_TIMESTAMP,
|
||||
"updated_at" TIMESTAMP(3),
|
||||
|
||||
CONSTRAINT "files_notary_pkey" PRIMARY KEY ("uid")
|
||||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "documents_notary_uid_key" ON "documents_notary"("uid");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "files_notary_uid_key" ON "files_notary"("uid");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "files_notary_file_path_key" ON "files_notary"("file_path");
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "documents_notary" ADD CONSTRAINT "documents_notary_folder_uid_fkey" FOREIGN KEY ("folder_uid") REFERENCES "office_folders"("uid") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "documents_notary" ADD CONSTRAINT "documents_notary_depositor_uid_fkey" FOREIGN KEY ("depositor_uid") REFERENCES "users"("uid") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "files_notary" ADD CONSTRAINT "files_notary_document_uid_fkey" FOREIGN KEY ("document_uid") REFERENCES "documents_notary"("uid") ON DELETE CASCADE ON UPDATE CASCADE;
|
@ -0,0 +1,16 @@
|
||||
-- CreateTable
|
||||
CREATE TABLE "documents_reminder" (
|
||||
"uid" TEXT NOT NULL,
|
||||
"document_uid" VARCHAR(255) NOT NULL,
|
||||
"reminder_date" TIMESTAMP(3) NOT NULL,
|
||||
"created_at" TIMESTAMP(3) DEFAULT CURRENT_TIMESTAMP,
|
||||
"updated_at" TIMESTAMP(3),
|
||||
|
||||
CONSTRAINT "documents_reminder_pkey" PRIMARY KEY ("uid")
|
||||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "documents_reminder_uid_key" ON "documents_reminder"("uid");
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "documents_reminder" ADD CONSTRAINT "documents_reminder_document_uid_fkey" FOREIGN KEY ("document_uid") REFERENCES "documents"("uid") ON DELETE CASCADE ON UPDATE CASCADE;
|
@ -0,0 +1,17 @@
|
||||
/*
|
||||
Warnings:
|
||||
|
||||
- You are about to drop the column `archived_at` on the `files_notary` table. All the data in the column will be lost.
|
||||
- You are about to drop the column `key` on the `files_notary` table. All the data in the column will be lost.
|
||||
- Added the required column `customer_uid` to the `documents_notary` table without a default value. This is not possible if the table is not empty.
|
||||
|
||||
*/
|
||||
-- AlterTable
|
||||
ALTER TABLE "documents_notary" ADD COLUMN "customer_uid" VARCHAR(255) NOT NULL;
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "files_notary" DROP COLUMN "archived_at",
|
||||
DROP COLUMN "key";
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "documents_notary" ADD CONSTRAINT "documents_notary_customer_uid_fkey" FOREIGN KEY ("customer_uid") REFERENCES "customers"("uid") ON DELETE CASCADE ON UPDATE CASCADE;
|
@ -0,0 +1,2 @@
|
||||
-- AlterTable
|
||||
ALTER TABLE "documents_notary" ADD COLUMN "document_name" VARCHAR(255) NOT NULL DEFAULT '';
|
@ -0,0 +1,9 @@
|
||||
/*
|
||||
Warnings:
|
||||
|
||||
- You are about to drop the column `document_name` on the `documents_notary` table. All the data in the column will be lost.
|
||||
|
||||
*/
|
||||
-- AlterTable
|
||||
ALTER TABLE "documents_notary" DROP COLUMN "document_name",
|
||||
ADD COLUMN "document" VARCHAR(255) NOT NULL DEFAULT '';
|
@ -0,0 +1,2 @@
|
||||
-- AlterTable
|
||||
ALTER TABLE "files_notary" ADD COLUMN "key" VARCHAR(255);
|
@ -37,7 +37,7 @@ model Contacts {
|
||||
last_name String @db.VarChar(255)
|
||||
email String @db.VarChar(255)
|
||||
phone_number String? @db.VarChar(50)
|
||||
cell_phone_number String? @db.VarChar(50)
|
||||
cell_phone_number String? @db.VarChar(50)
|
||||
civility ECivility @default(MALE)
|
||||
address Addresses? @relation(fields: [address_uid], references: [uid], onDelete: Cascade)
|
||||
address_uid String? @unique @db.VarChar(255)
|
||||
@ -51,24 +51,25 @@ model Contacts {
|
||||
}
|
||||
|
||||
model Users {
|
||||
uid String @id @unique @default(uuid()) @map("uid")
|
||||
idNot String @unique @db.VarChar(255)
|
||||
contact Contacts @relation(fields: [contact_uid], references: [uid], onDelete: Cascade)
|
||||
contact_uid String @unique @db.VarChar(255)
|
||||
role Roles @relation(fields: [roles_uid], references: [uid], onDelete: Cascade)
|
||||
roles_uid String @db.VarChar(255)
|
||||
office_role OfficeRoles? @relation(fields: [office_role_uid], references: [uid], onDelete: Cascade)
|
||||
office_role_uid String? @db.VarChar(255)
|
||||
created_at DateTime? @default(now())
|
||||
updated_at DateTime? @updatedAt
|
||||
checked_at DateTime?
|
||||
office_membership Offices @relation(fields: [office_uid], references: [uid], onDelete: Cascade)
|
||||
office_uid String @db.VarChar(255)
|
||||
office_folders OfficeFolders[] @relation("OfficeFolderHasStakeholders")
|
||||
appointment Appointments[]
|
||||
votes Votes[]
|
||||
uid String @id @unique @default(uuid()) @map("uid")
|
||||
idNot String @unique @db.VarChar(255)
|
||||
contact Contacts @relation(fields: [contact_uid], references: [uid], onDelete: Cascade)
|
||||
contact_uid String @unique @db.VarChar(255)
|
||||
role Roles @relation(fields: [roles_uid], references: [uid], onDelete: Cascade)
|
||||
roles_uid String @db.VarChar(255)
|
||||
office_role OfficeRoles? @relation(fields: [office_role_uid], references: [uid], onDelete: Cascade)
|
||||
office_role_uid String? @db.VarChar(255)
|
||||
created_at DateTime? @default(now())
|
||||
updated_at DateTime? @updatedAt
|
||||
checked_at DateTime?
|
||||
office_membership Offices @relation(fields: [office_uid], references: [uid], onDelete: Cascade)
|
||||
office_uid String @db.VarChar(255)
|
||||
office_folders OfficeFolders[] @relation("OfficeFolderHasStakeholders")
|
||||
appointment Appointments[]
|
||||
votes Votes[]
|
||||
user_notifications UserNotifications[]
|
||||
seats Seats[]
|
||||
seats Seats[]
|
||||
documents_notary DocumentsNotary[]
|
||||
|
||||
@@map("users")
|
||||
}
|
||||
@ -79,6 +80,7 @@ model Whitelist {
|
||||
active Boolean @default(true)
|
||||
created_at DateTime? @default(now())
|
||||
updated_at DateTime? @updatedAt
|
||||
|
||||
@@map("whitelist")
|
||||
}
|
||||
|
||||
@ -88,6 +90,7 @@ model UserWhitelist {
|
||||
active Boolean @default(true)
|
||||
created_at DateTime? @default(now())
|
||||
updated_at DateTime? @updatedAt
|
||||
|
||||
@@map("user_whitelist")
|
||||
}
|
||||
|
||||
@ -116,109 +119,140 @@ model Offices {
|
||||
}
|
||||
|
||||
model Customers {
|
||||
uid String @id @unique @default(uuid())
|
||||
status ECustomerStatus @default(PENDING)
|
||||
contact Contacts @relation(fields: [contact_uid], references: [uid], onDelete: Cascade)
|
||||
contact_uid String @unique @db.VarChar(255)
|
||||
created_at DateTime? @default(now())
|
||||
updated_at DateTime? @updatedAt
|
||||
office_folders OfficeFolders[] @relation("OfficeFolderHasCustomers")
|
||||
documents Documents[]
|
||||
password String? @db.VarChar(255)
|
||||
totpCodes TotpCodes[]
|
||||
office Offices @relation(fields: [office_uid], references: [uid], onDelete: Cascade)
|
||||
office_uid String @db.VarChar(255)
|
||||
notes Notes[]
|
||||
uid String @id @unique @default(uuid())
|
||||
status ECustomerStatus @default(PENDING)
|
||||
contact Contacts @relation(fields: [contact_uid], references: [uid], onDelete: Cascade)
|
||||
contact_uid String @unique @db.VarChar(255)
|
||||
created_at DateTime? @default(now())
|
||||
updated_at DateTime? @updatedAt
|
||||
office_folders OfficeFolders[] @relation("OfficeFolderHasCustomers")
|
||||
documents Documents[]
|
||||
password String? @db.VarChar(255)
|
||||
totpCodes TotpCodes[]
|
||||
office Offices @relation(fields: [office_uid], references: [uid], onDelete: Cascade)
|
||||
office_uid String @db.VarChar(255)
|
||||
notes Notes[]
|
||||
documents_notary DocumentsNotary[]
|
||||
|
||||
@@map("customers")
|
||||
}
|
||||
|
||||
model Notifications {
|
||||
uid String @id @unique @default(uuid())
|
||||
message String @db.VarChar(1000)
|
||||
redirection_url String @db.VarChar(255)
|
||||
created_at DateTime? @default(now())
|
||||
updated_at DateTime? @updatedAt
|
||||
userNotifications UserNotifications[]
|
||||
uid String @id @unique @default(uuid())
|
||||
message String @db.VarChar(1000)
|
||||
redirection_url String @db.VarChar(255)
|
||||
created_at DateTime? @default(now())
|
||||
updated_at DateTime? @updatedAt
|
||||
userNotifications UserNotifications[]
|
||||
|
||||
@@map("notifications")
|
||||
}
|
||||
|
||||
model UserNotifications {
|
||||
uid String @id @unique @default(uuid())
|
||||
user Users @relation(fields: [user_uid], references: [uid], onDelete: Cascade)
|
||||
user_uid String @db.VarChar(255)
|
||||
read Boolean @default(false)
|
||||
notification Notifications @relation(fields: [notification_uid], references: [uid], onDelete: Cascade)
|
||||
notification_uid String @db.VarChar(255)
|
||||
uid String @id @unique @default(uuid())
|
||||
user Users @relation(fields: [user_uid], references: [uid], onDelete: Cascade)
|
||||
user_uid String @db.VarChar(255)
|
||||
read Boolean @default(false)
|
||||
notification Notifications @relation(fields: [notification_uid], references: [uid], onDelete: Cascade)
|
||||
notification_uid String @db.VarChar(255)
|
||||
|
||||
@@map("user_notifications")
|
||||
}
|
||||
|
||||
model OfficeFolders {
|
||||
uid String @id @unique @default(uuid())
|
||||
folder_number String @db.VarChar(255)
|
||||
name String @db.VarChar(255)
|
||||
description String? @db.VarChar(1000)
|
||||
archived_description String? @db.VarChar(255)
|
||||
status EFolderStatus @default(LIVE)
|
||||
deed Deeds @relation(fields: [deed_uid], references: [uid], onDelete: Cascade)
|
||||
deed_uid String @unique @db.VarChar(255)
|
||||
office Offices @relation(fields: [office_uid], references: [uid], onDelete: Cascade)
|
||||
office_uid String @db.VarChar(255)
|
||||
created_at DateTime? @default(now())
|
||||
updated_at DateTime? @updatedAt
|
||||
stakeholders Users[] @relation("OfficeFolderHasStakeholders")
|
||||
customers Customers[] @relation("OfficeFolderHasCustomers")
|
||||
uid String @id @unique @default(uuid())
|
||||
folder_number String @db.VarChar(255)
|
||||
name String @db.VarChar(255)
|
||||
description String? @db.VarChar(1000)
|
||||
archived_description String? @db.VarChar(255)
|
||||
status EFolderStatus @default(LIVE)
|
||||
deed Deeds @relation(fields: [deed_uid], references: [uid], onDelete: Cascade)
|
||||
deed_uid String @unique @db.VarChar(255)
|
||||
office Offices @relation(fields: [office_uid], references: [uid], onDelete: Cascade)
|
||||
office_uid String @db.VarChar(255)
|
||||
created_at DateTime? @default(now())
|
||||
updated_at DateTime? @updatedAt
|
||||
stakeholders Users[] @relation("OfficeFolderHasStakeholders")
|
||||
customers Customers[] @relation("OfficeFolderHasCustomers")
|
||||
documents Documents[]
|
||||
documents_notary DocumentsNotary[]
|
||||
|
||||
folder_anchor OfficeFolderAnchors? @relation(fields: [folder_anchor_uid], references: [uid])
|
||||
folder_anchor_uid String? @unique @db.VarChar(255)
|
||||
notes Notes[]
|
||||
folder_anchor OfficeFolderAnchors? @relation(fields: [folder_anchor_uid], references: [uid])
|
||||
folder_anchor_uid String? @unique @db.VarChar(255)
|
||||
notes Notes[]
|
||||
|
||||
@@unique([folder_number, office_uid])
|
||||
@@map("office_folders")
|
||||
}
|
||||
|
||||
model OfficeFolderAnchors {
|
||||
uid String @id @unique @default(uuid())
|
||||
uid String @id @unique @default(uuid())
|
||||
|
||||
hash_sources String[]
|
||||
root_hash String @db.VarChar(255)
|
||||
hash_sources String[]
|
||||
root_hash String @db.VarChar(255)
|
||||
|
||||
blockchain EBlockchainName @default(TEZOS)
|
||||
status EAnchoringStatus @default(QUEUED)
|
||||
anchor_nb_try Int @default(0)
|
||||
blockchain EBlockchainName @default(TEZOS)
|
||||
status EAnchoringStatus @default(QUEUED)
|
||||
anchor_nb_try Int @default(0)
|
||||
|
||||
anchored_at DateTime?
|
||||
tx_id String? @db.VarChar(255)
|
||||
tx_link String? @db.VarChar(255)
|
||||
tx_hash String? @db.VarChar(255)
|
||||
anchored_at DateTime?
|
||||
tx_id String? @db.VarChar(255)
|
||||
tx_link String? @db.VarChar(255)
|
||||
tx_hash String? @db.VarChar(255)
|
||||
|
||||
folder OfficeFolders?
|
||||
folder OfficeFolders?
|
||||
|
||||
created_at DateTime? @default(now())
|
||||
updated_at DateTime? @updatedAt
|
||||
created_at DateTime? @default(now())
|
||||
updated_at DateTime? @updatedAt
|
||||
|
||||
@@map("office_folder_anchors")
|
||||
}
|
||||
|
||||
model Documents {
|
||||
uid String @id @unique @default(uuid())
|
||||
document_status EDocumentStatus @default(ASKED)
|
||||
document_type DocumentTypes @relation(fields: [document_type_uid], references: [uid])
|
||||
document_type_uid String @db.VarChar(255)
|
||||
folder OfficeFolders @relation(fields: [folder_uid], references: [uid])
|
||||
folder_uid String @db.VarChar(255)
|
||||
depositor Customers @relation(fields: [depositor_uid], references: [uid], onDelete: Cascade)
|
||||
depositor_uid String @db.VarChar(255)
|
||||
created_at DateTime? @default(now())
|
||||
updated_at DateTime? @updatedAt
|
||||
files Files[]
|
||||
document_history DocumentHistory[]
|
||||
uid String @id @unique @default(uuid())
|
||||
document_status EDocumentStatus @default(ASKED)
|
||||
document_type DocumentTypes @relation(fields: [document_type_uid], references: [uid])
|
||||
document_type_uid String @db.VarChar(255)
|
||||
folder OfficeFolders @relation(fields: [folder_uid], references: [uid])
|
||||
folder_uid String @db.VarChar(255)
|
||||
depositor Customers @relation(fields: [depositor_uid], references: [uid], onDelete: Cascade)
|
||||
depositor_uid String @db.VarChar(255)
|
||||
created_at DateTime? @default(now())
|
||||
updated_at DateTime? @updatedAt
|
||||
files Files[]
|
||||
document_history DocumentHistory[]
|
||||
reminders DocumentsReminder[]
|
||||
|
||||
@@map("documents")
|
||||
}
|
||||
|
||||
model DocumentsNotary {
|
||||
uid String @id @unique @default(uuid())
|
||||
folder OfficeFolders @relation(fields: [folder_uid], references: [uid])
|
||||
folder_uid String @db.VarChar(255)
|
||||
depositor Users @relation(fields: [depositor_uid], references: [uid], onDelete: Cascade)
|
||||
depositor_uid String @db.VarChar(255)
|
||||
created_at DateTime? @default(now())
|
||||
updated_at DateTime? @updatedAt
|
||||
files FilesNotary[]
|
||||
customer Customers @relation(fields: [customer_uid], references: [uid], onDelete: Cascade)
|
||||
customer_uid String @db.VarChar(255)
|
||||
document String @default("") @db.VarChar(255)
|
||||
|
||||
@@map("documents_notary")
|
||||
}
|
||||
|
||||
model DocumentsReminder {
|
||||
uid String @id @unique @default(uuid())
|
||||
document Documents @relation(fields: [document_uid], references: [uid], onDelete: Cascade)
|
||||
document_uid String @db.VarChar(255)
|
||||
reminder_date DateTime
|
||||
created_at DateTime? @default(now())
|
||||
updated_at DateTime? @updatedAt
|
||||
|
||||
@@map("documents_reminder")
|
||||
}
|
||||
|
||||
model DocumentHistory {
|
||||
uid String @id @unique @default(uuid())
|
||||
document_status EDocumentStatus @default(ASKED)
|
||||
@ -248,6 +282,22 @@ model Files {
|
||||
@@map("files")
|
||||
}
|
||||
|
||||
model FilesNotary {
|
||||
uid String @id @unique @default(uuid())
|
||||
document_notary DocumentsNotary @relation(fields: [document_uid], references: [uid], onDelete: Cascade)
|
||||
document_uid String @db.VarChar(255)
|
||||
file_path String @unique @db.VarChar(255)
|
||||
file_name String @db.VarChar(255)
|
||||
mimetype String @db.VarChar(255)
|
||||
hash String @db.VarChar(255)
|
||||
size Int
|
||||
key String? @db.VarChar(255)
|
||||
created_at DateTime? @default(now())
|
||||
updated_at DateTime? @updatedAt
|
||||
|
||||
@@map("files_notary")
|
||||
}
|
||||
|
||||
model DocumentTypes {
|
||||
uid String @id @unique @default(uuid())
|
||||
name String @db.VarChar(255)
|
||||
@ -327,8 +377,9 @@ model Rules {
|
||||
updated_at DateTime? @updatedAt
|
||||
role Roles[] @relation("RolesHasRules")
|
||||
office_roles OfficeRoles[] @relation("OfficeRolesHasRules")
|
||||
namespace String @db.VarChar(255) @default("notary")
|
||||
namespace String @default("notary") @db.VarChar(255)
|
||||
groups RulesGroups[] @relation("RulesGroupsHasRules")
|
||||
|
||||
@@map("rules")
|
||||
}
|
||||
|
||||
@ -338,8 +389,9 @@ model RulesGroups {
|
||||
created_at DateTime? @default(now())
|
||||
updated_at DateTime? @updatedAt
|
||||
rules Rules[] @relation("RulesGroupsHasRules")
|
||||
|
||||
@@map("rules_groups")
|
||||
}
|
||||
}
|
||||
|
||||
model Emails {
|
||||
uid String @id @unique @default(uuid())
|
||||
@ -380,54 +432,58 @@ model Votes {
|
||||
}
|
||||
|
||||
model TotpCodes {
|
||||
uid String @id @unique @default(uuid())
|
||||
customer Customers @relation(fields: [customer_uid], references: [uid], onDelete: Cascade)
|
||||
customer_uid String @db.VarChar(255)
|
||||
code String @db.VarChar(255)
|
||||
reason TotpCodesReasons @default(LOGIN)
|
||||
resent Boolean @default(false)
|
||||
expire_at DateTime? @default(now())
|
||||
created_at DateTime? @default(now())
|
||||
updated_at DateTime? @updatedAt
|
||||
uid String @id @unique @default(uuid())
|
||||
customer Customers @relation(fields: [customer_uid], references: [uid], onDelete: Cascade)
|
||||
customer_uid String @db.VarChar(255)
|
||||
code String @db.VarChar(255)
|
||||
reason TotpCodesReasons @default(LOGIN)
|
||||
resent Boolean @default(false)
|
||||
expire_at DateTime? @default(now())
|
||||
created_at DateTime? @default(now())
|
||||
updated_at DateTime? @updatedAt
|
||||
|
||||
@@map("totp_codes")
|
||||
}
|
||||
|
||||
model Subscriptions {
|
||||
uid String @id @unique @default(uuid())
|
||||
type ESubscriptionType
|
||||
status ESubscriptionStatus @default(ACTIVE)
|
||||
stripe_subscription_id String @db.VarChar(255)
|
||||
start_date DateTime @default(now())
|
||||
end_date DateTime
|
||||
nb_seats Int
|
||||
office Offices @relation(fields: [office_uid], references: [uid], onDelete: Cascade)
|
||||
office_uid String @db.VarChar(255)
|
||||
seats Seats[]
|
||||
created_at DateTime? @default(now())
|
||||
updated_at DateTime? @updatedAt
|
||||
uid String @id @unique @default(uuid())
|
||||
type ESubscriptionType
|
||||
status ESubscriptionStatus @default(ACTIVE)
|
||||
stripe_subscription_id String @db.VarChar(255)
|
||||
start_date DateTime @default(now())
|
||||
end_date DateTime
|
||||
nb_seats Int
|
||||
office Offices @relation(fields: [office_uid], references: [uid], onDelete: Cascade)
|
||||
office_uid String @db.VarChar(255)
|
||||
seats Seats[]
|
||||
created_at DateTime? @default(now())
|
||||
updated_at DateTime? @updatedAt
|
||||
|
||||
@@map("subscriptions")
|
||||
}
|
||||
|
||||
model Seats {
|
||||
uid String @id @unique @default(uuid())
|
||||
subscription Subscriptions @relation(fields: [subscription_uid], references: [uid], onDelete: Cascade)
|
||||
subscription_uid String @db.VarChar(255)
|
||||
user Users @relation(fields: [user_uid], references: [uid], onDelete: Cascade)
|
||||
user_uid String @db.VarChar(255)
|
||||
created_at DateTime? @default(now())
|
||||
updated_at DateTime? @updatedAt
|
||||
uid String @id @unique @default(uuid())
|
||||
subscription Subscriptions @relation(fields: [subscription_uid], references: [uid], onDelete: Cascade)
|
||||
subscription_uid String @db.VarChar(255)
|
||||
user Users @relation(fields: [user_uid], references: [uid], onDelete: Cascade)
|
||||
user_uid String @db.VarChar(255)
|
||||
created_at DateTime? @default(now())
|
||||
updated_at DateTime? @updatedAt
|
||||
|
||||
@@map("seats")
|
||||
}
|
||||
|
||||
model Notes {
|
||||
uid String @id @unique @default(uuid())
|
||||
content String @db.VarChar(1000)
|
||||
created_at DateTime? @default(now())
|
||||
updated_at DateTime? @updatedAt
|
||||
customer Customers @relation(fields: [customer_uid], references: [uid], onDelete: Cascade)
|
||||
customer_uid String @db.VarChar(255)
|
||||
uid String @id @unique @default(uuid())
|
||||
content String @db.VarChar(1000)
|
||||
created_at DateTime? @default(now())
|
||||
updated_at DateTime? @updatedAt
|
||||
customer Customers @relation(fields: [customer_uid], references: [uid], onDelete: Cascade)
|
||||
customer_uid String @db.VarChar(255)
|
||||
folder OfficeFolders @relation(fields: [folder_uid], references: [uid], onDelete: Cascade)
|
||||
folder_uid String @db.VarChar(255)
|
||||
folder_uid String @db.VarChar(255)
|
||||
|
||||
@@map("notes")
|
||||
}
|
||||
|
||||
|
@ -7,6 +7,7 @@ import MailchimpService from "@Services/common/MailchimpService/MailchimpService
|
||||
import { BackendVariables } from "@Common/config/variables/Variables";
|
||||
import UsersService from "@Services/super-admin/UsersService/UsersService";
|
||||
import User from "le-coffre-resources/dist/SuperAdmin";
|
||||
import { Customer } from "le-coffre-resources/dist/Notary";
|
||||
|
||||
@Service()
|
||||
export default class EmailBuilder {
|
||||
@ -138,4 +139,31 @@ export default class EmailBuilder {
|
||||
|
||||
|
||||
}
|
||||
|
||||
public async sendReminder(customer: Customer, documents: Documents[]) {
|
||||
const to = customer.contact!.email;
|
||||
const templateVariables = {
|
||||
office_name: customer.office?.name,
|
||||
last_name: customer.contact!.last_name,
|
||||
first_name: customer.contact!.first_name,
|
||||
link: this.variables.APP_HOST,
|
||||
};
|
||||
|
||||
const templateName = ETemplates.DOCUMENT_REMINDER;
|
||||
const subject = "Vous avez des documents à déposer pour votre dossier.";
|
||||
|
||||
this.mailchimpService.create({
|
||||
templateName,
|
||||
to,
|
||||
subject,
|
||||
templateVariables,
|
||||
uid: "",
|
||||
from: null,
|
||||
cc: [],
|
||||
cci: [],
|
||||
sentAt: null,
|
||||
nbTrySend: null,
|
||||
lastTrySendDate: null,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -3,4 +3,5 @@ export const ETemplates = {
|
||||
DOCUMENT_REFUSED: "DOCUMENT_REFUSED",
|
||||
DOCUMENT_RECAP: "DOCUMENT_RECAP",
|
||||
SUBSCRIPTION_INVITATION: "SUBSCRIPTION_INVITATION",
|
||||
DOCUMENT_REMINDER: "DOCUMENT_REMINDER",
|
||||
};
|
102
src/common/repositories/DocumentsNotaryRepository.ts
Normal file
102
src/common/repositories/DocumentsNotaryRepository.ts
Normal file
@ -0,0 +1,102 @@
|
||||
import Database from "@Common/databases/database";
|
||||
import BaseRepository from "@Repositories/BaseRepository";
|
||||
import { Service } from "typedi";
|
||||
import { DocumentsNotary, Prisma } from "@prisma/client";
|
||||
import { DocumentNotary } from "le-coffre-resources/dist/Notary";
|
||||
|
||||
@Service()
|
||||
export default class DocumentsNotaryRepository extends BaseRepository {
|
||||
constructor(private database: Database) {
|
||||
super();
|
||||
}
|
||||
protected get model() {
|
||||
return this.database.getClient().documentsNotary;
|
||||
}
|
||||
protected get instanceDb() {
|
||||
return this.database.getClient();
|
||||
}
|
||||
|
||||
/**
|
||||
* @description : Find many documents
|
||||
*/
|
||||
public async findMany(query: Prisma.DocumentsNotaryFindManyArgs) {
|
||||
query.take = Math.min(query.take || this.defaultFetchRows, this.maxFetchRows);
|
||||
return this.model.findMany(query);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description : Create a document
|
||||
*/
|
||||
public async create(document: DocumentNotary): Promise<DocumentsNotary> {
|
||||
const createArgs: Prisma.DocumentsNotaryCreateArgs = {
|
||||
data: {
|
||||
folder: {
|
||||
connect: {
|
||||
uid: document.folder!.uid,
|
||||
},
|
||||
},
|
||||
depositor: {
|
||||
connect: {
|
||||
uid: document.depositor!.uid,
|
||||
},
|
||||
},
|
||||
customer: {
|
||||
connect: {
|
||||
uid: document.customer!.uid,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const documentCreated = await this.model.create({ ...createArgs });
|
||||
|
||||
return documentCreated;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description : Delete a document
|
||||
*/
|
||||
public async delete(uid: string): Promise<DocumentsNotary> {
|
||||
return this.model.delete({
|
||||
where: {
|
||||
uid: uid,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @description : Find unique document
|
||||
*/
|
||||
public async findOneByUid(uid: string, query?: Prisma.DocumentsNotaryInclude): Promise<DocumentsNotary | null> {
|
||||
return this.model.findUnique({
|
||||
where: {
|
||||
uid: uid,
|
||||
},
|
||||
include: query,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @description : Find unique document with relations
|
||||
*/
|
||||
public async findOneByUidWithOffice(uid: string) {
|
||||
return this.model.findUnique({
|
||||
where: {
|
||||
uid: uid,
|
||||
},
|
||||
include: { folder: { include: { office: true } } },
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @description : Find unique document with relations
|
||||
*/
|
||||
public async findOneByUidWithFiles(uid: string) {
|
||||
return this.model.findUnique({
|
||||
where: {
|
||||
uid: uid,
|
||||
},
|
||||
include: { files: true },
|
||||
});
|
||||
}
|
||||
}
|
46
src/common/repositories/DocumentsReminderRepository.ts
Normal file
46
src/common/repositories/DocumentsReminderRepository.ts
Normal file
@ -0,0 +1,46 @@
|
||||
import Database from "@Common/databases/database";
|
||||
import BaseRepository from "@Repositories/BaseRepository";
|
||||
import { Service } from "typedi";
|
||||
import { DocumentsReminder, Prisma } from "@prisma/client";
|
||||
import { DocumentReminder } from "le-coffre-resources/dist/Notary";
|
||||
|
||||
@Service()
|
||||
export default class DocumentsReminderRepository extends BaseRepository {
|
||||
constructor(private database: Database) {
|
||||
super();
|
||||
}
|
||||
protected get model() {
|
||||
return this.database.getClient().documentsReminder;
|
||||
}
|
||||
protected get instanceDb() {
|
||||
return this.database.getClient();
|
||||
}
|
||||
|
||||
/**
|
||||
* @description : Find many documents
|
||||
*/
|
||||
public async findMany(query: Prisma.DocumentsReminderFindManyArgs) {
|
||||
query.take = Math.min(query.take || this.defaultFetchRows, this.maxFetchRows);
|
||||
return this.model.findMany(query);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description : Create a document
|
||||
*/
|
||||
public async create(documentReminder: DocumentReminder): Promise<DocumentsReminder> {
|
||||
const createArgs: Prisma.DocumentsReminderCreateArgs = {
|
||||
data: {
|
||||
document: {
|
||||
connect: {
|
||||
uid: documentReminder.document!.uid,
|
||||
},
|
||||
},
|
||||
reminder_date: new Date(),
|
||||
},
|
||||
};
|
||||
|
||||
const documentReminderCreated = await this.model.create({ ...createArgs });
|
||||
|
||||
return documentReminderCreated;
|
||||
}
|
||||
}
|
84
src/common/repositories/FilesNotaryRepository.ts
Normal file
84
src/common/repositories/FilesNotaryRepository.ts
Normal file
@ -0,0 +1,84 @@
|
||||
import Database from "@Common/databases/database";
|
||||
import BaseRepository from "@Repositories/BaseRepository";
|
||||
import { Service } from "typedi";
|
||||
import { FilesNotary, Prisma } from "@prisma/client";
|
||||
import { FileNotary } from "le-coffre-resources/dist/Notary";
|
||||
|
||||
@Service()
|
||||
export default class FilesNotaryRepository extends BaseRepository {
|
||||
constructor(private database: Database) {
|
||||
super();
|
||||
}
|
||||
protected get model() {
|
||||
return this.database.getClient().filesNotary;
|
||||
}
|
||||
protected get instanceDb() {
|
||||
return this.database.getClient();
|
||||
}
|
||||
|
||||
/**
|
||||
* @description : Find many files
|
||||
*/
|
||||
public async findMany(query: Prisma.FilesNotaryFindManyArgs) {
|
||||
query.take = Math.min(query.take || this.defaultFetchRows, this.maxFetchRows);
|
||||
return this.model.findMany(query);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description : Create a file linked to a document
|
||||
*/
|
||||
public async create(file: FileNotary, key: string): Promise<FilesNotary> {
|
||||
const createArgs: Prisma.FilesNotaryCreateArgs = {
|
||||
data: {
|
||||
document_notary: {
|
||||
connect: {
|
||||
uid: file.document!.uid,
|
||||
},
|
||||
},
|
||||
file_name: file.file_name,
|
||||
file_path: file.file_path,
|
||||
mimetype: file.mimetype,
|
||||
hash: file.hash,
|
||||
size: file.size,
|
||||
key: key,
|
||||
},
|
||||
};
|
||||
return this.model.create({ ...createArgs, include: { document_notary: true } });
|
||||
}
|
||||
|
||||
/**
|
||||
* @description : Find unique file
|
||||
*/
|
||||
public async findOneByUid(uid: string, query?: Prisma.FilesNotaryInclude) {
|
||||
return this.model.findUnique({
|
||||
where: {
|
||||
uid: uid,
|
||||
},
|
||||
include: query,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @description : Find unique file with office
|
||||
*/
|
||||
public async findOneByUidWithOffice(uid: string) {
|
||||
return this.model.findUnique({
|
||||
where: {
|
||||
uid: uid,
|
||||
},
|
||||
include: { document_notary: { include: { folder: { include: { office: true } } } } },
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @description : Find unique file with document
|
||||
*/
|
||||
public async findOneByUidWithDocument(uid: string) {
|
||||
return this.model.findUnique({
|
||||
where: {
|
||||
uid: uid,
|
||||
},
|
||||
include: { document_notary: true },
|
||||
});
|
||||
}
|
||||
}
|
90
src/services/common/FilesNotaryService/FilesNotaryService.ts
Normal file
90
src/services/common/FilesNotaryService/FilesNotaryService.ts
Normal file
@ -0,0 +1,90 @@
|
||||
import { BackendVariables } from "@Common/config/variables/Variables";
|
||||
import { Prisma } from "@prisma/client";
|
||||
import FilesNotaryRepository from "@Repositories/FilesNotaryRepository";
|
||||
import FilesRepository from "@Repositories/FilesRepository";
|
||||
import BaseService from "@Services/BaseService";
|
||||
import { FileNotary } from "le-coffre-resources/dist/Notary";
|
||||
import { Readable } from "stream";
|
||||
import { Service } from "typedi";
|
||||
import { v4 } from "uuid";
|
||||
|
||||
import CryptoService from "../CryptoService/CryptoService";
|
||||
import IpfsService from "../IpfsService/IpfsService";
|
||||
|
||||
@Service()
|
||||
export default class FilesNotaryService extends BaseService {
|
||||
constructor(
|
||||
private filesRepository: FilesRepository,
|
||||
private ipfsService: IpfsService,
|
||||
private variables: BackendVariables,
|
||||
private cryptoService: CryptoService,
|
||||
private filesNotaryRepository: FilesNotaryRepository,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* @description : Get all files
|
||||
* @throws {Error} If files cannot be ge
|
||||
*/
|
||||
public async get(query: Prisma.FilesFindManyArgs) {
|
||||
return this.filesRepository.findMany(query);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description : Get a file by uid
|
||||
* @throws {Error} If project cannot be created
|
||||
*/
|
||||
public async getByUid(uid: string) {
|
||||
return this.filesNotaryRepository.findOneByUid(uid);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description : Get a file by uid with office
|
||||
* @throws {Error} If project cannot be created
|
||||
*/
|
||||
public async getByUidWithOffice(uid: string) {
|
||||
return this.filesNotaryRepository.findOneByUidWithOffice(uid);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description : Get a file by uid with document
|
||||
* @throws {Error} If project cannot be created
|
||||
*/
|
||||
public async getByUidWithDocument(uid: string) {
|
||||
return this.filesNotaryRepository.findOneByUidWithDocument(uid);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description : view a file
|
||||
* @throws {Error} If file cannot be deleted
|
||||
*/
|
||||
public async download(uid: string) {
|
||||
const file = await this.filesNotaryRepository.findOneByUid(uid);
|
||||
if (!file?.key) return null;
|
||||
const fileResult = await fetch(file.file_path.concat("?pinataGatewayToken=").concat(this.variables.PINATA_GATEWAY_TOKEN));
|
||||
const fileArrayBuffer = await fileResult.arrayBuffer();
|
||||
return { file: file, buffer: await this.cryptoService.decrypt(Buffer.from(fileArrayBuffer), file.key) };
|
||||
}
|
||||
|
||||
/**
|
||||
* @description : Create a new file
|
||||
* @throws {Error} If file cannot be created
|
||||
*/
|
||||
public async create(file: FileNotary, fileData: Express.Multer.File) {
|
||||
const key = v4();
|
||||
const encryptedFile = await this.cryptoService.encrypt(fileData.buffer, key);
|
||||
const hash = await this.cryptoService.getHash(fileData.buffer);
|
||||
|
||||
const upload = await this.ipfsService.pinFile(Readable.from(encryptedFile), fileData.originalname);
|
||||
let fileToCreate: FileNotary = file;
|
||||
fileToCreate.file_name = fileData.originalname;
|
||||
fileToCreate.file_path = this.variables.PINATA_GATEWAY.concat(upload.IpfsHash);
|
||||
fileToCreate.mimetype = fileData.mimetype;
|
||||
fileToCreate.size = fileData.size;
|
||||
fileToCreate.hash = hash;
|
||||
fileToCreate.archived_at = null;
|
||||
|
||||
return this.filesNotaryRepository.create(fileToCreate, key);
|
||||
}
|
||||
}
|
@ -1,13 +1,14 @@
|
||||
import { BackendVariables } from "@Common/config/variables/Variables";
|
||||
import { Files, Prisma } from "@prisma/client";
|
||||
import FilesRepository from "@Repositories/FilesRepository";
|
||||
import BaseService from "@Services/BaseService";
|
||||
import { Service } from "typedi";
|
||||
import { File } from "le-coffre-resources/dist/SuperAdmin";
|
||||
import { Readable } from "stream";
|
||||
import { Service } from "typedi";
|
||||
import { v4 } from "uuid";
|
||||
|
||||
import CryptoService from "../CryptoService/CryptoService";
|
||||
import IpfsService from "../IpfsService/IpfsService";
|
||||
import { BackendVariables } from "@Common/config/variables/Variables";
|
||||
import { Readable } from "stream";
|
||||
import { v4 } from "uuid";
|
||||
import { Files, Prisma } from "@prisma/client";
|
||||
|
||||
@Service()
|
||||
export default class FilesService extends BaseService {
|
||||
|
@ -113,24 +113,22 @@ export default class IdNotService extends BaseService {
|
||||
super();
|
||||
}
|
||||
|
||||
public async getIdNotToken(code: string) {
|
||||
public async getIdNotToken(code: string) {
|
||||
const query = new URLSearchParams({
|
||||
client_id: this.variables.IDNOT_CLIENT_ID,
|
||||
client_secret: this.variables.IDNOT_CLIENT_SECRET,
|
||||
redirect_uri: this.variables.IDNOT_REDIRECT_URL,
|
||||
code: code,
|
||||
grant_type: "authorization_code",
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
const token = await fetch(this.variables.IDNOT_BASE_URL + this.variables.IDNOT_CONNEXION_URL + "?" + query, { method: "POST" });
|
||||
|
||||
if(token.status !== 200) console.error(await token.text());
|
||||
|
||||
|
||||
if (token.status !== 200) console.error(await token.text());
|
||||
|
||||
const decodedToken = (await token.json()) as IIdNotToken;
|
||||
|
||||
|
||||
const decodedIdToken = jwt.decode(decodedToken.id_token) as IdNotJwtPayload;
|
||||
|
||||
|
||||
const decodedIdToken = jwt.decode(decodedToken.id_token) as IdNotJwtPayload;
|
||||
|
||||
return decodedIdToken;
|
||||
}
|
||||
@ -178,7 +176,7 @@ export default class IdNotService extends BaseService {
|
||||
}
|
||||
|
||||
public async getOfficeMemberships(officeId: string) {
|
||||
const officeInfos = await this.officeService.getByUid(officeId);
|
||||
const officeInfos = await this.officeService.getByUid(officeId);
|
||||
const office = Office.hydrate<Office>(officeInfos!);
|
||||
const searchParams = new URLSearchParams({
|
||||
key: this.variables.IDNOT_API_KEY,
|
||||
@ -187,7 +185,7 @@ export default class IdNotService extends BaseService {
|
||||
await fetch(`${this.variables.IDNOT_API_BASE_URL}/api/pp/v2/entites/${office.idNot}/personnes?` + searchParams, {
|
||||
method: "GET",
|
||||
})
|
||||
).json()) as any;
|
||||
).json()) as any;
|
||||
}
|
||||
|
||||
public getOfficeStatus(statusName: string) {
|
||||
@ -291,13 +289,13 @@ export default class IdNotService extends BaseService {
|
||||
await this.userService.updateCheckedAt(user.uid!);
|
||||
}
|
||||
|
||||
public async updateOffice(officeId: string) {
|
||||
public async updateOffice(officeId: string) {
|
||||
const officeInfos = await this.officeService.getByUid(officeId);
|
||||
const office = Office.hydrate<Office>(officeInfos!);
|
||||
const searchParams = new URLSearchParams({
|
||||
key: this.variables.IDNOT_API_KEY,
|
||||
});
|
||||
const officeRawData = await fetch(`${this.variables.IDNOT_API_BASE_URL}/api/pp/v2/entities/${office.idNot}?` + searchParams, {
|
||||
const officeRawData = await fetch(`${this.variables.IDNOT_API_BASE_URL}/api/pp/v2/entites/${office.idNot}?` + searchParams, {
|
||||
method: "GET",
|
||||
});
|
||||
if (officeRawData.status === 404) {
|
||||
@ -339,7 +337,7 @@ export default class IdNotService extends BaseService {
|
||||
const officeLocationData = (await (
|
||||
await fetch(`${this.variables.IDNOT_API_BASE_URL + userData.entite.locationsUrl}?` + searchParams, { method: "GET" })
|
||||
).json()) as IOfficeLocation;
|
||||
|
||||
|
||||
const office = await this.officeService.get({ where: { idNot: decodedToken.entity_idn } });
|
||||
|
||||
// if(officeLocationData.result[0]!.adrGeoCodePostal.slice(0,2) !== "35") {
|
||||
@ -378,17 +376,17 @@ export default class IdNotService extends BaseService {
|
||||
},
|
||||
};
|
||||
|
||||
if(!userToAdd.contact.email) {
|
||||
if (!userToAdd.contact.email) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
let userHydrated = User.hydrate<User>(userToAdd);
|
||||
const user = await this.userService.create(userHydrated);
|
||||
const userOffice = await this.officeService.getByUid(user.office_uid);
|
||||
userHydrated = User.hydrate<User>(user);
|
||||
const userOfficeHydrated = Office.hydrate<Office>(userOffice!);
|
||||
|
||||
if(office.length === 0) {
|
||||
if (office.length === 0) {
|
||||
const officeRoles = await this.officeRolesService.get({
|
||||
where: { office: { idNot: "0000" } },
|
||||
include: { office: true, rules: true },
|
||||
@ -401,17 +399,16 @@ export default class IdNotService extends BaseService {
|
||||
where: { office: { idNot: "0000" } },
|
||||
include: { office: true },
|
||||
});
|
||||
|
||||
|
||||
const officeRolesHydrated = OfficeRole.hydrateArray<OfficeRole>(officeRoles);
|
||||
const deedTypesHydrated = DeedType.hydrateArray<DeedType>(deedTypes);
|
||||
const documentTypesHydrated = DocumentType.hydrateArray<DocumentType>(documentTypes);
|
||||
|
||||
|
||||
|
||||
await this.duplicateOfficeRoles(officeRolesHydrated, userOfficeHydrated);
|
||||
const documentTypesCreated = await this.duplicateDocumentTypes(documentTypesHydrated, userOfficeHydrated);
|
||||
await this.duplicateDeedTypes(deedTypesHydrated, documentTypesCreated, userOfficeHydrated);
|
||||
}
|
||||
|
||||
|
||||
const officeRole = await this.getOfficeRole(userData.typeLien.name, user.office_uid);
|
||||
|
||||
if (officeRole) {
|
||||
@ -427,37 +424,35 @@ export default class IdNotService extends BaseService {
|
||||
|
||||
public async duplicateDocumentTypes(documentTypes: DocumentType[], office: Office): Promise<DocumentType[]> {
|
||||
let newDocumentTypes: DocumentType[] = [];
|
||||
for(const documentType of documentTypes) {
|
||||
for (const documentType of documentTypes) {
|
||||
documentType.office = office;
|
||||
const documentTypeCreated = await this.documentTypesService.create(documentType);
|
||||
newDocumentTypes.push(DocumentType.hydrate<DocumentType>(documentTypeCreated));
|
||||
};
|
||||
}
|
||||
return newDocumentTypes;
|
||||
}
|
||||
|
||||
public async duplicateDeedTypes(deedTypes: DeedType[], documentTypes: DocumentType[], office: Office) {
|
||||
for (const deedType of deedTypes) {
|
||||
for (const deedType of deedTypes) {
|
||||
let newDocumentTypes: DocumentType[] = [];
|
||||
for (const document of deedType.document_types!) {
|
||||
for (const document of deedType.document_types!) {
|
||||
const newDocumentType = documentTypes.find((documentType) => documentType.name === document.name);
|
||||
if(!newDocumentType) continue;
|
||||
if (!newDocumentType) continue;
|
||||
newDocumentTypes.push(newDocumentType!);
|
||||
};
|
||||
}
|
||||
deedType.document_types = newDocumentTypes;
|
||||
deedType.office = office;
|
||||
await this.deedTypesService.create(deedType);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public async duplicateOfficeRoles(officeRoles: OfficeRole[], office: Office){
|
||||
for(const officeRole of officeRoles) {
|
||||
public async duplicateOfficeRoles(officeRoles: OfficeRole[], office: Office) {
|
||||
for (const officeRole of officeRoles) {
|
||||
officeRole.office = office;
|
||||
await this.officeRolesService.create(officeRole);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public async updateUsers() {
|
||||
const usersReq = await this.userService.getUsersToBeChecked();
|
||||
const users = User.hydrateArray<User>(usersReq);
|
||||
|
@ -1,12 +1,14 @@
|
||||
import { Customers, Prisma } from "@prisma/client";
|
||||
import EmailBuilder from "@Common/emails/EmailBuilder";
|
||||
import { Customers, Documents, Prisma } from "@prisma/client";
|
||||
import CustomersRepository from "@Repositories/CustomersRepository";
|
||||
import BaseService from "@Services/BaseService";
|
||||
import { Customer } from "le-coffre-resources/dist/Notary";
|
||||
import { Customer, DocumentReminder } from "le-coffre-resources/dist/Notary";
|
||||
import { Service } from "typedi";
|
||||
import DocumentsReminderService from "../DocumentsReminder/DocumentsReminder";
|
||||
|
||||
@Service()
|
||||
export default class CustomersService extends BaseService {
|
||||
constructor(private customerRepository: CustomersRepository) {
|
||||
constructor(private customerRepository: CustomersRepository, private emailBuilder: EmailBuilder, private documentsReminderService : DocumentsReminderService) {
|
||||
super();
|
||||
}
|
||||
|
||||
@ -49,4 +51,17 @@ export default class CustomersService extends BaseService {
|
||||
public async getByContact(contactUid: string): Promise<Customers | null> {
|
||||
return this.customerRepository.findOneByContact(contactUid);
|
||||
}
|
||||
|
||||
public async sendDocumentsReminder(customer: Customer, documents: Documents[]): Promise<void> {
|
||||
//Call email builder to send mail
|
||||
const email = this.emailBuilder.sendReminder(customer, documents);
|
||||
//Call DocumentsReminder service to create add the reminder in database
|
||||
if (!email) return;
|
||||
for (const document of documents) {
|
||||
//Create document reminder
|
||||
const documentReminder = new DocumentReminder();
|
||||
documentReminder.document = document;
|
||||
await this.documentsReminderService.create(documentReminder);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,61 @@
|
||||
import { DocumentsNotary, Prisma } from "@prisma/client";
|
||||
import { Document, DocumentNotary } from "le-coffre-resources/dist/Notary";
|
||||
import DocumentsNotaryRepository from "@Repositories/DocumentsNotaryRepository";
|
||||
import BaseService from "@Services/BaseService";
|
||||
import { Service } from "typedi";
|
||||
|
||||
@Service()
|
||||
export default class DocumentsService extends BaseService {
|
||||
constructor(private documentsNotaryRepository: DocumentsNotaryRepository) {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* @description : Get all documents
|
||||
* @throws {Error} If documents cannot be get
|
||||
*/
|
||||
public async get(query: Prisma.DocumentsNotaryFindManyArgs) {
|
||||
return this.documentsNotaryRepository.findMany(query);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description : Create a new document
|
||||
* @throws {Error} If document cannot be created
|
||||
*/
|
||||
public async create(document: DocumentNotary): Promise<DocumentsNotary> {
|
||||
return this.documentsNotaryRepository.create(document);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description : Delete a document
|
||||
* @throws {Error} If document cannot be deleted
|
||||
*/
|
||||
public async delete(uid: string): Promise<DocumentsNotary> {
|
||||
const documentEntity = await this.documentsNotaryRepository.findOneByUid(uid, { files: true });
|
||||
if (!documentEntity) throw new Error("document not found");
|
||||
const document = Document.hydrate<Document>(documentEntity, { strategy: "excludeAll" });
|
||||
|
||||
const isDocumentEmpty = document.files && !document!.files.find((file) => file.archived_at === null);
|
||||
|
||||
if (!isDocumentEmpty && document.document_status !== "REFUSED") {
|
||||
throw new Error("Can't delete a document with file");
|
||||
}
|
||||
return this.documentsNotaryRepository.delete(uid);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description : Get a document by uid
|
||||
* @throws {Error} If document cannot be get by uid
|
||||
*/
|
||||
public async getByUid(uid: string, query?: Prisma.DocumentsNotaryInclude): Promise<DocumentsNotary | null> {
|
||||
return this.documentsNotaryRepository.findOneByUid(uid, query);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description : Get a document by uid
|
||||
* @throws {Error} If document cannot be get by uid
|
||||
*/
|
||||
public async getByUidWithOffice(uid: string) {
|
||||
return this.documentsNotaryRepository.findOneByUidWithOffice(uid);
|
||||
}
|
||||
}
|
28
src/services/notary/DocumentsReminder/DocumentsReminder.ts
Normal file
28
src/services/notary/DocumentsReminder/DocumentsReminder.ts
Normal file
@ -0,0 +1,28 @@
|
||||
import { DocumentsReminder, Prisma } from "@prisma/client";
|
||||
import { DocumentReminder } from "le-coffre-resources/dist/Notary";
|
||||
import BaseService from "@Services/BaseService";
|
||||
import { Service } from "typedi";
|
||||
import DocumentsReminderRepository from "@Repositories/DocumentsReminderRepository";
|
||||
|
||||
@Service()
|
||||
export default class DocumentsReminderService extends BaseService {
|
||||
constructor(private documentsReminderRepository: DocumentsReminderRepository) {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* @description : Get all documents
|
||||
* @throws {Error} If documents cannot be get
|
||||
*/
|
||||
public async get(query: Prisma.DocumentsReminderFindManyArgs) {
|
||||
return this.documentsReminderRepository.findMany(query);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description : Create a new document
|
||||
* @throws {Error} If document cannot be created
|
||||
*/
|
||||
public async create(document: DocumentReminder): Promise<DocumentsReminder> {
|
||||
return this.documentsReminderRepository.create(document);
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user