From 337db2f0781e3422fc2a5c3683612bdc5dbf973b Mon Sep 17 00:00:00 2001 From: Anthony Janin Date: Mon, 11 Aug 2025 16:32:44 +0200 Subject: [PATCH] Improve data import --- next.config.js | 3 + .../Api/LeCoffreApi/sdk/DatabaseService.ts | 52 ++++ .../Api/LeCoffreApi/sdk/DeedTypeService.ts | 2 - src/common/Api/LeCoffreApi/sdk/ImportData.ts | 264 ++++++------------ .../ClientView/ClientBox/index.tsx | 15 - src/front/Config/VariablesFront.ts | 2 + src/pages/_app.tsx | 4 + 7 files changed, 153 insertions(+), 189 deletions(-) create mode 100644 src/common/Api/LeCoffreApi/sdk/DatabaseService.ts diff --git a/next.config.js b/next.config.js index 6a4eec96..f22a82d2 100644 --- a/next.config.js +++ b/next.config.js @@ -20,6 +20,7 @@ const nextConfig = { NEXT_PUBLIC_HOTJAR_SITE_ID: process.env.NEXT_PUBLIC_HOTJAR_SITE_ID, NEXT_PUBLIC_HOTJAR_VERSION: process.env.NEXT_PUBLIC_HOTJAR_VERSION, NEXT_PUBLIC_4NK_URL: process.env.NEXT_PUBLIC_4NK_URL, + NEXT_PUBLIC_API_URL: process.env.NEXT_PUBLIC_API_URL, }, serverRuntimeConfig: { @@ -36,6 +37,7 @@ const nextConfig = { NEXT_PUBLIC_HOTJAR_SITE_ID: process.env.NEXT_PUBLIC_HOTJAR_SITE_ID, NEXT_PUBLIC_HOTJAR_VERSION: process.env.NEXT_PUBLIC_HOTJAR_VERSION, NEXT_PUBLIC_4NK_URL: process.env.NEXT_PUBLIC_4NK_URL, + NEXT_PUBLIC_API_URL: process.env.NEXT_PUBLIC_API_URL, }, env: { @@ -52,6 +54,7 @@ const nextConfig = { NEXT_PUBLIC_HOTJAR_SITE_ID: process.env.NEXT_PUBLIC_HOTJAR_SITE_ID, NEXT_PUBLIC_HOTJAR_VERSION: process.env.NEXT_PUBLIC_HOTJAR_VERSION, NEXT_PUBLIC_4NK_URL: process.env.NEXT_PUBLIC_4NK_URL, + NEXT_PUBLIC_API_URL: process.env.NEXT_PUBLIC_API_URL, }, // webpack: config => { diff --git a/src/common/Api/LeCoffreApi/sdk/DatabaseService.ts b/src/common/Api/LeCoffreApi/sdk/DatabaseService.ts new file mode 100644 index 00000000..d8cbd83e --- /dev/null +++ b/src/common/Api/LeCoffreApi/sdk/DatabaseService.ts @@ -0,0 +1,52 @@ +import getConfig from 'next/config'; +const { publicRuntimeConfig } = getConfig(); + +export default class DatabaseService { + + // Empêcher l'instanciation de cette classe utilitaire + private constructor() { } + + /** + * Récupère les données d'une table avec pagination + * @param tableName Nom de la table à consulter + * @param page Numéro de page (commence à 1) + * @param limit Nombre d'éléments par page + * @returns Données de la table avec pagination + */ + public static async getTableData(tableName: string, page: number = 1, limit: number = 10): Promise { + // Vérification des paramètres + if (!tableName) { + throw new Error('Le nom de la table est requis'); + } + + // Validation du nom de la table (par sécurité) + const tableNameRegex = /^[a-zA-Z0-9_]+$/; + if (!tableNameRegex.test(tableName)) { + throw new Error('Nom de table invalide'); + } + + try { + // Construction de l'URL avec paramètres de pagination + const url = `${publicRuntimeConfig.NEXT_PUBLIC_API_URL}/db/${tableName}?page=${page}&limit=${limit}`; + + // Appel à l'API REST + const response = await fetch(url, { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + }, + }); + + if (!response.ok) { + const errorData = await response.json(); + throw new Error(errorData.message || 'Erreur lors de la récupération des données'); + } + + const data = await response.json(); + return data; + } catch (error) { + console.error('Erreur lors de l\'accès à la base de données:', error); + throw error; + } + } +} diff --git a/src/common/Api/LeCoffreApi/sdk/DeedTypeService.ts b/src/common/Api/LeCoffreApi/sdk/DeedTypeService.ts index fa010ed6..b07dae69 100644 --- a/src/common/Api/LeCoffreApi/sdk/DeedTypeService.ts +++ b/src/common/Api/LeCoffreApi/sdk/DeedTypeService.ts @@ -177,8 +177,6 @@ export default class DeedTypeService extends AbstractService { } public static updateDeedType(process: any, newData: any): Promise { - console.log(process); - return new Promise((resolve: () => void) => { this.messageBus.updateProcess(process.processId, { updated_at: new Date().toISOString(), ...newData }, [], null).then((processUpdated: any) => { const newStateId: string = processUpdated.diffs[0]?.state_id; diff --git a/src/common/Api/LeCoffreApi/sdk/ImportData.ts b/src/common/Api/LeCoffreApi/sdk/ImportData.ts index 2a2318e5..eb7b00c8 100644 --- a/src/common/Api/LeCoffreApi/sdk/ImportData.ts +++ b/src/common/Api/LeCoffreApi/sdk/ImportData.ts @@ -3,6 +3,7 @@ import { v4 as uuidv4 } from 'uuid'; import User from 'src/sdk/User'; import MessageBus from 'src/sdk/MessageBus'; +import DatabaseService from './DatabaseService'; import RuleService from './RuleService'; import RuleGroupService from './RuleGroupService'; import RoleService from './RoleService'; @@ -36,8 +37,8 @@ export default class ImportData { }, { name: 'Groupes de règles', - function: async (progressCallback?: (subProgress: number, description?: string) => void, prevResults?: any[]) => - await this.importRuleGroups(prevResults![0], progressCallback) + function: async (progressCallback?: (subProgress: number, description?: string) => void) => + await this.importRuleGroups(progressCallback) }, { name: 'Rôles', @@ -171,190 +172,109 @@ export default class ImportData { } private static async importRules(onProgress?: (progress: number, description?: string) => void): Promise { - // Constantes de progression - pourraient être paramétrées + const rules: any[] = []; + const INIT_PROGRESS = 0; const FETCH_PROGRESS = 30; - const CREATE_START_PROGRESS = FETCH_PROGRESS; const CREATE_END_PROGRESS = 90; const FINAL_PROGRESS = 100; - onProgress?.(INIT_PROGRESS, 'Initialisation'); - return await new Promise((resolve: (rules: any[]) => void) => { - const defaultRules: any[] = [ - // Actes et documents - { - name: "POST deeds", - label: "Créer un template de type d'acte", - namespace: "collaborator" - }, - { - name: "PUT deeds", - label: "Modifier un type d'acte", - namespace: "collaborator" - }, - { - name: "DELETE deeds", - label: "Supprimer des types d'actes", - namespace: "collaborator" - }, - { - name: "GET deed-types", - label: "Lecture des types d'actes", - namespace: "collaborator" - }, - { - name: "POST deed-types", - label: "Création des types d'actes", - namespace: "collaborator" - }, - { - name: "PUT deed-types", - label: "Modification des types d'actes", - namespace: "collaborator" - }, - { - name: "DELETE deed-types", - label: "Suppression des types d'actes", - namespace: "collaborator" - }, - { - name: "GET document-types", - label: "Lecture des types de documents", - namespace: "collaborator" - }, - { - name: "POST document-types", - label: "Création des types de documents", - namespace: "collaborator" - }, - { - name: "PUT document-types", - label: "Modification des types de documents", - namespace: "collaborator" - }, - { - name: "DELETE document-types", - label: "Suppression des types de documents", - namespace: "collaborator" - }, - // RIB - { - name: "GET rib", - label: "Lire le RIB de l'office", - namespace: "collaborator" - }, - { - name: "POST rib", - label: "Déposer le RIB de l'office", - namespace: "collaborator" - }, - { - name: "PUT rib", - label: "Editer le RIB de l'office", - namespace: "collaborator" - }, - { - name: "DELETE rib", - label: "Supprimer le RIB de l'office", - namespace: "collaborator" - }, - // Abonnements - { - name: "GET subscriptions", - label: "Récupérer les abonnements", - namespace: "collaborator" - }, - { - name: "POST subscriptions", - label: "Inviter un collaborateur à l'abonnement", - namespace: "collaborator" - }, - { - name: "PUT subscriptions", - label: "Modifier l'abonnement", - namespace: "collaborator" - }, - { - name: "GET stripe", - label: "Gérer l'abonnement de l'office", - namespace: "collaborator" - }, - { - name: "POST stripe", - label: "Payer un abonnement", - namespace: "collaborator" - } - ]; - RuleService.getRules().then(async (processes: any[]) => { - onProgress?.(FETCH_PROGRESS, 'Récupération des règles existantes'); - const rules: any[] = processes.map((process: any) => process.processData); - if (rules.length === 0) { - const totalRules = defaultRules.length; - for (let i = 0; i < totalRules; i++) { - const validatorId: string = '884cb36a346a79af8697559f16940141f068bdf1656f88fa0df0e9ecd7311fb8:0'; - rules.push((await RuleService.createRule(defaultRules[i], validatorId)).processData); - // Progression dynamique pendant la création des règles - const progressRange = CREATE_END_PROGRESS - CREATE_START_PROGRESS; - const progress = CREATE_START_PROGRESS + ((i + 1) / totalRules) * progressRange; - onProgress?.(progress, `Création de la règle ${i + 1}/${totalRules} : ${defaultRules[i].label}`); - } - } - onProgress?.(FINAL_PROGRESS, 'Importation des règles terminée'); - resolve(rules); - }); - }); + let page = 1; + let limit = 10; + let totalPages = 1; + + onProgress?.(FETCH_PROGRESS, 'Récupération des règles existantes'); + let result = await DatabaseService.getTableData('rules', page, limit); + if (result && result.success && result.pagination) { + totalPages = result.pagination.totalPages || 1; + } + + const FETCH_PAGE_PROGRESS_START = FETCH_PROGRESS; + const FETCH_PAGE_PROGRESS_END = 60; + const CREATE_START_PROGRESS = 60; + + while (result && result.success) { + const fetchPageProgress = FETCH_PAGE_PROGRESS_START + ((page / totalPages) * (FETCH_PAGE_PROGRESS_END - FETCH_PAGE_PROGRESS_START)); + + onProgress?.(fetchPageProgress, `Page ${page}/${totalPages} : Récupération des règles`); + const existingRules: any[] = (await RuleService.getRules()).map((process: any) => process.processData); + const filteredRules: any[] = result.data.filter((rule: any) => !existingRules.some((existingRule: any) => existingRule.uid === rule.uid)); + + const totalFilteredRules = filteredRules.length; + for (let i = 0; i < totalFilteredRules; i++) { + const validatorId: string = '884cb36a346a79af8697559f16940141f068bdf1656f88fa0df0e9ecd7311fb8:0'; + rules.push((await RuleService.createRule(filteredRules[i], validatorId)).processData); + + const progressRange = CREATE_END_PROGRESS - CREATE_START_PROGRESS; + const ruleProgressIncrement = progressRange / (totalFilteredRules * totalPages); + const progress = CREATE_START_PROGRESS + ((page - 1) * totalFilteredRules + i + 1) * ruleProgressIncrement; + onProgress?.(progress, `Page ${page}/${totalPages} : Création de la règle ${i + 1}/${totalFilteredRules} - ${filteredRules[i].label}`); + } + + if (!result.pagination.hasNextPage) { + break; + } + page++; + + result = await DatabaseService.getTableData('rules', page, limit); + } + + onProgress?.(FINAL_PROGRESS, 'Importation des règles terminée'); + return rules; } - private static async importRuleGroups(rules: any[], onProgress?: (progress: number, description?: string) => void): Promise { - // Constantes de progression - pourraient être paramétrées + private static async importRuleGroups(onProgress?: (progress: number, description?: string) => void): Promise { + const ruleGroups: any[] = []; + const INIT_PROGRESS = 0; const FETCH_PROGRESS = 30; - const CREATE_START_PROGRESS = FETCH_PROGRESS; const CREATE_END_PROGRESS = 90; const FINAL_PROGRESS = 100; - onProgress?.(INIT_PROGRESS, 'Initialisation'); - return await new Promise((resolve: (ruleGroups: any[]) => void) => { - const defaultRuleGroups: any[] = [ - { - name: "Gestion des matrices d'actes et des documents", - rules: rules - .filter((rule: any) => rule.name.includes("deeds") || rule.name.includes("deed-types") || rule.name.includes("document-types")) - .map((rule: any) => ({ uid: rule.uid })) - }, - { - name: "Intégration du RIB", - rules: rules - .filter((rule: any) => rule.name.includes("rib")) - .map((rule: any) => ({ uid: rule.uid })) - }, - { - name: "Gestion de l'abonnement", - rules: rules - .filter((rule: any) => rule.name.includes("subscriptions") || rule.name.includes("stripe")) - .map((rule: any) => ({ uid: rule.uid })) - } - ]; - RuleGroupService.getRuleGroups().then(async (processes: any[]) => { - onProgress?.(FETCH_PROGRESS, 'Récupération des groupes de règles existants'); - const ruleGroups: any[] = processes.map((process: any) => process.processData); - if (ruleGroups.length === 0) { - const totalGroups = defaultRuleGroups.length; - for (let i = 0; i < totalGroups; i++) { - const validatorId: string = '884cb36a346a79af8697559f16940141f068bdf1656f88fa0df0e9ecd7311fb8:0'; - ruleGroups.push((await RuleGroupService.createRuleGroup(defaultRuleGroups[i], validatorId)).processData); - // Progression dynamique pendant la création des groupes de règles - const progressRange = CREATE_END_PROGRESS - CREATE_START_PROGRESS; - const progress = CREATE_START_PROGRESS + ((i + 1) / totalGroups) * progressRange; - onProgress?.(progress, `Création du groupe de règles ${i + 1}/${totalGroups} : ${defaultRuleGroups[i].name}`); - } - } - onProgress?.(FINAL_PROGRESS, 'Importation des groupes de règles terminée'); - resolve(ruleGroups); - }); - }); + let page = 1; + let limit = 10; + let totalPages = 1; + + onProgress?.(FETCH_PROGRESS, 'Récupération des groupes de règles existants'); + let result = await DatabaseService.getTableData('rules_groups', page, limit); + if (result && result.success && result.pagination) { + totalPages = result.pagination.totalPages || 1; + } + + const FETCH_PAGE_PROGRESS_START = FETCH_PROGRESS; + const FETCH_PAGE_PROGRESS_END = 60; + const CREATE_START_PROGRESS = 60; + + while (result && result.success) { + const fetchPageProgress = FETCH_PAGE_PROGRESS_START + ((page / totalPages) * (FETCH_PAGE_PROGRESS_END - FETCH_PAGE_PROGRESS_START)); + + onProgress?.(fetchPageProgress, `Page ${page}/${totalPages} : Récupération du groupe de règles`); + const existingRuleGroups: any[] = (await RuleGroupService.getRuleGroups()).map((process: any) => process.processData); + const filteredRuleGroups: any[] = result.data.filter((rule: any) => !existingRuleGroups.some((existingRule: any) => existingRule.uid === rule.uid)); + + const totalFilteredRuleGroups = filteredRuleGroups.length; + for (let i = 0; i < totalFilteredRuleGroups; i++) { + const validatorId: string = '884cb36a346a79af8697559f16940141f068bdf1656f88fa0df0e9ecd7311fb8:0'; + ruleGroups.push((await RuleGroupService.createRuleGroup(filteredRuleGroups[i], validatorId)).processData); + + const progressRange = CREATE_END_PROGRESS - CREATE_START_PROGRESS; + const ruleProgressIncrement = progressRange / (totalFilteredRuleGroups * totalPages); + const progress = CREATE_START_PROGRESS + ((page - 1) * totalFilteredRuleGroups + i + 1) * ruleProgressIncrement; + onProgress?.(progress, `Page ${page}/${totalPages} : Création du groupe de règles ${i + 1}/${totalFilteredRuleGroups} - ${filteredRuleGroups[i].label}`); + } + + if (!result.pagination.hasNextPage) { + break; + } + page++; + + result = await DatabaseService.getTableData('rules_groups', page, limit); + } + + onProgress?.(FINAL_PROGRESS, 'Importation des groupes de règles terminée'); + return ruleGroups; } private static async importRoles(onProgress?: (progress: number, description?: string) => void): Promise { diff --git a/src/front/Components/Layouts/Folder/FolderInformation/ClientView/ClientBox/index.tsx b/src/front/Components/Layouts/Folder/FolderInformation/ClientView/ClientBox/index.tsx index fd44a797..540b49aa 100644 --- a/src/front/Components/Layouts/Folder/FolderInformation/ClientView/ClientBox/index.tsx +++ b/src/front/Components/Layouts/Folder/FolderInformation/ClientView/ClientBox/index.tsx @@ -30,12 +30,6 @@ export default function ClientBox(props: IProps) { const { isOpen: isDeleteModalOpen, open: openDeleteModal, close: closeDeleteModal } = useOpenable(); const { isOpen: isErrorModalOpen, open: openErrorModal, close: closeErrorModal } = useOpenable(); - // TODO: review - const handleOpenConnectionLink = useCallback(() => { - const url = `http://localhost:3000/client-dashboard/${folderUid}/profile/${customer.uid}`; - alert(url); - }, [customer.uid, folderUid]); - const handleDelete = useCallback( (customerUid: string) => { LoaderService.getInstance().show(); @@ -100,15 +94,6 @@ export default function ClientBox(props: IProps) { )} -
- -
Numéro de téléphone diff --git a/src/front/Config/VariablesFront.ts b/src/front/Config/VariablesFront.ts index 3cc66864..36e62658 100644 --- a/src/front/Config/VariablesFront.ts +++ b/src/front/Config/VariablesFront.ts @@ -31,6 +31,8 @@ export class FrontendVariables { public _4NK_URL!: string; + public API_URL!: string; + private constructor() {} public static getInstance(): FrontendVariables { diff --git a/src/pages/_app.tsx b/src/pages/_app.tsx index 508fba63..c07fcb6d 100644 --- a/src/pages/_app.tsx +++ b/src/pages/_app.tsx @@ -36,6 +36,7 @@ type AppPropsWithLayout = AppProps & { hotjarSiteId: number; hotjarVersion: number; _4nkUrl: string; + apiUrl: string; }; const { publicRuntimeConfig } = getConfig(); @@ -57,6 +58,7 @@ const MyApp = (({ hotjarSiteId, hotjarVersion, _4nkUrl, + apiUrl, }: AppPropsWithLayout) => { const getLayout = Component.getLayout ?? ((page) => ); @@ -75,6 +77,7 @@ const MyApp = (({ instance.HOTJAR_SITE_ID = hotjarSiteId; instance.HOTJAR_VERSION = hotjarVersion; instance._4NK_URL = _4nkUrl; + instance.API_URL = apiUrl; const [isConnected, setIsConnected] = useState(false); const [isReady, setIsReady] = useState(false); @@ -139,6 +142,7 @@ MyApp.getInitialProps = async () => { hotjarSiteId: publicRuntimeConfig.NEXT_PUBLIC_HOTJAR_SITE_ID, hotjarVersion: publicRuntimeConfig.NEXT_PUBLIC_HOTJAR_VERSION, _4nkUrl: publicRuntimeConfig.NEXT_PUBLIC_4NK_URL, + apiUrl: publicRuntimeConfig.NEXT_PUBLIC_API_URL, }; };