459 lines
16 KiB
TypeScript

import BaseService from "@Services/BaseService";
import { BackendVariables } from "@Common/config/variables/Variables";
import { Service } from "typedi";
import jwt from "jsonwebtoken";
import UsersService from "@Services/super-admin/UsersService/UsersService";
import { IdNotJwtPayload } from "../AuthService/AuthService";
import User, { DeedType, Office, OfficeRole, Role, DocumentType } from "le-coffre-resources/dist/SuperAdmin";
import RolesService from "@Services/super-admin/RolesService/RolesService";
import OfficesService from "@Services/super-admin/OfficesService/OfficesService";
import { EOfficeStatus } from "@prisma/client";
import OfficeRolesService from "@Services/super-admin/OfficeRolesService/OfficeRolesService";
import DeedTypesService from "@Services/super-admin/DeedTypesService/DeedTypesService";
import DocumentTypesService from "@Services/super-admin/DocumentTypesService/DocumentTypesService";
interface IIdNotToken {
access_token: string;
expires_in: number;
id_token: string;
token_type: string;
}
interface IRattachementData {
entiteUrl: string;
personneUrl: string;
entite: {
codeCrpcen: string;
typeEntite: {
name: string;
};
ou: string;
denominationSociale: string;
statutEntite: {
name: string;
};
locationsUrl: string;
};
personne: {
numeroTelephonePro: string;
prenom: string;
nomUsuel: string;
mobilePro: string;
numeroAdherentCrpcen: string;
civilite: string;
};
typeLien: {
name: string;
};
numeroMobile: string;
numeroTelephone: string;
statutDuRattachement: boolean;
mailRattachement: string;
}
interface IOfficeData {
ou: string;
intitule: string;
denominationSociale: string;
departementResidence: {
libelle: string;
code: string;
}[];
libelle: string;
codeCrpcen: string;
locationsUrl: string;
statutEntite: {
name: string;
};
typeEntite: {
name: string;
};
}
interface IOfficeLocation {
totalResultCount: number;
page: number;
size: number;
result: {
mail: string;
numeroTelephone: string;
adrGeo4: string;
adrGeoCodePostal: string;
adrGeoVille: string;
ou: string;
lastModified: string;
deleted: boolean;
}[];
}
enum EIdnotRole {
DIRECTEUR = "Directeur général du CSN",
NOTAIRE_TITULAIRE = "Notaire titulaire",
NOTAIRE_ASSOCIE = "Notaire associé",
NOTAIRE_SALARIE = "Notaire salarié",
COLLABORATEUR = "Collaborateur",
SECRETAIRE_GENERAL = "Secrétaire général",
SUPPLEANT = "Suppléant",
ADMINISTRATEUR = "Administrateur",
RESPONSABLE = "Responsable",
CURATEUR = "Curateur",
}
@Service()
export default class IdNotService extends BaseService {
constructor(
protected variables: BackendVariables,
private userService: UsersService,
private officeService: OfficesService,
private rolesService: RolesService,
private officeRolesService: OfficeRolesService,
private deedTypesService: DeedTypesService,
private documentTypesService: DocumentTypesService,
) {
super();
}
public async getIdNotToken(code: string) {
const query = new URLSearchParams({
client_id: this.variables.IDNOT_CLIENT_ID,
client_secret: this.variables.IDNOT_CLIENT_SECRET,
redirect_uri: this.variables.IDNOT_REDIRECT_URL,
code: code,
grant_type: "authorization_code",
});
const token = await fetch(this.variables.IDNOT_BASE_URL + this.variables.IDNOT_CONNEXION_URL + "?" + query, { method: "POST" });
if(token.status !== 200) console.error(await token.text());
const decodedToken = (await token.json()) as IIdNotToken;
const decodedIdToken = jwt.decode(decodedToken.id_token) as IdNotJwtPayload;
return decodedIdToken;
}
public async getRole(roleName: string): Promise<Role> {
switch (roleName) {
case EIdnotRole.NOTAIRE_TITULAIRE:
return (await this.rolesService.get({ where: { name: "admin" } }))[0]!;
case EIdnotRole.NOTAIRE_ASSOCIE:
return (await this.rolesService.get({ where: { name: "admin" } }))[0]!;
case EIdnotRole.NOTAIRE_SALARIE:
return (await this.rolesService.get({ where: { name: "notary" } }))[0]!;
case EIdnotRole.COLLABORATEUR:
return (await this.rolesService.get({ where: { name: "notary" } }))[0]!;
case EIdnotRole.SUPPLEANT:
return (await this.rolesService.get({ where: { name: "notary" } }))[0]!;
case EIdnotRole.ADMINISTRATEUR:
return (await this.rolesService.get({ where: { name: "notary" } }))[0]!;
case EIdnotRole.CURATEUR:
return (await this.rolesService.get({ where: { name: "notary" } }))[0]!;
default:
return (await this.rolesService.get({ where: { name: "default" } }))[0]!;
}
}
public async getOfficeRole(roleName: string, officeUid: string) {
switch (roleName) {
case EIdnotRole.NOTAIRE_TITULAIRE:
return (await this.officeRolesService.get({ where: { AND: [{ name: "Notaire" }, { office_uid: officeUid }] } }))[0]!;
case EIdnotRole.NOTAIRE_ASSOCIE:
return (await this.officeRolesService.get({ where: { AND: [{ name: "Notaire" }, { office_uid: officeUid }] } }))[0]!;
case EIdnotRole.NOTAIRE_SALARIE:
return (await this.officeRolesService.get({ where: { AND: [{ name: "Notaire" }, { office_uid: officeUid }] } }))[0]!;
case EIdnotRole.COLLABORATEUR:
return (await this.officeRolesService.get({ where: { AND: [{ name: "Collaborateur" }, { office_uid: officeUid }] } }))[0]!;
case EIdnotRole.SUPPLEANT:
return (await this.officeRolesService.get({ where: { AND: [{ name: "Collaborateur" }, { office_uid: officeUid }] } }))[0]!;
case EIdnotRole.ADMINISTRATEUR:
return (await this.officeRolesService.get({ where: { AND: [{ name: "Collaborateur" }, { office_uid: officeUid }] } }))[0]!;
case EIdnotRole.CURATEUR:
return (await this.officeRolesService.get({ where: { AND: [{ name: "Collaborateur" }, { office_uid: officeUid }] } }))[0]!;
default:
return;
}
}
public getOfficeStatus(statusName: string) {
switch (statusName) {
case "Pourvu":
return EOfficeStatus.ACTIVATED;
case "Pourvu mais décédé":
return EOfficeStatus.ACTIVATED;
case "Sans titulaire":
return EOfficeStatus.ACTIVATED;
case "Vacance":
return EOfficeStatus.ACTIVATED;
case "En activité":
return EOfficeStatus.ACTIVATED;
default:
return EOfficeStatus.DESACTIVATED;
}
}
public async updateUser(userId: string) {
const userInfos = await this.userService.getByUid(userId, { contact: true, role: true, office_membership: true });
const user = User.hydrate<User>(userInfos!);
const searchParams = new URLSearchParams({
key: this.variables.IDNOT_API_KEY,
});
let userData = (await (
await fetch(
`${this.variables.IDNOT_API_BASE_URL}/api/pp/v2/rattachements/${user.idNot}_${user.office_membership!.idNot}?` +
searchParams,
{
method: "GET",
},
)
).json()) as IRattachementData;
if (!userData.statutDuRattachement) {
const rattachements = (await (
await fetch(`${this.variables.IDNOT_API_BASE_URL}/api/pp/v2/personnes/${user.idNot}/rattachements?` + searchParams, {
method: "GET",
})
).json()) as any;
if (rattachements.totalResultCount === 0) {
await this.userService.updateCheckedAt(user.uid!);
//await this.userService.delete(user.uid!);
return;
}
const rattachementsResults = rattachements.result as IRattachementData[];
if (!rattachementsResults) return;
rattachementsResults.forEach(async (rattachement) => {
if (rattachement.statutDuRattachement) {
const officeData = (await (
await fetch(`${this.variables.IDNOT_API_BASE_URL + rattachement.entiteUrl}?` + searchParams, {
method: "GET",
})
).json()) as IOfficeData;
if (officeData.typeEntite.name === "office") {
userData = rattachement;
}
}
});
}
let updates = 0;
if (user.office_membership!.idNot !== userData.entite.ou) {
updates++;
let officeData = (await this.officeService.get({ where: { idNot: userData.entite.ou } }))[0];
if (!officeData) {
const officeLocationData = (await (
await fetch(`${this.variables.IDNOT_API_BASE_URL + userData.entite.locationsUrl}?` + searchParams, { method: "GET" })
).json()) as IOfficeLocation;
const office = {
idNot: userData.entite.ou,
name: userData.entite.denominationSociale,
crpcen: userData.entite.codeCrpcen,
office_status: this.getOfficeStatus(userData.entite.statutEntite.name),
address: {
address: officeLocationData.result[0]!.adrGeo4,
city: officeLocationData.result[0]!.adrGeoVille.split(" ")[0] ?? officeLocationData.result[0]!.adrGeoVille,
zip_code: Number(officeLocationData.result[0]!.adrGeoCodePostal),
created_at: null,
updated_at: null,
},
created_at: null,
updated_at: null,
};
officeData = await this.officeService.create(office);
}
user.office_membership = officeData;
}
if (user.contact!.email !== userData.mailRattachement) {
updates++;
user.contact!.email = userData.mailRattachement;
}
if (user.contact!.cell_phone_number !== userData.numeroMobile) {
updates++;
user.contact!.cell_phone_number = userData.numeroMobile;
}
if (updates != 0) await this.userService.update(user.uid!, user);
await this.userService.updateCheckedAt(user.uid!);
}
public async updateOffice(officeId: string) {
const officeInfos = await this.officeService.getByUid(officeId);
const office = Office.hydrate<Office>(officeInfos!);
const searchParams = new URLSearchParams({
key: this.variables.IDNOT_API_KEY,
});
const officeRawData = await fetch(`${this.variables.IDNOT_API_BASE_URL}/api/pp/v2/entities/${office.idNot}?` + searchParams, {
method: "GET",
});
if (officeRawData.status === 404) {
await this.officeService.updateCheckedAt(office.uid!);
//await this.officeService.delete(office.uid!);
return;
}
const officeData = (await officeRawData.json()) as IOfficeData;
let updates = 0;
if (office.name !== officeData.denominationSociale) {
updates++;
office.name = officeData.denominationSociale;
}
if (office.office_status !== this.getOfficeStatus(officeData.statutEntite.name)) {
updates++;
office.office_status = this.getOfficeStatus(officeData.statutEntite.name);
}
if (updates != 0) await this.officeService.update(office.uid!, office);
await this.officeService.updateCheckedAt(office.uid!);
}
public async getOrCreateUser(decodedToken: IdNotJwtPayload) {
let user = await this.userService.getByProvider("idNot", decodedToken.sub);
if (!user) {
const searchParams = new URLSearchParams({
key: this.variables.IDNOT_API_KEY,
});
const userData = (await (
await fetch(`${this.variables.IDNOT_API_BASE_URL}/api/pp/v2/rattachements/${decodedToken.profile_idn}?` + searchParams, {
method: "GET",
})
).json()) as IRattachementData;
if (!userData.statutDuRattachement || userData.entite.typeEntite.name !== "office") {
return null;
}
const officeLocationData = (await (
await fetch(`${this.variables.IDNOT_API_BASE_URL + userData.entite.locationsUrl}?` + searchParams, { method: "GET" })
).json()) as IOfficeLocation;
const office = await this.officeService.get({ where: { idNot: decodedToken.entity_idn } });
// if(officeLocationData.result[0]!.adrGeoCodePostal.slice(0,2) !== "35") {
// return null;
// }
const role = await this.getRole(userData.typeLien.name);
const userToAdd = {
idNot: decodedToken.sub,
office_membership: {
idNot: decodedToken.entity_idn,
name: userData.entite.denominationSociale,
crpcen: userData.entite.codeCrpcen,
office_status: this.getOfficeStatus(userData.entite.statutEntite.name),
address: {
address: officeLocationData.result[0]!.adrGeo4,
city: officeLocationData.result[0]!.adrGeoVille.split(" ")[0] ?? officeLocationData.result[0]!.adrGeoVille, //officeLocationData.result[0]!.adrPostaleVille,
zip_code: Number(officeLocationData.result[0]!.adrGeoCodePostal),
created_at: null,
updated_at: null,
},
created_at: null,
updated_at: null,
},
role: role,
contact: {
first_name: userData.personne.prenom,
last_name: userData.personne.nomUsuel,
email: userData.mailRattachement,
phone_number: userData.numeroTelephone,
cell_phone_number: userData.numeroMobile ?? userData.numeroTelephone,
civility: userData.personne.civilite,
created_at: null,
updated_at: null,
},
};
if(!userToAdd.contact.email) {
return null;
}
let userHydrated = User.hydrate<User>(userToAdd);
const user = await this.userService.create(userHydrated);
const userOffice = await this.officeService.getByUid(user.office_uid);
userHydrated = User.hydrate<User>(user);
const userOfficeHydrated = Office.hydrate<Office>(userOffice!);
if(office.length === 0) {
const officeRoles = await this.officeRolesService.get({
where: { office: { idNot: "0000" } },
include: { office: true, rules: true },
});
const deedTypes = await this.deedTypesService.get({
where: { office: { idNot: "0000" } },
include: { office: true, document_types: { include: { office: true } } },
});
const documentTypes = await this.documentTypesService.get({
where: { office: { idNot: "0000" } },
include: { office: true },
});
const officeRolesHydrated = OfficeRole.hydrateArray<OfficeRole>(officeRoles);
const deedTypesHydrated = DeedType.hydrateArray<DeedType>(deedTypes);
const documentTypesHydrated = DocumentType.hydrateArray<DocumentType>(documentTypes);
await this.duplicateOfficeRoles(officeRolesHydrated, userOfficeHydrated);
const documentTypesCreated = await this.duplicateDocumentTypes(documentTypesHydrated, userOfficeHydrated);
await this.duplicateDeedTypes(deedTypesHydrated, documentTypesCreated, userOfficeHydrated);
}
const officeRole = await this.getOfficeRole(userData.typeLien.name, user.office_uid);
if (officeRole) {
const officeRoleHydrated = OfficeRole.hydrate<OfficeRole>(officeRole!);
userHydrated.office_role = officeRoleHydrated;
await this.userService.update(user.uid, userHydrated);
}
return user;
}
return user;
}
public async duplicateDocumentTypes(documentTypes: DocumentType[], office: Office): Promise<DocumentType[]> {
let newDocumentTypes: DocumentType[] = [];
for(const documentType of documentTypes) {
documentType.office = office;
const documentTypeCreated = await this.documentTypesService.create(documentType);
newDocumentTypes.push(DocumentType.hydrate<DocumentType>(documentTypeCreated));
};
return newDocumentTypes;
}
public async duplicateDeedTypes(deedTypes: DeedType[], documentTypes: DocumentType[], office: Office) {
for (const deedType of deedTypes) {
let newDocumentTypes: DocumentType[] = [];
for (const document of deedType.document_types!) {
const newDocumentType = documentTypes.find((documentType) => documentType.name === document.name);
if(!newDocumentType) continue;
newDocumentTypes.push(newDocumentType!);
};
deedType.document_types = newDocumentTypes;
deedType.office = office;
await this.deedTypesService.create(deedType);
};
}
public async duplicateOfficeRoles(officeRoles: OfficeRole[], office: Office){
for(const officeRole of officeRoles) {
officeRole.office = office;
await this.officeRolesService.create(officeRole);
};
}
public async updateUsers() {
const usersReq = await this.userService.getUsersToBeChecked();
const users = User.hydrateArray<User>(usersReq);
users.forEach(async (user) => {
await this.updateUser(user.uid!);
});
}
public async updateOffices() {
const officesReq = await this.officeService.getOfficesToBeChecked();
const offices = Office.hydrateArray<Office>(officesReq);
offices.forEach(async (office) => {
await this.updateOffice(office.uid!);
});
}
}