merge dev in staging (#23)

This commit is contained in:
Arnaud D. Natali 2023-04-28 13:41:54 +02:00 committed by GitHub
commit 4c9b1b3b6e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
98 changed files with 12787 additions and 0 deletions

69
.circleci/config.yml Normal file
View File

@ -0,0 +1,69 @@
version: 2.1
orbs:
kubernetes: circleci/kubernetes@1.0.0
helm: circleci/helm@2.0.1
jobs:
build-push-docker-image:
docker:
- image: cimg/base:stable
environment:
TAG: << pipeline.git.tag >>
steps:
- checkout
- add_ssh_keys:
fingerprints:
- "4c:8e:00:16:94:44:d9:ad:e9:e9:2c:8b:02:d4:8d:7a"
- run: cp $HOME/.ssh/id_rsa_4c8e00169444d9ade9e92c8b02d48d7a id_rsa
- setup_remote_docker:
version: 20.10.12
docker_layer_caching: true
- run: docker login rg.fr-par.scw.cloud/lecoffre -u nologin -p $SCW_SECRET_KEY
- run: docker build --tag rg.fr-par.scw.cloud/lecoffre/back:$TAG .
- run: docker push rg.fr-par.scw.cloud/lecoffre/back:$TAG
deploy-docker-image:
docker:
- image: cimg/base:stable
environment:
TAG: << pipeline.git.tag >>
steps:
- checkout
- kubernetes/install-kubeconfig:
kubeconfig: KUBECONFIG_DATA
- helm/install-helm-client
- run:
name: Deploy
command: >
helm upgrade
lecoffre-back devops/ -i -f devops/values.yaml
-n lecoffre
--create-namespace
--set lecoffreBack.image.repository='rg.fr-par.scw.cloud/lecoffre/back'
--set lecoffreBack.image.tag=$TAG
workflows:
version: 2
build-and-register:
jobs:
- build-push-docker-image:
filters:
tags:
only: /^v.*/
branches:
ignore: /.*/
- deploy-docker-image:
requires:
- build-push-docker-image
context:
- staging
filters:
tags:
only: /^v.*/
branches:
ignore: /.*/

7
.env.example Normal file
View File

@ -0,0 +1,7 @@
WEB_LABEL=Web
WEB_PORT=3000
WEB_ROOT_URL=/
API_LABEL=Api
API_PORT=3001
API_ROOT_URL=/api/v1

7
.env.test Normal file
View File

@ -0,0 +1,7 @@
DATABASE_URL="postgresql://prisma:prisma@localhost:5433/tests"
DATABASE_PORT="5433"
DATABASE_USER="prisma"
DATABASE_PASSWORD="prisma"
DATABASE_NAME="tests"
DATABASE_HOSTNAME="localhost"
DEV_PRISMA_STUDIO_DB_URL="postgresql://prisma:prisma@localhost:5433/tests"

29
.gitignore vendored
View File

@ -1,3 +1,31 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
dist
.next
# dependencies
/node_modules
# envs
.env
# misc
.DS_Store
*.pem
# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.pnpm-debug.log*
# local env files
.env*.local
# typescript
*.tsbuildinfo
dist
dist-*
cabal-dev
@ -21,3 +49,4 @@ cabal.project.local
cabal.project.local~
.HTF/
.ghc.environment.*
id_rsa

44
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,44 @@
{
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnSave": false,
"[typescript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[typescriptreact]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[json]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[jsonc]": {
"editor.defaultFormatter": "vscode.json-language-features"
},
"[javascript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[scss]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"terminal.integrated.env.linux": {
"PATH": "${env:HOME}/elrondsdk/vendor-rust/bin:${env:HOME}/elrondsdk/erdpy-venv/bin:${env:HOME}/elrondsdk/vmtools:${env:HOME}/elrondsdk/nodejs/latest/bin:${env:PATH}",
"VIRTUAL_ENV": "${env:HOME}/elrondsdk/erdpy-venv",
"RUSTUP_HOME": "${env:HOME}/elrondsdk/vendor-rust",
"CARGO_HOME": "${env:HOME}/elrondsdk/vendor-rust"
},
"terminal.integrated.env.osx": {
"PATH": "${env:HOME}/elrondsdk/vendor-rust/bin:${env:HOME}/elrondsdk/erdpy-venv/bin:${env:HOME}/elrondsdk/vmtools:${env:HOME}/elrondsdk/nodejs/latest/bin:${env:PATH}",
"VIRTUAL_ENV": "${env:HOME}/elrondsdk/erdpy-venv",
"RUSTUP_HOME": "${env:HOME}/elrondsdk/vendor-rust",
"CARGO_HOME": "${env:HOME}/elrondsdk/vendor-rust"
},
"terminal.integrated.environmentChangesIndicator": "on",
"terminal.integrated.inheritEnv": true,
"workbench.dialogs.customEnabled": true,
"rust-client.rustupPath": "${env:HOME}/elrondsdk/vendor-rust/bin/rustup",
"rust-client.rlsPath": "${env:HOME}/elrondsdk/vendor-rust/bin/rls",
"rust-client.disableRustup": true,
"rust-client.autoStartRls": false,
"[prisma]": {
"editor.defaultFormatter": "Prisma.prisma"
}
}

46
Dockerfile Normal file
View File

@ -0,0 +1,46 @@
# Install dependencies only when needed
FROM node:19-alpine AS deps
WORKDIR leCoffre
RUN npm install -D prisma@4.11.0
COPY package.json ./
RUN apk update && apk add openssh-client git
COPY id_rsa /root/.ssh/id_rsa
RUN chmod 600 ~/.ssh/id_rsa
RUN eval "$(ssh-agent -s)" && ssh-add /root/.ssh/id_rsa
RUN ssh-keyscan github.com smart-chain-fr/leCoffre-resources.git >> /root/.ssh/known_hosts
RUN npm install --frozen-lockfile
# Rebuild the source code only when needed
FROM node:19-alpine AS builder
WORKDIR leCoffre
COPY --from=deps leCoffre/node_modules ./node_modules
COPY --from=deps leCoffre/package.json package.json
COPY tsconfig.json tsconfig.json
COPY src src
RUN npx prisma generate
RUN npm run build
# Production image, copy all the files and run next
FROM node:19-alpine AS production
WORKDIR leCoffre
RUN adduser -D lecoffreuser --uid 10000 && chown -R 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
USER lecoffreuser
CMD ["npm", "run", "api:start"]
EXPOSE 3001

View File

@ -1,2 +1,34 @@
# leCoffre
[Owner: Elise Hautefaye]
### A. Docker Launch application
#### 1) Local RSA Key for docker build
1) Create a file named : `id_rsa` in /src/.ssh
2) Get the RSA Private key on Keeper who is allowed to read the `leCoffre-ressources repo`
3) You can find Key on Keeper inside the folder **LeCoffre project > SSH Key**
4) Copy past in the `id_rsa` that you created step 1
:rotating_light: **Be aware to have the id_rsa included in your .gitignore! This ssh shouldn't be push on github**
> You need to do the same task in the front and back repo.
#### 2) Build images
###### a- Back end
`docker build -t "le-coffre-back" -f Dockerfile .`
###### b- Front end
`docker build -t "le-coffre-front" -f Dockerfile .`
#### 3) Docker Compose
Docker compose allow to launch multiples images
1) **le-coffre-front**
2) **le-coffre-back**
3) **postgres**
> Launch your docker container with following command :
`docker compose up` -> Logs in terminal
`docker compose up -d`

23
devops/.helmignore Normal file
View File

@ -0,0 +1,23 @@
# Patterns to ignore when building packages.
# This supports shell glob matching, relative path matching, and
# negation (prefixed with !). Only one pattern per line.
.DS_Store
# Common VCS dirs
.git/
.gitignore
.bzr/
.bzrignore
.hg/
.hgignore
.svn/
# Common backup files
*.swp
*.bak
*.tmp
*.orig
*~
# Various IDEs
.project
.idea/
*.tmproj
.vscode/

25
devops/Chart.yaml Normal file
View File

@ -0,0 +1,25 @@
apiVersion: v2
name: leCoffre-back
description: A Helm chart for Kubernetes
# A chart can be either an 'application' or a 'library' chart.
#
# Application charts are a collection of templates that can be packaged into versioned archives
# to be deployed.
#
# Library charts provide useful utilities or functions for the chart developer. They're included as
# a dependency of application charts to inject those utilities and functions into the rendering
# pipeline. Library charts do not define any templates and therefore cannot be deployed.
type: application
# This is the chart version. This version number should be incremented each time you make changes
# to the chart and its templates, including the app version.
# Versions are expected to follow Semantic Versioning (https://semver.org/)
version: 0.0.1
# This is the version number of the application being deployed. This version number should be
# incremented each time you make changes to the application. Versions are not expected to
# follow Semantic Versioning. They should reflect the version the application is using.
# It is recommended to use it with quotes.
appVersion: 0.5.6

View File

@ -0,0 +1,19 @@
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: docker-pull-secret
spec:
refreshInterval: 1h
secretStoreRef:
name: dockerpullsecret-vault-cluster-secret-store
kind: ClusterSecretStore
target:
template:
type: kubernetes.io/dockerconfigjson
name: docker-pull-secret
creationPolicy: Owner
data:
- secretKey: .dockerconfigjson
remoteRef:
key: {{ .Values.dockerPullSecret }}
property: .dockerconfigjson

View File

@ -0,0 +1,71 @@
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: lecoffre-back
namespace: {{ .Values.namespace }}
{{if .Values.lecoffreBack.ingress.annotations}}
annotations:
{{toYaml .Values.lecoffreBack.ingress.annotations | indent 4 }}
{{end}}
spec:
tls:
- hosts: {{ .Values.lecoffreBack.ingress.tls.hosts }}
secretName: {{ .Values.lecoffreBack.ingress.tls.secretName }}
rules:
- host: {{ .Values.lecoffreBack.ingress.host }}
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: lecoffre-back-svc
port:
number: 80
---
apiVersion: v1
kind: Service
metadata:
name: lecoffre-back-svc
namespace: {{ .Values.namespace }}
labels:
spec:
ports:
- port: 80
name: http
targetPort: 3001
selector:
app: lecoffre-back
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: lecoffre-back
namespace: {{ .Values.namespace }}
labels:
app: lecoffre-back
spec:
replicas: 1
selector:
matchLabels:
app: lecoffre-back
template:
metadata:
annotations:
{{toYaml .Values.lecoffreBack.vault.annotations | indent 8 }}
labels:
app: lecoffre-back
spec:
serviceAccountName: {{ .Values.lecoffreBack.serviceAccountName }}
imagePullSecrets:
- name: docker-pull-secret
containers:
- name: lecoffre-back
image: "{{ .Values.lecoffreBack.image.repository }}:v{{ .Chart.AppVersion }}"
{{if .Values.lecoffreBack.resources}}
resources:
{{toYaml .Values.lecoffreBack.resources | indent 10}}
{{end}}
imagePullPolicy: {{ .Values.lecoffreBack.image.pullPolicy }}
command: [{{ .Values.lecoffreBack.command }}]

View File

@ -0,0 +1,14 @@
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ .Values.lecoffreBack.serviceAccountName }}
---
apiVersion: v1
kind: Secret
metadata:
name: {{ .Values.lecoffreBack.serviceAccountName }}-token
annotations:
kubernetes.io/service-account.name: {{ .Values.lecoffreBack.serviceAccountName }}
type: kubernetes.io/service-account-token

44
devops/values.yaml Normal file
View File

@ -0,0 +1,44 @@
dockerPullSecret: secret/data/minteed-stg/config/dockerpullsecret
namespace: lecoffre
lecoffreBack:
serviceAccountName: lecoffre-back-sa
command: "'sh', '-c', '. /vault/secrets/envs-api && npm run api:start'"
vault:
role : custom_lecoffre-back_injector_rol
server: https://vault-stg.smart-chain.fr
annotations:
vault.hashicorp.com/agent-pre-populate-only: "true"
vault.hashicorp.com/agent-inject: "true"
vault.hashicorp.com/agent-inject-secret-envs-api: secret/data/lecoffre-back-stg/config/envs-api
vault.hashicorp.com/role: custom_lecoffre-back_injector_rol
vault.hashicorp.com/agent-inject-template-envs-api: |
{{ with secret "secret/data/lecoffre-back-stg/config/envs-api" }}
{{ range $k, $v := .Data.data }}
export {{ $k }}="{{ $v }}"
{{ end }}
{{ end }}
imagePullSecrets:
- name: docker-pull-secret
image:
pullPolicy: Always
repository: "rg.fr-par.scw.cloud/lecoffre/back"
resources:
requests:
cpu: 200m
memory: 1Gi
limits:
memory: 2Gi
ingress:
host: api.stg.lecoffre.smart-chain.fr
tls:
hosts:
- api.stg.lecoffre.smart-chain.fr
secretName: api-tls
annotations:
kubernetes.io/ingress.class: nginx
cert-manager.io/cluster-issuer: letsencrypt-prod
nginx.ingress.kubernetes.io/from-to-www-redirect: "true"
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"

12
docker-compose-test.yml Normal file
View File

@ -0,0 +1,12 @@
version: "3.8"
services:
db:
image: postgres:13
restart: always
container_name: integration-tests-prisma
ports:
- '5433:5432'
environment:
POSTGRES_USER: prisma
POSTGRES_PASSWORD: prisma
POSTGRES_DB: tests

67
docker-compose.yml Normal file
View File

@ -0,0 +1,67 @@
version: "3.8"
volumes:
db_storage:
services:
front-end:
image: "le-coffre-front"
ports:
- ${FRONT_PORT}:${FRONT_PORT}
environment:
- FRONT_PORT
- BACK_API_PROTOCOL
- BACK_API_HOST
- BACK_API_PORT
- BACK_API_ROOT_URL
- BACK_API_VERSION
- FRONT_APP_HOST
- FRONT_APP_PORT
- IDNOT_AUTHORIZE_ENDPOINT
- IDNOT_CLIENT_ID
backend:
image: "le-coffre-back"
ports:
- ${APP_PORT}:${APP_PORT}
environment:
- DATABASE_HOST
- DATABASE_PORT
- DATABASE_USERNAME
- DATABASE_PASSWORD
- DATABASE_NAME
- APP_LABEL
- APP_PORT
- APP_ROOT_URL
- API_ROOT_URL
- DEV_PRISMA_STUDIO_DB_URL
- IDNOT_CONNEXION_URL
- IDNOT_CLIENT_ID
- IDNOT_CLIENT_SECRET
- IDNOT_REDIRECT_URL
postgres:
image: postgres:11
restart: always
environment:
- POSTGRES_USER
- POSTGRES_PASSWORD
- POSTGRES_DB
- DATABASE_USERNAME
- DATABASE_PASSWORD
- DATABASE_NAME=${DATABASE_NAME}
ports:
- ${DATABASE_PORT}:5432
volumes:
- db_storage:/var/lib/postgresql/data
- ./init-data.sh:/docker-entrypoint-initdb.d/init-data.sh
healthcheck:
test:
[
"CMD-SHELL",
"pg_isready -h localhost -U ${POSTGRES_USER} -d ${POSTGRES_DB}",
]
interval: 5s
timeout: 5s
retries: 10

16
init-data.sh Executable file
View File

@ -0,0 +1,16 @@
#!/bin/bash
set -e;
# Make sure this script doesn't encounter any errors while building the docker container for the first time
# Carriage returns might be a problem (the first line #!/bin/bash will create an error)
# On Windows Docker Desktop i had to use the following command (in linux env):
# $ sed -i -e 's/\r$//' init-data.sh
if [ -n "${DATABASE_USERNAME:-}" ] && [ -n "${DATABASE_PASSWORD:-}" ]; then
psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL
CREATE USER ${DATABASE_USERNAME} WITH PASSWORD '${DATABASE_PASSWORD}';
ALTER USER ${DATABASE_USERNAME} CREATEDB;
EOSQL
else
echo "SETUP INFO: No Environment variables given!"
fi

19
jest.config.js Normal file
View File

@ -0,0 +1,19 @@
/** @type {import('ts-jest').JestConfigWithTsJest} */
module.exports = {
preset: 'ts-jest',
testEnvironment: 'node',
"moduleNameMapper": {
"@Services/(.*)": "<rootDir>/src/services/$1",
"@App/(.*)": "<rootDir>/src/app/$1",
"@Api/(.*)": "<rootDir>/src/app/api/$1",
"@Pages/(.*)": "<rootDir>/src/pages/$1",
"@Common/(.*)": "<rootDir>/src/common/$1",
"@Repositories/(.*)": "<rootDir>/src/common/repositories/$1",
"@Entries/(.*)": "<rootDir>/src/common/entries/$1",
"@Config/(.*)": "<rootDir>/src/common/config/$1",
"@Entities/(.*)": "<rootDir>/src/common/entities/$1",
"@System/(.*)": "<rootDir>/src/common/system/$1",
"@ControllerPattern/(.*)": "<rootDir>/src/common/system/controller-pattern/$1",
"@Test/(.*)": "<rootDir>/src/test/$1"
}
};

5
nodemon.json Normal file
View File

@ -0,0 +1,5 @@
{
"watch": ["./src/", "./.env", "./package.json", "./tsconfig.json"],
"exec": "npm run start",
"ext": "ts"
}

5341
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

81
package.json Normal file
View File

@ -0,0 +1,81 @@
{
"name": "lecoffre-back",
"version": "1.0.0",
"description": "lecoffre project",
"_moduleAliases": {
"@App": "./dist/app",
"@Api": "./dist/app/api",
"@Pages": "./dist/pages",
"@Common": "./dist/common",
"@Services": "./dist/services",
"@Repositories": "./dist/common/repositories",
"@Entries": "./dist/common/entries",
"@Config": "./dist/common/config",
"@Entities": "./dist/common/entities",
"@System": "./dist/common/system",
"@ControllerPattern": "./dist/common/system/controller-pattern",
"@Test": "./dist/test"
},
"scripts": {
"build-db": "npx prisma migrate dev",
"build": "tsc",
"start": "tsc && node ./dist/entries/App.js",
"dev": "nodemon -V",
"build:test": "tsc && mocha ./dist/entries/Test.js",
"format": "prettier --write src",
"migrate:test": "dotenv -e .env.test -- npx prisma migrate deploy",
"docker:up:test": "docker-compose -f docker-compose-test.yml up -d",
"docker:down:test": "docker-compose down",
"test": "tsc && npm run docker:up:test && npm run migrate:test && dotenv -e .env.test -- jest -i --verbose ./dist/test/* && npm run docker:down:test"
},
"repository": {
"type": "git",
"url": "git+https://github.com/smart-chain-fr/leCoffre-back.git"
},
"author": "",
"license": "ISC",
"bugs": {
"url": "https://github.com/smart-chain-fr/leCoffre-back/issues"
},
"homepage": "https://github.com/smart-chain-fr/leCoffre-back#readme",
"dependencies": {
"@prisma/client": "^4.11.0",
"class-transformer": "^0.5.1",
"class-validator": "^0.14.0",
"classnames": "^2.3.2",
"cors": "^2.8.5",
"express": "^4.18.2",
"jsonwebtoken": "^9.0.0",
"le-coffre-resources": "git@github.com:smart-chain-fr/leCoffre-resources.git#v2.24",
"module-alias": "^2.2.2",
"next": "^13.1.5",
"node-cache": "^5.1.2",
"node-schedule": "^2.1.1",
"prisma-query": "^2.0.0",
"reflect-metadata": "^0.1.13",
"ts-node": "^10.9.1",
"tslib": "^2.4.1",
"typedi": "^0.10.0",
"typescript": "^4.9.4",
"uuid": "^9.0.0"
},
"devDependencies": {
"@types/cors": "^2.8.13",
"@types/express": "^4.17.16",
"@types/jest": "^29.5.0",
"@types/jsonwebtoken": "^9.0.1",
"@types/node": "^18.11.18",
"@types/node-schedule": "^2.1.0",
"@types/uuid": "^9.0.0",
"dotenv": "^16.0.3",
"jest": "^29.5.0",
"nodemon": "^2.0.20",
"prettier": "2.8.4",
"prisma": "^4.11.0",
"ts-jest": "^29.0.5"
},
"prisma": {
"schema": "src/common/databases/schema.prisma",
"seed": "ts-node src/common/databases/seeders/seeder.ts"
}
}

17
prettier.config.js Normal file
View File

@ -0,0 +1,17 @@
module.exports = {
overrides: [
{
files: ["src/**/*.ts", "src/**/*.tsx", "src/**/*.scss", "./*.js"],
options: {
tabWidth: 4,
useTabs: true,
singleQuote: false,
trailingComma: "all",
printWidth: 140,
semi: true,
bracketSameLine: true,
},
},
],
};

14
src/app/HomeController.ts Normal file
View File

@ -0,0 +1,14 @@
import { type Response, type Request } from "express";
import { Controller, Get } from "@ControllerPattern/index";
import { Service } from "typedi";
import ApiController from "@Common/system/controller-pattern/ApiController";
@Controller()
@Service()
export default class HomeController extends ApiController {
@Get("/")
protected async get(req: Request, res: Response) {
// const query = processFindManyQuery(req.query);
this.httpSuccess(res, "Welcome to the home page!");
}
}

View File

@ -0,0 +1,32 @@
import { Response, Request } from "express";
import { Controller,Post } from "@ControllerPattern/index";
import ApiController from "@Common/system/controller-pattern/ApiController";
import { Service } from "typedi";
import AuthService from "@Services/private-services/AuthService/AuthService";
//import User from "le-coffre-resources/dist/Notary";
@Controller()
@Service()
export default class UserInfoController extends ApiController {
constructor(private authService: AuthService) {
super();
}
/**
* @description Get user created from IdNot authentification
* @returns User
*/
@Post("/api/v1/idnot-user/:code")
protected async getUserInfosFromIdnot(req: Request, response: Response) {
try {
const code = req.params["code"];
const user = await this.authService.getUserFromIdNotTokens(code!);
//success
this.httpSuccess(response, user);
} catch (error) {
this.httpBadRequest(response, error);
return;
}
}
}

View File

@ -0,0 +1,133 @@
import { Response, Request } from "express";
import { Controller, Get, Post, Put } from "@ControllerPattern/index";
import ApiController from "@Common/system/controller-pattern/ApiController";
import CustomersService from "@Services/super-admin/CustomersService/CustomersService";
import { Service } from "typedi";
import ObjectHydrate from "@Common/helpers/ObjectHydrate";
import { Customer } from "le-coffre-resources/dist/SuperAdmin";
import { Customers } from "@prisma/client";
import { validateOrReject } from "class-validator";
@Controller()
@Service()
export default class CustomersController extends ApiController {
constructor(private customersService: CustomersService) {
super();
}
/**
* @description Get all customers
*/
@Get("/api/v1/super-admin/customers")
protected async get(req: Request, response: Response) {
try {
//get query
const query = JSON.parse(req.query["q"] as string);
//call service to get prisma entity
const customersEntity: Customers[] = await this.customersService.get(query);
//Hydrate ressource with prisma entity
const customers = ObjectHydrate.map<Customer>(Customer, customersEntity, { strategy: "exposeAll" });
//success
this.httpSuccess(response, customers);
} catch (error) {
this.httpBadRequest(response, error);
return;
}
}
/**
* @description Create a new customer
*/
@Post("/api/v1/super-admin/customers")
protected async post(req: Request, response: Response) {
try {
//init IUser resource with request body values
const customerEntity = new Customer();
ObjectHydrate.hydrate(customerEntity, req.body);
//validate user
await validateOrReject(customerEntity, { groups: ["create"] });
//call service to get prisma entity
const prismaEntityCreated = await this.customersService.create(customerEntity);
//Hydrate ressource with prisma entity
const customerEntityCreated = ObjectHydrate.hydrate<Customer>(new Customer(), prismaEntityCreated, {
strategy: "exposeAll",
});
//success
this.httpSuccess(response, customerEntityCreated);
} catch (error) {
this.httpBadRequest(response, error);
return;
}
}
/**
* @description Modify a specific customer by uid
*/
@Put("/api/v1/super-admin/customers/:uid")
protected async put(req: Request, response: Response) {
try {
const uid = req.params["uid"];
if (!uid) {
throw new Error("No uid provided");
}
//init IUser resource with request body values
const customerEntity = new Customer();
ObjectHydrate.hydrate(customerEntity, req.body);
//validate user
await validateOrReject(customerEntity, { groups: ["update"] });
//call service to get prisma entity
const prismaEntityUpdated = await this.customersService.update(uid, customerEntity);
//Hydrate ressource with prisma entity
const customerEntityUpdated = ObjectHydrate.hydrate<Customer>(new Customer(), prismaEntityUpdated, {
strategy: "exposeAll",
});
//success
this.httpSuccess(response, customerEntityUpdated);
} catch (error) {
this.httpBadRequest(response, error);
return;
}
}
/**
* @description Get a specific customer by uid
*/
@Get("/api/v1/super-admin/customers/:uid")
protected async getOneByUid(req: Request, response: Response) {
try {
const uid = req.params["uid"];
if (!uid) {
throw new Error("No uid provided");
}
let customerEntity: Customers;
//get query
if (req.query["q"]) {
const query = JSON.parse(req.query["q"] as string);
customerEntity = await this.customersService.getByUid(uid, query);
} else {
//call service to get prisma entity
customerEntity = await this.customersService.getByUid(uid);
}
//Hydrate ressource with prisma entity
const customer = ObjectHydrate.hydrate<Customer>(new Customer(), customerEntity, { strategy: "exposeAll" });
//success
this.httpSuccess(response, customer);
} catch (error) {
this.httpBadRequest(response, error);
return;
}
}
}

View File

@ -0,0 +1,137 @@
import { Response, Request } from "express";
import { Controller, Get, Post, Put } from "@ControllerPattern/index";
import ApiController from "@Common/system/controller-pattern/ApiController";
import { Service } from "typedi";
import DeedTypesService from "@Services/super-admin/DeedTypesService/DeedTypesService";
import { DeedTypes } from "@prisma/client";
import ObjectHydrate from "@Common/helpers/ObjectHydrate";
import { DeedType } from "le-coffre-resources/dist/SuperAdmin";
import { validateOrReject } from "class-validator";
@Controller()
@Service()
export default class DeedTypesController extends ApiController {
constructor(private deedTypesService: DeedTypesService) {
super();
}
/**
* @description Get all deedtypes
* @returns Deedtype[] list of deedtypes
*/
@Get("/api/v1/super-admin/deed-types")
protected async get(req: Request, response: Response) {
try {
//get query
const query = JSON.parse(req.query["q"] as string);
//call service to get prisma entity
const prismaEntity: DeedTypes[] = await this.deedTypesService.get(query);
//Hydrate ressource with prisma entity
const DeedTypes = ObjectHydrate.map<DeedType>(DeedType, prismaEntity, { strategy: "exposeAll" });
//success
this.httpSuccess(response, DeedTypes);
} catch (error) {
this.httpBadRequest(response, error);
return;
}
}
/**
* @description Create a new deedtype
* @returns Deedtype created
*/
@Post("/api/v1/super-admin/deed-types")
protected async post(req: Request, response: Response) {
try {
//init DeedType resource with request body values
const deedTypeEntity = new DeedType();
ObjectHydrate.hydrate(deedTypeEntity, req.body);
//validate deed type
await validateOrReject(deedTypeEntity, { groups: ["create"] });
//call service to get prisma entity
const prismaEntityCreated = await this.deedTypesService.create(deedTypeEntity);
//Hydrate ressource with prisma entity
const deedTypeEntityCreated = ObjectHydrate.hydrate<DeedType>(new DeedType(), prismaEntityCreated, {
strategy: "exposeAll",
});
//success
this.httpSuccess(response, deedTypeEntityCreated);
} catch (error) {
this.httpBadRequest(response, error);
return;
}
}
/**
* @description Modify a specific deedtype by uid
* @returns Deedtype modified
*/
@Put("/api/v1/super-admin/deed-types/:uid")
protected async put(req: Request, response: Response) {
try {
const uid = req.params["uid"];
if (!uid) {
throw new Error("No uid provided");
}
//init DeedType resource with request body values
const deedTypeEntity = new DeedType();
ObjectHydrate.hydrate(deedTypeEntity, req.body);
//validate deed type
await validateOrReject(deedTypeEntity, { groups: ["update"] });
//call service to get prisma entity
const prismaEntityUpdated = await this.deedTypesService.update(uid, deedTypeEntity);
//Hydrate ressource with prisma entity
const deedTypeEntityUpdated = ObjectHydrate.hydrate<DeedType>(new DeedType(), prismaEntityUpdated, {
strategy: "exposeAll",
});
//success
this.httpSuccess(response, deedTypeEntityUpdated);
} catch (error) {
this.httpBadRequest(response, error);
return;
}
}
/**
* @description Get a specific deedtype by uid
* @returns IDeedtype
*/
@Get("/api/v1/super-admin/deed-types/:uid")
protected async getOneByUid(req: Request, response: Response) {
try {
const uid = req.params["uid"];
if (!uid) {
throw new Error("No uid provided");
}
let deedTypeEntity: DeedTypes;
//get query
if (req.query["q"]) {
const query = JSON.parse(req.query["q"] as string);
deedTypeEntity = await this.deedTypesService.getByUid(uid, query);
} else {
//call service to get prisma entity
deedTypeEntity = await this.deedTypesService.getByUid(uid);
}
//Hydrate ressource with prisma entity
const deedType = ObjectHydrate.hydrate<DeedType>(new DeedType(), deedTypeEntity, { strategy: "exposeAll" });
//success
this.httpSuccess(response, deedType);
} catch (error) {
this.httpBadRequest(response, error);
return;
}
}
}

View File

@ -0,0 +1,66 @@
import { Response, Request } from "express";
import { Controller, Get } from "@ControllerPattern/index";
import ApiController from "@Common/system/controller-pattern/ApiController";
import DeedsService from "@Services/super-admin/DeedsService/DeedsService";
import { Service } from "typedi";
import { Deeds } from "@prisma/client";
import Deed from "le-coffre-resources/dist/SuperAdmin";
import ObjectHydrate from "@Common/helpers/ObjectHydrate";
@Controller()
@Service()
export default class DeedsController extends ApiController {
constructor(private deedsService: DeedsService) {
super();
}
/**
* @description Get all deeds
* @returns Deed[] list of deeds
*/
@Get("/api/v1/super-admin/deeds")
protected async get(req: Request, response: Response) {
try {
//get query
const query = JSON.parse(req.query["q"] as string);
//call service to get prisma entity
const prismaEntity: Deeds[] = await this.deedsService.get(query);
//Hydrate ressource with prisma entity
const deeds = ObjectHydrate.map<Deed>(Deed, prismaEntity, { strategy: "exposeAll" });
//success
this.httpSuccess(response, deeds);
} catch (error) {
this.httpBadRequest(response, error);
return;
}
}
/**
* @description Get a specific deed by uid
* @returns Deed
*/
@Get("/api/v1/super-admin/deeds/:uid")
protected async getOneByUid(req: Request, response: Response) {
try {
const uid = req.params["uid"];
if (!uid) {
throw new Error("No uid provided");
}
//call service to get prisma entity
const deedEntity: Deeds = await this.deedsService.getByUid(uid);
//Hydrate ressource with prisma entity
const deed = ObjectHydrate.hydrate<Deed>(new Deed(), deedEntity, { strategy: "exposeAll" });
//success
this.httpSuccess(response, deed);
} catch (error) {
this.httpBadRequest(response, error);
return;
}
this.httpSuccess(response, await this.deedsService.getByUid("uid"));
}
}

View File

@ -0,0 +1,133 @@
import { Response, Request } from "express";
import { Controller, Get, Post, Put } from "@ControllerPattern/index";
import ApiController from "@Common/system/controller-pattern/ApiController";
import { Service } from "typedi";
import DocumentTypesService from "@Services/super-admin/DocumentTypesService/DocumentTypesService";
import { DocumentTypes } from "@prisma/client";
import ObjectHydrate from "@Common/helpers/ObjectHydrate";
import { DocumentType } from "le-coffre-resources/dist/SuperAdmin";
import { validateOrReject } from "class-validator";
//import { validateOrReject } from "class-validator";
@Controller()
@Service()
export default class DocumentTypesController extends ApiController {
constructor(private documentTypesService: DocumentTypesService) {
super();
}
/**
* @description Get all document-types
*/
@Get("/api/v1/super-admin/document-types")
protected async get(req: Request, response: Response) {
try {
//get query
const query = JSON.parse(req.query["q"] as string);
//call service to get prisma entity
const prismaEntity: DocumentTypes[] = await this.documentTypesService.get(query);
//Hydrate ressource with prisma entity
const documentTypes = ObjectHydrate.map<DocumentType>(DocumentType, prismaEntity, {
strategy: "exposeAll",
});
//success
this.httpSuccess(response, documentTypes);
} catch (error) {
this.httpBadRequest(response, error);
return;
}
}
/**
* @description Create a new documentType
*/
@Post("/api/v1/super-admin/document-types")
protected async post(req: Request, response: Response) {
try {
//init DocumentType resource with request body values
const documentTypeEntity = new DocumentType();
ObjectHydrate.hydrate(documentTypeEntity, req.body);
//validate user
await validateOrReject(documentTypeEntity, { groups: ["create"] });
//call service to get prisma entity
const prismaEntityCreated = await this.documentTypesService.create(documentTypeEntity);
//Hydrate ressource with prisma entity
const userEntityCreated = ObjectHydrate.hydrate<DocumentType>(new DocumentType(), prismaEntityCreated, {
strategy: "exposeAll",
});
//success
this.httpSuccess(response, userEntityCreated);
} catch (error) {
this.httpBadRequest(response, error);
return;
}
}
/**
* @description Modify a specific documentType by uid
*/
@Put("/api/v1/super-admin/document-types/:uid")
protected async put(req: Request, response: Response) {
try {
const uid = req.params["uid"];
if (!uid) {
throw new Error("No uid provided");
}
//init DocumentType resource with request body values
const documentTypeEntity = new DocumentType();
ObjectHydrate.hydrate(documentTypeEntity, req.body);
//validate user
await validateOrReject(documentTypeEntity, { groups: ["update"] });
//call service to get prisma entity
const prismaEntityUpdated = await this.documentTypesService.update(uid, documentTypeEntity);
//Hydrate ressource with prisma entity
const documentTypeEntityUpdated = ObjectHydrate.hydrate<DocumentType>(new DocumentType(), prismaEntityUpdated, {
strategy: "exposeAll",
});
//success
this.httpSuccess(response, documentTypeEntityUpdated);
} catch (error) {
this.httpBadRequest(response, error);
return;
}
}
/**
* @description Get a specific documentType by uid
*/
@Get("/api/v1/super-admin/document-types/:uid")
protected async getOneByUid(req: Request, response: Response) {
try {
const uid = req.params["uid"];
if (!uid) {
throw new Error("No uid provided");
}
let documentTypeEntity: DocumentTypes;
//get query
if (req.query["q"]) {
const query = JSON.parse(req.query["q"] as string);
documentTypeEntity = await this.documentTypesService.getByUid(uid, query);
} else {
//call service to get prisma entity
documentTypeEntity = await this.documentTypesService.getByUid(uid);
}
//Hydrate ressource with prisma entity
const user = ObjectHydrate.hydrate<DocumentType>(new DocumentType(), documentTypeEntity, { strategy: "exposeAll" });
//success
this.httpSuccess(response, user);
} catch (error) {
this.httpBadRequest(response, error);
return;
}
}
}

View File

@ -0,0 +1,160 @@
import { Response, Request } from "express";
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/super-admin/DocumentsService/DocumentsService";
import { Documents } from "@prisma/client";
import ObjectHydrate from "@Common/helpers/ObjectHydrate";
import { Document } from "le-coffre-resources/dist/SuperAdmin";
import { validateOrReject } from "class-validator";
@Controller()
@Service()
export default class DocumentsController extends ApiController {
constructor(private documentsService: DocumentsService) {
super();
}
/**
* @description Get all documents
* @returns IDocument[] list of documents
*/
@Get("/api/v1/super-admin/documents")
protected async get(req: Request, response: Response) {
try {
//get query
const query = JSON.parse(req.query["q"] as string);
//call service to get prisma entity
const prismaEntity: Documents[] = await this.documentsService.get(query);
//Hydrate ressource with prisma entity
const documents = ObjectHydrate.map<Document>(Document, prismaEntity, { strategy: "exposeAll" });
//success
this.httpSuccess(response, documents);
} catch (error) {
this.httpBadRequest(response, error);
return;
}
}
/**
* @description Create a new document
* @returns IDocument created
*/
@Post("/api/v1/super-admin/documents")
protected async post(req: Request, response: Response) {
try {
//init Document resource with request body values
const documentEntity = new Document();
ObjectHydrate.hydrate(documentEntity, req.body);
//validate document
await validateOrReject(documentEntity, { groups: ["create"] });
//call service to get prisma entity
const prismaEntityCreated = await this.documentsService.create(documentEntity);
//Hydrate ressource with prisma entity
const documentEntityCreated = ObjectHydrate.hydrate<Document>(new Document(), prismaEntityCreated, {
strategy: "exposeAll",
});
//success
this.httpSuccess(response, documentEntityCreated);
} catch (error) {
this.httpBadRequest(response, error);
return;
}
}
/**
* @description Update a specific document
*/
@Put("/api/v1/super-admin/documents/:uid")
protected async update(req: Request, response: Response) {
try {
const uid = req.params["uid"];
if (!uid) {
throw new Error("No uid provided");
}
//init Document resource with request body values
const documentEntity = new Document();
ObjectHydrate.hydrate(documentEntity, req.body);
//validate document
await validateOrReject(documentEntity, { groups: ["create"] });
//call service to get prisma entity
const prismaEntityUpdated: Documents = await this.documentsService.update(uid, documentEntity);
//Hydrate ressource with prisma entity
const document = ObjectHydrate.hydrate<Document>(new Document(), prismaEntityUpdated, { strategy: "exposeAll" });
//success
this.httpSuccess(response, document);
} catch (error) {
this.httpBadRequest(response, error);
return;
}
}
/**
* @description Delete a specific document
*/
@Delete("/api/v1/super-admin/documents/:uid")
protected async delete(req: Request, response: Response) {
try {
const uid = req.params["uid"];
if (!uid) {
throw new Error("No uid provided");
}
//call service to get prisma entity
const documentEntity: Documents = await this.documentsService.delete(uid);
//Hydrate ressource with prisma entity
const document = ObjectHydrate.hydrate<Document>(new Document(), documentEntity, { strategy: "exposeAll" });
//success
this.httpSuccess(response, document);
} catch (error) {
this.httpBadRequest(response, error);
return;
}
}
/**
* @description Get a specific document by uid
*/
@Get("/api/v1/super-admin/documents/:uid")
protected async getOneByUid(req: Request, response: Response) {
try {
const uid = req.params["uid"];
if (!uid) {
throw new Error("No uid provided");
}
let documentEntity: Documents;
//get query
if (req.query["q"]) {
const query = JSON.parse(req.query["q"] as string);
documentEntity = await this.documentsService.getByUid(uid, query);
} else {
//call service to get prisma entity
documentEntity = await this.documentsService.getByUid(uid);
}
//Hydrate ressource with prisma entity
const document = ObjectHydrate.hydrate<Document>(new Document(), documentEntity, { strategy: "exposeAll" });
//success
this.httpSuccess(response, document);
} catch (error) {
this.httpBadRequest(response, error);
return;
}
}
}

View File

@ -0,0 +1,132 @@
import { Response, Request } from "express";
import { Controller, Get, Post, Put } from "@ControllerPattern/index";
import ApiController from "@Common/system/controller-pattern/ApiController";
import OfficeFoldersService from "@Services/super-admin/OfficeFoldersService/OfficeFoldersService";
import { Service } from "typedi";
import { OfficeFolders } from "@prisma/client";
import ObjectHydrate from "@Common/helpers/ObjectHydrate";
import { OfficeFolder } from "le-coffre-resources/dist/SuperAdmin";
import { validateOrReject } from "class-validator";
@Controller()
@Service()
export default class OfficeFoldersController extends ApiController {
constructor(private officeFoldersService: OfficeFoldersService) {
super();
}
/**
* @description Get all folders
*/
@Get("/api/v1/super-admin/folders")
protected async get(req: Request, response: Response) {
try {
//get query
const query = JSON.parse(req.query["q"] as string);
//call service to get prisma entity
const prismaEntity: OfficeFolders[] = await this.officeFoldersService.get(query);
//Hydrate ressource with prisma entity
const officeFolders = ObjectHydrate.map<OfficeFolder>(OfficeFolder, prismaEntity, {
strategy: "exposeAll", enableImplicitConversion: true
});
//success
this.httpSuccess(response, officeFolders);
} catch (error) {
this.httpBadRequest(response, error);
return;
}
}
/**
* @description Create a new folder
*/
@Post("/api/v1/super-admin/folders")
protected async post(req: Request, response: Response) {
try {
//init OfficeFolder resource with request body values
const officeFolderEntity = new OfficeFolder();
ObjectHydrate.hydrate(officeFolderEntity, req.body);
//validate folder
await validateOrReject(officeFolderEntity, { groups: ["create"] });
//call service to get prisma entity
const prismaEntityCreated = await this.officeFoldersService.create(officeFolderEntity);
//Hydrate ressource with prisma entity
const officeFolderEntityCreated = ObjectHydrate.hydrate<OfficeFolder>(new OfficeFolder(), prismaEntityCreated, {
strategy: "exposeAll", enableImplicitConversion: true
});
//success
this.httpSuccess(response, officeFolderEntityCreated);
} catch (error) {
this.httpBadRequest(response, error);
return;
}
}
/**
* @description Modify a specific folder by uid
*/
@Put("/api/v1/super-admin/folders/:uid")
protected async put(req: Request, response: Response) {
try {
const uid = req.params["uid"];
if (!uid) {
throw new Error("No uid provided");
}
//init IUser resource with request body values
const officeFolderEntity = new OfficeFolder();
ObjectHydrate.hydrate(officeFolderEntity, req.body);
//validate user
await validateOrReject(officeFolderEntity, { groups: ["update"] });
//call service to get prisma entity
const prismaEntityUpdated = await this.officeFoldersService.update(uid, officeFolderEntity);
//Hydrate ressource with prisma entity
const officeFolderEntityUpdated = ObjectHydrate.hydrate<OfficeFolder>(new OfficeFolder(), prismaEntityUpdated, {
strategy: "exposeAll",
});
//success
this.httpSuccess(response, officeFolderEntityUpdated);
} catch (error) {
this.httpBadRequest(response, error);
return;
}
}
/**
* @description Get a specific folder by uid
* @returns IFolder
*/
@Get("/api/v1/super-admin/folders/:uid")
protected async getOneByUid(req: Request, response: Response) {
try {
const uid = req.params["uid"];
if (!uid) {
throw new Error("No uid provided");
}
let officeFolderEntity: OfficeFolders;
//get query
if (req.query["q"]) {
const query = JSON.parse(req.query["q"] as string);
officeFolderEntity = await this.officeFoldersService.getByUid(uid, query);
} else {
//call service to get prisma entity
officeFolderEntity = await this.officeFoldersService.getByUid(uid);
}
//Hydrate ressource with prisma entity
const officeFolder = ObjectHydrate.hydrate<OfficeFolder>(new OfficeFolder(), officeFolderEntity, { strategy: "exposeAll" });
//success
this.httpSuccess(response, officeFolder);
} catch (error) {
this.httpBadRequest(response, error);
return;
}
this.httpSuccess(response, await this.officeFoldersService.getByUid("uid"));
}
}

View File

@ -0,0 +1,116 @@
import { Response, Request } from "express";
import { Controller, Get, Post, Put } from "@ControllerPattern/index";
import ApiController from "@Common/system/controller-pattern/ApiController";
import OfficesService from "@Services/super-admin/OfficesService/OfficesService";
import { Service } from "typedi";
import { Offices } from "@prisma/client";
import ObjectHydrate from "@Common/helpers/ObjectHydrate";
import { Office as OfficeRessource } from "le-coffre-resources/dist/SuperAdmin";
import { validateOrReject } from "class-validator";
@Controller()
@Service()
export default class OfficesController extends ApiController {
constructor(private officesService: OfficesService) {
super();
}
/**
* @description Get all offices
*/
@Get("/api/v1/super-admin/offices")
protected async get(req: Request, response: Response) {
try {
//get query
const query = JSON.parse(req.query["q"] as string);
//call service to get prisma entity
const officesEntity: Offices[] = await this.officesService.get(query);
//Hydrate ressource with prisma entity
const offices = ObjectHydrate.map<OfficeRessource>(OfficeRessource, officesEntity, { strategy: "exposeAll" });
//success
this.httpSuccess(response, offices);
} catch (error) {
this.httpBadRequest(response, error);
return;
}
}
/**
* @description Create a new office
*/
@Post("/api/v1/super-admin/offices")
protected async post(req: Request, response: Response) {
try {
//init IUser resource with request body values
const officeEntity = new OfficeRessource();
ObjectHydrate.hydrate(officeEntity, req.body);
//validate user
await validateOrReject(officeEntity, { groups: ["create"] });
//call service to get prisma entity
const prismaEntityCreated = await this.officesService.create(officeEntity);
//Hydrate ressource with prisma entity
const officeEntityCreated = ObjectHydrate.hydrate<OfficeRessource>(new OfficeRessource(), prismaEntityCreated, {
strategy: "exposeAll",
});
//success
this.httpSuccess(response, officeEntityCreated);
} catch (error) {
this.httpBadRequest(response, error);
return;
}
}
/**
* @description Modify a specific office by uid
*/
@Put("/api/v1/super-admin/offices/:uid")
protected async put(req: Request, response: Response) {
try {
const uid = req.params["uid"];
if (!uid) {
throw new Error("No uid provided");
}
//init IUser resource with request body values
const officeEntity = new OfficeRessource();
ObjectHydrate.hydrate(officeEntity, req.body);
//validate user
await validateOrReject(officeEntity, { groups: ["update"] });
//call service to get prisma entity
const prismaEntityUpdated = await this.officesService.update(uid, officeEntity);
//Hydrate ressource with prisma entity
const officeEntityUpdated = ObjectHydrate.hydrate<OfficeRessource>(new OfficeRessource(), prismaEntityUpdated, {
strategy: "exposeAll",
});
//success
this.httpSuccess(response, officeEntityUpdated);
} catch (error) {
this.httpBadRequest(response, error);
return;
}
}
/**
* @description Get a specific office by uid
*/
@Get("/api/v1/super-admin/offices/:uid")
protected async getOneByUid(req: Request, response: Response) {
try {
const uid = req.params["uid"];
if (!uid) {
throw new Error("No uid provided");
}
let officeEntity: Offices;
//get query
if (req.query["q"]) {
const query = JSON.parse(req.query["q"] as string);
officeEntity = await this.officesService.getByUid(uid, query);
} else {
//call service to get prisma entity
officeEntity = await this.officesService.getByUid(uid);
}
//Hydrate ressource with prisma entity
const office = ObjectHydrate.hydrate<OfficeRessource>(new OfficeRessource(), officeEntity, { strategy: "exposeAll" });
//success
this.httpSuccess(response, office);
} catch (error) {
this.httpBadRequest(response, error);
return;
}
}
}

View File

@ -0,0 +1,137 @@
import { Response, Request } from "express";
import { Controller, Get, Post, Put } from "@ControllerPattern/index";
import ApiController from "@Common/system/controller-pattern/ApiController";
import UsersService from "@Services/super-admin/UsersService/UsersService";
import { Service } from "typedi";
import ObjectHydrate from "@Common/helpers/ObjectHydrate";
import { validateOrReject } from "class-validator";
import User from "le-coffre-resources/dist/Notary";
import { Users } from "@prisma/client";
import { plainToInstance } from "class-transformer";
@Controller()
@Service()
export default class UsersController extends ApiController {
constructor(private usersService: UsersService) {
super();
}
/**
* @description Get all users
*/
@Get("/api/v1/super-admin/users")
protected async get(req: Request, response: Response) {
try {
//get query
const query = JSON.parse(req.query["q"] as string);
//call service to get prisma entity
const usersEntity: Users[] = await this.usersService.get(query);
//Hydrate ressource with prisma entity
const users = plainToInstance<User, Users[]>(User, usersEntity, {
enableImplicitConversion: true,
excludeExtraneousValues: false,
});
//success
this.httpSuccess(response, users);
} catch (error) {
this.httpBadRequest(response, error);
return;
}
}
/**
* @description Create a new user
*/
@Post("/api/v1/super-admin/users")
protected async getAddresses(req: Request, response: Response) {
try {
//init IUser resource with request body values
const userEntity = new User();
ObjectHydrate.hydrate(userEntity, req.body);
//validate user
await validateOrReject(userEntity, { groups: ["create"] });
//call service to get prisma entity
const prismaEntityCreated = await this.usersService.create(userEntity);
//Hydrate ressource with prisma entity
const userEntityCreated = ObjectHydrate.hydrate<User>(new User(), prismaEntityCreated, {
strategy: "exposeAll",
});
//success
this.httpSuccess(response, userEntityCreated);
} catch (error) {
this.httpBadRequest(response, error);
return;
}
}
/**
* @description Modify a specific user by uid
*/
@Put("/api/v1/super-admin/users/:uid")
protected async put(req: Request, response: Response) {
try {
const uid = req.params["uid"];
if (!uid) {
throw new Error("No uid provided");
}
//init IUser resource with request body values
const userEntity = new User();
ObjectHydrate.hydrate(userEntity, req.body);
//validate user
await validateOrReject(userEntity, { groups: ["update"] });
//call service to get prisma entity
const prismaEntityUpdated = await this.usersService.update(uid, userEntity);
//Hydrate ressource with prisma entity
const userEntityUpdated = ObjectHydrate.hydrate<User>(new User(), prismaEntityUpdated, {
strategy: "exposeAll",
});
//success
this.httpSuccess(response, userEntityUpdated);
} catch (error) {
this.httpBadRequest(response, error);
return;
}
}
/**
* @description Get a specific user by uid
*/
@Get("/api/v1/super-admin/users/:uid")
protected async getOneByUid(req: Request, response: Response) {
try {
const uid = req.params["uid"];
if (!uid) {
throw new Error("No uid provided");
}
let userEntity: Users;
//get query
if (req.query["q"]) {
const query = JSON.parse(req.query["q"] as string);
userEntity = await this.usersService.getByUid(uid, query);
} else {
//call service to get prisma entity
userEntity = await this.usersService.getByUid(uid);
}
//Hydrate ressource with prisma entity
const user = ObjectHydrate.hydrate<User>(new User(), userEntity, { strategy: "exposeAll" });
//success
this.httpSuccess(response, user);
} catch (error) {
this.httpBadRequest(response, error);
return;
}
}
}

29
src/app/index.ts Normal file
View File

@ -0,0 +1,29 @@
import { Container } from "typedi";
import HomeController from "./HomeController";
import UsersController from "./api/super-admin/UsersController";
import FoldersController from "./api/super-admin/OfficeFoldersController";
import CustomersController from "./api/super-admin/CustomersController";
import OfficesController from "./api/super-admin/OfficesController";
import DeedsController from "./api/super-admin/DeedsController";
import DeedTypesController from "./api/super-admin/DeedTypesController";
import DocumentsController from "./api/super-admin/DocumentsController";
import DocumentTypesController from "./api/super-admin/DocumentTypesController";
import IdNotUserInfoController from "./api/idnot-user/UserInfoController";
/**
* @description This allow to declare all controllers used in the application
*/
export default {
start: () => {
Container.get(HomeController);
Container.get(UsersController);
Container.get(FoldersController);
Container.get(CustomersController);
Container.get(OfficesController);
Container.get(DeedsController);
Container.get(DeedTypesController);
Container.get(DocumentsController);
Container.get(DocumentTypesController);
Container.get(IdNotUserInfoController);
},
};

View File

@ -0,0 +1,24 @@
import HttpException from "@Common/system/controller-pattern/exceptions/HttpException";
import HttpCodes from "@Common/system/controller-pattern/HttpCodes";
import { NextFunction, Request, Response } from "express";
export default function errorHandler(error: any, req: Request, response: Response, next: NextFunction) {
const errorStatus: number = error["status"];
/**
* Used on when try to parse json on request
*/
if (error instanceof SyntaxError && errorStatus === 400 && "body" in error) {
response.status(HttpCodes.BAD_REQUEST).send({
body: error["body"],
type: error as any["type"],
});
return;
}
if (error instanceof HttpException) {
response.status(error.httpCode).send(error.message);
return;
}
next(error);
}

View File

@ -0,0 +1,4 @@
export default interface IDatabaseConfig {
name: string;
url?: string;
}

View File

@ -0,0 +1,68 @@
import { IsNotEmpty, IsOptional, validateOrReject } from "class-validator";
import dotenv from "dotenv";
import { Service } from "typedi";
@Service()
export class BackendVariables {
@IsNotEmpty()
public readonly DATABASE_PORT!: string;
@IsNotEmpty()
public readonly DATABASE_HOST!: string;
@IsNotEmpty()
public readonly DATABASE_USERNAME!: string;
@IsNotEmpty()
public readonly DATABASE_PASSWORD!: string;
@IsNotEmpty()
public readonly DATABASE_NAME!: string;
@IsNotEmpty()
public readonly API_ROOT_URL!: string;
@IsOptional()
public readonly APP_LABEL!: string;
@IsNotEmpty()
public readonly APP_PORT!: string;
@IsNotEmpty()
public readonly APP_ROOT_URL!: string;
public readonly NODE_ENV = process.env.NODE_ENV;
@IsNotEmpty()
public readonly IDNOT_CONNEXION_URL!: string;
@IsNotEmpty()
public readonly IDNOT_CLIENT_ID!: string;
@IsNotEmpty()
public readonly IDNOT_CLIENT_SECRET!: string;
@IsNotEmpty()
public readonly IDNOT_REDIRECT_URL!: string;
public constructor() {
dotenv.config();
this.DATABASE_PORT = process.env["DATABASE_PORT"]!;
this.DATABASE_HOST = process.env["DATABASE_HOST"]!;
this.DATABASE_USERNAME = process.env["DATABASE_USERNAME"]!;
this.DATABASE_PASSWORD = process.env["DATABASE_PASSWORD"]!;
this.DATABASE_NAME = process.env["DATABASE_NAME"]!;
this.API_ROOT_URL = process.env["API_ROOT_URL"]!;
this.APP_PORT = process.env["APP_PORT"]!;
this.APP_ROOT_URL = process.env["APP_ROOT_URL"]!;
this.APP_LABEL = process.env["APP_LABEL"]!;
this.IDNOT_CONNEXION_URL = process.env["IDNOT_CONNEXION_URL"]!;
this.IDNOT_CLIENT_ID = process.env["IDNOT_CLIENT_ID"]!;
this.IDNOT_CLIENT_SECRET = process.env["IDNOT_CLIENT_SECRET"]!;
this.IDNOT_REDIRECT_URL = process.env["IDNOT_REDIRECT_URL"]!;
}
public async validate() {
await validateOrReject(this);
return this;
}
}

View File

@ -0,0 +1,29 @@
import { Service } from "typedi";
import DbProvider from "@Common/system/database";
import dotenv from "dotenv";
import { BackendVariables } from "@Common/config/variables/Variables";
dotenv.config();
@Service()
export default class Database {
protected readonly dbProvider: DbProvider;
constructor(private variables: BackendVariables) {
this.dbProvider = new DbProvider({
name: this.getDatabaseName(),
});
}
public getClient() {
return this.dbProvider.getClient();
}
public async connect() {
await this.dbProvider.connect();
return this.dbProvider.getClient();
}
private getDatabaseName(): string {
const name = this.variables.DATABASE_NAME;
if (!name) throw new Error("Database name is undefined!. Add name of db in the url.");
return name;
}
}

View File

@ -0,0 +1,445 @@
-- CreateEnum
CREATE TYPE "ECivility" AS ENUM ('MALE', 'FEMALE', 'OTHERS');
-- CreateEnum
CREATE TYPE "EFolderStatus" AS ENUM ('LIVE', 'ARCHIVED');
-- CreateEnum
CREATE TYPE "EOfficeStatus" AS ENUM ('ACTIVATED', 'DESACTIVATED');
-- CreateEnum
CREATE TYPE "ENotificationStatus" AS ENUM ('READ', 'UNREAD');
-- CreateEnum
CREATE TYPE "ECustomerStatus" AS ENUM ('VALIDATED', 'PENDING', 'ERRONED');
-- CreateEnum
CREATE TYPE "EDocumentStatus" AS ENUM ('ASKED', 'DEPOSITED', 'VALIDATED', 'ANCHORED', 'REFUSED');
-- CreateTable
CREATE TABLE "addresses" (
"uid" TEXT NOT NULL,
"address" VARCHAR(255) NOT NULL,
"city" VARCHAR(255) NOT NULL,
"zip_code" INTEGER NOT NULL,
"created_at" TIMESTAMP(3) DEFAULT CURRENT_TIMESTAMP,
"updated_at" TIMESTAMP(3),
CONSTRAINT "addresses_pkey" PRIMARY KEY ("uid")
);
-- CreateTable
CREATE TABLE "contacts" (
"uid" TEXT NOT NULL,
"first_name" VARCHAR(255) NOT NULL,
"last_name" VARCHAR(255) NOT NULL,
"email" VARCHAR(255) NOT NULL,
"phone_number" VARCHAR(50),
"cell_phone_number" VARCHAR(50),
"civility" "ECivility" NOT NULL DEFAULT 'MALE',
"address_uid" VARCHAR(255) NOT NULL,
"birthdate" TIMESTAMP(3),
"created_at" TIMESTAMP(3) DEFAULT CURRENT_TIMESTAMP,
"updated_at" TIMESTAMP(3),
CONSTRAINT "contacts_pkey" PRIMARY KEY ("uid")
);
-- CreateTable
CREATE TABLE "users" (
"uid" TEXT NOT NULL,
"idNot" VARCHAR(255) NOT NULL,
"contact_uid" VARCHAR(255) NOT NULL,
"created_at" TIMESTAMP(3) DEFAULT CURRENT_TIMESTAMP,
"updated_at" TIMESTAMP(3),
"office_uid" VARCHAR(255) NOT NULL,
CONSTRAINT "users_pkey" PRIMARY KEY ("uid")
);
-- CreateTable
CREATE TABLE "offices" (
"uid" TEXT NOT NULL,
"idNot" VARCHAR(255) NOT NULL,
"name" VARCHAR(255) NOT NULL,
"crpcen" VARCHAR(255) NOT NULL,
"address_uid" VARCHAR(255) NOT NULL,
"office_status" "EOfficeStatus" NOT NULL DEFAULT 'DESACTIVATED',
"created_at" TIMESTAMP(3) DEFAULT CURRENT_TIMESTAMP,
"updated_at" TIMESTAMP(3),
CONSTRAINT "offices_pkey" PRIMARY KEY ("uid")
);
-- CreateTable
CREATE TABLE "customers" (
"uid" TEXT NOT NULL,
"status" "ECustomerStatus" NOT NULL DEFAULT 'PENDING',
"contact_uid" VARCHAR(255) NOT NULL,
"created_at" TIMESTAMP(3) DEFAULT CURRENT_TIMESTAMP,
"updated_at" TIMESTAMP(3),
CONSTRAINT "customers_pkey" PRIMARY KEY ("uid")
);
-- CreateTable
CREATE TABLE "user_has_notifications" (
"uid" TEXT NOT NULL,
"user_uid" VARCHAR(255) NOT NULL,
"notification_uid" VARCHAR(255) NOT NULL,
"notification_status" "ENotificationStatus" NOT NULL DEFAULT 'UNREAD',
"created_at" TIMESTAMP(3) DEFAULT CURRENT_TIMESTAMP,
"updated_at" TIMESTAMP(3),
CONSTRAINT "user_has_notifications_pkey" PRIMARY KEY ("uid")
);
-- CreateTable
CREATE TABLE "notifications" (
"uid" TEXT NOT NULL,
"message" VARCHAR(255) NOT NULL,
"redirection_url" VARCHAR(255) NOT NULL,
"created_at" TIMESTAMP(3) DEFAULT CURRENT_TIMESTAMP,
"updated_at" TIMESTAMP(3),
CONSTRAINT "notifications_pkey" PRIMARY KEY ("uid")
);
-- CreateTable
CREATE TABLE "office_folders" (
"uid" TEXT NOT NULL,
"folder_number" VARCHAR(255) NOT NULL,
"name" VARCHAR(255) NOT NULL,
"description" VARCHAR(255),
"archived_description" VARCHAR(255),
"status" "EFolderStatus" NOT NULL DEFAULT 'LIVE',
"deed_uid" VARCHAR(255) NOT NULL,
"office_uid" VARCHAR(255) NOT NULL,
"created_at" TIMESTAMP(3) DEFAULT CURRENT_TIMESTAMP,
"updated_at" TIMESTAMP(3),
CONSTRAINT "office_folders_pkey" PRIMARY KEY ("uid")
);
-- CreateTable
CREATE TABLE "office_folder_has_customers" (
"uid" TEXT NOT NULL,
"customer_uid" VARCHAR(255) NOT NULL,
"office_folder_uid" VARCHAR(255) NOT NULL,
"created_at" TIMESTAMP(3) DEFAULT CURRENT_TIMESTAMP,
"updated_at" TIMESTAMP(3),
CONSTRAINT "office_folder_has_customers_pkey" PRIMARY KEY ("uid")
);
-- CreateTable
CREATE TABLE "office_folder_has_stakeholder" (
"uid" TEXT NOT NULL,
"office_folder_uid" VARCHAR(255) NOT NULL,
"user_stakeholder_uid" VARCHAR(255) NOT NULL,
"created_at" TIMESTAMP(3) DEFAULT CURRENT_TIMESTAMP,
"updated_at" TIMESTAMP(3),
CONSTRAINT "office_folder_has_stakeholder_pkey" PRIMARY KEY ("uid")
);
-- CreateTable
CREATE TABLE "documents" (
"uid" TEXT NOT NULL,
"document_status" "EDocumentStatus" NOT NULL DEFAULT 'ASKED',
"document_type_uid" VARCHAR(255) NOT NULL,
"blockchain_anchor_uid" VARCHAR(255),
"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_pkey" PRIMARY KEY ("uid")
);
-- CreateTable
CREATE TABLE "document_history" (
"uid" TEXT NOT NULL,
"document_status" "EDocumentStatus" NOT NULL DEFAULT 'ASKED',
"refused_reason" VARCHAR(255),
"document_uid" VARCHAR(255) NOT NULL,
"created_at" TIMESTAMP(3) DEFAULT CURRENT_TIMESTAMP,
"updated_at" TIMESTAMP(3),
CONSTRAINT "document_history_pkey" PRIMARY KEY ("uid")
);
-- CreateTable
CREATE TABLE "files" (
"uid" TEXT NOT NULL,
"document_uid" VARCHAR(255) NOT NULL,
"file_path" VARCHAR(255) NOT NULL,
"created_at" TIMESTAMP(3) DEFAULT CURRENT_TIMESTAMP,
"updated_at" TIMESTAMP(3),
CONSTRAINT "files_pkey" PRIMARY KEY ("uid")
);
-- CreateTable
CREATE TABLE "blockchain_anchors" (
"uid" TEXT NOT NULL,
"smartSigJobId" VARCHAR(255) NOT NULL,
"created_at" TIMESTAMP(3) DEFAULT CURRENT_TIMESTAMP,
"updated_at" TIMESTAMP(3),
CONSTRAINT "blockchain_anchors_pkey" PRIMARY KEY ("uid")
);
-- CreateTable
CREATE TABLE "document_types" (
"uid" TEXT NOT NULL,
"name" VARCHAR(255) NOT NULL,
"public_description" VARCHAR(255) NOT NULL,
"private_description" VARCHAR(255),
"office_uid" VARCHAR(255) NOT NULL,
"archived_at" TIMESTAMP(3),
"created_at" TIMESTAMP(3) DEFAULT CURRENT_TIMESTAMP,
"updated_at" TIMESTAMP(3),
CONSTRAINT "document_types_pkey" PRIMARY KEY ("uid")
);
-- CreateTable
CREATE TABLE "deed_has_document_types" (
"uid" TEXT NOT NULL,
"document_type_uid" VARCHAR(255) NOT NULL,
"deed_uid" VARCHAR(255) NOT NULL,
"created_at" TIMESTAMP(3) DEFAULT CURRENT_TIMESTAMP,
"updated_at" TIMESTAMP(3),
CONSTRAINT "deed_has_document_types_pkey" PRIMARY KEY ("uid")
);
-- CreateTable
CREATE TABLE "deed" (
"uid" TEXT NOT NULL,
"deed_type_uid" VARCHAR(255) NOT NULL,
"created_at" TIMESTAMP(3) DEFAULT CURRENT_TIMESTAMP,
"updated_at" TIMESTAMP(3),
CONSTRAINT "deed_pkey" PRIMARY KEY ("uid")
);
-- CreateTable
CREATE TABLE "deed_types" (
"uid" TEXT NOT NULL,
"name" VARCHAR(255) NOT NULL,
"description" VARCHAR(255) NOT NULL,
"archived_at" TIMESTAMP(3),
"office_uid" VARCHAR(255) NOT NULL,
"created_at" TIMESTAMP(3) DEFAULT CURRENT_TIMESTAMP,
"updated_at" TIMESTAMP(3),
CONSTRAINT "deed_types_pkey" PRIMARY KEY ("uid")
);
-- CreateTable
CREATE TABLE "deed_type_has_document_types" (
"uid" TEXT NOT NULL,
"document_type_uid" VARCHAR(255) NOT NULL,
"deed_type_uid" VARCHAR(255) NOT NULL,
"created_at" TIMESTAMP(3) DEFAULT CURRENT_TIMESTAMP,
"updated_at" TIMESTAMP(3),
CONSTRAINT "deed_type_has_document_types_pkey" PRIMARY KEY ("uid")
);
-- CreateIndex
CREATE UNIQUE INDEX "addresses_uid_key" ON "addresses"("uid");
-- CreateIndex
CREATE UNIQUE INDEX "contacts_uid_key" ON "contacts"("uid");
-- CreateIndex
CREATE UNIQUE INDEX "contacts_email_key" ON "contacts"("email");
-- CreateIndex
CREATE UNIQUE INDEX "contacts_cell_phone_number_key" ON "contacts"("cell_phone_number");
-- CreateIndex
CREATE UNIQUE INDEX "contacts_address_uid_key" ON "contacts"("address_uid");
-- CreateIndex
CREATE UNIQUE INDEX "users_uid_key" ON "users"("uid");
-- CreateIndex
CREATE UNIQUE INDEX "users_idNot_key" ON "users"("idNot");
-- CreateIndex
CREATE UNIQUE INDEX "users_contact_uid_key" ON "users"("contact_uid");
-- CreateIndex
CREATE UNIQUE INDEX "offices_uid_key" ON "offices"("uid");
-- CreateIndex
CREATE UNIQUE INDEX "offices_idNot_key" ON "offices"("idNot");
-- CreateIndex
CREATE UNIQUE INDEX "offices_crpcen_key" ON "offices"("crpcen");
-- CreateIndex
CREATE UNIQUE INDEX "offices_address_uid_key" ON "offices"("address_uid");
-- CreateIndex
CREATE UNIQUE INDEX "customers_uid_key" ON "customers"("uid");
-- CreateIndex
CREATE UNIQUE INDEX "customers_contact_uid_key" ON "customers"("contact_uid");
-- CreateIndex
CREATE UNIQUE INDEX "user_has_notifications_uid_key" ON "user_has_notifications"("uid");
-- CreateIndex
CREATE UNIQUE INDEX "user_has_notifications_notification_uid_user_uid_key" ON "user_has_notifications"("notification_uid", "user_uid");
-- CreateIndex
CREATE UNIQUE INDEX "notifications_uid_key" ON "notifications"("uid");
-- CreateIndex
CREATE UNIQUE INDEX "office_folders_uid_key" ON "office_folders"("uid");
-- CreateIndex
CREATE UNIQUE INDEX "office_folders_deed_uid_key" ON "office_folders"("deed_uid");
-- CreateIndex
CREATE UNIQUE INDEX "office_folders_folder_number_office_uid_key" ON "office_folders"("folder_number", "office_uid");
-- CreateIndex
CREATE UNIQUE INDEX "office_folder_has_customers_uid_key" ON "office_folder_has_customers"("uid");
-- CreateIndex
CREATE UNIQUE INDEX "office_folder_has_customers_office_folder_uid_customer_uid_key" ON "office_folder_has_customers"("office_folder_uid", "customer_uid");
-- CreateIndex
CREATE UNIQUE INDEX "office_folder_has_stakeholder_uid_key" ON "office_folder_has_stakeholder"("uid");
-- CreateIndex
CREATE UNIQUE INDEX "office_folder_has_stakeholder_office_folder_uid_user_stakeh_key" ON "office_folder_has_stakeholder"("office_folder_uid", "user_stakeholder_uid");
-- CreateIndex
CREATE UNIQUE INDEX "documents_uid_key" ON "documents"("uid");
-- CreateIndex
CREATE UNIQUE INDEX "document_history_uid_key" ON "document_history"("uid");
-- CreateIndex
CREATE UNIQUE INDEX "files_uid_key" ON "files"("uid");
-- CreateIndex
CREATE UNIQUE INDEX "files_file_path_key" ON "files"("file_path");
-- CreateIndex
CREATE UNIQUE INDEX "blockchain_anchors_uid_key" ON "blockchain_anchors"("uid");
-- CreateIndex
CREATE UNIQUE INDEX "blockchain_anchors_smartSigJobId_key" ON "blockchain_anchors"("smartSigJobId");
-- CreateIndex
CREATE UNIQUE INDEX "document_types_uid_key" ON "document_types"("uid");
-- CreateIndex
CREATE UNIQUE INDEX "document_types_name_office_uid_key" ON "document_types"("name", "office_uid");
-- CreateIndex
CREATE UNIQUE INDEX "deed_has_document_types_uid_key" ON "deed_has_document_types"("uid");
-- CreateIndex
CREATE UNIQUE INDEX "deed_has_document_types_deed_uid_document_type_uid_key" ON "deed_has_document_types"("deed_uid", "document_type_uid");
-- CreateIndex
CREATE UNIQUE INDEX "deed_uid_key" ON "deed"("uid");
-- CreateIndex
CREATE UNIQUE INDEX "deed_types_uid_key" ON "deed_types"("uid");
-- CreateIndex
CREATE UNIQUE INDEX "deed_types_name_office_uid_key" ON "deed_types"("name", "office_uid");
-- CreateIndex
CREATE UNIQUE INDEX "deed_type_has_document_types_uid_key" ON "deed_type_has_document_types"("uid");
-- CreateIndex
CREATE UNIQUE INDEX "deed_type_has_document_types_deed_type_uid_document_type_ui_key" ON "deed_type_has_document_types"("deed_type_uid", "document_type_uid");
-- AddForeignKey
ALTER TABLE "contacts" ADD CONSTRAINT "contacts_address_uid_fkey" FOREIGN KEY ("address_uid") REFERENCES "addresses"("uid") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "users" ADD CONSTRAINT "users_contact_uid_fkey" FOREIGN KEY ("contact_uid") REFERENCES "contacts"("uid") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "users" ADD CONSTRAINT "users_office_uid_fkey" FOREIGN KEY ("office_uid") REFERENCES "offices"("uid") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "offices" ADD CONSTRAINT "offices_address_uid_fkey" FOREIGN KEY ("address_uid") REFERENCES "addresses"("uid") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "customers" ADD CONSTRAINT "customers_contact_uid_fkey" FOREIGN KEY ("contact_uid") REFERENCES "contacts"("uid") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "user_has_notifications" ADD CONSTRAINT "user_has_notifications_user_uid_fkey" FOREIGN KEY ("user_uid") REFERENCES "users"("uid") ON DELETE RESTRICT ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "user_has_notifications" ADD CONSTRAINT "user_has_notifications_notification_uid_fkey" FOREIGN KEY ("notification_uid") REFERENCES "notifications"("uid") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "office_folders" ADD CONSTRAINT "office_folders_deed_uid_fkey" FOREIGN KEY ("deed_uid") REFERENCES "deed"("uid") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "office_folders" ADD CONSTRAINT "office_folders_office_uid_fkey" FOREIGN KEY ("office_uid") REFERENCES "offices"("uid") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "office_folder_has_customers" ADD CONSTRAINT "office_folder_has_customers_customer_uid_fkey" FOREIGN KEY ("customer_uid") REFERENCES "customers"("uid") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "office_folder_has_customers" ADD CONSTRAINT "office_folder_has_customers_office_folder_uid_fkey" FOREIGN KEY ("office_folder_uid") REFERENCES "office_folders"("uid") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "office_folder_has_stakeholder" ADD CONSTRAINT "office_folder_has_stakeholder_office_folder_uid_fkey" FOREIGN KEY ("office_folder_uid") REFERENCES "office_folders"("uid") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "office_folder_has_stakeholder" ADD CONSTRAINT "office_folder_has_stakeholder_user_stakeholder_uid_fkey" FOREIGN KEY ("user_stakeholder_uid") REFERENCES "users"("uid") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "documents" ADD CONSTRAINT "documents_document_type_uid_fkey" FOREIGN KEY ("document_type_uid") REFERENCES "document_types"("uid") ON DELETE RESTRICT ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "documents" ADD CONSTRAINT "documents_blockchain_anchor_uid_fkey" FOREIGN KEY ("blockchain_anchor_uid") REFERENCES "blockchain_anchors"("uid") ON DELETE SET NULL ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "documents" ADD CONSTRAINT "documents_folder_uid_fkey" FOREIGN KEY ("folder_uid") REFERENCES "office_folders"("uid") ON DELETE RESTRICT ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "documents" ADD CONSTRAINT "documents_depositor_uid_fkey" FOREIGN KEY ("depositor_uid") REFERENCES "customers"("uid") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "document_history" ADD CONSTRAINT "document_history_document_uid_fkey" FOREIGN KEY ("document_uid") REFERENCES "documents"("uid") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "files" ADD CONSTRAINT "files_document_uid_fkey" FOREIGN KEY ("document_uid") REFERENCES "documents"("uid") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "document_types" ADD CONSTRAINT "document_types_office_uid_fkey" FOREIGN KEY ("office_uid") REFERENCES "offices"("uid") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "deed_has_document_types" ADD CONSTRAINT "deed_has_document_types_document_type_uid_fkey" FOREIGN KEY ("document_type_uid") REFERENCES "document_types"("uid") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "deed_has_document_types" ADD CONSTRAINT "deed_has_document_types_deed_uid_fkey" FOREIGN KEY ("deed_uid") REFERENCES "deed"("uid") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "deed" ADD CONSTRAINT "deed_deed_type_uid_fkey" FOREIGN KEY ("deed_type_uid") REFERENCES "deed_types"("uid") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "deed_types" ADD CONSTRAINT "deed_types_office_uid_fkey" FOREIGN KEY ("office_uid") REFERENCES "offices"("uid") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "deed_type_has_document_types" ADD CONSTRAINT "deed_type_has_document_types_document_type_uid_fkey" FOREIGN KEY ("document_type_uid") REFERENCES "document_types"("uid") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "deed_type_has_document_types" ADD CONSTRAINT "deed_type_has_document_types_deed_type_uid_fkey" FOREIGN KEY ("deed_type_uid") REFERENCES "deed_types"("uid") ON DELETE CASCADE ON UPDATE CASCADE;

View File

@ -0,0 +1,3 @@
# Please do not edit this file manually
# It should be added in your version-control system (i.e. Git)
provider = "postgresql"

View File

@ -0,0 +1,327 @@
// This the Prisma schema file
generator client {
provider = "prisma-client-js"
//binaryTargets = ["native"]
}
datasource db {
provider = "postgresql"
url = env("DEV_PRISMA_STUDIO_DB_URL")
}
// Entités -> snake_case
// table -> CamelCase
// Models au sein de la Database (Prisma)
// Permet d'utiliser du cable_case dans les tables et du SnakeCase dans les models
// id String @unique @default(auto()) @map("_id") @db.ObjectId // @map de la table checker le naming avec le tiret
model Addresses {
uid String @id @unique @default(uuid())
address String @db.VarChar(255)
city String @db.VarChar(255)
zip_code Int
created_at DateTime? @default(now())
updated_at DateTime? @updatedAt
contacts Contacts?
office Offices?
@@map("addresses")
}
model Contacts {
uid String @id @unique @default(uuid())
first_name String @db.VarChar(255)
last_name String @db.VarChar(255)
email String @unique @db.VarChar(255)
phone_number String? @db.VarChar(50)
cell_phone_number String? @unique @db.VarChar(50)
civility ECivility @default(MALE)
address Addresses? @relation(fields: [address_uid], references: [uid], onDelete: Cascade)
address_uid String @unique @db.VarChar(255)
birthdate DateTime?
created_at DateTime? @default(now())
updated_at DateTime? @updatedAt
users Users?
customers Customers?
@@map("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)
created_at DateTime? @default(now())
updated_at DateTime? @updatedAt
office_membership Offices @relation(fields: [office_uid], references: [uid], onDelete: Cascade)
office_uid String @db.VarChar(255)
user_has_notifications UserHasNotifications[]
office_folder_has_stakeholder OfficeFolderHasStakeholders[]
@@map("users")
}
model Offices {
uid String @id @unique @default(uuid())
idNot String @unique @db.VarChar(255)
name String @db.VarChar(255)
crpcen String @unique @db.VarChar(255)
address Addresses @relation(fields: [address_uid], references: [uid], onDelete: Cascade)
address_uid String @unique @db.VarChar(255)
office_status EOfficeStatus @default(DESACTIVATED)
created_at DateTime? @default(now())
updated_at DateTime? @updatedAt
deed_types DeedTypes[]
users Users[]
office_folders OfficeFolders[]
document_types DocumentTypes[]
@@map("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_folder_has_customers OfficeFolderHasCustomers[]
documents Documents[]
@@map("customers")
}
model UserHasNotifications {
uid String @id @unique @default(uuid())
user Users @relation(fields: [user_uid], references: [uid])
user_uid String @db.VarChar(255)
notification Notifications @relation(fields: [notification_uid], references: [uid], onDelete: Cascade)
notification_uid String @db.VarChar(255)
notification_status ENotificationStatus @default(UNREAD)
created_at DateTime? @default(now())
updated_at DateTime? @updatedAt
@@unique([notification_uid, user_uid])
@@map("user_has_notifications")
}
model Notifications {
uid String @id @unique @default(uuid())
message String @db.VarChar(255)
redirection_url String @db.VarChar(255)
created_at DateTime? @default(now())
updated_at DateTime? @updatedAt
user_has_notifications UserHasNotifications[]
@@map("notifications")
}
model OfficeFolders {
uid String @id @unique @default(uuid())
folder_number String @db.VarChar(255)
name String @db.VarChar(255)
description String? @db.VarChar(255)
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
office_folder_has_customers OfficeFolderHasCustomers[]
office_folder_has_stakeholder OfficeFolderHasStakeholders[]
documents Documents[]
@@unique([folder_number, office_uid])
@@map("office_folders")
}
model OfficeFolderHasCustomers {
uid String @id @unique @default(uuid())
customer Customers @relation(fields: [customer_uid], references: [uid], onDelete: Cascade)
customer_uid String @db.VarChar(255)
office_folder OfficeFolders @relation(fields: [office_folder_uid], references: [uid], onDelete: Cascade)
office_folder_uid String @db.VarChar(255)
created_at DateTime? @default(now())
updated_at DateTime? @updatedAt
@@unique([office_folder_uid, customer_uid])
@@map("office_folder_has_customers")
}
model OfficeFolderHasStakeholders {
uid String @id @unique @default(uuid())
office_folder OfficeFolders @relation(fields: [office_folder_uid], references: [uid], onDelete: Cascade)
office_folder_uid String @db.VarChar(255)
user_stakeholder Users @relation(fields: [user_stakeholder_uid], references: [uid], onDelete: Cascade)
user_stakeholder_uid String @db.VarChar(255)
created_at DateTime? @default(now())
updated_at DateTime? @updatedAt
@@unique([office_folder_uid, user_stakeholder_uid])
@@map("office_folder_has_stakeholder")
}
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)
blockchain_anchor BlockchainAnchors? @relation(fields: [blockchain_anchor_uid], references: [uid])
blockchain_anchor_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[]
@@map("documents")
}
model DocumentHistory {
uid String @id @unique @default(uuid())
document_status EDocumentStatus @default(ASKED)
refused_reason String? @db.VarChar(255)
document Documents @relation(fields: [document_uid], references: [uid], onDelete: Cascade)
document_uid String @db.VarChar(255)
created_at DateTime? @default(now())
updated_at DateTime? @updatedAt
@@map("document_history")
}
model Files {
uid String @id @unique @default(uuid())
document Documents @relation(fields: [document_uid], references: [uid], onDelete: Cascade)
document_uid String @db.VarChar(255)
file_path String @unique @db.VarChar(255)
created_at DateTime? @default(now())
updated_at DateTime? @updatedAt
@@map("files")
}
model BlockchainAnchors {
uid String @id @unique @default(uuid())
smartSigJobId String @unique @db.VarChar(255)
created_at DateTime? @default(now())
updated_at DateTime? @updatedAt
documents Documents[]
@@map("blockchain_anchors")
}
model DocumentTypes {
uid String @id @unique @default(uuid())
name String @db.VarChar(255)
public_description String @db.VarChar(255)
private_description String? @db.VarChar(255)
office Offices @relation(fields: [office_uid], references: [uid], onDelete: Cascade)
office_uid String @db.VarChar(255)
archived_at DateTime?
created_at DateTime? @default(now())
updated_at DateTime? @updatedAt
documents Documents[]
deed_has_document_types DeedHasDocumentTypes[]
deed_type_has_document_types DeedTypeHasDocumentTypes[]
@@unique([name, office_uid])
@@map("document_types")
}
model DeedHasDocumentTypes {
uid String @id @unique @default(uuid())
document_type DocumentTypes @relation(fields: [document_type_uid], references: [uid], onDelete: Cascade)
document_type_uid String @db.VarChar(255)
deed Deeds @relation(fields: [deed_uid], references: [uid], onDelete: Cascade)
deed_uid String @db.VarChar(255)
created_at DateTime? @default(now())
updated_at DateTime? @updatedAt
@@unique([deed_uid, document_type_uid])
@@map("deed_has_document_types")
}
model Deeds {
uid String @id @unique @default(uuid())
deed_type DeedTypes @relation(fields: [deed_type_uid], references: [uid], onDelete: Cascade)
deed_type_uid String @db.VarChar(255)
created_at DateTime? @default(now())
updated_at DateTime? @updatedAt
deed_has_document_types DeedHasDocumentTypes[]
office_folder OfficeFolders?
@@map("deed")
}
model DeedTypes {
uid String @id @unique @default(uuid())
name String @db.VarChar(255)
description String @db.VarChar(255)
archived_at DateTime?
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
deed Deeds[]
deed_type_has_document_types DeedTypeHasDocumentTypes[]
@@unique([name, office_uid])
@@map("deed_types")
}
model DeedTypeHasDocumentTypes {
uid String @id @unique @default(uuid())
document_type DocumentTypes @relation(fields: [document_type_uid], references: [uid], onDelete: Cascade)
document_type_uid String @db.VarChar(255)
deed_type DeedTypes @relation(fields: [deed_type_uid], references: [uid], onDelete: Cascade)
deed_type_uid String @db.VarChar(255)
created_at DateTime? @default(now())
updated_at DateTime? @updatedAt
@@unique([deed_type_uid, document_type_uid])
@@map("deed_type_has_document_types")
}
enum ECivility {
MALE
FEMALE
OTHERS
}
enum EFolderStatus {
LIVE
ARCHIVED
}
enum EOfficeStatus {
ACTIVATED
DESACTIVATED
}
enum ENotificationStatus {
READ
UNREAD
}
enum ECustomerStatus {
VALIDATED
PENDING
ERRONED
}
enum EDocumentStatus {
ASKED
DEPOSITED
VALIDATED
ANCHORED
REFUSED
}

View File

@ -0,0 +1,512 @@
import {
Addresses,
Contacts,
Customers,
DeedHasDocumentTypes,
DeedTypeHasDocumentTypes,
DeedTypes,
Deeds,
DocumentHistory,
DocumentTypes,
Documents,
EDocumentStatus,
EFolderStatus,
EOfficeStatus,
Files,
OfficeFolderHasCustomers,
OfficeFolders,
Offices,
Users,
ECivility,
ECustomerStatus,
PrismaClient
} from "@prisma/client";
(async () => {
const prisma = new PrismaClient();
const existingData = await prisma.contacts.findFirst({ where: { email: "john.doe@example.com" } });
if (existingData) {
console.log('Seed data already exists. Skipping seeding process.');
return;
}
const randomString = () => {
const chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
let result = "";
for (let i = 10; i > 0; --i) result += chars[Math.floor(Math.random() * chars.length)];
return result;
};
const uidCustomer1: string = randomString();
const uidCustomer2: string = randomString();
const uidContact1: string = randomString();
const uidContact2: string = randomString();
const uidAddress1: string = randomString();
const uidAddress2: string = randomString();
const uidOffice1: string = randomString();
const uidOffice2: string = randomString();
const uidUser1: string = randomString();
const uidUser2: string = randomString();
const uidOfficeFolder1: string = randomString();
const uidOfficeFolder2: string = randomString();
const uidOfficeFolder3: string = randomString();
const uidOfficeFolder4: string = randomString();
const uidOfficeFolder5: string = randomString();
const uidDeed1: string = randomString();
const uidDeed2: string = randomString();
const uidDeed3: string = randomString();
const uidDeed4: string = randomString();
const uidDeed5: string = randomString();
const uidDeedType1: string = randomString();
const uidDeedType2: string = randomString();
const uidDocument1: string = randomString();
const uidDocument2: string = randomString();
const uidDocumentType1: string = randomString();
const uidDocumentType2: string = randomString();
const uidOfficeFolderHasCustomer1: string = randomString();
const uidOfficeFolderHasCustomer2: string = randomString();
const uidFiles1: string = randomString();
const uidFiles2: string = randomString();
const uidDeedHasDocumentType1: string = randomString();
const uidDeedHasDocumentType2: string = randomString();
const uidDeedTypeHasDocumentType1: string = randomString();
const uidDeedTypeHasDocumentType2: string = randomString();
const uidDocumentHistory1: string = randomString();
const uidDocumentHistory2: string = randomString();
const customers: Customers[] = [
{
uid: uidCustomer1,
contact_uid: uidContact1,
created_at: new Date(),
updated_at: new Date(),
status: ECustomerStatus.PENDING,
},
{
uid: uidCustomer2,
contact_uid: uidContact2,
created_at: new Date(),
updated_at: new Date(),
status: ECustomerStatus.PENDING,
},
];
const addresses: Addresses[] = [
{
uid: uidAddress1,
address: "123 Main St",
city: "Los Angeles",
zip_code: 90001,
created_at: new Date(),
updated_at: new Date(),
},
{
uid: uidAddress2,
address: "Rue Pierre Emillion",
city: "Paris",
zip_code: 75003,
created_at: new Date(),
updated_at: new Date(),
},
];
const contacts: Contacts[] = [
{
uid: uidContact1,
address_uid: uidAddress1,
first_name: "John",
last_name: "Doe",
email: "john.doe@example.com",
phone_number: randomString(),
cell_phone_number: randomString(),
birthdate: null,
created_at: new Date(),
updated_at: new Date(),
civility: ECivility.MALE,
},
{
uid: uidContact2,
address_uid: uidAddress2,
first_name: "Jane",
last_name: "Doe",
email: "jane.doe@example.com",
phone_number: randomString(),
cell_phone_number: randomString(),
birthdate: null,
created_at: new Date(),
updated_at: new Date(),
civility: ECivility.FEMALE,
},
];
const offices: Offices[] = [
{
uid: uidOffice1,
idNot: randomString(),
name: "LA Office",
crpcen: randomString(),
address_uid: uidAddress1,
created_at: new Date(),
updated_at: new Date(),
office_status: EOfficeStatus.ACTIVATED,
},
{
uid: uidOffice2,
idNot: randomString(),
name: "NYC Office",
crpcen: randomString(),
address_uid: uidAddress2,
created_at: new Date(),
updated_at: new Date(),
office_status: EOfficeStatus.DESACTIVATED,
},
];
const users: Users[] = [
{
uid: uidUser1,
created_at: new Date(),
updated_at: new Date(),
idNot: randomString(),
contact_uid: uidContact1,
office_uid: uidOffice1,
},
{
uid: uidUser2,
created_at: new Date(),
updated_at: new Date(),
idNot: randomString(),
contact_uid: uidContact2,
office_uid: uidOffice2,
},
];
const officeFolders: OfficeFolders[] = [
{
uid: uidOfficeFolder1,
folder_number: "0001",
name: "Dossier",
deed_uid: uidDeed1,
status: EFolderStatus.LIVE,
created_at: new Date(),
updated_at: new Date(),
office_uid: uidOffice1,
description: null,
archived_description: null,
},
{
uid: uidOfficeFolder2,
folder_number: "0002",
name: "Dossier",
deed_uid: uidDeed2,
status: EFolderStatus.LIVE,
created_at: new Date(),
updated_at: new Date(),
office_uid: uidOffice2,
description: null,
archived_description: null,
},
{
uid: uidOfficeFolder3,
folder_number: "0003",
name: "Dossier",
deed_uid: uidDeed3,
status: EFolderStatus.LIVE,
created_at: new Date(),
updated_at: new Date(),
office_uid: uidOffice2,
description: null,
archived_description: null,
},
{
uid: uidOfficeFolder4,
folder_number: "0004",
name: "Dossier",
deed_uid: uidDeed4,
status: EFolderStatus.ARCHIVED,
created_at: new Date(),
updated_at: new Date(),
office_uid: uidOffice2,
description: null,
archived_description: null,
},
{
uid: uidOfficeFolder5,
folder_number: "0005",
name: "Dossier",
deed_uid: uidDeed5,
status: EFolderStatus.ARCHIVED,
created_at: new Date(),
updated_at: new Date(),
office_uid: uidOffice2,
description: null,
archived_description: null,
}
];
const deeds: Deeds[] = [
{
uid: uidDeed1,
deed_type_uid: uidDeedType1,
created_at: new Date(),
updated_at: new Date(),
},
{
uid: uidDeed2,
deed_type_uid: uidDeedType2,
created_at: new Date(),
updated_at: new Date(),
},
{
uid: uidDeed3,
deed_type_uid: uidDeedType2,
created_at: new Date(),
updated_at: new Date(),
},
{
uid: uidDeed4,
deed_type_uid: uidDeedType2,
created_at: new Date(),
updated_at: new Date(),
},
{
uid: uidDeed5,
deed_type_uid: uidDeedType2,
created_at: new Date(),
updated_at: new Date(),
}
];
const deedTypes: DeedTypes[] = [
{
uid: uidDeedType1,
name: "Acte de mariage",
archived_at: null,
description: "Acte regroupant deux personnes en mariage",
office_uid: uidOffice1,
created_at: new Date(),
updated_at: new Date(),
},
{
uid: uidDeedType2,
name: "Vente d'un bien immobilier",
archived_at: null,
description: "Permet de vendre un bien immobilier à une entité ou une personne physique",
office_uid: uidOffice2,
created_at: new Date(),
updated_at: new Date(),
},
];
const documents: Documents[] = [
{
uid: uidDocument1,
blockchain_anchor_uid: null,
depositor_uid: uidCustomer1,
document_status: EDocumentStatus.ASKED,
folder_uid: uidOfficeFolder1,
document_type_uid: uidDocumentType1,
created_at: new Date(),
updated_at: new Date(),
},
{
uid: uidDocument2,
blockchain_anchor_uid: null,
depositor_uid: uidCustomer2,
document_status: EDocumentStatus.ASKED,
folder_uid: uidOfficeFolder2,
document_type_uid: uidDocumentType2,
created_at: new Date(),
updated_at: new Date(),
},
];
const documentTypes: DocumentTypes[] = [
{
uid: uidDocumentType1,
archived_at: null,
name: "Acte de naissance",
office_uid: uidOffice1,
private_description: "Ce document est confidentiel, et ne doit pas être divulgué",
public_description: "Acte de naissance est un document officiel qui atteste de la naissance d'une personne",
created_at: new Date(),
updated_at: new Date(),
},
{
uid: uidDocumentType2,
archived_at: null,
name: "Carte d'identité",
office_uid: uidOffice2,
private_description: "Ce document est confidentiel, demander un recto-verso au client",
public_description: "Carte d'identité est un document officiel qui atteste de l'identité d'une personne",
created_at: new Date(),
updated_at: new Date(),
},
];
const officeFolderHasCustomers: OfficeFolderHasCustomers[] = [
{
uid: uidOfficeFolderHasCustomer1,
customer_uid: uidCustomer1,
office_folder_uid: uidOfficeFolder1,
created_at: new Date(),
updated_at: new Date(),
},
{
uid: uidOfficeFolderHasCustomer2,
customer_uid: uidCustomer2,
office_folder_uid: uidOfficeFolder2,
created_at: new Date(),
updated_at: new Date(),
},
];
const files: Files[] = [
{
uid: uidFiles1,
document_uid: uidDocument1,
file_path: "https://www.google1.com",
created_at: new Date(),
updated_at: new Date(),
},
{
uid: uidFiles2,
document_uid: uidDocument2,
file_path: "https://www.google2.com",
created_at: new Date(),
updated_at: new Date(),
},
];
const deedHasDocumentTypes: DeedHasDocumentTypes[] = [
{
uid: uidDeedHasDocumentType1,
deed_uid: uidDeed1,
document_type_uid: uidDocumentType1,
created_at: new Date(),
updated_at: new Date(),
},
{
uid: uidDeedHasDocumentType2,
deed_uid: uidDeed2,
document_type_uid: uidDocumentType2,
created_at: new Date(),
updated_at: new Date(),
},
];
const deedTypeHasDocumentTypes: DeedTypeHasDocumentTypes[] = [
{
uid: uidDeedTypeHasDocumentType1,
deed_type_uid: uidDeedType1,
document_type_uid: uidDocumentType1,
created_at: new Date(),
updated_at: new Date(),
},
{
uid: uidDeedTypeHasDocumentType2,
deed_type_uid: uidDeedType2,
document_type_uid: uidDocumentType2,
created_at: new Date(),
updated_at: new Date(),
},
];
const documentHistories: DocumentHistory[] = [
{
uid: uidDocumentHistory1,
document_status: EDocumentStatus.ASKED,
document_uid: uidDocument1,
refused_reason: "Le document n'est pas conforme",
created_at: new Date(),
updated_at: new Date(),
},
{
uid: uidDocumentHistory2,
document_status: EDocumentStatus.DEPOSITED,
document_uid: uidDocument1,
refused_reason: "Le document n'est pas conforme",
created_at: new Date(),
updated_at: new Date(),
},
];
for (const address of addresses) {
await prisma.addresses.create({data: address});
}
for (const contact of contacts) {
await prisma.contacts.create({ data: contact });
}
for (const office of offices) {
await prisma.offices.create({ data: office });
}
for (const user of users) {
await prisma.users.create({ data: user });
}
for (const customer of customers) {
await prisma.customers.create({ data: customer });
}
for (const deedType of deedTypes) {
await prisma.deedTypes.create({ data: deedType });
}
for (const deed of deeds) {
await prisma.deeds.create({ data: deed });
}
for (const officeFolder of officeFolders) {
await prisma.officeFolders.create({ data: officeFolder });
}
for (const documentType of documentTypes) {
await prisma.documentTypes.create({ data: documentType });
}
for (const document of documents) {
await prisma.documents.create({ data: document });
}
for (const file of files) {
await prisma.files.create({ data: file });
}
for (const documentHistory of documentHistories) {
await prisma.documentHistory.create({ data: documentHistory });
}
for (const officeFolderHasCustomer of officeFolderHasCustomers) {
await prisma.officeFolderHasCustomers.create({ data: officeFolderHasCustomer });
}
for (const deedHasDocumentType of deedHasDocumentTypes) {
await prisma.deedHasDocumentTypes.create({ data: deedHasDocumentType });
}
for (const deedTypeHasDocumentType of deedTypeHasDocumentTypes) {
await prisma.deedTypeHasDocumentTypes.create({ data: deedTypeHasDocumentType });
}
console.log(">MOCK DATA - Seeding completed!");
})();

View File

@ -0,0 +1,13 @@
import { type ClassTransformOptions, plainToClassFromExist, plainToInstance } from "class-transformer";
export default abstract class ObjectHydrate {
public static hydrate<T = {}>(object: T, from: Partial<T>, options?: ClassTransformOptions): T {
return plainToClassFromExist(object, from, options);
}
public static map<T = {}>(ClassEntity: { new (): T }, fromArray: Partial<T>[], options?: ClassTransformOptions): T[] {
return fromArray.map((from) => {
return plainToInstance(ClassEntity, from, options);
});
}
}

View File

@ -0,0 +1,42 @@
import Database from "@Common/databases/database";
import BaseRepository from "@Repositories/BaseRepository";
import { Service } from "typedi";
import { Addresses } from "@prisma/client";
@Service()
export default class AddressesRepository extends BaseRepository {
constructor(private database: Database) {
super();
}
protected get model() {
return this.database.getClient().addresses;
}
protected get instanceDb() {
return this.database.getClient();
}
/**
* @description : Find many addresses
*/
public async findMany(query: any): Promise<Addresses[]> {
query.take = Math.min(query.take || this.defaultFetchRows, this.maxFetchRows);
return this.model.findMany(query);
}
/**
* @description : Find one address
*/
public async findOneByUid(uid: string): Promise<Addresses> {
const addressEntity = await this.model.findUnique({
where: {
uid: uid,
},
});
if (!addressEntity) {
throw new Error("Address not found");
}
return addressEntity;
}
}

View File

@ -0,0 +1,4 @@
export default abstract class BaseRepository {
protected readonly maxFetchRows = 100;
protected readonly defaultFetchRows = 50;
}

View File

@ -0,0 +1,42 @@
import Database from "@Common/databases/database";
import BaseRepository from "@Repositories/BaseRepository";
import { Service } from "typedi";
import { Contacts } from "@prisma/client";
@Service()
export default class ContactsRepository extends BaseRepository {
constructor(private database: Database) {
super();
}
protected get model() {
return this.database.getClient().contacts;
}
protected get instanceDb() {
return this.database.getClient();
}
/**
* @description : Find many contacts
*/
public async findMany(query: any): Promise<Contacts[]> {
query.take = Math.min(query.take || this.defaultFetchRows, this.maxFetchRows);
return this.model.findMany(query);
}
/**
* @description : Find unique contact
*/
public async findOneByUid(uid: string): Promise<Contacts> {
const contactEntity = await this.model.findUnique({
where: {
uid: uid,
},
});
if (!contactEntity) {
throw new Error("contact not found");
}
return contactEntity;
}
}

View File

@ -0,0 +1,111 @@
import Database from "@Common/databases/database";
import BaseRepository from "@Repositories/BaseRepository";
import { Service } from "typedi";
import { Customers, ECivility, ECustomerStatus, Prisma } from "@prisma/client";
import { Customer } from "le-coffre-resources/dist/SuperAdmin";
@Service()
export default class CustomersRepository extends BaseRepository {
constructor(private database: Database) {
super();
}
protected get model() {
return this.database.getClient().customers;
}
protected get instanceDb() {
return this.database.getClient();
}
/**
* @description : Find many customers
*/
public async findMany(query: any): Promise<Customers[]> {
query.take = Math.min(query.take || this.defaultFetchRows, this.maxFetchRows);
return this.model.findMany(query);
}
/**
* @description : Create a customer
*/
public async create(customer: Customer): Promise<Customers> {
const createArgs: Prisma.CustomersCreateArgs = {
data: {
status: ECustomerStatus.PENDING,
contact: {
create: {
first_name: customer.contact.first_name,
last_name: customer.contact.last_name,
email: customer.contact.email,
phone_number: customer.contact.phone_number,
cell_phone_number: customer.contact?.cell_phone_number,
civility: ECivility[customer.contact.civility as keyof typeof ECivility],
address: {}
},
},
},
};
if (customer.contact.address) {
createArgs.data.contact!.create!.address!.create = {
address: customer.contact.address!.address,
zip_code: customer.contact.address!.zip_code,
city: customer.contact.address!.city,
};
}
return this.model.create(createArgs);
}
/**
* @description : Update data from a customer
*/
public async update(uid: string, customer: Customer): Promise<Customers> {
const updateArgs: Prisma.CustomersUpdateArgs = {
where: {
uid: uid,
},
data: {
status: ECustomerStatus[customer.status as keyof typeof ECustomerStatus],
contact: {
update: {
first_name: customer.contact.first_name,
last_name: customer.contact.last_name,
email: customer.contact.email,
phone_number: customer.contact.phone_number,
cell_phone_number: customer.contact.cell_phone_number,
civility: ECivility[customer.contact.civility as keyof typeof ECivility],
address: {}
},
},
},
}
if (customer.contact.address) {
updateArgs.data.contact!.update!.address!.update = {
address: customer.contact.address!.address,
zip_code: customer.contact.address!.zip_code,
city: customer.contact.address!.city,
};
}
return this.model.update(updateArgs);
}
/**
* @description : Find unique customer
*/
public async findOneByUid(uid: string, query?: any): Promise<Customers> {
const findOneArgs: Prisma.CustomersFindUniqueArgs = {
where: {
uid: uid,
}
};
if(query) {
findOneArgs.include = query
}
const customerEntity = await this.model.findUnique(findOneArgs);
if (!customerEntity) {
throw new Error("Customer not found");
}
return customerEntity;
}
}

View File

@ -0,0 +1,42 @@
import Database from "@Common/databases/database";
import { DeedTypeHasDocumentTypes } from "@prisma/client";
import BaseRepository from "@Repositories/BaseRepository";
import { Service } from "typedi";
@Service()
export default class DeedTypeHasDocumentTypesRepository extends BaseRepository {
constructor(private database: Database) {
super();
}
protected get model() {
return this.database.getClient().deedTypeHasDocumentTypes;
}
protected get instanceDb() {
return this.database.getClient();
}
/**
* @description : Find many relations between deed type and a document type
*/
public async findMany(query: any): Promise<DeedTypeHasDocumentTypes[]> {
query.take = Math.min(query.take || this.defaultFetchRows, this.maxFetchRows);
return this.model.findMany(query);
}
/**
* @description : Find unique relation between deed type and a document type
*/
public async findOneByUid(uid: string): Promise<DeedTypeHasDocumentTypes> {
const deedTypeHasDoculmentTypesEntity = await this.model.findUnique({
where: {
uid: uid,
},
});
if (!deedTypeHasDoculmentTypesEntity) {
throw new Error("deed type not found");
}
return deedTypeHasDoculmentTypesEntity;
}
}

View File

@ -0,0 +1,111 @@
import Database from "@Common/databases/database";
import BaseRepository from "@Repositories/BaseRepository";
import { Service } from "typedi";
import { DeedTypes, Prisma } from "@prisma/client";
import { DeedType } from "le-coffre-resources/dist/SuperAdmin";
@Service()
export default class DeedTypesRepository extends BaseRepository {
constructor(private database: Database) {
super();
}
protected get model() {
return this.database.getClient().deedTypes;
}
protected get instanceDb() {
return this.database.getClient();
}
/**
* @description : Find many deed types
*/
public async findMany(query: any): Promise<DeedTypes[]> {
query.take = Math.min(query.take || this.defaultFetchRows, this.maxFetchRows);
return this.model.findMany(query);
}
/**
* @description : Create new deed type
*/
public async create(deedType: DeedType): Promise<DeedTypes> {
const createArgs: Prisma.DeedTypesCreateArgs = {
data: {
name: deedType.name,
description: deedType.description,
office: {
connect: {
uid: deedType.office.uid,
},
},
}
};
if (deedType.deed_type_has_document_types) {
createArgs.data.deed_type_has_document_types = {
createMany: {
data: deedType.deed_type_has_document_types.map((relation) => ({
document_type_uid: relation.document_type.uid!,
})),
skipDuplicates: true,
},
};
}
return this.model.create(createArgs);
}
/**
* @description : Update data of a deed type
*/
public async update(uid: string, deedType: DeedType): Promise<DeedTypes> {
const updateArgs: Prisma.DeedTypesUpdateArgs = {
where: {
uid: uid,
},
data: {
name: deedType.name,
description: deedType.description,
archived_at: deedType.archived_at,
office: {
connect: {
uid: deedType.office.uid,
},
},
},
include: {
deed_type_has_document_types: true,
},
};
if (deedType.deed_type_has_document_types) {
updateArgs.data.deed_type_has_document_types = {
deleteMany: { deed_type_uid: uid },
createMany: {
data: deedType.deed_type_has_document_types.map((relation) => ({
document_type_uid: relation.document_type.uid!,
})),
skipDuplicates: true,
},
};
}
return this.model.update(updateArgs);
}
/**
* @description : Find unique deed type
*/
public async findOneByUid(uid: string, query?: any): Promise<DeedTypes> {
const findOneArgs: Prisma.DeedTypesFindUniqueArgs = {
where: {
uid: uid,
}
};
if(query) {
findOneArgs.include = query
}
const deedTypeEntity = await this.model.findUnique(findOneArgs);
if (!deedTypeEntity) {
throw new Error("deed type not found");
}
return deedTypeEntity;
}
}

View File

@ -0,0 +1,42 @@
import Database from "@Common/databases/database";
import { DeedHasDocumentTypes } from "@prisma/client";
import BaseRepository from "@Repositories/BaseRepository";
import { Service } from "typedi";
@Service()
export default class DeedHasDocumentTypesRepository extends BaseRepository {
constructor(private database: Database) {
super();
}
protected get model() {
return this.database.getClient().deedHasDocumentTypes;
}
protected get instanceDb() {
return this.database.getClient();
}
/**
* @description : Find many deeds
*/
public async findMany(query: any): Promise<DeedHasDocumentTypes[]> {
query.take = Math.min(query.take || this.defaultFetchRows, this.maxFetchRows);
return this.model.findMany(query);
}
/**
* @description : Find unique relation between deed and a document type
*/
public async findOneByUid(uid: string): Promise<DeedHasDocumentTypes> {
const deedHasDocumentTypesEntity = await this.model.findUnique({
where: {
uid: uid,
},
});
if (!deedHasDocumentTypesEntity) {
throw new Error("relation between deed and document type not found");
}
return deedHasDocumentTypesEntity;
}
}

View File

@ -0,0 +1,105 @@
import Database from "@Common/databases/database";
import BaseRepository from "@Repositories/BaseRepository";
import { Service } from "typedi";
import { Deeds, Prisma } from "@prisma/client";
import { Deed } from "le-coffre-resources/dist/Notary";
@Service()
export default class DeedsRepository extends BaseRepository {
constructor(private database: Database) {
super();
}
protected get model() {
return this.database.getClient().deeds;
}
protected get instanceDb() {
return this.database.getClient();
}
/**
* @description : Find many users
*/
public async findMany(query: any): Promise<Deeds[]> {
query.take = Math.min(query.take || this.defaultFetchRows, this.maxFetchRows);
return this.model.findMany(query);
}
/**
* @description : Create a deed based on a deed type
*/
public async create(deed: Deed): Promise<Deeds> {
const createArgs: Prisma.DeedsCreateArgs = {
data: {
deed_type: {
connect: {
uid: deed.deed_type.uid,
},
},
},
};
const deedTypeWithDocumentTypes = await this.instanceDb.deedTypes.findUniqueOrThrow({
where: {
uid: deed.deed_type.uid,
},
include: { deed_type_has_document_types: true },
});
if (deedTypeWithDocumentTypes.archived_at) throw new Error("deed type is archived");
if (deedTypeWithDocumentTypes.deed_type_has_document_types) {
createArgs.data.deed_has_document_types = {
createMany: {
data: deedTypeWithDocumentTypes.deed_type_has_document_types.map((relation) => ({
document_type_uid: relation.document_type_uid,
})),
skipDuplicates: true,
},
};
}
return this.model.create(createArgs);
}
/**
* @description : Update data of a deed type
*/
public async update(uid: string, deed: Deed): Promise<Deeds> {
const updateArgs: Prisma.DeedsUpdateArgs = {
where: {
uid: uid,
},
data: {},
include: {
deed_has_document_types: true,
},
};
if (deed.deed_has_document_types) {
updateArgs.data.deed_has_document_types = {
deleteMany: { deed_uid: uid },
createMany: {
data: deed.deed_has_document_types.map((relation) => ({
document_type_uid: relation.document_type.uid!,
})),
skipDuplicates: true,
},
};
}
return this.model.update(updateArgs);
}
/**
* @description : Find unique deed
*/
public async findOneByUid(uid: string): Promise<Deeds> {
const deedTypeEntity = await this.model.findUnique({
where: {
uid: uid,
},
});
if (!deedTypeEntity) {
throw new Error("deed not found");
}
return deedTypeEntity;
}
}

View File

@ -0,0 +1,87 @@
import Database from "@Common/databases/database";
import BaseRepository from "@Repositories/BaseRepository";
import { Service } from "typedi";
import { DocumentTypes, Prisma } from "prisma/prisma-client";
import { DocumentType } from "le-coffre-resources/dist/SuperAdmin";
@Service()
export default class DocumentTypesRepository extends BaseRepository {
constructor(private database: Database) {
super();
}
protected get model() {
return this.database.getClient().documentTypes;
}
protected get instanceDb() {
return this.database.getClient();
}
/**
* @description : Find many document types
*/
public async findMany(query: any): Promise<DocumentTypes[]> {
query.take = Math.min(query.take || this.defaultFetchRows, this.maxFetchRows);
return this.model.findMany(query);
}
/**
* @description : Create a document type
*/
public async create(documentType: DocumentType): Promise<DocumentTypes> {
return this.model.create({
data: {
name: documentType.name,
public_description: documentType.public_description,
private_description: documentType.private_description,
office: {
connect: {
uid: documentType.office.uid,
},
},
},
});
}
/**
* @description : update given document type
*/
public async update(uid: string, documentType: DocumentType): Promise<DocumentTypes> {
return this.model.update({
where: {
uid: uid,
},
data: {
name: documentType.name,
public_description: documentType.public_description,
private_description: documentType.private_description,
archived_at: documentType.archived_at,
office: {
connect: {
uid: documentType.office.uid,
},
},
},
});
}
/**
* @description : find unique document type
*/
public async findOneByUid(uid: string, query?: any): Promise<DocumentTypes> {
const findOneArgs: Prisma.DocumentTypesFindUniqueArgs = {
where: {
uid: uid,
}
};
if(query) {
findOneArgs.include = query
}
const documentTypeEntity = await this.model.findUnique(findOneArgs);
if (!documentTypeEntity) {
throw new Error("Document Type not found");
}
return documentTypeEntity;
}
}

View File

@ -0,0 +1,133 @@
import Database from "@Common/databases/database";
import BaseRepository from "@Repositories/BaseRepository";
import { Service } from "typedi";
import { Documents, EDocumentStatus, Prisma } from "@prisma/client";
import { Document } from "le-coffre-resources/dist/SuperAdmin";
@Service()
export default class DocumentsRepository extends BaseRepository {
constructor(private database: Database) {
super();
}
protected get model() {
return this.database.getClient().documents;
}
protected get instanceDb() {
return this.database.getClient();
}
/**
* @description : Find many documents
*/
public async findMany(query: any): Promise<Documents[]> {
query.take = Math.min(query.take || this.defaultFetchRows, this.maxFetchRows);
return this.model.findMany(query);
}
/**
* @description : Create a document
*/
public async create(document: Document): Promise<Documents> {
const documentCreated = await this.model.create({
data: {
folder: {
connect: {
uid: document.folder.uid,
},
},
depositor: {
connect: {
uid: document.depositor.uid,
},
},
document_type: {
connect: {
uid: document.document_type.uid,
},
},
},
});
await this.instanceDb.documentHistory.create({
data: {
document: {
connect: {
uid: documentCreated.uid,
},
},
},
});
return documentCreated;
}
/**
* @description : Create many documents linked to an office folder
*/
public async createMany(documents: Document[]): Promise<Prisma.BatchPayload> {
return this.model.createMany({
data: documents.map((document) => ({
folder_uid: document.folder.uid!,
depositor_uid: document.depositor.uid!,
document_type_uid: document.document_type.uid!,
})),
skipDuplicates: true,
});
}
/**
* @description : Update data of a document
*/
public async update(uid: string, document: Document, refusedReason?: string): 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],
refused_reason: refusedReason,
},
},
depositor: {
connect: {
uid: document.depositor.uid,
},
},
},
});
}
/**
* @description : Delete a document
*/
public async delete(uid: string): Promise<Documents> {
return this.model.delete({
where: {
uid: uid,
},
});
}
/**
* @description : Find unique document
*/
public async findOneByUid(uid: string, query?: any): Promise<Documents> {
const findOneArgs: Prisma.DocumentsFindUniqueArgs = {
where: {
uid: uid,
}
};
if(query) {
findOneArgs.include = query
}
const documentEntity = await this.model.findUnique(findOneArgs);
if (!documentEntity) {
throw new Error("Document not found");
}
return documentEntity;
}
}

View File

@ -0,0 +1,84 @@
import Database from "@Common/databases/database";
import BaseRepository from "@Repositories/BaseRepository";
import { Service } from "typedi";
import { Files } from "@prisma/client";
import { File } from "le-coffre-resources/dist/SuperAdmin"
@Service()
export default class FilesRepository extends BaseRepository {
constructor(private database: Database) {
super();
}
protected get model() {
return this.database.getClient().files;
}
protected get instanceDb() {
return this.database.getClient();
}
/**
* @description : Find many files
*/
public async findMany(query: any): Promise<Files[]> {
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: File): Promise<Files> {
return this.model.create({
data: {
document: {
connect: {
uid: file.document.uid
}
},
file_path: file.file_path
},
});
}
/**
* @description : Update data of a file
*/
public async update(uid: string, file: File): Promise<Files> {
return this.model.update({
where: {
uid: uid,
},
data: {
file_path: file.file_path
},
});
}
/**
* @description : Delete a file
*/
public async delete(uid: string): Promise<Files> {
return this.model.delete({
where: {
uid: uid,
}
});
}
/**
* @description : Find unique file
*/
public async findOneByUid(uid: string): Promise<Files> {
const fileEntity = await this.model.findUnique({
where: {
uid: uid,
},
});
if (!fileEntity) {
throw new Error("File not found");
}
return fileEntity;
}
}

View File

@ -0,0 +1,43 @@
import Database from "@Common/databases/database";
import { OfficeFolderHasCustomers } from "@prisma/client";
import BaseRepository from "@Repositories/BaseRepository";
import { Service } from "typedi";
@Service()
export default class OfficeFoldersHasCustomerRepository extends BaseRepository {
constructor(private database: Database) {
super();
}
protected get model() {
return this.database.getClient().officeFolderHasCustomers;
}
protected get instanceDb() {
return this.database.getClient();
}
/**
* @description : Find many relations
*/
public async findMany(query: any): Promise<OfficeFolderHasCustomers[]> {
query.take = Math.min(query.take || this.defaultFetchRows, this.maxFetchRows);
return this.model.findMany(query);
}
/**
* @description : Find a unique relation between an office folder and customers
*/
public async findOneByUid(uid: string): Promise<OfficeFolderHasCustomers> {
const officeFolderHasCustomersEntity = await this.model.findUnique({
where: {
uid: uid,
},
});
if (!officeFolderHasCustomersEntity) {
throw new Error("relation between office folder and customer not found");
}
return officeFolderHasCustomersEntity;
}
}

View File

@ -0,0 +1,42 @@
import Database from "@Common/databases/database";
import { OfficeFolderHasStakeholders } from "@prisma/client";
import BaseRepository from "@Repositories/BaseRepository";
import { Service } from "typedi";
@Service()
export default class OfficeFoldersHasStakeholderRepository extends BaseRepository {
constructor(private database: Database) {
super();
}
protected get model() {
return this.database.getClient().officeFolderHasStakeholders;
}
protected get instanceDb() {
return this.database.getClient();
}
/**
* @description : Find many relations
*/
public async findMany(query: any): Promise<OfficeFolderHasStakeholders[]> {
query.take = Math.min(query.take || this.defaultFetchRows, this.maxFetchRows);
return this.model.findMany(query);
}
/**
* @description : Find a unique relation between an office folder and stakeholders
*/
public async findOneByUid(uid: string): Promise<OfficeFolderHasStakeholders> {
const officeFolderHasStakeholdersEntity = await this.model.findUnique({
where: {
uid: uid,
},
});
if (!officeFolderHasStakeholdersEntity) {
throw new Error("relation between office folder and stakeholder not found");
}
return officeFolderHasStakeholdersEntity;
}
}

View File

@ -0,0 +1,146 @@
import Database from "@Common/databases/database";
import BaseRepository from "@Repositories/BaseRepository";
import { Service } from "typedi";
import { EFolderStatus, OfficeFolders, Prisma } from "@prisma/client";
import { OfficeFolder } from "le-coffre-resources/dist/SuperAdmin";
@Service()
export default class OfficeFoldersRepository extends BaseRepository {
constructor(private database: Database) {
super();
}
protected get model() {
return this.database.getClient().officeFolders;
}
protected get instanceDb() {
return this.database.getClient();
}
/**
* @description : Find many office folders
*/
public async findMany(query: any): Promise<OfficeFolders[]> {
query.take = Math.min(query.take || this.defaultFetchRows, this.maxFetchRows);
return this.model.findMany(query);
}
/**
* @description : Create new office folder with stakeholders
*/
public async create(officeFolder: OfficeFolder): Promise<OfficeFolders> {
const createArgs: Prisma.OfficeFoldersCreateArgs = {
data: {
folder_number: officeFolder.folder_number,
name: officeFolder.name,
description: officeFolder.description,
status: EFolderStatus.LIVE,
deed: {
create: {
deed_type: {
connect: {
uid: officeFolder.deed.deed_type.uid,
},
},
},
},
office: {
connect: {
idNot: officeFolder.office.idNot,
},
},
},
include: {
office_folder_has_stakeholder: true,
}
};
if (officeFolder.office_folder_has_stakeholder) {
createArgs.data.office_folder_has_stakeholder = {
createMany: {
data: officeFolder.office_folder_has_stakeholder.map((relation) => ({
user_stakeholder_uid: relation.user_stakeholder.uid!,
})),
skipDuplicates: true
},
};
}
return this.model.create(createArgs);
}
/**
* @description : Update data of an office folder
*/
public async update(officeFolderuid: string, officeFolder: OfficeFolder): Promise<OfficeFolders> {
const updateArgs: Prisma.OfficeFoldersUpdateArgs = {
where: {
uid: officeFolderuid,
},
data: {
folder_number: officeFolder.folder_number,
name: officeFolder.name,
description: officeFolder.description,
status: EFolderStatus[officeFolder.status as keyof typeof EFolderStatus],
archived_description: officeFolder.archived_description,
},
include: {
office_folder_has_stakeholder: true,
office_folder_has_customers: true,
documents: true,
}
};
if (officeFolder.office_folder_has_stakeholder) {
updateArgs.data.office_folder_has_stakeholder = {
deleteMany: { office_folder_uid: officeFolderuid },
createMany: {
data: officeFolder.office_folder_has_stakeholder.map((relation) => ({
user_stakeholder_uid: relation.user_stakeholder.uid!,
})),
skipDuplicates: true
},
}
}
if (officeFolder.office_folder_has_customers) {
updateArgs.data.office_folder_has_customers = {
deleteMany: { office_folder_uid: officeFolderuid },
createMany: {
data: officeFolder.office_folder_has_customers.map((relation) => ({
customer_uid: relation.customer.uid!,
})),
skipDuplicates: true
},
}
}
if (officeFolder.documents) {
updateArgs.data.documents = {
createMany: {
data: officeFolder.documents.map((relation) => ({
document_type_uid: relation.document_type.uid!,
depositor_uid: relation.depositor.uid!
})),
skipDuplicates: true
},
}
}
return this.model.update(updateArgs);
}
/**
* @description : Find one office folder
*/
public async findOneByUid(uid: string, query?: any): Promise<OfficeFolders> {
const findOneArgs: Prisma.OfficeFoldersFindUniqueArgs = {
where: {
uid: uid,
}
};
if(query) {
findOneArgs.include = query
}
const officeFolderEntity = await this.model.findUnique(findOneArgs);
if (!officeFolderEntity) {
throw new Error("office folder not found");
}
return officeFolderEntity;
}
}

View File

@ -0,0 +1,92 @@
import Database from "@Common/databases/database";
import BaseRepository from "@Repositories/BaseRepository";
import { Service } from "typedi";
import { EOfficeStatus, Offices, Prisma } from "@prisma/client";
import { Office as OfficeRessource } from "le-coffre-resources/dist/SuperAdmin";
@Service()
export default class OfficesRepository extends BaseRepository {
constructor(private database: Database) {
super();
}
protected get model() {
return this.database.getClient().offices;
}
protected get instanceDb() {
return this.database.getClient();
}
/**
* @description : Find many users
*/
public async findMany(query: any): Promise<Offices[]> {
query.take = Math.min(query.take || this.defaultFetchRows, this.maxFetchRows);
return this.model.findMany(query);
}
/**
* @description : Create an office
*/
public async create(office: OfficeRessource): Promise<Offices> {
return this.model.create({
data: {
idNot: office.idNot,
name: office.name,
crpcen: office.crpcen,
address: {
create: {
address: office.address.address,
zip_code: office.address.zip_code,
city: office.address.city,
},
},
office_status: EOfficeStatus.DESACTIVATED,
},
});
}
/**
* @description : Update data from an office
*/
public async update(uid: string, office: OfficeRessource): Promise<Offices> {
return this.model.update({
where: {
uid: uid,
},
data: {
name: office.name,
address: {
create: {
address: office.address.address,
zip_code: office.address.zip_code,
city: office.address.city,
},
},
office_status: EOfficeStatus[office.office_status as keyof typeof EOfficeStatus],
},
});
}
/**
* @description : Find one office
*/
public async findOneByUid(uid: string, query?: any): Promise<Offices> {
const findOneArgs: Prisma.OfficesFindUniqueArgs = {
where: {
uid: uid,
}
};
if(query) {
findOneArgs.include = query
}
const officeEntity = await this.model.findUnique(findOneArgs);
if (!officeEntity) {
throw new Error("office not found");
}
return officeEntity;
}
}

View File

@ -0,0 +1,148 @@
import Database from "@Common/databases/database";
import BaseRepository from "@Repositories/BaseRepository";
import { Service } from "typedi";
import { ECivility, Prisma, Users } from "@prisma/client";
import User from "le-coffre-resources/dist/SuperAdmin";
@Service()
export default class UsersRepository extends BaseRepository {
constructor(private database: Database) {
super();
}
protected get model() {
return this.database.getClient().users;
}
protected get instanceDb() {
return this.database.getClient();
}
/**
* @description : Find many users
*/
public async findMany(query: any): Promise<Users[]> {
query.take = Math.min(query.take || this.defaultFetchRows, this.maxFetchRows);
return this.model.findMany(query);
}
/**
* @description : Create a user
*/
public async create(user: User): Promise<Users> {
const createArgs: Prisma.UsersCreateArgs = {
data: {
idNot: user.idNot,
office_membership: {
connectOrCreate: {
where: {
idNot: user.office_membership.idNot,
},
create: {
idNot: user.office_membership.idNot,
name: user.office_membership.name,
crpcen: user.office_membership.crpcen,
address: {
create: {
address: user.office_membership.address.address,
zip_code: user.office_membership.address.zip_code,
city: user.office_membership.address.city,
},
},
},
},
},
contact: {
create: {
first_name: user.contact.first_name,
last_name: user.contact.last_name,
email: user.contact.email,
phone_number: user.contact.phone_number,
cell_phone_number: user.contact.cell_phone_number,
civility: ECivility[user.contact.civility as keyof typeof ECivility],
address: {},
},
},
},
}
if (user.contact.address) {
createArgs.data.contact!.create!.address!.create = {
address: user.contact.address!.address,
zip_code: user.contact.address!.zip_code,
city: user.contact.address!.city,
};
}
return this.model.create(createArgs);
}
/**
* @description : Update data from a user
*/
public async update(uid: string, user: User): Promise<Users> {
const updateArgs: Prisma.UsersUpdateArgs = {
where: {
uid: uid,
},
data: {
idNot: user.idNot,
office_membership: {
connectOrCreate: {
where: {
idNot: user.office_membership.idNot,
},
create: {
idNot: user.office_membership.idNot,
name: user.office_membership.name,
crpcen: user.office_membership.crpcen,
address: {
create: {
address: user.office_membership.address.address,
zip_code: user.office_membership.address.zip_code,
city: user.office_membership.address.city,
},
},
},
},
},
contact: {
update: {
first_name: user.contact.first_name,
last_name: user.contact.last_name,
email: user.contact.email,
phone_number: user.contact.phone_number,
cell_phone_number: user.contact.cell_phone_number,
civility: ECivility[user.contact.civility as keyof typeof ECivility],
address: {}
},
},
},
};
if (user.contact.address) {
updateArgs.data.contact!.update!.address!.update = {
address: user.contact.address!.address,
zip_code: user.contact.address!.zip_code,
city: user.contact.address!.city,
};
}
return this.model.update(updateArgs);
}
/**
* @description : Find one user
*/
public async findOneByUid(uid: string, query?: any): Promise<Users> {
const findOneArgs: Prisma.UsersFindUniqueArgs = {
where: {
uid: uid,
}
};
if(query) {
findOneArgs.include = query
}
const userEntity = await this.model.findUnique(findOneArgs);
if (!userEntity) {
throw new Error("User not found");
}
return userEntity;
}
}

View File

@ -0,0 +1,33 @@
import express, { Express, Router } from "express";
import { Service } from "typedi";
import ServerInterface, { IConfig } from "./ServerInterface";
@Service()
export default class ExpressServer implements ServerInterface {
private router: Express = express();
private subRouter: Router = express.Router();
public getRouter(): Router {
return this.subRouter;
}
public init(config: IConfig) {
this.router.use(...config.middlwares);
this.router.use(config.rootUrl, this.subRouter);
if (config.errorHandler) this.router.use(config.errorHandler);
this.router.listen(config.port, () => {
console.table(
[
{
"Entry label": config.label,
Port: config.port,
"Root url": config.rootUrl,
},
],
["Entry label", "Port", "Root url"],
);
});
return this;
}
}

View File

@ -0,0 +1,39 @@
import express, { Express, Router } from "express";
import { Service } from "typedi";
import ServerInterface, { IConfig } from "./ServerInterface";
@Service()
export default class ExpressServer implements ServerInterface {
public router: Express = express();
private subRouter: Router = express.Router();
public getRouter(): Router {
return this.subRouter;
}
protected getMainRouter(): Express {
return this.router;
}
public init(config: IConfig) {
this.router.use(...config.middlwares);
this.router.use(config.rootUrl, this.subRouter);
if (config.errorHandler) this.router.use(config.errorHandler);
return this;
}
public listen() {
return this.router.listen(3001, () => {
console.table(
[
{
"Entry label": "le coffre API",
Port: 3001,
"Root url": "/api",
},
],
["Entry label", "Port", "Root url"],
);
});
}
}

View File

@ -0,0 +1,50 @@
import express, { Express } from "express";
import { Service } from "typedi";
import next from "next";
import url from "url";
interface IConfig {
label: string;
isDev: boolean;
port: number;
rootUrl: string;
}
@Service()
export default class Server {
private router: Express = express();
constructor() {}
public getRouter(): Express {
return this.router;
}
public init(config: IConfig) {
const app = next({ dev: config.isDev });
const handler = app.getRequestHandler();
app.prepare().then(() => {
const subRouter = express.Router();
subRouter.get("/*", async (req, res) => {
const parsedUrl = url.parse(req.url, true);
await handler(req, res, parsedUrl);
});
this.router.use(config.rootUrl, subRouter);
this.router.listen(config.port, () => {
console.table(
[
{
"Entry label": config.label,
Port: config.port,
"Root url": config.rootUrl,
},
],
["Entry label", "Port", "Root url"],
);
});
});
return this;
}
}

View File

@ -0,0 +1,16 @@
import { NextFunction, Request, Response, Router } from "express";
import { RequestHandlerParams } from "express-serve-static-core";
export interface IConfig {
label: string;
port: number;
rootUrl: string;
middlwares: RequestHandlerParams[];
errorHandler?: (error: any, req: Request, res: Response, next: NextFunction) => void;
}
export default interface ServerInterface {
getRouter(): Router;
init(config: IConfig): this;
}

View File

@ -0,0 +1,8 @@
import { Service } from "typedi";
import BaseController from "@Common/system/controller-pattern/BaseController";
import HttpCodes from "@Common/system/controller-pattern/HttpCodes";
@Service()
export default abstract class ApiController extends BaseController {}
export { HttpCodes as ResponseStatusCodes };

View File

@ -0,0 +1,41 @@
import { StRoute } from "./StRoute";
import { Response } from "express";
import HttpCodes from "@Common/system/controller-pattern/HttpCodes";
type IResponseData = {} | string | number | boolean | null | unknown;
export default abstract class BaseController {
public expressRoutes!: StRoute[];
public httpCode: typeof HttpCodes = HttpCodes;
protected httpSuccess(response: Response, responseData: IResponseData = null) {
return this.httpResponse(response, HttpCodes.SUCCESS, responseData);
}
protected httpCreated(response: Response, responseData: IResponseData = null) {
return this.httpResponse(response, HttpCodes.CREATED, responseData);
}
protected httpBadRequest(response: Response, responseData: IResponseData = "Http Bad Request") {
return this.httpResponse(response, HttpCodes.BAD_REQUEST, responseData);
}
protected httpNotFoundRequest(response: Response, responseData: IResponseData = "Not Found") {
return this.httpResponse(response, HttpCodes.NOT_FOUND, responseData);
}
protected httpInternaleError(response: Response, responseData: IResponseData = "http Internal Server Error") {
return this.httpResponse(response, HttpCodes.INTERNAL_ERROR, responseData);
}
protected httpNotImplemented(response: Response, responseData: IResponseData = "http Internal Server Error") {
return this.httpResponse(response, HttpCodes.NOT_IMPLEMENTED, responseData);
}
protected httpResponse(response: Response, httpCode: HttpCodes, responseData: IResponseData = {}) {
if (responseData instanceof Error) {
throw responseData;
}
return response.status(httpCode).send(responseData);
}
}

View File

@ -0,0 +1,36 @@
import { type Response, type Request, type NextFunction } from "express";
import Container from "typedi";
import ExpressServer from "../ExpressServer";
import type BaseController from "./BaseController";
import ErrorCatch from "./ErrorCatch";
import { StRoute } from "./StRoute";
/**
* @description Decorator to supports defining requests handler for Express on the class. Its fully support TypeScript and dependency injection.
*/
function Controller() {
return <T extends { new (...args: any[]): BaseController }>(constructor: T) => {
const controller = Container.get(constructor);
if (!controller.expressRoutes || !Array.isArray(controller.expressRoutes)) return;
controller.expressRoutes.forEach((route) => createRoute(controller, route));
};
}
function createRoute(controller: any, route: StRoute) {
const server: ExpressServer = Container.get(ExpressServer);
const errorCatch = Container.get(ErrorCatch);
const args = [
...route.frontMiddlewares,
async (req: Request, res: Response, next: NextFunction) => {
try {
await route.func.call(controller, req, res);
} catch (error) {
errorCatch.handle(req, res, next, error);
}
},
...route.backMiddlewares,
];
server.getRouter()[route.type](route.path, ...args);
}
export default Controller;

View File

@ -0,0 +1,14 @@
import { Request, Response, NextFunction } from "express";
import { Service } from "typedi";
/**
* Capture primitive errors to preserve application crash
*/
@Service()
export default class ErrorCatch {
constructor() {}
public handle(request: Request, response: Response, next: NextFunction, ...args: any[]): void {
next(args[args.length - 1] ?? "Unknown Error");
}
}

View File

@ -0,0 +1,10 @@
enum HttpCodes {
SUCCESS = 200,
CREATED = 201,
BAD_REQUEST = 400,
INTERNAL_ERROR = 500,
UNKNOWN_ERROR = 520,
NOT_IMPLEMENTED = 501,
NOT_FOUND = 404,
}
export default HttpCodes;

View File

@ -0,0 +1,36 @@
import BaseController from "./BaseController";
import { StRoute } from "./StRoute";
function MethodsAny(
type: StRoute["type"],
path: string,
frontMiddlewares: StRoute["frontMiddlewares"] = [],
backMiddlewares: StRoute["backMiddlewares"] = [],
) {
return (target: any, memberName: string, propertyDescriptor: PropertyDescriptor) => {
const func = propertyDescriptor.value;
const constructor: typeof BaseController = target.constructor;
constructor.prototype.expressRoutes ??= [];
constructor.prototype.expressRoutes.push({ type, path, func, frontMiddlewares, backMiddlewares });
};
}
/**
* @description Decorator Method GET
*/
export const Get = MethodsAny.bind(null, "get");
/**
* @description Decorator Method POST
*/
export const Post = MethodsAny.bind(null, "post");
/**
* @description Decorator Method DELETE
*/
export const Delete = MethodsAny.bind(null, "delete");
/**
* @description Decorator Method PUT
*/
export const Put = MethodsAny.bind(null, "put");

View File

@ -0,0 +1,9 @@
import { type Request, type Response, type NextFunction } from "express";
export interface StRoute {
type: "get" | "post" | "delete" | "put";
path: string;
func: (requests: Request, response: Response) => Promise<void>;
frontMiddlewares: ((requests: Request, response: Response, next: NextFunction) => void)[];
backMiddlewares: ((requests: Request, response: Response, next: NextFunction) => void)[];
}

View File

@ -0,0 +1,7 @@
import HttpCodes from "../HttpCodes";
export default class HttpException extends Error {
constructor(message: string, public httpCode: HttpCodes = HttpCodes.UNKNOWN_ERROR) {
super(message);
}
}

View File

@ -0,0 +1,2 @@
export { default as Controller } from "./Controller";
export * from "./Methods";

View File

@ -0,0 +1,36 @@
import { BackendVariables } from "@Common/config/variables/Variables";
import { PrismaClient } from "@prisma/client";
import dotenv from "dotenv";
import Container from "typedi";
import IDatabaseConfig from "../../config/database/IDatabaseConfig";
dotenv.config();
export default class DbProvider {
protected readonly variables = Container.get(BackendVariables);
protected url = `postgres://${this.variables.DATABASE_USERNAME}:${this.variables.DATABASE_PASSWORD}@${this.variables.DATABASE_HOST}:${this.variables.DATABASE_PORT}/${this.variables.DATABASE_NAME}`;
protected client = new PrismaClient({
datasources: {
db: {
url: this.url,
},
},
});
constructor(protected config: IDatabaseConfig) {}
public async connect(): Promise<void> {
await this.client.$connect();
console.info(`⚡️[Prisma]: Connected to ${this.config.name}`); // A Logger middleware is to be added here
}
public getClient() {
return this.client;
}
public async disconnect(): Promise<void> {
await this.client.$disconnect();
console.info(`⚡️[Prisma]: Disconnected from ${this.config.name}`); // A Logger middleware is to be added here
}
}

View File

@ -0,0 +1,5 @@
export class ORMBadQueryError extends Error {
constructor(message: string, public error: Error) {
super(message);
}
}

View File

@ -0,0 +1,5 @@
import IDatabaseConfig from "@Common/config/database/IDatabaseConfig";
import DbProvider from "./DbProvider";
export type { IDatabaseConfig };
export default DbProvider;

33
src/entries/App.ts Normal file
View File

@ -0,0 +1,33 @@
import "module-alias/register";
import "reflect-metadata";
import { Container } from "typedi";
import ExpressServer from "@Common/system/ExpressServer";
import routes from "@App/index";
import cors from "cors";
import bodyParser from "body-parser";
// import TezosLink from "@Common/databases/TezosLink";
import errorHandler from "@App/middlewares/ErrorHandler";
import { BackendVariables } from "@Common/config/variables/Variables";
(async () => {
try {
const variables = await Container.get(BackendVariables).validate();
const port = variables.APP_PORT;
const rootUrl = variables.APP_ROOT_URL;
const label = variables.APP_LABEL ?? "Unknown Service";
// Container.get(TezosLink).connect();
Container.get(ExpressServer).init({
label,
port: parseInt(port),
rootUrl,
middlwares: [cors({ origin: "*" }), bodyParser.urlencoded({ extended: true }), bodyParser.json()],
errorHandler,
});
routes.start();
} catch (e) {
console.error(e);
}
})();

View File

@ -0,0 +1,6 @@
export default abstract class BaseService {
/** @TODO place methods in a config file */
public static readonly whitelisted: string[] = ["/chains/main/blocks"];
public static readonly blacklisted: string[] = ["/context/contracts", "/monitor", "/network"];
public static readonly rollingPatterns: string[] = ["/head", "/injection/operation"];
}

View File

@ -0,0 +1,26 @@
import AddressesRepository from "@Repositories/AddressesRepository";
import BaseService from "@Services/BaseService";
import { Service } from "typedi";
@Service()
export default class AddressesService extends BaseService {
constructor(private addressRepository: AddressesRepository) {
super();
}
/**
* @description : Get all addresses
* @throws {Error} If addresses cannot be get
*/
public async get(query: any) {
return this.addressRepository.findMany(query);
}
/**
* @description : Get a address by uid
* @throws {Error} If address cannot be get
*/
public async getByUid(uid: string) {
return this.addressRepository.findOneByUid(uid);
}
}

View File

@ -0,0 +1,54 @@
import jwt from "jsonwebtoken";
import BaseService from "@Services/BaseService";
import "reflect-metadata";
import { BackendVariables } from "@Common/config/variables/Variables";
import Container, { Service } from "typedi";
type IdNotTokens = {
access_token: string;
id_token: string;
};
@Service()
export default class AuthService extends BaseService {
protected readonly variables = Container.get(BackendVariables);
private constructor() {
super();
}
/**
* @description : Get IdNot id_token and access_token
* @throws {Error} If jwt pair cannot be get
*/
public async getUserFromIdNotTokens(code: string) {
const tokens = await this.getIdNotTokens(code);
return jwt.decode(tokens.id_token);
}
private async getIdNotTokens(code: string): Promise<IdNotTokens> {
const url = new URL(
this.variables.IDNOT_CONNEXION_URL.concat("?") +
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",
}),
);
try {
const headers = new Headers({
"Content-Type": "application/x-www-form-urlencoded",
});
const res = await fetch(url, {
method: "POST",
headers: headers,
});
const data = await res.json();
return data as IdNotTokens;
} catch (error) {
console.log(error);
throw new Error();
}
}
}

View File

@ -0,0 +1,26 @@
import ContactsRepository from "@Repositories/ContactsRepository";
import BaseService from "@Services/BaseService";
import { Service } from "typedi";
@Service()
export default class ContactsService extends BaseService {
constructor(private contactRepository: ContactsRepository) {
super();
}
/**
* @description : Get all contacts
* @throws {Error} If contacts cannot be get
*/
public async get(query: any) {
return this.contactRepository.findMany(query);
}
/**
* @description : Get a contact by uid
* @throws {Error} If contact cannot be get
*/
public async getByUid(uid: string) {
return this.contactRepository.findOneByUid(uid);
}
}

View File

@ -0,0 +1,43 @@
import FilesRepository from "@Repositories/FilesRepository";
import BaseService from "@Services/BaseService";
import { Service } from "typedi";
import { File } from "le-coffre-resources/dist/SuperAdmin"
@Service()
export default class FilesService extends BaseService {
constructor(private filesRepository: FilesRepository) {
super();
}
/**
* @description : Get all files
* @throws {Error} If files cannot be ge
*/
public async get(query: any) {
return this.filesRepository.findMany(query);
}
/**
* @description : Create a new file
* @throws {Error} If file cannot be created
*/
public async create(file: File) {
return this.filesRepository.create(file);
}
/**
* @description : Modify a new file
* @throws {Error} If file cannot be modified
*/
public async put(uid: string, file: File) {
return this.filesRepository.update(uid, file);
}
/**
* @description : Get a file by uid
* @throws {Error} If project cannot be created
*/
public async getByUid(uid: string) {
return this.filesRepository.findOneByUid(uid);
}
}

View File

@ -0,0 +1,57 @@
import BaseService from "@Services/BaseService";
import { Service } from "typedi";
@Service()
export default class NotificationsService extends BaseService {
constructor() {
super();
}
/**
* @description : Get all notifications
* @returns : T
* @throws {Error} If notifications cannot be get
* @param : projectEntity: Partial<ProjectEntity>
*/
public async get() {
// const notifications = await this.usersRepository.findOne(uuid);
// if (!notifications) Promise.reject(new Error("Cannot get notifications"));
return { response: "/api/notifications > GET : All notifications > Not implemented yet" };
}
/**
* @description : Create a new notification
* @returns : T
* @throws {Error} If notification cannot be created
* @param : projectEntity: Partial<ProjectEntity>
*/
public async create() {
// const notification = await this.projectRepository.create(projectEntity);
// if (!notification) Promise.reject(new Error("Cannot create project"));
return { response: "/api/notifications > POST : Create notification > Not implemented yet" };
}
/**
* @description : Modify a new notification
* @returns : T
* @throws {Error} If notification cannot be modified
* @param : projectEntity: Partial<ProjectEntity>
*/
public async put() {
// const notification = await this.projectRepository.create(projectEntity);
// if (!notification) Promise.reject(new Error("Cannot create project"));
return { response: "/api/notifications > PUT : Modified notification > Not implemented yet" };
}
/**
* @description : Get a notification by uid
* @returns : T
* @throws {Error} If project cannot be created
* @param : projectEntity: Partial<ProjectEntity>
*/
public async getByUid(uid: string) {
// const notification = await this.usersRepository.findOne(uid);
// if (!notification) Promise.reject(new Error("Cannot get notification by uid"));
return { response: "/api/notifications/:uid > GET : notification by uid > Not implemented yet" };
}
}

View File

@ -0,0 +1,44 @@
import { Customers } from "@prisma/client";
import CustomersRepository from "@Repositories/CustomersRepository";
import BaseService from "@Services/BaseService";
import { Customer } from "le-coffre-resources/dist/SuperAdmin";
import { Service } from "typedi";
@Service()
export default class CustomersService extends BaseService {
constructor(private customerRepository: CustomersRepository) {
super();
}
/**
* @description : Get all Customers
* @throws {Error} If Customers cannot be get
*/
public async get(query: any) {
return this.customerRepository.findMany(query);
}
/**
* @description : Create a new customer
* @throws {Error} If customer cannot be created
*/
public async create(customerEntity: Customer): Promise<Customers> {
return this.customerRepository.create(customerEntity);
}
/**
* @description : Modify a customer
* @throws {Error} If customer cannot be modified
*/
public async update(uid: string, customerEntity: Customer): Promise<Customers> {
return this.customerRepository.update(uid, customerEntity);
}
/**
* @description : Get a customer by uid
* @throws {Error} If customer cannot be get by uid
*/
public async getByUid(uid: string, query?: any): Promise<Customers> {
return this.customerRepository.findOneByUid(uid, query);
}
}

View File

@ -0,0 +1,46 @@
import { DeedTypes } from "@prisma/client";
import DeedTypesRepository from "@Repositories/DeedTypesRepository";
import BaseService from "@Services/BaseService";
import { DeedType } from "le-coffre-resources/dist/SuperAdmin";
import { Service } from "typedi";
@Service()
export default class DeedTypesService extends BaseService {
constructor(
private deedTypeRepository: DeedTypesRepository,
) {
super();
}
/**
* @description : Get all deed-types
* @throws {Error} If deed-types cannot be get
*/
public async get(query: any): Promise<DeedTypes[]> {
return this.deedTypeRepository.findMany(query);
}
/**
* @description : Create a new deed-type
* @throws {Error} If deed-type cannot be created
*/
public async create(deedTypeEntity: DeedType): Promise<DeedTypes> {
return this.deedTypeRepository.create(deedTypeEntity);
}
/**
* @description : Modify a deed-type
* @throws {Error} If deed-type cannot be modifified
*/
public async update(uid: string, deedTypeEntity: DeedType): Promise<DeedTypes> {
return this.deedTypeRepository.update(uid, deedTypeEntity);
}
/**
* @description : Get a deedtype by uid
* @throws {Error} If deed-type cannot be get by uid
*/
public async getByUid(uid: string, query?: any) {
return this.deedTypeRepository.findOneByUid(uid, query);
}
}

View File

@ -0,0 +1,44 @@
import { Deeds } from "@prisma/client";
import DeedsRepository from "@Repositories/DeedsRepository";
import BaseService from "@Services/BaseService";
import { Deed } from "le-coffre-resources/dist/SuperAdmin";
import { Service } from "typedi";
@Service()
export default class DeedsService extends BaseService {
constructor(private deedRepository: DeedsRepository) {
super();
}
/**
* @description : Get all deeds
* @throws {Error} If deeds cannot be get
*/
public async get(query: any) {
return this.deedRepository.findMany(query);
}
/**
* @description : Create a new deed with document types
* @throws {Error} If deeds cannot be created
*/
public async create(deed: Deed): Promise<Deeds> {
return this.deedRepository.create(deed);
}
/**
* @description : Update data of a deed with document types
* @throws {Error} If deeds cannot be updated with document types or one of them
*/
public async update(deeduid: string, deed: Deed): Promise<Deeds> {
return this.deedRepository.update(deeduid, deed);
}
/**
* @description : Get a deed by uid
* @throws {Error} If deed-type cannot be get by uid
*/
public async getByUid(uid: string) {
return this.deedRepository.findOneByUid(uid);
}
}

View File

@ -0,0 +1,44 @@
import { DocumentTypes } from "@prisma/client";
import DocumentTypesRepository from "@Repositories/DocumentTypesRepository";
import BaseService from "@Services/BaseService";
import { DocumentType } from "le-coffre-resources/dist/SuperAdmin";
import { Service } from "typedi";
@Service()
export default class DocumentTypesService extends BaseService {
constructor(private documentTypeRepository: DocumentTypesRepository) {
super();
}
/**
* @description : Get all document-types
* @throws {Error} If document-types cannot be get
*/
public async get(query: any) {
return this.documentTypeRepository.findMany(query);
}
/**
* @description : Create a new document-type
* @throws {Error} If document-types cannot be created
*/
public async create(documentTypeEntity: DocumentType): Promise<DocumentTypes> {
return this.documentTypeRepository.create(documentTypeEntity);
}
/**
* @description : Modify a document-type
* @throws {Error} If document-type cannot be modified
*/
public async update(uid: string, documentTypeEntity: DocumentType): Promise<DocumentTypes> {
return this.documentTypeRepository.update(uid, documentTypeEntity);
}
/**
* @description : Get a document-type by uid
* @throws {Error} If document-type is not found
*/
public async getByUid(uid: string, query?: any) {
return this.documentTypeRepository.findOneByUid(uid, query);
}
}

View File

@ -0,0 +1,60 @@
import { Documents, Prisma } from "@prisma/client";
import { Document } from "le-coffre-resources/dist/SuperAdmin";
import DocumentsRepository from "@Repositories/DocumentsRepository";
import BaseService from "@Services/BaseService";
import { Service } from "typedi";
@Service()
export default class DocumentsService extends BaseService {
constructor(private documentsRepository: DocumentsRepository) {
super();
}
/**
* @description : Get all documents
* @throws {Error} If documents cannot be get
*/
public async get(query: any) {
return this.documentsRepository.findMany(query);
}
/**
* @description : Create a new document
* @throws {Error} If document cannot be created
*/
public async create(document: Document): Promise<Documents> {
return this.documentsRepository.create(document);
}
/**
* @description : Create new documents
* @throws {Error} If documents or one of them cannot be created
*/
public async createMany(documents: Document[]): Promise<Prisma.BatchPayload> {
return this.documentsRepository.createMany(documents);
}
/**
* @description : Modify a document
* @throws {Error} If document cannot be modified
*/
public async update(uid: string, document: Document): Promise<Documents> {
return this.documentsRepository.update(uid, document);
}
/**
* @description : Delete a document
* @throws {Error} If document cannot be deleted
*/
public async delete(uid: string): Promise<Documents> {
return this.documentsRepository.delete(uid);
}
/**
* @description : Get a document by uid
* @throws {Error} If document cannot be get by uid
*/
public async getByUid(uid: string, query?: any) {
return this.documentsRepository.findOneByUid(uid, query);
}
}

View File

@ -0,0 +1,51 @@
import { OfficeFolders } from ".prisma/client";
import OfficeFoldersRepository from "@Repositories/OfficeFoldersRepository";
import BaseService from "@Services/BaseService";
import { OfficeFolder } from "le-coffre-resources/dist/SuperAdmin";
import { Service } from "typedi";
import DeedTypesService from "../DeedTypesService/DeedTypesService";
@Service()
export default class OfficeFoldersService extends BaseService {
constructor(
private officeFoldersRepository: OfficeFoldersRepository,
private deedTypeService: DeedTypesService
) {
super();
}
/**
* @description : Get all folders
* @throws {Error} If folders cannot be get
*/
public async get(query: any) {
return this.officeFoldersRepository.findMany(query);
}
/**
* @description : Create a new folder
* @throws {Error} If folder cannot be created
*/
public async create(officeFolderEntity: OfficeFolder): Promise<OfficeFolders> {
const deedType = await this.deedTypeService.getByUid(officeFolderEntity.deed.deed_type.uid!);
if(deedType.archived_at) throw new Error('deed type is archived');
return this.officeFoldersRepository.create(officeFolderEntity);
}
/**
* @description : Modify a folder
* @throws {Error} If folder cannot be modified
*/
public async update(officeFolderuid: string, officeFolderEntity: OfficeFolder): Promise<OfficeFolders> {
return this.officeFoldersRepository.update(officeFolderuid, officeFolderEntity);
}
/**
* @description : Get a folder by uid
* @throws {Error} If folder cannot be get by uid
*/
public async getByUid(uid: string, query?: any) {
return this.officeFoldersRepository.findOneByUid(uid, query);
}
}

View File

@ -0,0 +1,44 @@
import { Offices } from "@prisma/client";
import OfficesRepository from "@Repositories/OfficesRepository";
import BaseService from "@Services/BaseService";
import { Office as OfficeRessource } from "le-coffre-resources/dist/SuperAdmin";
import { Service } from "typedi";
@Service()
export default class OfficesService extends BaseService {
constructor(private officeRepository: OfficesRepository) {
super();
}
/**
* @description : Get all offices
* @throws {Error} If offices cannot be get
*/
public async get(query: any): Promise<Offices[]> {
return this.officeRepository.findMany(query);
}
/**
* @description : Create a new office
* @throws {Error} If office cannot be created
*/
public async create(officeEntity: OfficeRessource): Promise<Offices> {
return this.officeRepository.create(officeEntity);
}
/**
* @description : Modify an office
* @throws {Error} If office cannot be modified
*/
public async update(uid: string, officeEntity: OfficeRessource): Promise<Offices> {
return this.officeRepository.update(uid, officeEntity);
}
/**
* @description : Get a office by uid
* @throws {Error} If office cannot be get
*/
public async getByUid(uid: string, query?: any): Promise<Offices> {
return this.officeRepository.findOneByUid(uid, query);
}
}

View File

@ -0,0 +1,45 @@
import BaseService from "@Services/BaseService";
import "reflect-metadata";
import { Service } from "typedi";
import UsersRepository from "@Repositories/UsersRepository";
import User from "le-coffre-resources/dist/SuperAdmin";
import { Users } from "@prisma/client";
@Service()
export default class UsersService extends BaseService {
constructor(private userRepository: UsersRepository) {
super();
}
/**
* @description : Get all users
* @throws {Error} If users cannot be get
*/
public get(query: any): Promise<Users[]> {
return this.userRepository.findMany(query);
}
/**
* @description : Create a user
* @throws {Error} If user couldn't be created
*/
public create(userEntity: User): Promise<Users> {
return this.userRepository.create(userEntity);
}
/**
* @description : Modify a user
* @throws {Error} If user modification failed
*/
public update(uid: string, userEntity: User): Promise<Users> {
return this.userRepository.update(uid, userEntity);
}
/**
* @description : Get a user by uid
* @throws {Error} If user cannot be get by uid
*/
public getByUid(uid: string, query?: any): Promise<Users> {
return this.userRepository.findOneByUid(uid, query);
}
}

121
src/test/config/Init.ts Normal file
View File

@ -0,0 +1,121 @@
import { Customers, DeedTypes, DocumentTypes, ECivility, ECustomerStatus, Offices, PrismaClient, Users } from "@prisma/client";
import User, { Customer, DeedType, DocumentType, Office } from "le-coffre-resources/dist/SuperAdmin";
const prisma = new PrismaClient();
export const initOffice = (office: Office): Promise<Offices> => {
return prisma.offices.create({
data: {
idNot: office.idNot,
name: office.name,
crpcen: office.crpcen,
address: {
create: {
address: office.address.address,
zip_code: office.address.zip_code,
city: office.address.city,
},
},
},
});
};
export const initDocumentType = (documentType: DocumentType, office: Office): Promise<DocumentTypes> => {
return prisma.documentTypes.create({
data: {
name: documentType.name,
public_description: documentType.public_description,
private_description: documentType.private_description,
archived_at: null,
office_uid: office.uid!,
},
});
};
export const initDeedType = (deedType: DeedType, office: Office, documentTypes?: string[]): Promise<DeedTypes> => {
return prisma.deedTypes.create({
data: {
name: deedType.name,
description: deedType.description,
archived_at: null,
office_uid: office.uid!,
deed_type_has_document_types: {
createMany: {
data: documentTypes!.map((documentType) => ({
document_type_uid: documentType,
})),
skipDuplicates: true,
},
},
},
});
};
export const initCustomers = (customer: Customer): Promise<Customers> => {
return prisma.customers.create({
data: {
status: ECustomerStatus.PENDING,
contact: {
create: {
first_name: customer.contact.first_name,
last_name: customer.contact.last_name,
email: customer.contact.email,
phone_number: customer.contact.phone_number,
cell_phone_number: customer.contact?.cell_phone_number,
civility: ECivility[customer.contact.civility as keyof typeof ECivility],
address: {
create: {
address: customer.contact.address!.address,
zip_code: customer.contact.address!.zip_code,
city: customer.contact.address!.city,
},
},
},
},
},
});
};
export const initUsers = (user: User): Promise<Users> => {
return prisma.users.create({
data: {
idNot: user.idNot,
office_membership: {
connectOrCreate: {
where: {
idNot: user.office_membership.idNot,
},
create: {
idNot: user.office_membership.idNot,
name: user.office_membership.name,
crpcen: user.office_membership.crpcen,
address: {
create: {
address: user.office_membership.address.address,
zip_code: user.office_membership.address.zip_code,
city: user.office_membership.address.city,
},
},
},
},
},
contact: {
create: {
first_name: user.contact.first_name,
last_name: user.contact.last_name,
email: user.contact.email,
phone_number: user.contact.phone_number,
cell_phone_number: user.contact.cell_phone_number,
civility: ECivility[user.contact.civility as keyof typeof ECivility],
address: {
create: {
address: user.contact.address!.address,
zip_code: user.contact.address!.zip_code,
city: user.contact.address!.city,
},
},
},
},
},
});
};

View File

@ -0,0 +1,242 @@
import { EOfficeStatus } from "le-coffre-resources/dist/Customer/Office";
import User, { Address, Contact, Office, DeedType, DocumentType, Customer, OfficeFolder, Deed } from "le-coffre-resources/dist/SuperAdmin";
export const userAddress: Address = {
address: "1 avenue des champs élysées",
zip_code: 75008,
city: "paris",
created_at: null,
updated_at: null,
};
export const userAddress_: Address = {
address: "1 rue Victor Hugo",
zip_code: 75001,
city: "paris",
created_at: null,
updated_at: null,
};
export const userContact: Contact = {
first_name: "Philippe",
last_name: "le Bel",
address: userAddress,
email: "philippe.lebel@notaires.fr",
phone_number: "+33101020304",
cell_phone_number: "+33605060708",
civility: "MALE",
created_at: null,
updated_at: null,
};
export const userContact_: Contact = {
first_name: "Saint",
last_name: "Louise",
address: userAddress_,
email: "saint.louise@notaires.fr",
phone_number: "+33105060708",
cell_phone_number: "+33601020304",
civility: "FEMALE",
created_at: null,
updated_at: null,
};
export const customerContact: Contact = {
first_name: "John",
last_name: "Doe",
address: userAddress,
email: "john.doe@customer.fr",
phone_number: "+3313847505",
cell_phone_number: "+3313847505",
civility: "MALE",
created_at: null,
updated_at: null,
};
export const customerContact_: Contact = {
first_name: "Jocelyne",
last_name: "Doe",
address: userAddress,
email: "jocelyne.doe@customer.fr",
phone_number: "+331384894505",
cell_phone_number: "+331384894505",
civility: "FEMALE",
created_at: null,
updated_at: null,
};
export const officeAddress: Address = {
address: "1 rue Rivoli",
zip_code: 75001,
city: "paris",
created_at: null,
updated_at: null,
};
export const officeAddress_: Address = {
address: "1 rue de la paix",
zip_code: 75008,
city: "paris",
created_at: null,
updated_at: null,
};
export const office: Office = {
idNot: "123456789",
name: "first office",
crpcen: "0123456789CRPCEN",
office_status: EOfficeStatus.ACTIVATED,
address: officeAddress,
created_at: null,
updated_at: null,
};
export const office_: Office = {
idNot: "789101112",
name: "second office",
crpcen: "987654321CRPCEN",
office_status: EOfficeStatus.DESACTIVATED,
address: officeAddress_,
created_at: null,
updated_at: null,
};
export const user: User = {
idNot: "123456_123456789",
contact: userContact,
office_membership: office,
created_at: null,
updated_at: null,
};
export const user_: User = {
idNot: "654321_789101112",
contact: userContact_,
office_membership: office_,
created_at: null,
updated_at: null,
};
export const documentType: DocumentType = {
name: "Identity card",
public_description: "your ID card delivered by your country of residence",
private_description: "verify if this ID card is legit",
archived_at: null,
office: office,
created_at: null,
updated_at: null,
};
export const documentType_: DocumentType = {
name: "Electricity bill",
public_description: "an electricity bill payed within the last 3 months",
private_description: "verify if this electricity company is legit",
archived_at: null,
office: office,
created_at: null,
updated_at: null,
};
export const deedType: DeedType = {
name: "Wedding",
description: "we assume wedding involve two people",
archived_at: null,
office: office,
created_at: null,
updated_at: null,
deed_type_has_document_types: [
{
document_type: documentType,
deed_type: new DeedType(),
created_at: null,
updated_at: null,
},
],
};
export const deedType_: DeedType = {
name: "Inheritance",
description: "we assume inheritance involve two people",
archived_at: null,
office: office_,
created_at: null,
updated_at: null,
};
export const deed: Deed = {
deed_type: deedType,
created_at: null,
updated_at: null,
};
export const deed_: Deed = {
deed_type: deedType_,
created_at: null,
updated_at: null,
};
export const customer: Customer = {
contact: customerContact,
status: "PENDING",
created_at: null,
updated_at: null,
};
export const customer_: Customer = {
contact: customerContact_,
status: "ERRONED",
created_at: null,
updated_at: null,
};
export const officeFolder: OfficeFolder = {
name: "Dossier 1234567",
folder_number: "1234567",
description: "Dossier de mr Dupont",
archived_description: null,
status: "ARCHIVED",
deed: deed,
office: office,
office_folder_has_customers: [
{
customer: customer,
office_folder: new OfficeFolder(),
created_at: null,
updated_at: null,
},
{
customer: customer_,
office_folder: new OfficeFolder(),
created_at: null,
updated_at: null,
},
],
office_folder_has_stakeholder: [
{
user_stakeholder: user,
office_folder: new OfficeFolder(),
created_at: null,
updated_at: null,
},
{
user_stakeholder: user_,
office_folder: new OfficeFolder(),
created_at: null,
updated_at: null,
},
],
created_at: null,
updated_at: null,
};
export const officeFolder_: OfficeFolder = {
name: "Dossier 89101112",
folder_number: "89101112",
description: "Dossier de mme Dutunnel",
archived_description: null,
status: "LIVE",
deed: deed_,
office: office_,
created_at: null,
updated_at: null,
};

View File

@ -0,0 +1,166 @@
import "module-alias/register";
import "reflect-metadata";
import { Customer } from "le-coffre-resources/dist/SuperAdmin";
import CustomersService from "@Services/super-admin/CustomersService/CustomersService";
import { PrismaClient } from "@prisma/client";
import { customer, customerContact, customerContact_, customer_ } from "@Test/config/MockedData";
import Container from "typedi";
import CustomersRepository from "@Repositories/CustomersRepository";
const prisma = new PrismaClient();
const CustomersServiceTest = new CustomersService(Container.get(CustomersRepository));
afterAll(async () => {
/*
* Clean database after all tests execution.
* Due to cascade deletion, if addresses are deleted, all items following tables are dropped: contacts, customers, offices
*/
const deleteAddresses = prisma.addresses.deleteMany();
await prisma.$transaction([deleteAddresses]);
await prisma.$disconnect();
});
describe("test create function", () => {
it("should create a new customer", async () => {
const customerCreated = await CustomersServiceTest.create(customer);
expect(customerCreated?.status).toEqual("PENDING");
// verify if customer contact is created in db
const contactCreated = await prisma.contacts.findUnique({ where: { uid: customerCreated.contact_uid } });
expect(contactCreated?.first_name).toEqual(customer.contact.first_name);
expect(contactCreated?.last_name).toEqual(customer.contact.last_name);
expect(contactCreated?.cell_phone_number).toEqual(customer.contact.cell_phone_number);
expect(contactCreated?.phone_number).toEqual(customer.contact.phone_number);
expect(contactCreated?.civility).toEqual(customer.contact.civility);
expect(contactCreated?.email).toEqual(customer.contact.email);
// verify if customer address is created in db
const addressForContactCreated = await prisma.addresses.findUnique({ where: { uid: contactCreated?.address_uid } });
expect(addressForContactCreated?.address).toEqual(customer.contact.address?.address);
expect(addressForContactCreated?.zip_code).toEqual(customer.contact.address?.zip_code);
expect(addressForContactCreated?.city).toEqual(customer.contact.address?.city);
});
it("should not create an customer already created", async () => {
// try to create the same customer
async function duplicateCustomer() {
await CustomersServiceTest.create(customer);
}
await expect(duplicateCustomer).rejects.toThrow();
});
it("should not create an new customer with an email already created", async () => {
let newCustomer: Customer = JSON.parse(JSON.stringify(customer_));
newCustomer.contact.email = customerContact.email;
// try to create a new customer with already used email
async function createCustomerWithDuplicateEmail() {
await CustomersServiceTest.create(newCustomer);
}
await expect(createCustomerWithDuplicateEmail).rejects.toThrow();
});
it("should not create an customer with an phone number already created", async () => {
let newCustomer: Customer = JSON.parse(JSON.stringify(customer_));
newCustomer.contact.cell_phone_number = customerContact.cell_phone_number;
// try to create a new customer with already used cellphone number
async function duplicateCustomer() {
await CustomersServiceTest.create(newCustomer);
}
await expect(duplicateCustomer).rejects.toThrow();
});
it("should create an new customer if unique attributes differ from existing customers", async () => {
let newCustomer: Customer = JSON.parse(JSON.stringify(customer));
newCustomer.contact.email = customerContact_.email;
newCustomer.contact.cell_phone_number = customerContact_.cell_phone_number;
const customerCreated = await CustomersServiceTest.create(newCustomer);
expect(customerCreated?.status).toEqual("PENDING");
// verify if customer_ contact is created in db
const contactCreated = await prisma.contacts.findUnique({ where: { uid: customerCreated.contact_uid } });
expect(contactCreated?.first_name).toEqual(customer.contact.first_name);
expect(contactCreated?.last_name).toEqual(customer.contact.last_name);
expect(contactCreated?.cell_phone_number).toEqual(customer_.contact.cell_phone_number);
expect(contactCreated?.phone_number).toEqual(customer.contact.phone_number);
expect(contactCreated?.civility).toEqual(customer.contact.civility);
expect(contactCreated?.email).toEqual(customer_.contact.email);
// verify if customer_ address is created in db
const addressForContactCreated = await prisma.addresses.findUnique({ where: { uid: contactCreated?.address_uid } });
expect(addressForContactCreated?.address).toEqual(customer.contact.address?.address);
expect(addressForContactCreated?.zip_code).toEqual(customer.contact.address?.zip_code);
expect(addressForContactCreated?.city).toEqual(customer.contact.address?.city);
});
});
describe("test update function", () => {
it("should update an customer's data", async () => {
const customerCreated = await prisma.customers.findFirstOrThrow({ where: { contact: { email: customer_.contact.email } } });
// update the last customer created with his own new office and own contact
const updatedCustomer = await CustomersServiceTest.update(customerCreated.uid, customer_);
expect(updatedCustomer?.status).toEqual("ERRONED");
// verify if customer_ contact is created in db
const existingContact = await prisma.contacts.findUnique({ where: { uid: updatedCustomer.contact_uid } });
expect(existingContact?.first_name).toEqual(customer_.contact.first_name);
expect(existingContact?.last_name).toEqual(customer_.contact.last_name);
expect(existingContact?.cell_phone_number).toEqual(customer_.contact.cell_phone_number);
expect(existingContact?.phone_number).toEqual(customer_.contact.phone_number);
expect(existingContact?.civility).toEqual(customer_.contact.civility);
expect(existingContact?.email).toEqual(customer_.contact.email);
// verify if customer_ address is created in db
const addressForExistingContact = await prisma.addresses.findUnique({ where: { uid: existingContact?.address_uid } });
expect(addressForExistingContact?.address).toEqual(customer_.contact.address?.address);
expect(addressForExistingContact?.zip_code).toEqual(customer_.contact.address?.zip_code);
expect(addressForExistingContact?.city).toEqual(customer_.contact.address?.city);
});
it("should not update an customer with an email already used", async () => {
const customerUid = (await prisma.customers.findFirstOrThrow({ where: { contact: { email: customer_.contact.email } } })).uid;
let updatedCustomer: Customer = JSON.parse(JSON.stringify(customer_));
updatedCustomer.contact.email = customerContact.email;
// try to create a new customer with already used email
async function updateCustomerWithDuplicateEmail() {
await CustomersServiceTest.update(customerUid, updatedCustomer);
}
await expect(updateCustomerWithDuplicateEmail).rejects.toThrow();
});
it("should not update an customer with an phone number already used", async () => {
const customerUid = (await prisma.customers.findFirstOrThrow({ where: { contact: { email: customer_.contact.email } } })).uid;
let updatedCustomer: Customer = JSON.parse(JSON.stringify(customer_));
updatedCustomer.contact.cell_phone_number = customerContact.cell_phone_number;
// try to create a new customer with already used email
async function updateCustomerWithDuplicateEmail() {
await CustomersServiceTest.update(customerUid, updatedCustomer);
}
await expect(updateCustomerWithDuplicateEmail).rejects.toThrow();
});
});
describe("test get function", () => {
it("should return an array of Customers", async () => {
const req = {}
const customers = await CustomersServiceTest.get(req);
// verify result typing
expect(customers).toBeInstanceOf(Array<Customer>);
expect(customers.length).toEqual(2);
// verify result content
const customersCreated = await prisma.customers.findMany();
expect(customers).toContainEqual(customersCreated[0]);
expect(customers).toContainEqual(customersCreated[1]);
});
});

View File

@ -0,0 +1,179 @@
import "module-alias/register";
import "reflect-metadata";
import { Deed } from "le-coffre-resources/dist/SuperAdmin";
import DeedService from "@Services/super-admin/DeedsService/DeedsService";
import { PrismaClient } from "prisma/prisma-client";
import { deed, deedType, documentType, documentType_, office } from "@Test/config/MockedData";
import DeedsRepository from "@Repositories/DeedsRepository";
import Container from "typedi";
import { initDeedType, initDocumentType, initOffice } from "@Test/config/Init";
const prisma = new PrismaClient();
const DeedServiceTest = new DeedService(Container.get(DeedsRepository));
beforeAll(async () => {
office.uid = (await initOffice(office)).uid;
documentType.uid = (await initDocumentType(documentType, office)).uid;
documentType_.uid = (await initDocumentType(documentType_, office)).uid;
deedType.uid = (await initDeedType(deedType, office, [documentType.uid])).uid;
});
afterAll(async () => {
const deleteDeedTypes = prisma.deedTypes.deleteMany();
const deleteOffices = prisma.offices.deleteMany();
await prisma.$transaction([deleteDeedTypes, deleteOffices]);
await prisma.$disconnect();
});
describe("test create function", () => {
it("should not create a new deed if deed type is unknown", async () => {
let deedWithoutDeedTypeUid: Deed = JSON.parse(JSON.stringify(deed));
deedWithoutDeedTypeUid.deed_type.uid = "random uid";
// try to create a new deed with unknown deed type
async function createDeedWithUnknownDeedType() {
await DeedServiceTest.create(deedWithoutDeedTypeUid);
}
await expect(createDeedWithUnknownDeedType).rejects.toThrow();
});
it("should create a new deed based on existing deed type", async () => {
let deedWithDeedTypeUid: Deed = JSON.parse(JSON.stringify(deed));
deedWithDeedTypeUid.deed_type.uid = deedType.uid;
const deedCreated = await DeedServiceTest.create(deedWithDeedTypeUid);
expect(deedCreated.deed_type_uid).toEqual(deedType.uid);
});
it("should have by default the same document types as its deed type ", async () => {
const deedWithDocumentTypes = await prisma.deeds.findFirstOrThrow({ include: { deed_has_document_types: true } });
expect(deedWithDocumentTypes.deed_has_document_types.length).toEqual(1);
expect(deedWithDocumentTypes.deed_has_document_types[0]?.document_type_uid).toEqual(documentType.uid);
});
it("should create a the same deed based on existing deed type", async () => {
let deedWithDeedTypeUid: Deed = JSON.parse(JSON.stringify(deed));
deedWithDeedTypeUid.deed_type.uid = deedType.uid;
const deedCreated = await DeedServiceTest.create(deedWithDeedTypeUid);
expect(deedCreated.deed_type_uid).toEqual(deedType.uid);
});
it("should not create a new deed based on archivated deed type", async () => {
let deedArchivated: Deed = JSON.parse(JSON.stringify(deed));
deedArchivated.deed_type.uid = deedType.uid;
await prisma.deedTypes.update({
where: { uid: deedType.uid },
data: {
archived_at: new Date(Date.now()),
},
});
// try to create a new deed with archivated deed type
async function createDeedWithArchivatedDeedType() {
await DeedServiceTest.create(deedArchivated);
}
await expect(createDeedWithArchivatedDeedType).rejects.toThrow("deed type is archived");
});
});
describe("test update function", () => {
it("should add document types to a deed", async () => {
const deedUid = (await prisma.deeds.findFirstOrThrow({ where: { deed_type_uid: deedType.uid } })).uid;
let deedToUpdate: Deed = JSON.parse(JSON.stringify(deed));
deedToUpdate.deed_has_document_types = [
{
document_type: documentType,
deed: new Deed(),
created_at: null,
updated_at: null,
},
{
document_type: documentType_,
deed: new Deed(),
created_at: null,
updated_at: null,
},
];
await DeedServiceTest.update(deedUid, deedToUpdate);
const deedUpdated = await prisma.deeds.findFirstOrThrow({
where: {
uid: deedUid,
},
include: {
deed_has_document_types: true,
},
});
expect(deedUpdated.deed_has_document_types.length).toEqual(2);
});
it("should not add document types to a deed type that already has those document types ", async () => {
const deedUid = (await prisma.deeds.findFirstOrThrow({ where: { deed_type_uid: deedType.uid } })).uid;
let deedToUpdate: Deed = JSON.parse(JSON.stringify(deed));
deedToUpdate.deed_has_document_types = [
{
document_type: documentType,
deed: new Deed(),
created_at: null,
updated_at: null,
},
{
document_type: documentType_,
deed: new Deed(),
created_at: null,
updated_at: null,
},
];
await DeedServiceTest.update(deedUid, deedToUpdate);
const deedUpdated = await prisma.deeds.findFirstOrThrow({
where: {
uid: deedUid,
},
include: {
deed_has_document_types: true,
},
});
expect(deedUpdated.deed_has_document_types.length).toEqual(2);
});
it("should delete document types from a deed", async () => {
const deedUid = (await prisma.deeds.findFirstOrThrow({ where: { deed_type_uid: deedType.uid } })).uid;
let deedToUpdate: Deed = JSON.parse(JSON.stringify(deed));
// set relation between deed and document types empty
deedToUpdate.deed_has_document_types = [];
await DeedServiceTest.update(deedUid, deedToUpdate);
const deedUpdated = await prisma.deeds.findFirstOrThrow({
where: {
uid: deedUid,
},
include: {
deed_has_document_types: true,
},
});
expect(deedUpdated.deed_has_document_types.length).toEqual(0);
});
});
describe("test get function", () => {
it("should return an array of Deeds", async () => {
const deeds = await DeedServiceTest.get({});
// verify result typing
expect(deeds).toBeInstanceOf(Array<Deed>);
expect(deeds.length).toEqual(2);
// verify result content
expect(deeds[0]?.deed_type_uid).toEqual(deedType.uid);
expect(deeds[1]?.deed_type_uid).toEqual(deedType.uid);
});
});

View File

@ -0,0 +1,323 @@
import "module-alias/register";
import "reflect-metadata";
import { DeedType } from "le-coffre-resources/dist/SuperAdmin";
import DeedTypeService from "@Services/super-admin/DeedTypesService/DeedTypesService";
import { PrismaClient } from "prisma/prisma-client";
import { deedType, deedType_, documentType, documentType_, office, office_ } from "@Test/config/MockedData";
import DeedTypesRepository from "@Repositories/DeedTypesRepository";
import Container from "typedi";
import { initDocumentType, initOffice } from "@Test/config/Init";
const prisma = new PrismaClient();
const DeedTypeServiceTest = new DeedTypeService(Container.get(DeedTypesRepository));
beforeAll(async () => {
office.uid = (await initOffice(office)).uid;
office_.uid = (await initOffice(office_)).uid;
documentType.uid = (await initDocumentType(documentType, office)).uid;
documentType_.uid = (await initDocumentType(documentType_, office)).uid;
});
afterAll(async () => {
const deleteDeedTypes = prisma.deedTypes.deleteMany();
const deleteOffices = prisma.offices.deleteMany();
await prisma.$transaction([deleteDeedTypes, deleteOffices]);
await prisma.$disconnect();
});
describe("test create function", () => {
it("should not create a new deed type if office is unknown", async () => {
let deedTypeWithoutOfficeUid: DeedType = JSON.parse(JSON.stringify(deedType));
deedTypeWithoutOfficeUid.office.uid = "random uid";
// try to create a new deed type with unknown office
async function createDeedTypeWithUnknownOffice() {
await DeedTypeServiceTest.create(deedTypeWithoutOfficeUid);
}
await expect(createDeedTypeWithUnknownOffice).rejects.toThrow();
});
it("should create a new deed type", async () => {
const deedTypeCreated = await DeedTypeServiceTest.create(deedType);
expect(deedTypeCreated.name).toEqual(deedType.name);
expect(deedTypeCreated.description).toEqual(deedType.description);
expect(deedTypeCreated.archived_at).toBeNull();
expect(deedTypeCreated.office_uid).toEqual(office.uid);
});
it("should not create a new deed type with a name already used for a given office", async () => {
let deedTypeWithSameNameAndOffice: DeedType = JSON.parse(JSON.stringify(deedType_));
deedTypeWithSameNameAndOffice.office = office;
deedTypeWithSameNameAndOffice.name = deedType.name;
async function createDeedTypeWithSameNameAndOffice() {
await DeedTypeServiceTest.create(deedTypeWithSameNameAndOffice);
}
await expect(createDeedTypeWithSameNameAndOffice).rejects.toThrow();
});
it("should create the same deed type for a different office", async () => {
let deedTypeDuplicatedForNewOffice: DeedType = JSON.parse(JSON.stringify(deedType));
deedTypeDuplicatedForNewOffice.office = office_;
const deedTypeCreated = await DeedTypeServiceTest.create(deedTypeDuplicatedForNewOffice);
expect(deedTypeCreated.name).toEqual(deedType.name);
expect(deedTypeCreated.description).toEqual(deedType.description);
expect(deedTypeCreated.archived_at).toBeNull();
expect(deedTypeCreated.office_uid).toEqual(office_.uid);
});
it("should create the a new deed type version with a different name for a given office", async () => {
let deedTypeWithSameDescription: DeedType = JSON.parse(JSON.stringify(deedType));
deedTypeWithSameDescription.name = deedType_.name;
const deedTypeCreated = await DeedTypeServiceTest.create(deedTypeWithSameDescription);
expect(deedTypeCreated.name).toEqual(deedType_.name);
expect(deedTypeCreated.description).toEqual(deedType.description);
expect(deedTypeCreated.archived_at).toBeNull();
expect(deedTypeCreated.office_uid).toEqual(office.uid);
});
});
describe("test update function", () => {
it("should update a deed type data", async () => {
const deedTypeCreated = await prisma.deedTypes.findFirstOrThrow({ where: { name: deedType_.name, office_uid: office.uid } });
expect(deedTypeCreated.name).toEqual(deedType_.name);
expect(deedTypeCreated.description).toEqual(deedType.description);
expect(deedTypeCreated.archived_at).toBeNull();
expect(deedTypeCreated.office_uid).toEqual(deedType.office.uid);
let deedTypeWithNewDescription: DeedType = JSON.parse(JSON.stringify(deedType_));
deedTypeWithNewDescription.office = office;
// update the last deed type created with his the right description
const deedTypeUpdated = await DeedTypeServiceTest.update(deedTypeCreated.uid, deedTypeWithNewDescription);
expect(deedTypeUpdated.name).toEqual(deedType_.name);
expect(deedTypeUpdated.description).toEqual(deedType_.description);
expect(deedTypeUpdated.archived_at).toBeNull();
expect(deedTypeUpdated.office_uid).toEqual(deedType.office.uid);
});
it("should not update a deed type name with an already used name for given office", async () => {
const deedTypeUid = (await prisma.deedTypes.findFirstOrThrow({ where: { name: deedType_.name, office_uid: office.uid } })).uid;
let deedTypeWithSameNameAndOffice: DeedType = JSON.parse(JSON.stringify(deedType_));
deedTypeWithSameNameAndOffice.office.uid = office.uid;
deedTypeWithSameNameAndOffice.name = deedType.name;
// update the last deed type created with his the right description
async function updateDocumentTypeWithSameName() {
await DeedTypeServiceTest.update(deedTypeUid, deedTypeWithSameNameAndOffice);
}
await expect(updateDocumentTypeWithSameName).rejects.toThrow();
});
it("should not update a deed type office membership if the office already have this document type", async () => {
const deedTypeUid = (await prisma.deedTypes.findFirstOrThrow({ where: { name: deedType_.name, office_uid: office.uid } })).uid;
let deedTypeWithSameNameAndOffice: DeedType = JSON.parse(JSON.stringify(deedType_));
deedTypeWithSameNameAndOffice.office.uid = office.uid;
deedTypeWithSameNameAndOffice.name = deedType.name;
// try to duplicate deed type in a given office
async function updateDocumentTypeWithduplicatedName() {
await DeedTypeServiceTest.update(deedTypeUid, deedTypeWithSameNameAndOffice);
}
await expect(updateDocumentTypeWithduplicatedName).rejects.toThrow();
});
it("should update a deed type office membership", async () => {
const deedTypeCreated = await prisma.deedTypes.findFirstOrThrow({ where: { name: deedType_.name, office_uid: office.uid } });
expect(deedTypeCreated.name).toEqual(deedType_.name);
expect(deedTypeCreated.description).toEqual(deedType_.description);
expect(deedTypeCreated.archived_at).toBeNull();
expect(deedTypeCreated.office_uid).toEqual(office.uid);
// update the last deed type updated with a new office membership
const deedTypeUpdated = await DeedTypeServiceTest.update(deedTypeCreated.uid, deedType_);
expect(deedTypeUpdated.name).toEqual(deedType_.name);
expect(deedTypeUpdated.description).toEqual(deedType_.description);
expect(deedTypeUpdated.archived_at).toBeNull();
expect(deedTypeUpdated.office_uid).toEqual(deedType_.office.uid);
});
it("should archivate a deed type", async () => {
const deedTypeCreated = await prisma.deedTypes.findFirstOrThrow({ where: { name: deedType_.name, office_uid: office_.uid } });
expect(deedTypeCreated.name).toEqual(deedType_.name);
expect(deedTypeCreated.description).toEqual(deedType_.description);
expect(deedTypeCreated.archived_at).toBeNull();
expect(deedTypeCreated.office_uid).toEqual(deedType_.office.uid);
let deedTypeArchivated: DeedType = JSON.parse(JSON.stringify(deedType_));
const currentDate = new Date(Date.now());
deedTypeArchivated.archived_at = new Date(Date.now());
// archivate a deed type by giving a non null date for archivated_at attribute
const deedTypeUpdated = await DeedTypeServiceTest.update(deedTypeCreated.uid, deedTypeArchivated);
expect(deedTypeUpdated.name).toEqual(deedType_.name);
expect(deedTypeUpdated.description).toEqual(deedType_.description);
expect(deedTypeUpdated.archived_at).toEqual(currentDate);
expect(deedTypeUpdated.office_uid).toEqual(office_.uid);
});
it("should unarchivate a deed type", async () => {
const deedTypeCreated = await prisma.deedTypes.findFirstOrThrow({ where: { name: deedType_.name, office_uid: office_.uid } });
expect(deedTypeCreated.name).toEqual(deedType_.name);
expect(deedTypeCreated.description).toEqual(deedType_.description);
expect(deedTypeCreated.archived_at).not.toBeNull();
expect(deedTypeCreated.office_uid).toEqual(deedType_.office.uid);
// unarchivate a deed type by giving a null date for archivated_at attribute
const deedTypeUpdated = await DeedTypeServiceTest.update(deedTypeCreated.uid, deedType_);
expect(deedTypeUpdated.name).toEqual(deedType_.name);
expect(deedTypeUpdated.description).toEqual(deedType_.description);
expect(deedTypeUpdated.archived_at).toBeNull();
expect(deedTypeUpdated.office_uid).toEqual(office_.uid);
});
it("should add document types to a deed type", async () => {
const deedTypeUid = (await prisma.deedTypes.findFirstOrThrow({ where: { name: deedType.name, office_uid: office.uid } })).uid;
let deedTypeToUpdate: DeedType = JSON.parse(JSON.stringify(deedType));
deedTypeToUpdate.deed_type_has_document_types = [
{
document_type: documentType,
deed_type: new DeedType(),
created_at: null,
updated_at: null,
},
{
document_type: documentType_,
deed_type: new DeedType(),
created_at: null,
updated_at: null,
},
];
await DeedTypeServiceTest.update(deedTypeUid, deedTypeToUpdate);
const deedTypeUpdated = await prisma.deedTypes.findFirstOrThrow({
where: {
uid: deedTypeUid,
},
include: {
deed_type_has_document_types: true,
},
});
expect(deedTypeUpdated.deed_type_has_document_types.length).toEqual(2);
});
it("should not add document types to a deed type that already has those document types ", async () => {
const deedTypeUid = (await prisma.deedTypes.findFirstOrThrow({ where: { name: deedType.name, office_uid: office.uid } })).uid;
let deedTypeToUpdate: DeedType = JSON.parse(JSON.stringify(deedType));
deedTypeToUpdate.deed_type_has_document_types = [
{
document_type: documentType,
deed_type: new DeedType(),
created_at: null,
updated_at: null,
},
{
document_type: documentType_,
deed_type: new DeedType(),
created_at: null,
updated_at: null,
},
];
await DeedTypeServiceTest.update(deedTypeUid, deedTypeToUpdate);
const deedTypeUpdated = await prisma.deedTypes.findFirstOrThrow({
where: {
uid: deedTypeUid,
},
include: {
deed_type_has_document_types: true,
},
});
expect(deedTypeUpdated.deed_type_has_document_types.length).toEqual(2);
});
it("should delete document types from a deed", async () => {
const deedTypeUid = (await prisma.deedTypes.findFirstOrThrow({ where: { name: deedType.name, office_uid: office.uid } })).uid;
let deedTypeToUpdate: DeedType = JSON.parse(JSON.stringify(deedType));
// set relation between deed and document types empty
deedTypeToUpdate.deed_type_has_document_types = [];
await DeedTypeServiceTest.update(deedTypeUid, deedTypeToUpdate);
const deedTypeUpdated = await prisma.deedTypes.findFirstOrThrow({
where: {
uid: deedTypeUid,
},
include: {
deed_type_has_document_types: true,
},
});
expect(deedTypeUpdated.deed_type_has_document_types.length).toEqual(0);
});
});
describe("test get function", () => {
it("should return an array of DeedTypes", async () => {
const deedTypes = await DeedTypeServiceTest.get({ orderBy: [{ name: "asc" }, { created_at: "asc" }] });
// verify result typing
expect(deedTypes).toBeInstanceOf(Array<DeedType>);
expect(deedTypes.length).toEqual(3);
// verify result content
expect(deedTypes[0]?.name).toEqual(deedType_.name);
expect(deedTypes[0]?.description).toEqual(deedType_.description);
expect(deedTypes[0]?.archived_at).toBeNull();
expect(deedTypes[0]?.office_uid).toEqual(office_.uid);
expect(deedTypes[1]?.name).toEqual(deedType.name);
expect(deedTypes[1]?.description).toEqual(deedType.description);
expect(deedTypes[1]?.archived_at).toBeNull();
expect(deedTypes[1]?.office_uid).toEqual(office.uid);
expect(deedTypes[2]?.name).toEqual(deedType.name);
expect(deedTypes[2]?.description).toEqual(deedType.description);
expect(deedTypes[2]?.archived_at).toBeNull();
expect(deedTypes[2]?.office_uid).toEqual(office_.uid);
});
it("should return an array of DeedTypes per offices", async () => {
const deedTypesForFirstOffice = await DeedTypeServiceTest.get({ where: { office: {uid: office.uid} }, orderBy: { name: "asc" } });
expect(deedTypesForFirstOffice.length).toEqual(1);
// verify result content
expect(deedTypesForFirstOffice[0]?.name).toEqual(deedType.name);
expect(deedTypesForFirstOffice[0]?.description).toEqual(deedType.description);
expect(deedTypesForFirstOffice[0]?.archived_at).toBeNull();
expect(deedTypesForFirstOffice[0]?.office_uid).toEqual(office.uid);
const deedTypesForSecondOffice = await DeedTypeServiceTest.get({ where: { office: {uid: office_.uid} }, orderBy: { name: "asc" } });
expect(deedTypesForSecondOffice.length).toEqual(2);
// verify result content
expect(deedTypesForSecondOffice[0]?.name).toEqual(deedType_.name);
expect(deedTypesForSecondOffice[0]?.description).toEqual(deedType_.description);
expect(deedTypesForSecondOffice[0]?.archived_at).toBeNull();
expect(deedTypesForSecondOffice[0]?.office_uid).toEqual(office_.uid);
expect(deedTypesForSecondOffice[1]?.name).toEqual(deedType.name);
expect(deedTypesForSecondOffice[1]?.description).toEqual(deedType.description);
expect(deedTypesForSecondOffice[1]?.archived_at).toBeNull();
expect(deedTypesForSecondOffice[1]?.office_uid).toEqual(office_.uid);
});
});

View File

@ -0,0 +1,272 @@
import "module-alias/register";
import "reflect-metadata";
import { DocumentType } from "le-coffre-resources/dist/SuperAdmin";
import DocumentTypesService from "@Services/super-admin/DocumentTypesService/DocumentTypesService";
import { PrismaClient } from "prisma/prisma-client";
import { documentType, documentType_, office, office_ } from "@Test/config/MockedData";
import DocumentTypesRepository from "@Repositories/DocumentTypesRepository";
import Container from "typedi";
import { initOffice } from "@Test/config/Init";
const prisma = new PrismaClient();
const DocumentTypesServiceTest = new DocumentTypesService(Container.get(DocumentTypesRepository));
beforeAll(async () => {
office.uid = (await initOffice(office)).uid;
office_.uid = (await initOffice(office_)).uid;
});
afterAll(async () => {
const deleteDocumentTypes = prisma.documentTypes.deleteMany();
const deleteOffices = prisma.offices.deleteMany();
await prisma.$transaction([deleteDocumentTypes, deleteOffices]);
await prisma.$disconnect();
});
describe("test create function", () => {
it("should not create a new document type if office is unknown", async () => {
let documentTypeWithoutOfficeUid: DocumentType = JSON.parse(JSON.stringify(documentType));
documentTypeWithoutOfficeUid.office.uid = "random uid";
// try to create a new document type with unknown office
async function createDocumentTypeWithUnknownOffice() {
await DocumentTypesServiceTest.create(documentTypeWithoutOfficeUid);
}
await expect(createDocumentTypeWithUnknownOffice).rejects.toThrow();
});
it("should create a new document type", async () => {
let documentTypeWithOfficeUid: DocumentType = JSON.parse(JSON.stringify(documentType));
documentTypeWithOfficeUid.office.uid = office.uid;
const documentTypeCreated = await DocumentTypesServiceTest.create(documentTypeWithOfficeUid);
expect(documentTypeCreated.name).toEqual(documentType.name);
expect(documentTypeCreated.public_description).toEqual(documentType.public_description);
expect(documentTypeCreated.private_description).toEqual(documentType.private_description);
expect(documentTypeCreated.archived_at).toBeNull();
expect(documentTypeCreated.office_uid).toEqual(office.uid);
});
it("should not create a new document type with a name already used for a given office", async () => {
let documentTypeWithSameNameAndOffice: DocumentType = JSON.parse(JSON.stringify(documentType_));
documentTypeWithSameNameAndOffice.office.uid = office.uid;
documentTypeWithSameNameAndOffice.name = documentType.name;
async function createDocumentTypeWithSameNameAndOffice() {
await DocumentTypesServiceTest.create(documentTypeWithSameNameAndOffice);
}
await expect(createDocumentTypeWithSameNameAndOffice).rejects.toThrow();
});
it("should create the same document type for a different office", async () => {
let documentTypeDuplicatedForNewOffice: DocumentType = JSON.parse(JSON.stringify(documentType));
documentTypeDuplicatedForNewOffice.office.uid = office_.uid;
const documentTypeCreated = await DocumentTypesServiceTest.create(documentTypeDuplicatedForNewOffice);
expect(documentTypeCreated.name).toEqual(documentType.name);
expect(documentTypeCreated.public_description).toEqual(documentType.public_description);
expect(documentTypeCreated.private_description).toEqual(documentType.private_description);
expect(documentTypeCreated.archived_at).toBeNull();
expect(documentTypeCreated.office_uid).toEqual(office_.uid);
});
it("should create a new document type version with a different name for a given office", async () => {
let documentTypeWithSameDescription: DocumentType = JSON.parse(JSON.stringify(documentType));
documentTypeWithSameDescription.office.uid = office.uid;
documentTypeWithSameDescription.name = documentType_.name;
const documentTypeCreated = await DocumentTypesServiceTest.create(documentTypeWithSameDescription);
expect(documentTypeCreated.name).toEqual(documentType_.name);
expect(documentTypeCreated.public_description).toEqual(documentType.public_description);
expect(documentTypeCreated.private_description).toEqual(documentType.private_description);
expect(documentTypeCreated.archived_at).toBeNull();
expect(documentTypeCreated.office_uid).toEqual(office.uid);
});
});
describe("test update function", () => {
it("should update a document type", async () => {
const documentTypeCreated = await prisma.documentTypes.findFirstOrThrow({
where: { name: documentType_.name, office_uid: office.uid },
});
expect(documentTypeCreated.name).toEqual(documentType_.name);
expect(documentTypeCreated.public_description).toEqual(documentType.public_description);
expect(documentTypeCreated.private_description).toEqual(documentType.private_description);
expect(documentTypeCreated.archived_at).toBeNull();
expect(documentTypeCreated.office_uid).toEqual(office.uid);
let documentTypeWithNewDescription: DocumentType = JSON.parse(JSON.stringify(documentType_));
documentTypeWithNewDescription.office.uid = office.uid;
// update the last document type created with his the right descriptions
const documentTypeUpdated = await DocumentTypesServiceTest.update(documentTypeCreated.uid, documentTypeWithNewDescription);
expect(documentTypeUpdated.name).toEqual(documentType_.name);
expect(documentTypeUpdated.public_description).toEqual(documentType_.public_description);
expect(documentTypeUpdated.private_description).toEqual(documentType_.private_description);
expect(documentTypeUpdated.archived_at).toBeNull();
expect(documentTypeUpdated.office_uid).toEqual(office.uid);
});
it("should not update a document type name with an already used name for given office", async () => {
const documentTypeUid = (
await prisma.documentTypes.findFirstOrThrow({ where: { name: documentType_.name, office_uid: office.uid } })
).uid;
let documentTypeWithSameNameAndOffice: DocumentType = JSON.parse(JSON.stringify(documentType_));
documentTypeWithSameNameAndOffice.office.uid = office.uid;
documentTypeWithSameNameAndOffice.name = documentType.name;
// update the last document type created with his the right description
async function updateDocumentTypeWithSameName() {
await DocumentTypesServiceTest.update(documentTypeUid, documentTypeWithSameNameAndOffice);
}
await expect(updateDocumentTypeWithSameName).rejects.toThrow();
});
it("should not update a document type office membership if the office already has this document type", async () => {
const documentTypeUid = (
await prisma.documentTypes.findFirstOrThrow({ where: { name: documentType_.name, office_uid: office.uid } })
).uid;
let documentTypeWithSameNameAndOffice: DocumentType = JSON.parse(JSON.stringify(documentType_));
documentTypeWithSameNameAndOffice.office.uid = office.uid;
documentTypeWithSameNameAndOffice.name = documentType.name;
// try to duplicate document type in a given office
async function updateDocumentTypeWithduplicatedName() {
await DocumentTypesServiceTest.update(documentTypeUid, documentTypeWithSameNameAndOffice);
}
await expect(updateDocumentTypeWithduplicatedName).rejects.toThrow();
});
it("should update a document type office membership", async () => {
const documentTypeCreated = await prisma.documentTypes.findFirstOrThrow({
where: { name: documentType_.name, office_uid: office.uid },
});
expect(documentTypeCreated.name).toEqual(documentType_.name);
expect(documentTypeCreated.public_description).toEqual(documentType_.public_description);
expect(documentTypeCreated.private_description).toEqual(documentType_.private_description);
expect(documentTypeCreated.archived_at).toBeNull();
expect(documentTypeCreated.office_uid).toEqual(office.uid);
let documentTypeTransferedToNewOffice: DocumentType = JSON.parse(JSON.stringify(documentType_));
documentTypeTransferedToNewOffice.office.uid = office_.uid;
// update the last document type updated with a new office membership
const documentTypeUpdated = await DocumentTypesServiceTest.update(documentTypeCreated.uid, documentTypeTransferedToNewOffice);
expect(documentTypeUpdated.name).toEqual(documentType_.name);
expect(documentTypeUpdated.public_description).toEqual(documentType_.public_description);
expect(documentTypeUpdated.private_description).toEqual(documentType_.private_description);
expect(documentTypeUpdated.archived_at).toBeNull();
expect(documentTypeUpdated.office_uid).toEqual(office_.uid);
});
it("should archivate a document type", async () => {
const documentTypeCreated = await prisma.documentTypes.findFirstOrThrow({
where: { name: documentType_.name, office_uid: office_.uid },
});
expect(documentTypeCreated.name).toEqual(documentType_.name);
expect(documentTypeCreated.public_description).toEqual(documentType_.public_description);
expect(documentTypeCreated.private_description).toEqual(documentType_.private_description);
expect(documentTypeCreated.archived_at).toBeNull();
expect(documentTypeCreated.office_uid).toEqual(office_.uid);
let documentTypeArchivated: DocumentType = JSON.parse(JSON.stringify(documentType_));
documentTypeArchivated.office.uid = office_.uid;
const currentDate = new Date(Date.now());
documentTypeArchivated.archived_at = currentDate;
// archivate a document type by giving a non null date for archivated_at attribute
const documentTypeUpdated = await DocumentTypesServiceTest.update(documentTypeCreated.uid, documentTypeArchivated);
expect(documentTypeUpdated.name).toEqual(documentType_.name);
expect(documentTypeUpdated.public_description).toEqual(documentType_.public_description);
expect(documentTypeUpdated.private_description).toEqual(documentType_.private_description);
expect(documentTypeUpdated.archived_at).toEqual(currentDate);
expect(documentTypeUpdated.office_uid).toEqual(office_.uid);
});
it("should unarchivate a document type", async () => {
const documentTypeCreated = await prisma.documentTypes.findFirstOrThrow({
where: { name: documentType_.name, office_uid: office_.uid },
});
expect(documentTypeCreated.name).toEqual(documentType_.name);
expect(documentTypeCreated.public_description).toEqual(documentType_.public_description);
expect(documentTypeCreated.private_description).toEqual(documentType_.private_description);
expect(documentTypeCreated.archived_at).not.toBeNull();
expect(documentTypeCreated.office_uid).toEqual(office_.uid);
let documentTypeUnarchivated: DocumentType = JSON.parse(JSON.stringify(documentType_));
documentTypeUnarchivated.office.uid = office_.uid;
// unarchivate a document type by giving a null date for archivated_at attribute
const documentTypeUpdated = await DocumentTypesServiceTest.update(documentTypeCreated.uid, documentTypeUnarchivated);
expect(documentTypeUpdated.name).toEqual(documentType_.name);
expect(documentTypeUpdated.public_description).toEqual(documentType_.public_description);
expect(documentTypeUpdated.private_description).toEqual(documentType_.private_description);
expect(documentTypeUpdated.archived_at).toBeNull();
expect(documentTypeUpdated.office_uid).toEqual(office_.uid);
});
});
describe("test get function", () => {
it("should return an array of DocumentTypes", async () => {
const documentTypes = await DocumentTypesServiceTest.get({ orderBy: [{ name: "asc" }, { created_at: "asc" }] });
// verify result typing
expect(documentTypes).toBeInstanceOf(Array<DocumentType>);
expect(documentTypes.length).toEqual(3);
// verify result content
expect(documentTypes[0]?.name).toEqual(documentType_.name);
expect(documentTypes[0]?.public_description).toEqual(documentType_.public_description);
expect(documentTypes[0]?.private_description).toEqual(documentType_.private_description);
expect(documentTypes[0]?.archived_at).toBeNull();
expect(documentTypes[0]?.office_uid).toEqual(office_.uid);
expect(documentTypes[1]?.name).toEqual(documentType.name);
expect(documentTypes[1]?.public_description).toEqual(documentType.public_description);
expect(documentTypes[1]?.private_description).toEqual(documentType.private_description);
expect(documentTypes[1]?.archived_at).toBeNull();
expect(documentTypes[1]?.office_uid).toEqual(office.uid);
expect(documentTypes[2]?.name).toEqual(documentType.name);
expect(documentTypes[2]?.public_description).toEqual(documentType.public_description);
expect(documentTypes[2]?.private_description).toEqual(documentType.private_description);
expect(documentTypes[2]?.archived_at).toBeNull();
expect(documentTypes[2]?.office_uid).toEqual(office_.uid);
});
it("should return an array of DocumentTypes per offices", async () => {
const documentTypesForFirstOffice = await DocumentTypesServiceTest.get({ where: { office: {uid : office.uid }}, orderBy: { name: "asc" } });
expect(documentTypesForFirstOffice.length).toEqual(1);
// verify result content
expect(documentTypesForFirstOffice[0]?.name).toEqual(documentType.name);
expect(documentTypesForFirstOffice[0]?.public_description).toEqual(documentType.public_description);
expect(documentTypesForFirstOffice[0]?.private_description).toEqual(documentType.private_description);
expect(documentTypesForFirstOffice[0]?.archived_at).toBeNull();
expect(documentTypesForFirstOffice[0]?.office_uid).toEqual(office.uid);
const documentTypesForSecondOffice = await DocumentTypesServiceTest.get({ where: { office: {uid : office_.uid }}, orderBy: { name: "asc" } });
expect(documentTypesForSecondOffice.length).toEqual(2);
// verify result content
expect(documentTypesForSecondOffice[0]?.name).toEqual(documentType_.name);
expect(documentTypesForSecondOffice[0]?.public_description).toEqual(documentType_.public_description);
expect(documentTypesForSecondOffice[0]?.private_description).toEqual(documentType_.private_description);
expect(documentTypesForSecondOffice[0]?.archived_at).toBeNull();
expect(documentTypesForSecondOffice[0]?.office_uid).toEqual(office_.uid);
expect(documentTypesForSecondOffice[1]?.name).toEqual(documentType.name);
expect(documentTypesForSecondOffice[1]?.public_description).toEqual(documentType.public_description);
expect(documentTypesForSecondOffice[1]?.private_description).toEqual(documentType.private_description);
expect(documentTypesForSecondOffice[1]?.archived_at).toBeNull();
expect(documentTypesForSecondOffice[1]?.office_uid).toEqual(office_.uid);
});
});

View File

@ -0,0 +1,286 @@
import "module-alias/register";
import "reflect-metadata";
import { OfficeFolderHasCustomers, OfficeFolderHasStakeholders, PrismaClient } from "prisma/prisma-client";
import { customer, customer_, deedType, documentType, documentType_, office, officeFolder, officeFolder_, user, user_ } from "@Test/config/MockedData";
import Container from "typedi";
import OfficeFoldersRepository from "@Repositories/OfficeFoldersRepository";
import OfficeFolderService from "@Services/super-admin/OfficeFoldersService/OfficeFoldersService";
import { initCustomers, initDeedType, initDocumentType, initOffice, initUsers } from "@Test/config/Init";
import { OfficeFolder } from "le-coffre-resources/dist/SuperAdmin";
import DeedTypesService from "@Services/super-admin/DeedTypesService/DeedTypesService";
const prisma = new PrismaClient();
const OfficeFolderServiceTest = new OfficeFolderService(Container.get(OfficeFoldersRepository), Container.get(DeedTypesService));
beforeAll(async () => {
office.uid = (await initOffice(office)).uid;
documentType.uid = (await initDocumentType(documentType, office)).uid;
documentType_.uid = (await initDocumentType(documentType_, office)).uid;
deedType.uid = (await initDeedType(deedType, office, [documentType.uid])).uid;
user.uid = (await initUsers(user)).uid;
user_.uid = (await initUsers(user_)).uid;
customer.uid = (await initCustomers(customer)).uid;
customer_.uid = (await initCustomers(customer_)).uid;
});
afterAll(async () => {
/*
* Clean database after all tests execution.
* Due to cascade deletion, if addresses are deleted, all items following tables are dropped: contacts, customers, offices
*/
const deleteDeedTypes = prisma.deedTypes.deleteMany();
const deleteAddresses = prisma.addresses.deleteMany();
await prisma.$transaction([deleteDeedTypes, deleteAddresses]);
await prisma.$disconnect();
});
describe("test create function", () => {
it("should not create a new office folder if deed type is unknown", async () => {
let officeFolderWithoutDeedTypeUid: OfficeFolder = JSON.parse(JSON.stringify(officeFolder));
officeFolderWithoutDeedTypeUid.deed.deed_type.uid = "random uid";
// try to create a new deed with unknown deed type
async function createOfficeFolderWithUnknownDeedType() {
await OfficeFolderServiceTest.create(officeFolderWithoutDeedTypeUid);
}
await expect(createOfficeFolderWithUnknownDeedType).rejects.toThrow();
});
it("should not create a new office folder if deed type is archived", async () => {
let officeFolderWithArchivatedDeedType: OfficeFolder = JSON.parse(JSON.stringify(officeFolder));
// try to create a new deed with unknown deed type
async function createOfficeFolderWithArchivedDeedType() {
await OfficeFolderServiceTest.create(officeFolderWithArchivatedDeedType);
}
await expect(createOfficeFolderWithArchivedDeedType).rejects.toThrow("deed type is archived");
});
it("should create a new office folder based on existing deed type", async () => {
const officeFolderCreated = await OfficeFolderServiceTest.create(officeFolder);
const deedCreated = await prisma.deeds.findUniqueOrThrow({ where: { uid: officeFolderCreated.deed_uid } });
expect(officeFolderCreated.name).toEqual(officeFolder.name);
expect(officeFolderCreated.folder_number).toEqual(officeFolder.folder_number);
expect(officeFolderCreated.description).toEqual(officeFolder.description);
expect(officeFolderCreated.archived_description).toEqual(null);
expect(officeFolderCreated.status).toEqual("LIVE");
expect(officeFolderCreated.office_uid).toEqual(officeFolder.office.uid);
expect(deedCreated.deed_type_uid).toEqual(officeFolder.deed.deed_type.uid);
});
it("should contains stakeholders", async () => {
const officeFolderCreated = await prisma.officeFolders.findFirstOrThrow({
include: { office_folder_has_stakeholder: true },
});
const stakeholderRelation = await prisma.officeFolderHasStakeholders.findUniqueOrThrow({
where: {
office_folder_uid_user_stakeholder_uid: {
user_stakeholder_uid: user.uid!,
office_folder_uid: officeFolderCreated.uid,
},
},
});
const stakeholderRelation_ = await prisma.officeFolderHasStakeholders.findUniqueOrThrow({
where: {
office_folder_uid_user_stakeholder_uid: {
user_stakeholder_uid: user_.uid!,
office_folder_uid: officeFolderCreated.uid,
},
},
});
expect(officeFolderCreated.office_folder_has_stakeholder.length).toEqual(2);
const stakeholder: OfficeFolderHasStakeholders = {
uid: stakeholderRelation.uid,
office_folder_uid: officeFolderCreated.uid,
user_stakeholder_uid: user.uid!,
created_at: officeFolderCreated.created_at,
updated_at: officeFolderCreated.updated_at,
};
const stakeholder_: OfficeFolderHasStakeholders = {
uid: stakeholderRelation_.uid,
office_folder_uid: officeFolderCreated.uid,
user_stakeholder_uid: user_.uid!,
created_at: officeFolderCreated.created_at,
updated_at: officeFolderCreated.updated_at,
};
expect(officeFolderCreated.office_folder_has_stakeholder).toEqual(expect.arrayContaining([stakeholder, stakeholder_]));
});
it("should not create a new office folder with folder number already created", async () => {
let officeFolderWithSameFolderNumber: OfficeFolder = JSON.parse(JSON.stringify(officeFolder_));
officeFolderWithSameFolderNumber.folder_number = officeFolder.folder_number;
// try to create a new deed with unknown deed type
async function createOfficeFolderWithSameFolderNumber() {
await OfficeFolderServiceTest.create(officeFolderWithSameFolderNumber);
}
await expect(createOfficeFolderWithSameFolderNumber).rejects.toThrow();
});
it("should not create a new office folder if deed type is archived", async () => {
await prisma.deedTypes.update({ where: { uid: deedType.uid }, data: { archived_at: new Date(Date.now()) } });
// try to create a new deed with archivated deed type
async function createDeedWithArchivatedDeedType() {
await OfficeFolderServiceTest.create(officeFolder);
}
await expect(createDeedWithArchivatedDeedType).rejects.toThrow("deed type is archived");
});
});
describe("test update function", () => {
it("should add customers", async () => {
let officeFolderCreated = await prisma.officeFolders.findFirstOrThrow({
include: { office_folder_has_customers: true },
});
expect(officeFolderCreated.office_folder_has_customers).toEqual([]);
// mocked data contains the customers
await OfficeFolderServiceTest.update(officeFolderCreated.uid, officeFolder);
const customerRelation = await prisma.officeFolderHasCustomers.findUniqueOrThrow({
where: {
office_folder_uid_customer_uid: {
customer_uid: customer.uid!,
office_folder_uid: officeFolderCreated.uid,
},
},
});
const customerRelation_ = await prisma.officeFolderHasCustomers.findUniqueOrThrow({
where: {
office_folder_uid_customer_uid: {
customer_uid: customer_.uid!,
office_folder_uid: officeFolderCreated.uid,
},
},
});
officeFolderCreated = await prisma.officeFolders.findFirstOrThrow({
include: { office_folder_has_customers: true },
});
expect(officeFolderCreated.office_folder_has_customers.length).toEqual(2);
const officeFolderHasCustomer: OfficeFolderHasCustomers = {
uid: customerRelation.uid,
office_folder_uid: officeFolderCreated.uid,
customer_uid: customer.uid!,
created_at: customerRelation.created_at,
updated_at: customerRelation.updated_at,
};
const officeFolderHasCustomer_: OfficeFolderHasCustomers = {
uid: customerRelation_.uid,
office_folder_uid: officeFolderCreated.uid,
customer_uid: customer_.uid!,
created_at: customerRelation_.created_at,
updated_at: customerRelation_.updated_at,
};
expect(officeFolderCreated.office_folder_has_customers).toEqual(
expect.arrayContaining([officeFolderHasCustomer, officeFolderHasCustomer_]),
);
});
it("should remove customers", async () => {
let officeFolderCreated = await prisma.officeFolders.findFirstOrThrow({
include: { office_folder_has_customers: true },
});
expect(officeFolderCreated.office_folder_has_customers.length).toEqual(2);
let officeFolderWithLessCustomers: OfficeFolder = JSON.parse(JSON.stringify(officeFolder));
officeFolderWithLessCustomers.office_folder_has_customers!.pop();
// mocked data contains the customers
await OfficeFolderServiceTest.update(officeFolderCreated.uid, officeFolderWithLessCustomers);
const customerRelation = await prisma.officeFolderHasCustomers.findUniqueOrThrow({
where: {
office_folder_uid_customer_uid: {
customer_uid: customer.uid!,
office_folder_uid: officeFolderCreated.uid,
},
},
});
officeFolderCreated = await prisma.officeFolders.findFirstOrThrow({
include: { office_folder_has_customers: true },
});
expect(officeFolderCreated.office_folder_has_customers.length).toEqual(1);
const officeFolderHasCustomer: OfficeFolderHasCustomers = {
uid: customerRelation.uid,
office_folder_uid: officeFolderCreated.uid,
customer_uid: customer.uid!,
created_at: customerRelation.created_at,
updated_at: customerRelation.updated_at,
};
expect(officeFolderCreated.office_folder_has_customers).toEqual([officeFolderHasCustomer]);
});
it("should remove stakeholders", async () => {
let officeFolderCreated = await prisma.officeFolders.findFirstOrThrow({
include: { office_folder_has_stakeholder: true },
});
expect(officeFolderCreated.office_folder_has_stakeholder.length).toEqual(2);
let officeFolderWithLessStakeholders: OfficeFolder = JSON.parse(JSON.stringify(officeFolder));
officeFolderWithLessStakeholders.office_folder_has_stakeholder!.pop();
// mocked data contains the customers
await OfficeFolderServiceTest.update(officeFolderCreated.uid, officeFolderWithLessStakeholders);
const stakeholderRelation = await prisma.officeFolderHasStakeholders.findUniqueOrThrow({
where: {
office_folder_uid_user_stakeholder_uid: {
user_stakeholder_uid: user.uid!,
office_folder_uid: officeFolderCreated.uid,
},
},
});
officeFolderCreated = await prisma.officeFolders.findFirstOrThrow({
include: { office_folder_has_stakeholder: true },
});
expect(officeFolderCreated.office_folder_has_stakeholder.length).toEqual(1);
const officeFolderHasStakeholder: OfficeFolderHasStakeholders = {
uid: stakeholderRelation.uid,
office_folder_uid: officeFolderCreated.uid,
user_stakeholder_uid: user.uid!,
created_at: stakeholderRelation.created_at,
updated_at: stakeholderRelation.updated_at,
};
expect(officeFolderCreated.office_folder_has_stakeholder).toEqual([officeFolderHasStakeholder]);
});
it("should archivate an office folder", async () => {
const officeFolderCreated = await prisma.officeFolders.findFirstOrThrow({});
let officeFolderArchived: OfficeFolder = JSON.parse(JSON.stringify(officeFolder));
// mocked data for this office folder is "ARCHIVATED" by default
officeFolderArchived.archived_description = "folder complete";
const officeFolderUpdated = await OfficeFolderServiceTest.update(officeFolderCreated.uid, officeFolderArchived);
expect(officeFolderUpdated.archived_description).toEqual(officeFolderArchived.archived_description);
expect(officeFolderUpdated.status).toEqual("ARCHIVED");
});
it("should unarchivate an office folder", async () => {
const officeFolderCreated = await prisma.officeFolders.findFirstOrThrow({});
expect(officeFolderCreated.archived_description).toEqual("folder complete");
expect(officeFolderCreated.status).toEqual("ARCHIVED");
let officeFolderUnarchived: OfficeFolder = JSON.parse(JSON.stringify(officeFolder));
officeFolderUnarchived.status = "LIVE";
const officeFolderUpdated = await OfficeFolderServiceTest.update(officeFolderCreated.uid, officeFolderUnarchived);
expect(officeFolderUpdated.archived_description).toBeNull();
expect(officeFolderUpdated.status).toEqual("LIVE");
});
});
describe("test get function", () => {
it("should return an array of officeFolders", async () => {
const officeFolders = await OfficeFolderServiceTest.get({});
// verify result typing
expect(officeFolders).toBeInstanceOf(Array<OfficeFolder>);
expect(officeFolders.length).toEqual(1);
});
});

View File

@ -0,0 +1,225 @@
import "module-alias/register";
import "reflect-metadata";
import User from "le-coffre-resources/dist/SuperAdmin";
import UsersService from "@Services/super-admin/UsersService/UsersService";
import { PrismaClient } from "@prisma/client";
import { user, userContact, userContact_, user_ } from "@Test/config/MockedData";
import UsersRepository from "@Repositories/UsersRepository";
import Container from "typedi";
const prisma = new PrismaClient();
const UsersServiceTest = new UsersService(Container.get(UsersRepository));
afterAll(async () => {
/*
* Clean database after all tests execution.
* Due to cascade deletion, if addresses are deleted, all items following tables are dropped: contacts, users, offices
*/
const deleteAddresses = prisma.addresses.deleteMany();
await prisma.$transaction([deleteAddresses]);
await prisma.$disconnect();
});
describe("test create function", () => {
it("should create a new user", async () => {
const userCreated = await UsersServiceTest.create(user);
expect(userCreated?.idNot).toEqual(user.idNot);
// verify if user contact is created in db
const contactCreated = await prisma.contacts.findUnique({ where: { uid: userCreated.contact_uid } });
expect(contactCreated?.first_name).toEqual(user.contact.first_name);
expect(contactCreated?.last_name).toEqual(user.contact.last_name);
expect(contactCreated?.cell_phone_number).toEqual(user.contact.cell_phone_number);
expect(contactCreated?.phone_number).toEqual(user.contact.phone_number);
expect(contactCreated?.civility).toEqual(user.contact.civility);
expect(contactCreated?.email).toEqual(user.contact.email);
// verify if user address is created in db
const addressForContactCreated = await prisma.addresses.findUnique({ where: { uid: contactCreated?.address_uid } });
expect(addressForContactCreated?.address).toEqual(user.contact.address?.address);
expect(addressForContactCreated?.zip_code).toEqual(user.contact.address?.zip_code);
expect(addressForContactCreated?.city).toEqual(user.contact.address?.city);
// verify if user office is created in db
const officeCreated = await prisma.offices.findUnique({ where: { uid: userCreated.office_uid } });
expect(officeCreated?.idNot).toEqual(user.office_membership.idNot);
expect(officeCreated?.name).toEqual(user.office_membership.name);
expect(officeCreated?.crpcen).toEqual(user.office_membership.crpcen);
expect(officeCreated?.office_status).toEqual("DESACTIVATED");
// verify if user office's address is created in db
const addressForOfficeCreated = await prisma.addresses.findUnique({ where: { uid: officeCreated?.address_uid } });
expect(addressForOfficeCreated?.address).toEqual(user.office_membership.address.address);
expect(addressForOfficeCreated?.zip_code).toEqual(user.office_membership.address.zip_code);
expect(addressForOfficeCreated?.city).toEqual(user.office_membership.address.city);
});
it("should not create an user already created", async () => {
// try to create the same user
async function duplicateUser() {
await UsersServiceTest.create(user);
}
await expect(duplicateUser).rejects.toThrow();
});
it("should not create an new user with an email already created", async () => {
let newUser: User = JSON.parse(JSON.stringify(user_));
newUser.contact.email = userContact.email;
// try to create a new user with already used email
async function createUserWithDuplicateEmail() {
await UsersServiceTest.create(newUser);
}
await expect(createUserWithDuplicateEmail).rejects.toThrow();
});
it("should not create an user with an phone number already created", async () => {
let newUser: User = JSON.parse(JSON.stringify(user_));
newUser.contact.cell_phone_number = userContact.cell_phone_number;
// try to create a new user with already used cellphone number
async function duplicateUser() {
await UsersServiceTest.create(newUser);
}
await expect(duplicateUser).rejects.toThrow();
});
it("should create an new user if unique attributes differ from existing users", async () => {
let newUser: User = JSON.parse(JSON.stringify(user));
newUser.idNot = user_.idNot;
newUser.contact.email = userContact_.email;
newUser.contact.cell_phone_number = userContact_.cell_phone_number;
const userCreated = await UsersServiceTest.create(newUser);
expect(userCreated?.idNot).toEqual(user_.idNot);
// verify if user_ contact is created in db
const contactCreated = await prisma.contacts.findUnique({ where: { uid: userCreated.contact_uid } });
expect(contactCreated?.first_name).toEqual(user.contact.first_name);
expect(contactCreated?.last_name).toEqual(user.contact.last_name);
expect(contactCreated?.cell_phone_number).toEqual(user_.contact.cell_phone_number);
expect(contactCreated?.phone_number).toEqual(user.contact.phone_number);
expect(contactCreated?.civility).toEqual(user.contact.civility);
expect(contactCreated?.email).toEqual(user_.contact.email);
// verify if user_ address is created in db
const addressForContactCreated = await prisma.addresses.findUnique({ where: { uid: contactCreated?.address_uid } });
expect(addressForContactCreated?.address).toEqual(user.contact.address?.address);
expect(addressForContactCreated?.zip_code).toEqual(user.contact.address?.zip_code);
expect(addressForContactCreated?.city).toEqual(user.contact.address?.city);
// verify if user joined the existing office
const officeJoined = await prisma.offices.findUnique({ where: { uid: userCreated.office_uid } });
expect(officeJoined?.idNot).toEqual(user.office_membership.idNot);
expect(officeJoined?.name).toEqual(user.office_membership.name);
expect(officeJoined?.crpcen).toEqual(user.office_membership.crpcen);
expect(officeJoined?.office_status).toEqual("DESACTIVATED");
});
});
describe("test update function", () => {
it("should update an user's data", async () => {
const userCreated = await prisma.users.findFirstOrThrow({ where: { idNot: user_.idNot } });
const officeJoined = await prisma.offices.findUnique({ where: { uid: userCreated.office_uid } });
expect(officeJoined?.idNot).toEqual(user.office_membership.idNot);
expect(officeJoined?.name).toEqual(user.office_membership.name);
expect(officeJoined?.crpcen).toEqual(user.office_membership.crpcen);
expect(officeJoined?.office_status).toEqual("DESACTIVATED");
// update the last user created with his own new office and own contact
const updatedUser = await UsersServiceTest.update(userCreated.uid, user_);
expect(updatedUser?.idNot).toEqual(user_.idNot);
// verify if user_ contact is created in db
const existingContact = await prisma.contacts.findUnique({ where: { uid: updatedUser.contact_uid } });
expect(existingContact?.first_name).toEqual(user_.contact.first_name);
expect(existingContact?.last_name).toEqual(user_.contact.last_name);
expect(existingContact?.cell_phone_number).toEqual(user_.contact.cell_phone_number);
expect(existingContact?.phone_number).toEqual(user_.contact.phone_number);
expect(existingContact?.civility).toEqual(user_.contact.civility);
expect(existingContact?.email).toEqual(user_.contact.email);
// verify if user_ address is created in db
const addressForExistingContact = await prisma.addresses.findUnique({ where: { uid: existingContact?.address_uid } });
expect(addressForExistingContact?.address).toEqual(user_.contact.address?.address);
expect(addressForExistingContact?.zip_code).toEqual(user_.contact.address?.zip_code);
expect(addressForExistingContact?.city).toEqual(user_.contact.address?.city);
// verify if user_ joined the new office
const officeCreated = await prisma.offices.findUnique({ where: { uid: updatedUser.office_uid } });
expect(officeCreated?.idNot).toEqual(user_.office_membership.idNot);
expect(officeCreated?.name).toEqual(user_.office_membership.name);
expect(officeCreated?.crpcen).toEqual(user_.office_membership.crpcen);
expect(officeCreated?.office_status).toEqual("DESACTIVATED");
// verify is user_ office's address is created in db
const addressForOfficeCreated = await prisma.addresses.findUnique({ where: { uid: officeCreated?.address_uid } });
expect(addressForOfficeCreated?.address).toEqual(user_.office_membership.address.address);
expect(addressForOfficeCreated?.zip_code).toEqual(user_.office_membership.address.zip_code);
expect(addressForOfficeCreated?.city).toEqual(user_.office_membership.address.city);
});
it("should not update an user with an email already used", async () => {
const userUid = (await prisma.users.findFirstOrThrow({ where: { idNot: user_.idNot } })).uid;
let updatedUser: User = JSON.parse(JSON.stringify(user_));
updatedUser.contact.email = userContact.email;
// try to create a new user with already used email
async function updateUserWithDuplicateEmail() {
await UsersServiceTest.update(userUid, updatedUser);
}
await expect(updateUserWithDuplicateEmail).rejects.toThrow();
});
it("should not update an user with an phone number already used", async () => {
const userUid = (await prisma.users.findFirstOrThrow({ where: { idNot: user_.idNot } })).uid;
let updatedUser: User = JSON.parse(JSON.stringify(user_));
updatedUser.contact.cell_phone_number = userContact.cell_phone_number;
// try to create a new user with already used email
async function updateUserWithDuplicateEmail() {
await UsersServiceTest.update(userUid, updatedUser);
}
await expect(updateUserWithDuplicateEmail).rejects.toThrow();
});
});
describe("test get function", () => {
it("should return an array of Users", async () => {
const req = {};
const users = await UsersServiceTest.get(req);
// verify result typing
expect(users).toBeInstanceOf(Array<User>);
expect(users.length).toEqual(2);
// verify result content
const usersCreated = await prisma.users.findMany();
expect(users).toContainEqual(usersCreated[0]);
expect(users).toContainEqual(usersCreated[1]);
});
it("should return an array of Users per offices", async () => {
const officesCreated = await prisma.offices.findMany();
const reqForFirstOffice = { where: { office_uid: officesCreated[0]?.uid } };
const usersForFirstOffice = await UsersServiceTest.get(reqForFirstOffice);
expect(usersForFirstOffice.length).toEqual(1);
// verify result content
expect(usersForFirstOffice[0]?.idNot).toEqual(user.idNot);
const reqForSecondOffice = { where: { office_uid: officesCreated[1]?.uid } };
const usersForSecondOffice = await UsersServiceTest.get(reqForSecondOffice);
expect(usersForSecondOffice.length).toEqual(1);
// verify result content
expect(usersForSecondOffice[0]?.idNot).toEqual(user_.idNot);
});
});

124
temp.yaml Normal file
View File

@ -0,0 +1,124 @@
---
# Source: leCoffre-back/templates/service-account.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: lecoffre-back-sa
---
# Source: leCoffre-back/templates/service-account.yaml
apiVersion: v1
kind: Secret
metadata:
name: lecoffre-back-sa-token
annotations:
kubernetes.io/service-account.name: lecoffre-back-sa
type: kubernetes.io/service-account-token
---
# Source: leCoffre-back/templates/lecoffre-back.yaml
apiVersion: v1
kind: Service
metadata:
name: lecoffre-back-svc
namespace: lecoffre
labels:
spec:
ports:
- port: 80
name: http
targetPort: 1337
selector:
app: lecoffre-back
---
# Source: leCoffre-back/templates/lecoffre-back.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: lecoffre-back
namespace: lecoffre
labels:
app: lecoffre-back
spec:
replicas: 1
selector:
matchLabels:
app: lecoffre-back
template:
metadata:
annotations:
vault.hashicorp.com/agent-inject: "true"
vault.hashicorp.com/agent-inject-secret-envs-api: secret/data/lecoffre-back-stg/config/envs-api
vault.hashicorp.com/agent-inject-template-envs-api: |
{{ with secret "secret/data/lecoffre-back-stg/config/envs-api" }}
{{ range $k, $v := .Data.data }}
export {{ $k }}="{{ $v }}"
{{ end }}
{{ end }}
vault.hashicorp.com/agent-pre-populate-only: "true"
vault.hashicorp.com/role: custom_lecoffre-back_injector_rol
labels:
app: lecoffre-back
spec:
serviceAccountName: lecoffre-back-sa
imagePullSecrets:
- name: docker-pull-secret
containers:
- name: lecoffre-back
image: "rg.fr-par.scw.cloud/lecoffre/back:v0.3.2"
resources:
limits:
memory: 2Gi
requests:
cpu: 200m
memory: 1Gi
imagePullPolicy: Always
command: ['sh', '-c', '. /vault/secrets/envs-api && npm start']
---
# Source: leCoffre-back/templates/lecoffre-back.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: lecoffre-back
namespace: lecoffre
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
nginx.ingress.kubernetes.io/from-to-www-redirect: "true"
spec:
rules:
- host: api.stg.lecoffre.smart-chain.fr
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: lecoffre-back-svc
port:
number: 80
---
# Source: leCoffre-back/templates/docker-pull-secret.yaml
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: docker-pull-secret
spec:
refreshInterval: 1h
secretStoreRef:
name: dockerpullsecret-vault-cluster-secret-store
kind: ClusterSecretStore
target:
template:
type: kubernetes.io/dockerconfigjson
name: docker-pull-secret
creationPolicy: Owner
data:
- secretKey: .dockerconfigjson
remoteRef:
key: secret/data/minteed-stg/config/dockerpullsecret
property: .dockerconfigjson

103
tsconfig.json Normal file
View File

@ -0,0 +1,103 @@
{
"compilerOptions": {
"incremental": false,
// "module": "es2022",
"target": "es2017",
"module": "commonjs",
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"jsx": "preserve",
"sourceMap": true,
"outDir": "./dist",
"rootDir": "./src",
"noEmit": false,
"importHelpers": true,
"resolveJsonModule": true,
/* Strict Type-Checking Options */
"allowUnreachableCode": false,
"allowUnusedLabels": false,
"exactOptionalPropertyTypes": false,
"noImplicitOverride": true,
"strict": true,
"noImplicitAny": true,
"strictNullChecks": true,
"strictFunctionTypes": true,
"strictBindCallApply": true,
"strictPropertyInitialization": true,
"noImplicitThis": true,
"alwaysStrict": true,
"noPropertyAccessFromIndexSignature": true,
/* Additional Checks */
"noUnusedLocals": true,
"noImplicitReturns": true,
"noUncheckedIndexedAccess": true,
"useUnknownInCatchVariables": true,
/* Module Resolution Options */
"moduleResolution": "node",
"baseUrl": ".",
"paths": {
"@App/*": [
"src/app/*"
],
"@Api/*": [
"src/app/api/*"
],
"@Services/*": [
"src/services/*"
],
"@Repositories/*": [
"src/common/repositories/*"
],
"@Entries/*": [
"src/entries/*"
],
"@Common/*": [
"src/common/*"
],
"@Config/*": [
"src/common/config/*"
],
"@Entities/*": [
"src/common/ressources/*"
],
"@System/*": [
"src/common/system/*"
],
"@ControllerPattern/*": [
"src/common/system/controller-pattern/*"
],
"@Test/*":[
"src/test/*"
],
},
// "rootDirs": [],
// "typeRoots": [],
// "types": [],
// "allowSyntheticDefaultImports": true,
"esModuleInterop": true,
// "allowUmdGlobalAccess": true,
/* Source Map Options */
//"sourceRoot": "./src",
//"mapRoot": "./dist",
//"inlineSourceMap": false,
//"inlineSources": false,
/* Experimental Options */
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"allowJs": true,
"isolatedModules": true
},
"include": [
"**/*.ts",
"**/*.tsx",
"src/app/api/admin/UsersController.ts"
, "src/common/databases/seeders/seeder.ts" ],
"exclude": [
"node_modules"
]
}