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.APP_HOST}/authorized-client`, code: code, grant_type: "authorization_code", }); const token = await fetch(this.variables.IDNOT_BASE_URL + this.variables.IDNOT_CONNEXION_URL + "?" + query, { method: "POST" }); const decodedToken = (await token.json()) as IIdNotToken; const decodedIdToken = jwt.decode(decodedToken.id_token) as IdNotJwtPayload; return decodedIdToken; } public async getRole(roleName: string): Promise { 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(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(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; // 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, }, }; let userHydrated = User.hydrate(userToAdd); const user = await this.userService.create(userHydrated); userHydrated = User.hydrate(user); const officeRoles = await this.officeRolesService.get({ where: { office: { idNot: "0000" }}, include: { office: true, rules: true } }); const documentTypes = await this.documentTypesService.get({ where: { office: { idNot: "0000" }}, include: { office: true } }); const deedTypes = await this.deedTypesService.get({ where:{ office: { idNot: "0000" }}, include: { office: true, document_types: true } }); const officeRolesHydrated = OfficeRole.hydrateArray(officeRoles); const documentTypesHydrated = DocumentType.hydrateArray(documentTypes); const deedTypesHydrated = DeedType.hydrateArray(deedTypes); officeRolesHydrated.forEach(async (officeRole) => { officeRole.office.uid = user.office_uid; await this.officeRolesService.create(officeRole); }); documentTypesHydrated.forEach(async (documentType) => { documentType.office!.uid = user.office_uid; await this.documentTypesService.create(documentType); }); deedTypesHydrated.forEach(async (deedType) => { deedType.office!.uid = user.office_uid; await this.deedTypesService.create(deedType); }); const officeRole = await this.getOfficeRole(userData.typeLien.name, user.office_uid); if(officeRole) { const officeRoleHydrated = OfficeRole.hydrate(officeRole!); userHydrated.office_role = officeRoleHydrated; await this.userService.update(user.uid, userHydrated); } return user; } return user; } public async updateUsers() { const usersReq = await this.userService.getUsersToBeChecked(); const users = User.hydrateArray(usersReq); users.forEach(async (user) => { await this.updateUser(user.uid!); }); } public async updateOffices() { const officesReq = await this.officeService.getOfficesToBeChecked(); const offices = Office.hydrateArray(officesReq); offices.forEach(async (office) => { await this.updateOffice(office.uid!); }); } }