From 1147e5bc702e743518719cbd6f41687c0ee9302c Mon Sep 17 00:00:00 2001 From: "Yassine R." Date: Wed, 24 Jan 2024 16:42:34 +0100 Subject: [PATCH] fix(backend): fix imports --- .talismanrc | 34 ++- docker-compose.local.yml | 2 +- packages/backend/nodemon.json | 2 +- packages/backend/package.json | 4 +- .../src/_common/model/usager/Usager.type.ts | 5 +- .../src/_common/tmp-toulouse/MOTIF.const.ts | 8 + .../backend/src/_common/tmp-toulouse/PAYS.ts | 215 ++++++++++++++ .../TOULOUSE_STRUCTURE_ID.const.ts | 2 + .../_common/tmp-toulouse/TUsager.interface.ts | 34 +++ .../_common/tmp-toulouse/getDateFromXml.ts | 24 ++ .../backend/src/_common/tmp-toulouse/index.ts | 5 + ...91990700-generate-temp-tables-migration.ts | 27 ++ ...2191990701-open-toulouse-data-migration.ts | 36 +++ ...90702-import-toulouse-usagers-migration.ts | 276 ++++++++++++++++++ ...703-import-toulouse-entretien-migration.ts | 52 ++++ .../1692216772744-decisions-migration.ts | 260 +++++++++++++++++ ...1697659880955-import-passages-migration.ts | 107 +++++++ ...697704071510-import-courriers-migration.ts | 164 +++++++++++ ...96795-update-last-interaction-migration.ts | 115 ++++++++ .../interaction/TmpCourriersTable.typeorm.ts | 31 ++ .../interaction/TmpHistoriqueTable.typeorm.ts | 28 ++ .../entities/usager/UsagerTable.typeorm.ts | 5 +- .../_postgres/PG_CONNECT_OPTIONS.const.ts | 3 +- .../_postgres/appTypeormManager.service.ts | 2 +- .../_postgres/pgRepository.service.ts | 1 - .../historiqueRepository.service.ts | 15 + .../usager/usagerRepository.service.ts | 4 +- .../services/interactionsCreator.service.ts | 2 +- .../services/structure-deletor.service.ts | 10 +- .../custom-docs/buildCustomDoc.service.ts | 2 +- .../usagerHistoryStateManager.service.ts | 9 +- .../services/usagersCreator.service.ts | 2 +- packages/frontend/package.json | 4 +- .../shared/validators/email.validator.spec.ts | 49 ++++ packages/portail-admins/package.json | 4 +- packages/portail-usagers/package.json | 4 +- yarn.lock | 180 +++++++----- 37 files changed, 1615 insertions(+), 112 deletions(-) create mode 100644 packages/backend/src/_common/tmp-toulouse/MOTIF.const.ts create mode 100644 packages/backend/src/_common/tmp-toulouse/PAYS.ts create mode 100644 packages/backend/src/_common/tmp-toulouse/TOULOUSE_STRUCTURE_ID.const.ts create mode 100644 packages/backend/src/_common/tmp-toulouse/TUsager.interface.ts create mode 100644 packages/backend/src/_common/tmp-toulouse/getDateFromXml.ts create mode 100644 packages/backend/src/_common/tmp-toulouse/index.ts create mode 100644 packages/backend/src/_migrations/1692191990700-generate-temp-tables-migration.ts create mode 100644 packages/backend/src/_migrations/1692191990701-open-toulouse-data-migration.ts create mode 100644 packages/backend/src/_migrations/1692191990702-import-toulouse-usagers-migration.ts create mode 100644 packages/backend/src/_migrations/1692191990703-import-toulouse-entretien-migration.ts create mode 100644 packages/backend/src/_migrations/1692216772744-decisions-migration.ts create mode 100644 packages/backend/src/_migrations/1697659880955-import-passages-migration.ts create mode 100644 packages/backend/src/_migrations/1697704071510-import-courriers-migration.ts create mode 100644 packages/backend/src/_migrations/1700433996795-update-last-interaction-migration.ts create mode 100644 packages/backend/src/database/entities/interaction/TmpCourriersTable.typeorm.ts create mode 100644 packages/backend/src/database/entities/interaction/TmpHistoriqueTable.typeorm.ts create mode 100644 packages/backend/src/database/services/interaction/historiqueRepository.service.ts create mode 100644 packages/frontend/src/app/shared/validators/email.validator.spec.ts diff --git a/.talismanrc b/.talismanrc index e92ead12f6..f55dc6bbdf 100644 --- a/.talismanrc +++ b/.talismanrc @@ -1,26 +1,34 @@ fileignoreconfig: -- filename: _scripts/db/dumps/domifa_test.postgres.restore-data-only.sql +- filename: \_scripts/db/dumps/domifa_test.postgres.restore-data-only.sql checksum: 66f876156591123c240fbc85a80be6d5d8b47e44534e9e1b500f7c1dc1236ed6 -- filename: _scripts/db/dumps/domifa_test.postgres.truncate-restore-data-only.sql +- filename: \_scripts/db/dumps/domifa_test.postgres.truncate-restore-data-only.sql checksum: a2b8def2ce8fe7a42db556fc1cd480f96a55819f11cbd473804051ef74f1e2be -- filename: packages/backend/src/_common/decorators/IsValidPasswordDecorator.ts +- filename: packages/backend/src/\_common/decorators/IsValidPasswordDecorator.ts checksum: f0d4b3cd2e6e2d9b1e0271c34d64adacf87a5f1e7a505402a20869962543608d -- filename: packages/backend/src/_migrations/1699910877010-auto-migration.ts +- filename: packages/backend/src/\_migrations/1692191990702-import-toulouse-usagers-migration.ts + checksum: 2f01f0ce3c9311140cfb0dd3fc05dbdbe735a100154aebdc7e26ff698f2a9211 +- filename: packages/backend/src/\_migrations/1692216772744-decisions-migration.ts + checksum: be1c28fd2140bc53bfd395370a4c7db8c979efb97dc0b8411d765d71edfdc7eb +- filename: packages/backend/src/\_migrations/1699910877010-auto-migration.ts checksum: bd05dd6b68f7fe2ca36ab1180a0449878cf78f4e048d2e5979b3dbe5fba1db53 -- filename: packages/backend/src/_migrations/1701870413794-auto-migration.ts +- filename: packages/backend/src/\_migrations/1701870413794-auto-migration.ts checksum: 281adc67c437b0c3ea874865872dafb0b6a4b23be044694caa6f0d210bbba0f9 -- filename: packages/backend/src/_migrations/1702483465656-auto-migration.ts +- filename: packages/backend/src/\_migrations/1702483465656-auto-migration.ts checksum: 2dbc2450c1df10f68a54897946318976bf8163711f3143e0608ce6c0e7275447 -- filename: packages/backend/src/_migrations/_init-db/1603812391580-pr-env-create-database.ts +- filename: packages/backend/src/\_migrations/\_init-db/1603812391580-pr-env-create-database.ts checksum: b9c525d9cac633693975f7526357350057063772b3c978d6cd43841e676cebcc -- filename: packages/backend/src/_portail-admin/portail-admin-login/portail-admin-login.controller.spec.ts +- filename: packages/backend/src/\_portail-admin/portail-admin-login/portail-admin-login.controller.spec.ts checksum: 3bd78f8919cbe14a45484825d6ce816bc7e2a0456fc53b9beeb1fedb6bdb061a -- filename: packages/backend/src/_portail-usager/portail-usager-login/portail-usagers-login.controller.spec.ts +- filename: packages/backend/src/\_portail-usager/portail-usager-login/portail-usagers-login.controller.spec.ts checksum: 2e02fb9ee9e1324dfab89afeaf4357b6339df59376ea1191f44d394524d6efd8 -- filename: packages/backend/src/_tests/_core/constants/TESTS_USERS_STRUCTURE.mock.ts +- filename: packages/backend/src/\_tests/\_core/constants/TESTS_USERS_STRUCTURE.mock.ts checksum: 7fd396491726fce9ed96ac175c3acdb9ae93ecac0d66e7c6fc5554c5deeceb6f -- filename: packages/backend/src/_tests/_core/constants/TEST_USER_USAGER.mock.ts +- filename: packages/backend/src/\_tests/\_core/constants/TEST_USER_USAGER.mock.ts checksum: d48d45f595373ce56749cfe5b17dc6b09093d5ed9090617052652922b78b333d +- filename: packages/backend/src/_migrations/1692191990700-generate-temp-tables-migration.ts + checksum: e33f183d43233f56556d55460655e8b337ef7f098caca3099424ab2d853a928a +- filename: packages/backend/src/_migrations/1692191990702-import-toulouse-usagers-migration.ts + checksum: e53727c97e2fe4d2e481df0f554fd835e51a9f8671a3bccd2310a595b826cf64 - filename: packages/backend/src/auth/structures-auth.controller.spec.ts checksum: 5cc345a4fee5809b8cbb892e660cfc90a12c674b90919767037e9235a9f222ee - filename: packages/backend/src/database/services/user-usager/user-usager-security/userUsagerSecurityPasswordUpdater.service.ts @@ -53,7 +61,7 @@ fileignoreconfig: checksum: 7749036582dd467fd5c71aba534aec66fecabc3185b7fd7ee75705204877b654 - filename: packages/frontend/src/assets/files/news.json checksum: 87de77471263e0fd5b2561e4be2c9ea7fc1e34f29c24f168de3e378a6d738004 -- filename: packages/portail-usagers/src/app/modules/general/components/_static/cgu/cgu.component.html +- filename: packages/portail-usagers/src/app/modules/general/components/\_static/cgu/cgu.component.html checksum: 584da8c9b8ebc95d1d996d0201e0e57cf31e05c6704104e7adacba67a7eb4dd7 - filename: packages/portail-usagers/src/app/modules/usager-auth/services/usager-auth.service.ts checksum: 628884c40a4907e9161c55bbd77110f15fad0504c7060a7be6be6612fe44daec @@ -62,5 +70,5 @@ fileignoreconfig: - filename: packages/portail-usagers/src/app/modules/usager-auth/usager-login/usager-login.component.ts checksum: b04680c071a8098191859f5a67124df3d168478ee2f997a361595b7244d1f5f7 - filename: yarn.lock - checksum: 7d003c01f8bee02f4f1910d80b12164c613b81c13db0b2e81e330d4413efaa6c + checksum: b1eb3ca3b86acf56658fc56a7d93070cf7f80881078972160f302937d18db5c9 version: "1.0" diff --git a/docker-compose.local.yml b/docker-compose.local.yml index 52c88055e8..99b387ff6f 100644 --- a/docker-compose.local.yml +++ b/docker-compose.local.yml @@ -6,7 +6,7 @@ volumes: services: postgres: - image: postgis/postgis:14-3.4 + image: postgres:14.9-alpine3.18 container_name: domifa-postgres volumes: - postgres-data:/var/lib/postgresql/data diff --git a/packages/backend/nodemon.json b/packages/backend/nodemon.json index 9a6f85edf1..a8fdce52f0 100644 --- a/packages/backend/nodemon.json +++ b/packages/backend/nodemon.json @@ -2,5 +2,5 @@ "watch": ["src", ".env"], "ext": "ts", "ignore": ["src/**/*.spec.ts"], - "exec": "ts-node -r tsconfig-paths/register src/run-app.ts | pino-pretty --singleLine" + "exec": "ts-node -r tsconfig-paths/register src/run-app.ts | pino-pretty --singleLine" } diff --git a/packages/backend/package.json b/packages/backend/package.json index 39262d8082..add9e40c81 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -61,6 +61,7 @@ "@sentry/opentelemetry-node": "^7.91.0", "@socialgouv/streaming-file-encryption": "^1.1.0", "@types/source-map-support": "^0.5.4", + "@wmfs/xml2csv": "^1.32.0", "axios": "^1.6.2", "bcryptjs": "^2.4.3", "cache-manager": "^5.3.2", @@ -74,6 +75,7 @@ "email-templates": "^10.0.0", "exceljs": "^4.2.1", "express": "^4.18.2", + "fast-xml-parser": "^4.2.7", "fs-extra": "^11.1.1", "google-libphonenumber": "^3.2.33", "ics": "^2.41.0", @@ -104,7 +106,7 @@ "typeorm": "^0.3.17", "uuid": "^9.0.1", "xlsx": "^0.18.5", - "yup": "^0.32.11", + "yup": "^0.32.9", "yup-phone": "^1.3.2" }, "devDependencies": { diff --git a/packages/backend/src/_common/model/usager/Usager.type.ts b/packages/backend/src/_common/model/usager/Usager.type.ts index f8592e8dbd..4a27b622c8 100644 --- a/packages/backend/src/_common/model/usager/Usager.type.ts +++ b/packages/backend/src/_common/model/usager/Usager.type.ts @@ -40,7 +40,10 @@ export type Usager = AppEntity & { etapeDemande: number; rdv: UsagerRdv | null; entretien: UsagerEntretien; - pinnedNote: Partial | null; + pinnedNote: Pick< + UsagerNote, + "message" | "usagerRef" | "createdAt" | "createdBy" + > | null; // INFOS DOMICILIATION typeDom: UsagerTypeDom; diff --git a/packages/backend/src/_common/tmp-toulouse/MOTIF.const.ts b/packages/backend/src/_common/tmp-toulouse/MOTIF.const.ts new file mode 100644 index 0000000000..4741886a33 --- /dev/null +++ b/packages/backend/src/_common/tmp-toulouse/MOTIF.const.ts @@ -0,0 +1,8 @@ +export const MOTIF = { + 1: "Recommandé", + 4: "OFPRA", + 5: "CNDA", + 7: "Colis", + 8: "OFII", + 9: "DG des Etrangers en France", +}; diff --git a/packages/backend/src/_common/tmp-toulouse/PAYS.ts b/packages/backend/src/_common/tmp-toulouse/PAYS.ts new file mode 100644 index 0000000000..9ff0ff00d9 --- /dev/null +++ b/packages/backend/src/_common/tmp-toulouse/PAYS.ts @@ -0,0 +1,215 @@ +export const PAYS = { + 2: "Algérie", + 3: "Togo", + 5: "Arménie", + 6: "Espagne", + 7: "Pologne", + 8: "Bulgarie", + 9: "Mozambique", + 10: "Cote d'Ivoire", + 11: "Irak", + 12: "Maroc", + 13: "Syrie", + 14: "Roumanie", + 15: "Lituanie", + 17: "Tunisie", + 18: "Tchad", + 19: "Russie", + 21: "Sierra Leone", + 22: "Ukraine", + 23: "Rwanda", + 24: "Angola", + 25: "Italie", + 28: "Tchétchénie", + 29: "Madagascar", + 30: "Moldavie", + 35: "Azerbaidjan", + 38: "Slovaquie", + 39: "Portugal", + 41: "Niger", + 42: "Turquie", + 43: "Somalie", + 44: "Cameroun", + 45: "Iran", + 46: "Libye", + 47: "Allemagne", + 48: "Albanie", + 49: "Soudan", + 51: "Nigeria", + 52: "Ethiopie", + 55: "Finlande", + 62: "Suisse", + 63: "Laos", + 65: "Sénégal", + 68: "Biélorussie", + 73: "Viêtnam", + 74: "France", + 76: "Belgique", + 78: "Burkina Faso", + 81: "Colombie", + 83: "Bénin", + 85: "Mauritanie", + 88: "Estonie", + 90: "Bosnie-Herzgovine", + 92: "Mongolie", + 94: "Djibouti", + 96: "Israël", + 97: "Hongrie", + 98: "Thaïlande", + 101: "Burundi", + 104: "Jamaïque", + 105: "Angleterre", + 110: "Pakistan", + 111: "Ghana", + 113: "Brésil", + 114: "Afghanistan", + 116: "Gambie", + 117: "Lettonie", + 121: "Egypte", + 122: "Slovénie", + 137: "Argentine", + 138: "Japon", + 140: "Norvège", + 142: "Comores", + 147: "Mali", + 158: "Liban", + 160: "Cuba", + 161: "Cap-Vert", + 168: "Luxembourg", + 169: "Inde", + 170: "Canada", + 171: "Chili", + 173: "Mexique", + 174: "Cambodge", + 177: "Malaisie", + 179: "Haïti", + 180: "Palestine", + 182: "Irlande", + 186: "Chine", + 188: "Bangladesh", + 190: "Guatemala", + 191: "Suriname", + 192: "Vénézuéla", + 193: "Croatie", + 194: "République Tchèque", + 195: "Corée du Nord", + 197: "Philippines", + 198: "Monténégro", + 201: "Pays-Bas", + 202: "Autriche", + 206: "Andorre ", + 207: "Equateur", + 208: "Yémen", + 209: "République dominicaine", + 210: "Bolivie", + 211: "Erythrée", + 219: "Sri Lanka", + 220: "Ouzbékistan", + 222: "Zimbabwe", + 224: "Grèce", + 225: "Pérou", + 226: "Etats-Unis", + 227: "Géorgie", + 228: "Guinée", + 229: "Guinée Equatoriale", + 232: "", + 233: "Bélorussie", + 235: "Koweït", + 236: "Gabon", + 238: "Costa Rica", + 240: "Sahara occidental", + 241: "Serbie", + 242: "Birmanie", + 243: "Ouganda", + 244: "Indonesie", + 245: "Nouvelle-Zélande", + 248: "Emirats arabes unis", + 253: "Tanzanie ", + 254: "Danemark", + 257: "Nicaragua", + 260: "Suède", + 261: "Sao Tomé-et-Principe", + 262: "Royaume-Uni", + 265: "Paraguay", + 266: "Népal", + 267: "Arabie Soudite", + 268: "Honduras", + 269: "Kenya", + 273: "Guinée-Bissau", + 274: "Guyane Britannique", + 275: "Kosovo", + 276: "Australie", + 277: "Kazakhstan", + 278: "Jordanie", + 279: "Sainte-Lucie", + 280: "Corée du sud", + 281: "Zambie", + 282: "Île Maurice", + 283: "Abkhazie", + 284: "Afrique du Sud", + 285: "Antigua-et-Barbuda", + 286: "Bahamas", + 287: "Bahreïn", + 288: "Barbade", + 289: "Belize", + 290: "Bhoutan", + 291: "Botswana", + 292: "Brunei", + 293: "Chypre du Nord", + 294: "Chypre du Sud", + 295: "Dominique", + 296: "Fidji", + 297: "Grenade", + 298: "Îles Cook", + 299: "Îles Marshall", + 300: "Irlande du Nord", + 301: "Islande", + 302: "Kirghizistan", + 303: "Kiribati", + 304: "Lesotho", + 305: "Liechtenstein", + 306: "Malawi", + 307: "Maldives", + 308: "Malte", + 309: "Monaco", + 310: "Namibie", + 311: "Nauru", + 312: "Niue", + 313: "Oman", + 314: "Ossétie du Sud", + 315: "Palaos", + 316: "Panama", + 317: "Papouasie-Nouvelle-Guinée", + 318: "République centrafricaine", + 319: "République de Macédoine", + 320: "Congo - Brazzaville", + 321: "Congo - Kinshasa", + 322: "Saint-Christophe-et-Niévès", + 323: "Saint-Marin", + 324: "Saint-Vincent-et-les-Grenadines", + 325: "Salomon", + 326: "Salvador", + 327: "Samoa", + 328: "Seychelles", + 329: "Singapour", + 330: "Soudan du Sud", + 331: "Swaziland", + 342: "Tadjikistan", + 343: "Taïwan", + 344: "Timor oriental", + 345: "Tonga", + 346: "Trinité-et-Tobago", + 347: "Turkménistan", + 348: "Tuvalu", + 349: "Uruguay", + 350: "Vanuatu", + 351: "Vatican", + 352: "Micronésie", + 353: "Myanmar", + 354: "Qatar", + 355: "Somaliland", + 356: "Tchécoslovaquie", + 357: "Yougoslavie", + 358: "Zaïre", + 359: "Liberia", +}; diff --git a/packages/backend/src/_common/tmp-toulouse/TOULOUSE_STRUCTURE_ID.const.ts b/packages/backend/src/_common/tmp-toulouse/TOULOUSE_STRUCTURE_ID.const.ts new file mode 100644 index 0000000000..331593a6b7 --- /dev/null +++ b/packages/backend/src/_common/tmp-toulouse/TOULOUSE_STRUCTURE_ID.const.ts @@ -0,0 +1,2 @@ +export const TOULOUSE_STRUCTURE_ID = 1; +export const TOULOUSE_USER_ID = 1; diff --git a/packages/backend/src/_common/tmp-toulouse/TUsager.interface.ts b/packages/backend/src/_common/tmp-toulouse/TUsager.interface.ts new file mode 100644 index 0000000000..ddba7b6076 --- /dev/null +++ b/packages/backend/src/_common/tmp-toulouse/TUsager.interface.ts @@ -0,0 +1,34 @@ +export interface TUsager { + IDDomicilie: number; + Nom: string; + Nom_epouse: string | null; + prénom: string; + genre: number; + date_naissance: any; // ou date_naissance: number; selon ce que vous préférez + Nationalité: number; + Pays_naissance: number; + Remarques: string; + Piece_identité: number; + date_validité_PI: string; // ou date_validité_PI: number; selon ce que vous préférez + Service_presc: number; + valide: number; // peut-être considéré comme un boolean si cela représente une valeur booléenne (1 ou 0) + du: string; // ou du: number; selon ce que vous préférez + au: string; // ou au: number; selon ce que vous préférez + Num_domici: number; + enfant: number; // peut-être considéré comme un boolean si cela représente une valeur booléenne (1 ou 0) + enfant_de: string | number; // peut-être considéré comme un boolean si cela représente une valeur booléenne (1 ou 0) + relation: string | null; + motif: number; + dernier_retrait: string; // ou dernier_retrait: number; selon ce que vous préférez + date_creation: string | null; + lieu_naiss: string; + codeb: number; + ame: number; // peut-être considéré comme un boolean si cela représente une valeur booléenne (1 ou 0) + courrier_sens: number; // peut-être considéré comme un boolean si cela représente une valeur booléenne (1 ou 0) + comportement: number; + procuration: number; // peut-être considéré comme un boolean si cela représente une valeur booléenne (1 ou 0) + nom_procuration: string | null; + telephone: string | null; + email: string | null; + nomenveloppe: number; // peut-être considéré comme un boolean si cela représente une valeur booléenne (1 ou 0) +} diff --git a/packages/backend/src/_common/tmp-toulouse/getDateFromXml.ts b/packages/backend/src/_common/tmp-toulouse/getDateFromXml.ts new file mode 100644 index 0000000000..f6641d2130 --- /dev/null +++ b/packages/backend/src/_common/tmp-toulouse/getDateFromXml.ts @@ -0,0 +1,24 @@ +import { isNil } from "lodash"; +import { isValid, parse, startOfDay } from "date-fns"; +import striptags from "striptags"; + +export const getDateFromXml = (dateString: string | number): Date => { + const parsedDate = startOfDay( + parse(dateString.toString(), "yyyyMMdd", new Date()) + ); + if (!isValid(parsedDate)) { + throw new Error("CANNOT ADD DATE " + dateString); + } + return parsedDate; +}; + +export const getText = (str?: string): string => { + if (isNil(str)) { + return ""; + } + + return striptags(str.toString()) + .replace(/[\\$~*<>{}]/gi, "") + .replace(/\s+/g, " ") + .trim(); +}; diff --git a/packages/backend/src/_common/tmp-toulouse/index.ts b/packages/backend/src/_common/tmp-toulouse/index.ts new file mode 100644 index 0000000000..b4c0868c15 --- /dev/null +++ b/packages/backend/src/_common/tmp-toulouse/index.ts @@ -0,0 +1,5 @@ +// @index('./*', f => `export * from '${f.path}'`) +export * from "./getDateFromXml"; +export * from "./PAYS"; +export * from "./TOULOUSE_STRUCTURE_ID.const"; +export * from "./TUsager.interface"; diff --git a/packages/backend/src/_migrations/1692191990700-generate-temp-tables-migration.ts b/packages/backend/src/_migrations/1692191990700-generate-temp-tables-migration.ts new file mode 100644 index 0000000000..5165f0130c --- /dev/null +++ b/packages/backend/src/_migrations/1692191990700-generate-temp-tables-migration.ts @@ -0,0 +1,27 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class AutoMigration1692191990700 implements MigrationInterface { + name = "AutoMigration1692191990700"; + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `CREATE TABLE "TmpHistorique" ("uuid" uuid NOT NULL DEFAULT uuid_generate_v4(), "id_domicilie" integer, "date" text, "type" character varying, CONSTRAINT "PK_523a02c717798d1433428afd730" PRIMARY KEY ("uuid"))` + ); + await queryRunner.query( + `CREATE INDEX "IDX_9e9c1ff1cb8c52d25db6bf797f" ON "TmpHistorique" ("id_domicilie") ` + ); + await queryRunner.query( + `CREATE INDEX "IDX_3acc64a514fefafef16717cb93" ON "TmpHistorique" ("type") ` + ); + await queryRunner.query( + `CREATE TABLE "TmpCourriers" ("uuid" uuid NOT NULL DEFAULT uuid_generate_v4(), "IDDomicilie" integer, "date" integer, "Date_recup" integer, "motif" integer, CONSTRAINT "PK_8520f03ab40677e4503ae9fdf0a" PRIMARY KEY ("uuid"))` + ); + await queryRunner.query( + `CREATE INDEX "IDX_9b82e742c9c3762d05a73b6a40" ON "TmpCourriers" ("IDDomicilie") ` + ); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`DROP TABLE "TmpHistorique"`); + } +} diff --git a/packages/backend/src/_migrations/1692191990701-open-toulouse-data-migration.ts b/packages/backend/src/_migrations/1692191990701-open-toulouse-data-migration.ts new file mode 100644 index 0000000000..5ec82a8336 --- /dev/null +++ b/packages/backend/src/_migrations/1692191990701-open-toulouse-data-migration.ts @@ -0,0 +1,36 @@ +import { XMLParser } from "fast-xml-parser"; +import { readFile, writeFile } from "fs-extra"; +import { MigrationInterface } from "typeorm"; +import { domifaConfig } from "../config"; + +export class ManualMigration1692191990701 implements MigrationInterface { + name = "OpenDomicilieXmlMigration1692191990701"; + + public async up(): Promise { + const inputFile = + domifaConfig().upload.basePath + "/toulouse/Domicilie.XML"; + + const outputFile = + domifaConfig().upload.basePath + "/toulouse/usagers.json"; + + const xmlData = await readFile(inputFile, "utf8"); + + const options = { + attributeNamePrefix: "_", + attrNodeName: "attr", + textNodeName: "#text", + ignoreAttributes: false, + parseAttributeValue: true, + }; + + const parser = new XMLParser(options); + const jsonData = parser.parse(xmlData); + + await writeFile(outputFile, JSON.stringify(jsonData, null, 2), "utf8"); + } + + // eslint-disable-next-line @typescript-eslint/no-empty-function + public async down(): Promise { + /* document why this async method 'down' is empty */ + } +} diff --git a/packages/backend/src/_migrations/1692191990702-import-toulouse-usagers-migration.ts b/packages/backend/src/_migrations/1692191990702-import-toulouse-usagers-migration.ts new file mode 100644 index 0000000000..f06fc2c8f1 --- /dev/null +++ b/packages/backend/src/_migrations/1692191990702-import-toulouse-usagers-migration.ts @@ -0,0 +1,276 @@ +import { isNil } from "lodash"; +import { ucFirst } from "./../usagers/services/custom-docs/buildCustomDoc.service"; +import { MigrationInterface } from "typeorm"; +import { v4 as uuidv4 } from "uuid"; +import { Usager } from "../_common/model"; +import { + myDataSource, + usagerNotesRepository, + UsagerNotesTable, + usagerRepository, + UsagerTable, +} from "../database"; + +import { usagersCreator } from "../usagers/services"; +import { domifaConfig } from "../config"; +import { readFile } from "fs-extra"; +import { differenceInCalendarDays } from "date-fns"; +import { + TOULOUSE_STRUCTURE_ID, + TUsager, + PAYS, + getDateFromXml, + getText, + TOULOUSE_USER_ID, +} from "../_common/tmp-toulouse"; +import { + UsagerTypeDom, + UsagerAyantDroit, + StructureLight, +} from "@domifa/common"; +import { resetUsagers } from "../structures/services"; + +export class ManualMigration1692191990702 implements MigrationInterface { + name = "ImportUsagersFromJson1692191990702"; + public async up(): Promise { + await resetUsagers({ id: TOULOUSE_STRUCTURE_ID } as StructureLight); + + console.log("2️⃣ Début de l'import des domiciliés"); + + const filePath = domifaConfig().upload.basePath + "/toulouse/usagers.json"; + const jsonData = await readFile(filePath, "utf8"); + + let raw = JSON.parse(jsonData).HF_DOCUMENT.Domicilie as TUsager[]; + + console.log(""); + console.log(raw.length + " dossiers à importer"); + console.log(""); + + raw = raw.filter( + (usager: TUsager) => + usager.date_naissance !== "0" && + usager.date_naissance !== "" && + usager.date_naissance !== 0 + ); + + const usagers = raw.filter( + (usager: TUsager) => parseInt(usager?.enfant_de as string, 10) === 0 + ); + console.log("\t" + usagers.length + " dossiers uniques à importer"); + const ayantsDroits = raw.filter( + (usager: TUsager) => parseInt(usager?.enfant_de as string, 10) !== 0 + ); + + console.log("\t" + ayantsDroits.length + " ayants-drois à importer"); + + const childrens = this.extractChidrens(ayantsDroits); + let i = 0; + + const queryRunner = myDataSource.createQueryRunner(); + + await queryRunner.startTransaction(); + + for (const usagerToulouse of usagers) { + if (i % 2000 === 0) { + await queryRunner.commitTransaction(); + await queryRunner.startTransaction(); + console.log(i + "/" + usagers.length + " dossiers importés"); + } + i++; + let typeDom: UsagerTypeDom = "PREMIERE_DOM"; + + if ( + usagerToulouse?.date_creation && + usagerToulouse?.du && + differenceInCalendarDays( + getDateFromXml(usagerToulouse?.date_creation), + getDateFromXml(usagerToulouse?.du) + ) > 0 + ) { + typeDom = "RENOUVELLEMENT"; + } + + const statut = usagerToulouse.valide === 1 ? "VALIDE" : "RADIE"; + let dateDebut: Date; + let dateFin: Date; + let dateDecision: Date; + + if (statut === "RADIE") { + if (usagerToulouse.au) { + dateDebut = getDateFromXml(usagerToulouse.au); + dateFin = getDateFromXml(usagerToulouse.au); + dateDecision = getDateFromXml(usagerToulouse.au); + } else if (usagerToulouse.dernier_retrait) { + dateDebut = getDateFromXml(usagerToulouse.dernier_retrait); + dateFin = getDateFromXml(usagerToulouse.dernier_retrait); + dateDecision = getDateFromXml(usagerToulouse.dernier_retrait); + } else { + dateDebut = getDateFromXml(usagerToulouse.date_creation); + dateFin = getDateFromXml(usagerToulouse.date_creation); + dateDecision = getDateFromXml(usagerToulouse.date_creation); + } + } else { + dateDebut = getDateFromXml(usagerToulouse.du); + dateFin = getDateFromXml(usagerToulouse.au); + dateDecision = getDateFromXml(usagerToulouse.du); + } + + const lastInteractionDate = usagerToulouse?.dernier_retrait + ? getDateFromXml(usagerToulouse?.dernier_retrait) + : null; + + const partialUsager: Partial = { + ref: usagerToulouse.IDDomicilie, + nom: usagerToulouse.Nom.trim().toUpperCase(), + surnom: usagerToulouse?.Nom_epouse + ? usagerToulouse?.Nom_epouse.toString().trim().toUpperCase() + : null, + prenom: usagerToulouse.prénom + ? ucFirst(usagerToulouse.prénom).trim() + : "Prénom", + sexe: usagerToulouse.genre === 2 ? "homme" : "femme", + telephone: { + numero: usagerToulouse?.telephone ?? "", + countryCode: "FR", + }, + email: usagerToulouse?.email ?? null, + villeNaissance: this.getBirthPlace( + usagerToulouse?.lieu_naiss, + usagerToulouse?.Pays_naissance + ), + ayantsDroits: + typeof childrens[usagerToulouse.Num_domici.toString()] !== "undefined" + ? childrens[usagerToulouse.Num_domici.toString()] + : [], + dateNaissance: getDateFromXml(usagerToulouse.date_naissance), + customRef: + usagerToulouse?.Num_domici?.toString() ?? + usagerToulouse.IDDomicilie.toString(), + lastInteraction: { + dateInteraction: lastInteractionDate, + colisIn: 0, + courrierIn: 0, + recommandeIn: 0, + enAttente: false, + }, + historique: [], + structureId: TOULOUSE_STRUCTURE_ID, + decision: { + uuid: uuidv4(), + dateDecision, + statut, + userName: "Croix-Rouge Toulouse", + userId: TOULOUSE_USER_ID, + dateFin, + dateDebut, + typeDom, + motif: usagerToulouse.valide !== 1 ? "AUTRE" : null, + motifDetails: usagerToulouse.valide !== 1 ? "Non renseigné" : null, + }, + }; + + usagersCreator.setUsagerDefaultAttributes(partialUsager); + const usager = new UsagerTable(partialUsager); + await usagerRepository.save(usager); + + if (usagerToulouse?.procuration === 1) { + const message = getText(usagerToulouse?.nom_procuration); + + await usagerNotesRepository.save( + new UsagerNotesTable({ + message: `Procuration: ${message}`, + usagerRef: usager.ref, + usagerUUID: usager.uuid, + pinned: false, + structureId: TOULOUSE_STRUCTURE_ID, + createdBy: { + userName: "Croix-Rouge Toulouse", + userId: TOULOUSE_USER_ID, + }, + archived: false, + }) + ); + } + + if (getText(usagerToulouse?.Remarques) !== "") { + const newNote = new UsagerNotesTable({ + message: getText(usagerToulouse?.Remarques), + usagerRef: usager.ref, + usagerUUID: usager.uuid, + pinned: true, + structureId: TOULOUSE_STRUCTURE_ID, + createdBy: { + userName: "Croix-Rouge Toulouse", + userId: TOULOUSE_USER_ID, + }, + archived: false, + }); + await usagerNotesRepository.save(newNote); + + await usagerRepository.update( + { uuid: usager.uuid }, + { + pinnedNote: { + message: newNote.message, + usagerRef: newNote.usagerRef, + createdAt: newNote.createdAt, + createdBy: newNote.createdBy, + }, + } + ); + } + } + + await queryRunner.commitTransaction(); + await queryRunner.release(); + + console.log("2️⃣ Import des usagers terminés ✅"); + } + + public async down(): Promise { + console.log("down"); + } + + public extractChidrens = ( + tmpChildrens: TUsager[] + ): { + [key: number]: UsagerAyantDroit[]; + } => { + const usagersByRef = {}; + + for (const child of tmpChildrens) { + if (child.date_naissance) { + const ayantDroit: UsagerAyantDroit = { + nom: child.Nom, + prenom: child.prénom, + dateNaissance: getDateFromXml(child.date_naissance), + lien: "ENFANT", + }; + const key = child.enfant_de.toString(); + if (typeof usagersByRef[key] === "undefined") { + usagersByRef[key] = []; + } + usagersByRef[key].push(ayantDroit); + } + } + + return usagersByRef; + }; + + public getBirthPlace(villeNaissance?: string, pays?: number): string { + if ( + typeof villeNaissance !== "string" || + isNil(villeNaissance) || + villeNaissance === "" + ) { + return "Non renseigné"; + } + villeNaissance = villeNaissance.toString().trim(); + villeNaissance = ucFirst(villeNaissance); + + if (pays) { + villeNaissance = villeNaissance + ", " + PAYS[pays]; + } + return villeNaissance; + } +} diff --git a/packages/backend/src/_migrations/1692191990703-import-toulouse-entretien-migration.ts b/packages/backend/src/_migrations/1692191990703-import-toulouse-entretien-migration.ts new file mode 100644 index 0000000000..efda438603 --- /dev/null +++ b/packages/backend/src/_migrations/1692191990703-import-toulouse-entretien-migration.ts @@ -0,0 +1,52 @@ +import { MigrationInterface } from "typeorm"; +import { + myDataSource, + usagerEntretienRepository, + usagerRepository, +} from "../database"; +import { TOULOUSE_STRUCTURE_ID } from "../_common/tmp-toulouse"; + +export class ManualMigration1692191990703 implements MigrationInterface { + name = "CreaationEntretien1692191990703"; + + public async up(): Promise { + console.log("Suppression des entretiens ... 🏃‍♀️"); + await usagerEntretienRepository.delete({ + structureId: TOULOUSE_STRUCTURE_ID, + }); + + const usagers = await usagerRepository.find({ + where: { structureId: TOULOUSE_STRUCTURE_ID }, + select: { uuid: true, ref: true }, + }); + + let i = 0; + console.log("Création des entretiens ... 🏃‍♀️"); + + const queryRunner = myDataSource.createQueryRunner(); + await queryRunner.startTransaction(); + + for (const usager of usagers) { + i++; + if (i % 4000 === 0) { + await queryRunner.commitTransaction(); + console.log(i + "/" + usagers.length + " entretiens importés"); + await queryRunner.startTransaction(); + } + + await usagerEntretienRepository.save({ + structureId: TOULOUSE_STRUCTURE_ID, + usagerUUID: usager.uuid, + usagerRef: usager.ref, + }); + } + await queryRunner.commitTransaction(); + + console.log("3️⃣ Création des entretiens terminée ✅ "); + await queryRunner.release(); + } + + public async down(): Promise { + console.log("down"); + } +} diff --git a/packages/backend/src/_migrations/1692216772744-decisions-migration.ts b/packages/backend/src/_migrations/1692216772744-decisions-migration.ts new file mode 100644 index 0000000000..1e68c0e9d3 --- /dev/null +++ b/packages/backend/src/_migrations/1692216772744-decisions-migration.ts @@ -0,0 +1,260 @@ +import { In, MigrationInterface, QueryRunner } from "typeorm"; + +import { UsagerHistory, UsagerHistoryState } from "../_common/model"; +import { addYears, endOfDay, format, startOfDay, subDays } from "date-fns"; +import { v4 as uuidv4 } from "uuid"; +import { + UsagerHistoryTable, + myDataSource, + usagerHistoryRepository, + usagerRepository, +} from "../database"; +import { UsagerDecision, UsagerEntretien, UsagerTypeDom } from "@domifa/common"; +import { + TOULOUSE_STRUCTURE_ID, + TOULOUSE_USER_ID, + getDateFromXml, +} from "../_common/tmp-toulouse"; +import { tmpHistoriqueRepository } from "../database/services/interaction/historiqueRepository.service"; + +export class ImportDecisionsMigration1692216772744 + implements MigrationInterface +{ + name = "ImportDecisionsMigration1692216772744"; + + public async up(): Promise { + if ((await tmpHistoriqueRepository.count()) === 0) { + throw new Error("Chargement des fichiers historique incomplets"); + } + const queryRunner = myDataSource.createQueryRunner(); + + console.log(""); + console.log("Lancement de la migration d'import des decisions"); + console.log(""); + await queryRunner.startTransaction(); + await usagerHistoryRepository.delete({ + structureId: TOULOUSE_STRUCTURE_ID, + }); + + console.log("Réinitialisation des variables de migration"); + await usagerRepository.update( + { structureId: TOULOUSE_STRUCTURE_ID }, + { migrated: false } + ); + await queryRunner.commitTransaction(); + + console.log( + await usagerRepository.countMigratedUsagers(TOULOUSE_STRUCTURE_ID) + ); + + const decisions = await tmpHistoriqueRepository.find({ + where: { + type: In(["creation", "renouv", "cloture", "resiliation"]), + }, + order: { + id_domicilie: "ASC", + date: "ASC", + }, + }); + + const usagersByRef: { [key: string]: UsagerDecision[] } = {}; + + for (const decision of decisions) { + const key = decision.id_domicilie.toString(); + if (typeof usagersByRef[key] === "undefined") { + usagersByRef[key] = []; + } + + const dateFin = + decision.type === "cloture" || decision.type === "resiliation" + ? getDateFromXml(decision.date) + : addYears(getDateFromXml(decision.date), 1); + + const newDecision: UsagerDecision = { + uuid: uuidv4(), + statut: + decision.type === "cloture" || decision.type === "resiliation" + ? "RADIE" + : "VALIDE", + userName: "Croix-Rouge Toulouse", + userId: TOULOUSE_USER_ID, + dateDebut: getDateFromXml(decision.date), + dateFin, + dateDecision: getDateFromXml(decision.date), + typeDom: + decision.type === "creation" ? "PREMIERE_DOM" : "RENOUVELLEMENT", + motif: + decision.type === "cloture" || decision.type === "resiliation" + ? "AUTRE" + : null, + motifDetails: + decision.type === "cloture" || decision.type === "resiliation" + ? "Non renseigné" + : null, + }; + + usagersByRef[key].push(newDecision); + } + + let cpt = 0; + + while ( + (await usagerRepository.countMigratedUsagers(TOULOUSE_STRUCTURE_ID)) > 0 + ) { + const usagers = await usagerRepository.find({ + where: { structureId: TOULOUSE_STRUCTURE_ID, migrated: false }, + take: 500, + select: [ + "ref", + "rdv", + "ayantsDroits", + "uuid", + "decision", + "historique", + "typeDom", + "etapeDemande", + ], + }); + + console.log( + `${cpt} décisions / ${Object.keys(usagersByRef).length} - ${format( + new Date(), + "HH:mm:ss" + )}` + ); + + await queryRunner.startTransaction(); + for (const usager of usagers) { + cpt++; + + const key = usager.ref.toString(); + + if (typeof usagersByRef[key] === "undefined") { + usagersByRef[key] = []; + } + + usagersByRef[key].push(usager.decision); + const uniqueCombinations = new Set(); + + const uniqueDecision = usagersByRef[key].filter( + (decision: UsagerDecision) => { + const dateDebutFormatted = new Date(decision.dateDebut) + .toISOString() + .split("T")[0]; + const key = `${decision.statut}_${dateDebutFormatted}`; // Combine statut and dateDebut + + if (uniqueCombinations.has(key)) { + return false; // Exclure cet élément, car la combinaison est déjà présente + } + uniqueCombinations.add(key); + return true; // Conserver cet élément, car la combinaison est unique + } + ); + + uniqueDecision.sort((a: UsagerDecision, b: UsagerDecision) => { + const dateA = endOfDay(new Date(a.dateDebut)).getTime(); + const dateB = endOfDay(new Date(b.dateDebut)).getTime(); + return dateA - dateB; + }); + + const usagerHistory: UsagerHistory = new UsagerHistoryTable({ + usagerUUID: usager.uuid, + usagerRef: usager.ref, + structureId: TOULOUSE_STRUCTURE_ID, + import: null, + states: [], + }); + + const typeDom: UsagerTypeDom = + { ...uniqueDecision }.filter( + (decision) => decision.statut === "VALIDE" + ).length > 1 || usager.typeDom === "RENOUVELLEMENT" + ? "RENOUVELLEMENT" + : "PREMIERE_DOM"; + + for (const decision of uniqueDecision) { + usager.decision = decision; + usager.historique.push(decision); + + const previousState = usagerHistory?.states.length + ? usagerHistory.states[usagerHistory.states.length - 1] + : undefined; + + const isActive = + decision.statut === "VALIDE" || + ((decision.statut === "ATTENTE_DECISION" || + decision.statut === "INSTRUCTION") && + (previousState?.isActive ?? false)); + + decision.typeDom = typeDom; + const state: UsagerHistoryState = { + uuid: uuidv4(), + createdAt: startOfDay(new Date(decision.dateDebut)), + createdEvent: "new-decision", + isActive, + historyBeginDate: startOfDay(new Date(decision.dateDebut)), + historyEndDate: undefined, + decision, + typeDom, + etapeDemande: usager.etapeDemande, + entretien: { + domiciliation: null, + typeMenage: null, + revenus: null, + orientation: null, + liencommune: null, + residence: null, + cause: null, + rattachement: null, + raison: null, + accompagnement: null, + accompagnementDetail: null, + } as UsagerEntretien, + ayantsDroits: [...usager.ayantsDroits], + rdv: usager.rdv, + }; + + usagerHistory.states = [ + ...usagerHistory.states.map((s, i) => { + if (i === usagerHistory.states.length - 1) { + // finish previous history state + s.historyEndDate = endOfDay( + subDays(new Date(state.historyBeginDate), 1) + ); + } + return s; + }), + state, + ]; + } + + await usagerHistoryRepository.save(usagerHistory); + await usagerRepository.update( + { + uuid: usager.uuid, + }, + { + decision: usager.decision, + historique: usager.historique, + migrated: true, + typeDom, + } + ); + } + } + + console.log( + `${cpt} décisions / ${Object.keys(usagersByRef).length} - ${format( + new Date(), + "HH:mm:ss" + )}` + ); + + await queryRunner.release(); + } + + // eslint-disable-next-line @typescript-eslint/no-unused-vars + public async down(_queryRunner: QueryRunner): Promise { + console.log("down"); + } +} diff --git a/packages/backend/src/_migrations/1697659880955-import-passages-migration.ts b/packages/backend/src/_migrations/1697659880955-import-passages-migration.ts new file mode 100644 index 0000000000..05acd21ba6 --- /dev/null +++ b/packages/backend/src/_migrations/1697659880955-import-passages-migration.ts @@ -0,0 +1,107 @@ +/* eslint-disable @typescript-eslint/no-unused-vars */ +import { interactionRepository } from "../database/services/interaction/interactionRepository.service"; +import { In, MigrationInterface, QueryRunner } from "typeorm"; +import { InteractionsTable, myDataSource, usagerRepository } from "../database"; +import { + TOULOUSE_STRUCTURE_ID, + TOULOUSE_USER_ID, + getDateFromXml, +} from "../_common/tmp-toulouse"; +import { tmpHistoriqueRepository } from "../database/services/interaction/historiqueRepository.service"; +import { format } from "date-fns"; + +export class ImportPassagesToulouseMigration1697659880955 + implements MigrationInterface +{ + name = "ImportPassagesToulouseMigration1697659880955"; + public async up(): Promise { + if ((await tmpHistoriqueRepository.count()) === 0) { + throw new Error("Chargement des fichiers historique incomplets"); + } + + const queryRunner = myDataSource.createQueryRunner(); + + console.log(""); + console.log("Lancement de la migration d'import des passages 🏃‍♂️"); + console.log(""); + await queryRunner.startTransaction(); + + console.log("Réinitialisation des variables de migration"); + await usagerRepository.update( + { structureId: TOULOUSE_STRUCTURE_ID }, + { migrated: false } + ); + + console.log("Suppression des précédents passages"); + await interactionRepository.delete({ + structureId: TOULOUSE_STRUCTURE_ID, + type: "visite", + }); + await queryRunner.commitTransaction(); + + const total = await usagerRepository.countMigratedUsagers( + TOULOUSE_STRUCTURE_ID + ); + console.log(total + " usagers à migrer"); + let cpt = 0; + + while ( + (await usagerRepository.countMigratedUsagers(TOULOUSE_STRUCTURE_ID)) > 0 + ) { + const usagerIdsToUpdate = []; + const usagers = await usagerRepository.find({ + where: { structureId: TOULOUSE_STRUCTURE_ID, migrated: false }, + take: 1000, + select: ["ref", "uuid", "nom"], + }); + + await queryRunner.startTransaction(); + for (const usager of usagers) { + cpt++; + usagerIdsToUpdate.push(usager.uuid); + const interactions = await tmpHistoriqueRepository.find({ + where: { + type: "courrier", + id_domicilie: usager.ref, + }, + }); + + if (interactions.length > 0) { + const interactionsToSave = interactions.map( + (interaction) => + new InteractionsTable({ + usagerUUID: usager.uuid, + usagerRef: usager.ref, + dateInteraction: getDateFromXml(interaction.date), + type: "visite", + userName: "Croix-Rouge Toulouse", + userId: TOULOUSE_USER_ID, + structureId: TOULOUSE_STRUCTURE_ID, + interactionOutUUID: null, + }) + ); + + await interactionRepository.save(interactionsToSave); + } + } + + await usagerRepository.update( + { uuid: In(usagerIdsToUpdate) }, + { migrated: true } + ); + + console.log( + `${cpt}/${total} dossiers sont les passages sont importés ${format( + new Date(), + "HH:mm:ss" + )}` + ); + await queryRunner.commitTransaction(); + } + await queryRunner.release(); + } + + public async down(_queryRunner: QueryRunner): Promise { + // + } +} diff --git a/packages/backend/src/_migrations/1697704071510-import-courriers-migration.ts b/packages/backend/src/_migrations/1697704071510-import-courriers-migration.ts new file mode 100644 index 0000000000..a5bbc48e4d --- /dev/null +++ b/packages/backend/src/_migrations/1697704071510-import-courriers-migration.ts @@ -0,0 +1,164 @@ +/* eslint-disable @typescript-eslint/no-unused-vars */ +import { In, IsNull, MigrationInterface, QueryRunner } from "typeorm"; +import { + TOULOUSE_STRUCTURE_ID, + TOULOUSE_USER_ID, + getDateFromXml, +} from "../_common/tmp-toulouse"; +import { + interactionRepository, + myDataSource, + structureRepository, + usagerRepository, + userStructureRepository, +} from "../database"; +import { tmpCourriersRepository } from "../database/services/interaction/historiqueRepository.service"; +import { interactionsCreator } from "../interactions/services"; +import { InteractionDto } from "../interactions/dto"; +import { MOTIF } from "../_common/tmp-toulouse/MOTIF.const"; +import { format } from "date-fns"; + +export class ImportCourriersToulouseMigration1697704071510 + implements MigrationInterface +{ + name = "ImportCourriersToulouseMigration1697704071510"; + + public async up(): Promise { + if ((await tmpCourriersRepository.count()) === 0) { + throw new Error("Chargement des fichiers Courriers incomplets"); + } + + const queryRunner = myDataSource.createQueryRunner(); + await queryRunner.startTransaction(); + console.log(""); + console.log("Lancement de la migration d'import des courriers"); + console.log(""); + + console.log("Mise à jour des dossiers"); + await usagerRepository.update( + { structureId: TOULOUSE_STRUCTURE_ID }, + { migrated: false } + ); + + console.log("Suppression des courriers"); + await interactionRepository.delete({ + structureId: TOULOUSE_STRUCTURE_ID, + type: In(["courrierIn", "courrierOut"]), + }); + + console.log("Suppression des courriers temporaires non exploitables"); + await tmpCourriersRepository.delete({ + date: IsNull(), + }); + await queryRunner.commitTransaction(); + + const user: any = await userStructureRepository.findOneBy({ + structureId: TOULOUSE_STRUCTURE_ID, + id: TOULOUSE_USER_ID, + }); + + const structure = await structureRepository.findOneBy({ + id: TOULOUSE_STRUCTURE_ID, + }); + + let cpt = 0; + + user.structure = structure; + + console.log("Début de l'import courriers des usagers"); + + const total = await usagerRepository.countMigratedUsagers( + TOULOUSE_STRUCTURE_ID + ); + + while ( + (await usagerRepository.countMigratedUsagers(TOULOUSE_STRUCTURE_ID)) > 0 + ) { + await queryRunner.startTransaction(); + + const usagers = await usagerRepository.find({ + where: { structureId: TOULOUSE_STRUCTURE_ID, migrated: false }, + take: 400, + }); + + const usagerIdsToUpdate = []; + + for (const usager of usagers) { + cpt++; + usagerIdsToUpdate.push(usager.uuid); + const interactions = await tmpCourriersRepository.find({ + where: { + IDDomicilie: usager.ref, + }, + order: { + date: "ASC", + Date_recup: "ASC", + }, + }); + + if (interactions.length > 0) { + for (const interaction of interactions) { + const newInteraction: InteractionDto = { + usagerRef: usager.ref, + userId: user.id, + userName: user.nom + " " + user.prenom, + type: "courrierIn", + nbCourrier: 1, + content: this.getMotif(interaction.motif), + dateInteraction: getDateFromXml(interaction.date), + }; + + await interactionsCreator.createInteraction({ + interaction: newInteraction, + user, + usager, + }); + + if (interaction?.Date_recup) { + const newInteraction: InteractionDto = { + usagerRef: usager.ref, + userId: user.id, + userName: user.nom + " " + user.prenom, + type: "courrierOut", + nbCourrier: 1, + content: this.getMotif(interaction.motif), + dateInteraction: getDateFromXml(interaction.Date_recup), + }; + + await interactionsCreator.createInteraction({ + interaction: newInteraction, + user, + usager, + }); + } + } + } + } + + await usagerRepository.update( + { uuid: In(usagerIdsToUpdate) }, + { migrated: true } + ); + + console.log( + `${cpt}/${total} dossiers sont les courriers sont importés ${format( + new Date(), + "HH:mm:ss" + )}` + ); + await queryRunner.commitTransaction(); + } + await queryRunner.release(); + } + + public async down(_queryRunner: QueryRunner): Promise { + // + } + + public getMotif(motif?: number) { + if (!motif || motif === 0) { + return ""; + } + return MOTIF[motif] ?? ""; + } +} diff --git a/packages/backend/src/_migrations/1700433996795-update-last-interaction-migration.ts b/packages/backend/src/_migrations/1700433996795-update-last-interaction-migration.ts new file mode 100644 index 0000000000..7119f3fac4 --- /dev/null +++ b/packages/backend/src/_migrations/1700433996795-update-last-interaction-migration.ts @@ -0,0 +1,115 @@ +import { In, MigrationInterface, QueryRunner } from "typeorm"; +import { + interactionRepository, + myDataSource, + usagerRepository, +} from "../database"; +import { TOULOUSE_STRUCTURE_ID } from "../_common/tmp-toulouse"; +import { INTERACTION_OK_LIST } from "../_common/model"; +import { differenceInCalendarDays, format, parseISO } from "date-fns"; +import { appLogger } from "../util"; + +export class UpdateLastInteractionMigration1700433996795 + implements MigrationInterface +{ + name = "UpdateLastInteractionMigration1700433996795"; + + public async up(): Promise { + const queryRunner = myDataSource.createQueryRunner(); + console.log(""); + appLogger.info("Mise à jour des dates de dernier passage 🏃‍♂️"); + console.log(""); + + await queryRunner.startTransaction(); + console.log("Réinitialisation des variables de migration"); + await usagerRepository.update( + { structureId: TOULOUSE_STRUCTURE_ID }, + { migrated: false } + ); + await queryRunner.commitTransaction(); + + const total = await usagerRepository.countMigratedUsagers( + TOULOUSE_STRUCTURE_ID + ); + let cpt = 0; + + while ( + (await usagerRepository.countMigratedUsagers(TOULOUSE_STRUCTURE_ID)) > 0 + ) { + console.log( + `${cpt}/${total} dates de dernier passage à jour ${format( + new Date(), + "HH:mm:ss" + )}` + ); + const usagers = await usagerRepository.find({ + where: { structureId: TOULOUSE_STRUCTURE_ID, migrated: false }, + select: ["uuid", "ref", "lastInteraction", "decision"], + take: 1000, + }); + await queryRunner.startTransaction(); + + for (const usager of usagers) { + cpt++; + + const dateDebut = parseISO( + usager.decision.dateDebut as unknown as string + ); + + if (typeof usager.lastInteraction.dateInteraction === "string") { + usager.lastInteraction.dateInteraction = parseISO( + usager.lastInteraction.dateInteraction + ); + } + + const interaction = await interactionRepository.findOne({ + where: { type: In(INTERACTION_OK_LIST), usagerUUID: usager.uuid }, + select: { + dateInteraction: true, + }, + order: { + dateInteraction: "DESC", + }, + }); + + if (interaction?.dateInteraction) { + if (typeof interaction.dateInteraction === "string") { + interaction.dateInteraction = parseISO(interaction.dateInteraction); + } + + usager.lastInteraction.dateInteraction = + differenceInCalendarDays(interaction.dateInteraction, dateDebut) > 0 + ? interaction.dateInteraction + : dateDebut; + } else if ( + !interaction?.dateInteraction && + !usager.lastInteraction.dateInteraction + ) { + usager.lastInteraction.dateInteraction = dateDebut; + } + + await usagerRepository.update( + { uuid: usager.uuid }, + { + migrated: true, + lastInteraction: usager.lastInteraction, + } + ); + } + + await queryRunner.commitTransaction(); + } + console.log( + `${cpt}/${total} dates de dernier passage à jour ${format( + new Date(), + "HH:mm:ss" + )}` + ); + await queryRunner.release(); + } + + // eslint-disable-next-line @typescript-eslint/no-unused-vars + public async down(_queryRunner: QueryRunner): Promise { + // + } +} diff --git a/packages/backend/src/database/entities/interaction/TmpCourriersTable.typeorm.ts b/packages/backend/src/database/entities/interaction/TmpCourriersTable.typeorm.ts new file mode 100644 index 0000000000..0fa22ccb37 --- /dev/null +++ b/packages/backend/src/database/entities/interaction/TmpCourriersTable.typeorm.ts @@ -0,0 +1,31 @@ +import { Entity, Column, PrimaryGeneratedColumn, Index } from "typeorm"; + +export interface TmpCourriers { + IDDomicilie: number; + motif: number; + date: number; + Date_recup: number; +} + +@Entity("TmpCourriers") +export class TmpCourriersTable { + @PrimaryGeneratedColumn("uuid") + public uuid?: string; + + @Index() + @Column({ type: "integer", nullable: true }) + IDDomicilie: number; + + @Column({ type: "integer", nullable: true }) + date: number; + + @Column({ type: "integer", nullable: true }) + Date_recup: number; + + @Column({ type: "integer", nullable: true }) + motif: number; + + public constructor(entity?: Partial) { + Object.assign(this, entity); + } +} diff --git a/packages/backend/src/database/entities/interaction/TmpHistoriqueTable.typeorm.ts b/packages/backend/src/database/entities/interaction/TmpHistoriqueTable.typeorm.ts new file mode 100644 index 0000000000..52d6869543 --- /dev/null +++ b/packages/backend/src/database/entities/interaction/TmpHistoriqueTable.typeorm.ts @@ -0,0 +1,28 @@ +import { Entity, Column, PrimaryGeneratedColumn, Index } from "typeorm"; + +export interface TmpHistorique { + id_domicilie: number; + date: string; + type: string; +} + +@Entity("TmpHistorique") +export class TmpHistoriqueTable { + @PrimaryGeneratedColumn("uuid") + public uuid?: string; + + @Index() + @Column({ type: "integer", nullable: true }) + id_domicilie: number; + + @Column({ type: "text", nullable: true }) + date: string; + + @Index() + @Column({ nullable: true }) + type: string; + + public constructor(entity?: Partial) { + Object.assign(this, entity); + } +} diff --git a/packages/backend/src/database/entities/usager/UsagerTable.typeorm.ts b/packages/backend/src/database/entities/usager/UsagerTable.typeorm.ts index c77a3fb531..8b0b2041dc 100644 --- a/packages/backend/src/database/entities/usager/UsagerTable.typeorm.ts +++ b/packages/backend/src/database/entities/usager/UsagerTable.typeorm.ts @@ -142,7 +142,10 @@ export class UsagerTable public numeroDistribution!: string | null; @Column({ type: "jsonb", default: null, nullable: true }) - public pinnedNote!: Partial | null; + public pinnedNote!: Pick< + UsagerNote, + "usagerRef" | "createdAt" | "createdBy" | "message" + > | null; public constructor(entity?: Partial) { super(entity); diff --git a/packages/backend/src/database/services/_postgres/PG_CONNECT_OPTIONS.const.ts b/packages/backend/src/database/services/_postgres/PG_CONNECT_OPTIONS.const.ts index 405f6cc70d..551133eb71 100644 --- a/packages/backend/src/database/services/_postgres/PG_CONNECT_OPTIONS.const.ts +++ b/packages/backend/src/database/services/_postgres/PG_CONNECT_OPTIONS.const.ts @@ -28,12 +28,13 @@ if (isTypescriptMode) { export const PG_CONNECT_OPTIONS: PostgresConnectionOptions = { applicationName: "domifa-api", + url: "", poolErrorHandler: (err: Error) => { appLogger.error("PG pool error:", { error: err, sentry: true }); }, type: "postgres", synchronize: false, - migrationsTransactionMode: "each", + migrationsTransactionMode: "none", migrationsRun: (domifaConfig().envId !== "test" && domifaConfig().cron.enable) || domifaConfig().envId === "local", diff --git a/packages/backend/src/database/services/_postgres/appTypeormManager.service.ts b/packages/backend/src/database/services/_postgres/appTypeormManager.service.ts index c8b61852db..fe9378236d 100644 --- a/packages/backend/src/database/services/_postgres/appTypeormManager.service.ts +++ b/packages/backend/src/database/services/_postgres/appTypeormManager.service.ts @@ -19,7 +19,7 @@ async function migrateUp(connection: DataSource): Promise { appLogger.warn(`\nStart migrations ....`); const migrations = await connection.runMigrations({ - transaction: "each", + transaction: "all", }); appLogger.warn(`\nMigration success: ${migrations.length}\n`); diff --git a/packages/backend/src/database/services/_postgres/pgRepository.service.ts b/packages/backend/src/database/services/_postgres/pgRepository.service.ts index 85620ad69c..8f883a7dff 100644 --- a/packages/backend/src/database/services/_postgres/pgRepository.service.ts +++ b/packages/backend/src/database/services/_postgres/pgRepository.service.ts @@ -25,7 +25,6 @@ function get | number = T>( typeorm, aggregateAsNumber, countBy, - _parseCounts, }; diff --git a/packages/backend/src/database/services/interaction/historiqueRepository.service.ts b/packages/backend/src/database/services/interaction/historiqueRepository.service.ts new file mode 100644 index 0000000000..7d43461125 --- /dev/null +++ b/packages/backend/src/database/services/interaction/historiqueRepository.service.ts @@ -0,0 +1,15 @@ +import { + TmpHistorique, + TmpHistoriqueTable, +} from "../../entities/interaction/TmpHistoriqueTable.typeorm"; +import { + TmpCourriers, + TmpCourriersTable, +} from "../../entities/interaction/TmpCourriersTable.typeorm"; +import { myDataSource } from "../_postgres"; + +export const tmpHistoriqueRepository = + myDataSource.getRepository(TmpHistoriqueTable); + +export const tmpCourriersRepository = + myDataSource.getRepository(TmpCourriersTable); diff --git a/packages/backend/src/database/services/usager/usagerRepository.service.ts b/packages/backend/src/database/services/usager/usagerRepository.service.ts index a4077a5eb4..83aae59652 100644 --- a/packages/backend/src/database/services/usager/usagerRepository.service.ts +++ b/packages/backend/src/database/services/usager/usagerRepository.service.ts @@ -154,10 +154,10 @@ async function countTotalActifs(): Promise<{ }; } -async function countMigratedUsagers(): Promise { +async function countMigratedUsagers(structureId: number): Promise { return myDataSource .getRepository(UsagerTable) - .countBy({ migrated: false }); + .countBy({ migrated: false, structureId }); } async function findLastFiveCustomRef({ diff --git a/packages/backend/src/interactions/services/interactionsCreator.service.ts b/packages/backend/src/interactions/services/interactionsCreator.service.ts index f1720e7835..4c5923d547 100644 --- a/packages/backend/src/interactions/services/interactionsCreator.service.ts +++ b/packages/backend/src/interactions/services/interactionsCreator.service.ts @@ -98,7 +98,7 @@ async function createInteraction({ usagerUUID: usager.uuid, userId: user.id, userName: `${user.prenom} ${user.nom}`, - dateInteraction: now, + dateInteraction: interaction.dateInteraction ?? now, interactionOutUUID: null, procuration, }; diff --git a/packages/backend/src/structures/services/structure-deletor.service.ts b/packages/backend/src/structures/services/structure-deletor.service.ts index 53ebf9fd15..bd6d7cb17a 100644 --- a/packages/backend/src/structures/services/structure-deletor.service.ts +++ b/packages/backend/src/structures/services/structure-deletor.service.ts @@ -27,7 +27,7 @@ async function generateDeleteToken(uuid: string): Promise { } async function deleteStructureUsagers( - structure: Pick + structure: Pick ) { await deleteStructureDocuments(structure); @@ -35,15 +35,15 @@ async function deleteStructureUsagers( } async function deleteStructure( - structure: Pick + structure: Pick ): Promise { await deleteStructureUsagers(structure); return structureRepository.delete({ id: structure.id }); } -async function resetUsagers( - structure: Pick +export async function resetUsagers( + structure: Pick ): Promise { // Suppression des Documents await usagerDocsRepository.delete({ @@ -64,7 +64,7 @@ async function resetUsagers( } async function deleteStructureDocuments( - structure: Pick + structure: Pick ) { const oldUsagerFolder = join( domifaConfig().upload.basePath, diff --git a/packages/backend/src/usagers/services/custom-docs/buildCustomDoc.service.ts b/packages/backend/src/usagers/services/custom-docs/buildCustomDoc.service.ts index a6efb39afd..3aa6f5eeb8 100644 --- a/packages/backend/src/usagers/services/custom-docs/buildCustomDoc.service.ts +++ b/packages/backend/src/usagers/services/custom-docs/buildCustomDoc.service.ts @@ -248,7 +248,7 @@ export function buildCustomDoc({ } export const ucFirst = (value: string) => { - return value === undefined || value === null + return !value || value === "" ? "" : value.charAt(0).toUpperCase() + value.slice(1); }; diff --git a/packages/backend/src/usagers/services/usagerHistoryStateManager.service.ts b/packages/backend/src/usagers/services/usagerHistoryStateManager.service.ts index eb57090d3c..57f426aa61 100644 --- a/packages/backend/src/usagers/services/usagerHistoryStateManager.service.ts +++ b/packages/backend/src/usagers/services/usagerHistoryStateManager.service.ts @@ -105,12 +105,11 @@ function buildHistoryFromNewDecision({ createdEvent: UsagerHistoryStateCreationEvent; historyBeginDate?: Date; }) { - const decision = usager.decision; - if (!decision.typeDom) { - decision.typeDom = usager.typeDom; + if (!usager.decision.typeDom) { + usager.decision.typeDom = usager.typeDom; } - if (!decision.dateDebut) { - decision.dateDebut = decision.dateDecision; + if (!usager.decision.dateDebut) { + usager.decision.dateDebut = usager.decision.dateDecision; } if (!usagerHistory) { diff --git a/packages/backend/src/usagers/services/usagersCreator.service.ts b/packages/backend/src/usagers/services/usagersCreator.service.ts index f2767a055b..31c8e1ecb2 100644 --- a/packages/backend/src/usagers/services/usagersCreator.service.ts +++ b/packages/backend/src/usagers/services/usagersCreator.service.ts @@ -13,7 +13,7 @@ async function findNextUsagerRef(structureId: number): Promise { return usager?.ref ? usager?.ref + 1 : 1; } -function setUsagerDefaultAttributes(usager: Usager): void { +function setUsagerDefaultAttributes(usager: Partial): void { usager.options = { transfert: { actif: false, diff --git a/packages/frontend/package.json b/packages/frontend/package.json index be3dadb720..9aaff5cf0d 100644 --- a/packages/frontend/package.json +++ b/packages/frontend/package.json @@ -47,7 +47,7 @@ "date-fns": "^2.30.0", "file-saver": "^2.0.5", "google-libphonenumber": "^3.2.33", - "intl-tel-input": "18.3.4", + "intl-tel-input": "18.3.5", "jwt-decode": "^3.1.2", "ngx-bootstrap": "^12.0.0", "ngx-countup": "^13.1.0", @@ -76,7 +76,7 @@ "@types/jest": "^29.5.8", "@types/node": "^20.3.3", "@typescript-eslint/eslint-plugin": "^6.16.0", - "@typescript-eslint/parser": "6.18.0", + "@typescript-eslint/parser": "6.18.1", "eslint": "^8.53.0", "eslint-config-standard-with-typescript": "^42.0.0", "eslint-plugin-import": "^2.29.0", diff --git a/packages/frontend/src/app/shared/validators/email.validator.spec.ts b/packages/frontend/src/app/shared/validators/email.validator.spec.ts new file mode 100644 index 0000000000..53ad2e5ab4 --- /dev/null +++ b/packages/frontend/src/app/shared/validators/email.validator.spec.ts @@ -0,0 +1,49 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { EmailValidator } from "./email.validator"; + +describe("EmailValidator", () => { + it("should return null for an empty or undefined control value", () => { + const control: any = { value: "" }; + expect(EmailValidator(control)).toBeNull(); + + control.value = undefined; + expect(EmailValidator(control)).toBeNull(); + }); + + it("should return null for valid emails", () => { + const emailsOk = [ + "simple.email@example.com", + "admin@example.org", + "78@pole-emploi.fr", + "firstname-lastname@example.com", + "115.gironde@gmail.com", + "0626281379@orange.fr", + "firstname+tag+sorting@example.com", + "2014asea@strasbourg.com", + ]; + emailsOk.forEach((email: string) => { + const control: any = { value: email }; + expect(EmailValidator(control)).toEqual(null); + }); + }); + + it("should return an error object for invalid emails", () => { + const emailsNotOk = [ + " @ ", + "plainaddress", + "@missingusername.com", + "username@.com", + "username@.com.", + ".username@example.com", + "username@-example.com", + "username@example..com", + "Abc..123@example.com", + "username@example.c", + "username@10.10.10.256", + ]; + emailsNotOk.forEach((email: string) => { + const control: any = { value: email }; + expect(EmailValidator(control)).toEqual({ invalidEmail: true }); + }); + }); +}); diff --git a/packages/portail-admins/package.json b/packages/portail-admins/package.json index 32431ee9e6..1ffc581e29 100644 --- a/packages/portail-admins/package.json +++ b/packages/portail-admins/package.json @@ -65,8 +65,8 @@ "@types/jest": "^29.5.8", "@types/node": "^20.3.3", "@types/rimraf": "^4.0.5", - "@typescript-eslint/eslint-plugin": "6.18.0", - "@typescript-eslint/parser": "6.18.0", + "@typescript-eslint/eslint-plugin": "6.18.1", + "@typescript-eslint/parser": "6.18.1", "eslint": "^8.53.0", "eslint-config-prettier": "^9.0.0", "eslint-plugin-import": "^2.29.0", diff --git a/packages/portail-usagers/package.json b/packages/portail-usagers/package.json index e8b2dcfd74..2693da42ac 100644 --- a/packages/portail-usagers/package.json +++ b/packages/portail-usagers/package.json @@ -58,8 +58,8 @@ "@types/google-libphonenumber": "^7.4.30", "@types/jest": "^29.5.8", "@types/node": "^20.3.3", - "@typescript-eslint/eslint-plugin": "6.18.0", - "@typescript-eslint/parser": "6.18.0", + "@typescript-eslint/eslint-plugin": "6.18.1", + "@typescript-eslint/parser": "6.18.1", "eslint": "^8.53.0", "eslint-config-standard-with-typescript": "^42.0.0", "eslint-plugin-import": "^2.29.0", diff --git a/yarn.lock b/yarn.lock index 27454749db..52ad660dab 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2381,6 +2381,7 @@ __metadata: "@types/uuid": ^9.0.7 "@typescript-eslint/eslint-plugin": ^6.16.0 "@typescript-eslint/parser": ^6.16.0 + "@wmfs/xml2csv": ^1.32.0 axios: ^1.6.2 bcryptjs: ^2.4.3 cache-manager: ^5.3.2 @@ -2399,6 +2400,7 @@ __metadata: eslint-plugin-promise: ^6.1.1 exceljs: ^4.2.1 express: ^4.18.2 + fast-xml-parser: ^4.2.7 fs-extra: ^11.1.1 google-libphonenumber: ^3.2.33 ics: ^2.41.0 @@ -2440,7 +2442,7 @@ __metadata: typescript: 4.9.5 uuid: ^9.0.1 xlsx: ^0.18.5 - yup: ^0.32.11 + yup: ^0.32.9 yup-phone: ^1.3.2 languageName: unknown linkType: soft @@ -2519,7 +2521,7 @@ __metadata: "@types/jest": ^29.5.8 "@types/node": ^20.3.3 "@typescript-eslint/eslint-plugin": ^6.16.0 - "@typescript-eslint/parser": 6.18.0 + "@typescript-eslint/parser": 6.18.1 angular-user-idle: ^4.0.0 bootstrap: ^5.3.2 date-fns: ^2.30.0 @@ -2531,7 +2533,7 @@ __metadata: eslint-plugin-prettier: ^5.0.1 file-saver: ^2.0.5 google-libphonenumber: ^3.2.33 - intl-tel-input: 18.3.4 + intl-tel-input: 18.3.5 jest: ^29.7.0 jest-preset-angular: ^14.0.0 jwt-decode: ^3.1.2 @@ -2594,8 +2596,8 @@ __metadata: "@types/jest": ^29.5.8 "@types/node": ^20.3.3 "@types/rimraf": ^4.0.5 - "@typescript-eslint/eslint-plugin": 6.18.0 - "@typescript-eslint/parser": 6.18.0 + "@typescript-eslint/eslint-plugin": 6.18.1 + "@typescript-eslint/parser": 6.18.1 bootstrap: ^5.3.2 class-validator: ^0.14.0 date-fns: ^2.30.0 @@ -2657,8 +2659,8 @@ __metadata: "@types/google-libphonenumber": ^7.4.30 "@types/jest": ^29.5.8 "@types/node": ^20.3.3 - "@typescript-eslint/eslint-plugin": 6.18.0 - "@typescript-eslint/parser": 6.18.0 + "@typescript-eslint/eslint-plugin": 6.18.1 + "@typescript-eslint/parser": 6.18.1 angular-user-idle: ^4.0.0 bootstrap: ^5.3.2 date-fns: ^2.30.0 @@ -6929,15 +6931,15 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/eslint-plugin@npm:6.18.0, @typescript-eslint/eslint-plugin@npm:^6.16.0": - version: 6.18.0 - resolution: "@typescript-eslint/eslint-plugin@npm:6.18.0" +"@typescript-eslint/eslint-plugin@npm:6.18.1, @typescript-eslint/eslint-plugin@npm:^6.16.0": + version: 6.18.1 + resolution: "@typescript-eslint/eslint-plugin@npm:6.18.1" dependencies: "@eslint-community/regexpp": ^4.5.1 - "@typescript-eslint/scope-manager": 6.18.0 - "@typescript-eslint/type-utils": 6.18.0 - "@typescript-eslint/utils": 6.18.0 - "@typescript-eslint/visitor-keys": 6.18.0 + "@typescript-eslint/scope-manager": 6.18.1 + "@typescript-eslint/type-utils": 6.18.1 + "@typescript-eslint/utils": 6.18.1 + "@typescript-eslint/visitor-keys": 6.18.1 debug: ^4.3.4 graphemer: ^1.4.0 ignore: ^5.2.4 @@ -6950,7 +6952,7 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: a0e946c03b3d55326fa2f090341c57063670d654ab3681f48e88af940d2ee843bd4d124655e27820ae284b705232ecfc0665ad39ace95d5210c04ee66d57d58d + checksum: 933ede339bfac8377f94b211253bce40ace272a01466c290b38e681ec4752128ce63f827bbe6cc70cc0383d01655c8a22b25c640841fe90dfa4e57f73baaf2a9 languageName: node linkType: hard @@ -6992,21 +6994,21 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/parser@npm:6.18.0, @typescript-eslint/parser@npm:^6.16.0, @typescript-eslint/parser@npm:^6.4.0": - version: 6.18.0 - resolution: "@typescript-eslint/parser@npm:6.18.0" +"@typescript-eslint/parser@npm:6.18.1, @typescript-eslint/parser@npm:^6.16.0, @typescript-eslint/parser@npm:^6.4.0": + version: 6.18.1 + resolution: "@typescript-eslint/parser@npm:6.18.1" dependencies: - "@typescript-eslint/scope-manager": 6.18.0 - "@typescript-eslint/types": 6.18.0 - "@typescript-eslint/typescript-estree": 6.18.0 - "@typescript-eslint/visitor-keys": 6.18.0 + "@typescript-eslint/scope-manager": 6.18.1 + "@typescript-eslint/types": 6.18.1 + "@typescript-eslint/typescript-estree": 6.18.1 + "@typescript-eslint/visitor-keys": 6.18.1 debug: ^4.3.4 peerDependencies: eslint: ^7.0.0 || ^8.0.0 peerDependenciesMeta: typescript: optional: true - checksum: 2f9eb1b8f142cb191de6a6f34b913df1c09ea66bb09bd92c201e28fe84b6f3c13cbed3469c94d498e96ea06349b643632bb693dcf27b85908d7221b58c24bcff + checksum: f123310976a73d9f08470dbad917c9e7b038e9e1362924a225a29d35fac1a2726d447952ca77b914d47f50791d235bb66f5171c7a4a0536e9c170fb20e73a2e4 languageName: node linkType: hard @@ -7057,13 +7059,13 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/scope-manager@npm:6.18.0": - version: 6.18.0 - resolution: "@typescript-eslint/scope-manager@npm:6.18.0" +"@typescript-eslint/scope-manager@npm:6.18.1": + version: 6.18.1 + resolution: "@typescript-eslint/scope-manager@npm:6.18.1" dependencies: - "@typescript-eslint/types": 6.18.0 - "@typescript-eslint/visitor-keys": 6.18.0 - checksum: 9958dcd95605b9699e1fe823cc38869d542f2cb90cde443938c1352de4161703ed6619e772bc12b8b7df2a44623ebf1e6b2b8d1222e5df22880185d0652040ee + "@typescript-eslint/types": 6.18.1 + "@typescript-eslint/visitor-keys": 6.18.1 + checksum: d6708f9f2658ab68f9f4628b93c4131fb82c362383b4d5d671491082ff610258f2fc9e293739618dc76ed6d2c5909f000a54b9b905e58a5172e6e2f731666245 languageName: node linkType: hard @@ -7084,12 +7086,12 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/type-utils@npm:6.18.0": - version: 6.18.0 - resolution: "@typescript-eslint/type-utils@npm:6.18.0" +"@typescript-eslint/type-utils@npm:6.18.1": + version: 6.18.1 + resolution: "@typescript-eslint/type-utils@npm:6.18.1" dependencies: - "@typescript-eslint/typescript-estree": 6.18.0 - "@typescript-eslint/utils": 6.18.0 + "@typescript-eslint/typescript-estree": 6.18.1 + "@typescript-eslint/utils": 6.18.1 debug: ^4.3.4 ts-api-utils: ^1.0.1 peerDependencies: @@ -7097,7 +7099,7 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: 537b2f0b85c4225538a14e5030fc25c3f6ea610ea59dd9ac25e59a2aadd01344e2b154fcd5ab2245d055d977e4ff2b7ab30369f28eb78b6059702a2899fbdd3c + checksum: 44d7e14460f8a22a0c5c58ff7004cb40061e722dfcec3ac4ee15d40dafe68c61e555a79e81af8ffa0ca845fb3caf3ed5376853b9a94e2f3c823ac5e8267230c8 languageName: node linkType: hard @@ -7122,10 +7124,10 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/types@npm:6.18.0": - version: 6.18.0 - resolution: "@typescript-eslint/types@npm:6.18.0" - checksum: 516ad2feb7e7c7b5aac805b287be794e6e42371bc6a5bdd7c9fc230d98bbbcc4877c96377ccce68aede68ec58a64ef9d1e4c5b15cfb55e9a050bafe7b36624c1 +"@typescript-eslint/types@npm:6.18.1": + version: 6.18.1 + resolution: "@typescript-eslint/types@npm:6.18.1" + checksum: f1713785c4dd49e6aae4186042679d205312a1c6cbfcdad133abf5c61f71c115e04c6643aa6a8aacd732e6b64030d71bbc92762164b7f231d98fc2e31c3f8ed8 languageName: node linkType: hard @@ -7183,12 +7185,12 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/typescript-estree@npm:6.18.0": - version: 6.18.0 - resolution: "@typescript-eslint/typescript-estree@npm:6.18.0" +"@typescript-eslint/typescript-estree@npm:6.18.1": + version: 6.18.1 + resolution: "@typescript-eslint/typescript-estree@npm:6.18.1" dependencies: - "@typescript-eslint/types": 6.18.0 - "@typescript-eslint/visitor-keys": 6.18.0 + "@typescript-eslint/types": 6.18.1 + "@typescript-eslint/visitor-keys": 6.18.1 debug: ^4.3.4 globby: ^11.1.0 is-glob: ^4.0.3 @@ -7198,7 +7200,7 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: 64afa0a81af66dfcb1d3027872abc07451691dff956c8b3174da675307050404c720465be5322490859d633e76705fd5e0fd5f040aa4cc1078bd837281e52065 + checksum: fc5fb8abea9a6c3b774f62989b9a463569d141c32f6f2febef11d4161acaff946b204226234077b1126294fcf86a83c5fc9227f34ea3ba4cc9d39ca843dfae97 languageName: node linkType: hard @@ -7220,20 +7222,20 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/utils@npm:6.18.0": - version: 6.18.0 - resolution: "@typescript-eslint/utils@npm:6.18.0" +"@typescript-eslint/utils@npm:6.18.1": + version: 6.18.1 + resolution: "@typescript-eslint/utils@npm:6.18.1" dependencies: "@eslint-community/eslint-utils": ^4.4.0 "@types/json-schema": ^7.0.12 "@types/semver": ^7.5.0 - "@typescript-eslint/scope-manager": 6.18.0 - "@typescript-eslint/types": 6.18.0 - "@typescript-eslint/typescript-estree": 6.18.0 + "@typescript-eslint/scope-manager": 6.18.1 + "@typescript-eslint/types": 6.18.1 + "@typescript-eslint/typescript-estree": 6.18.1 semver: ^7.5.4 peerDependencies: eslint: ^7.0.0 || ^8.0.0 - checksum: 5c8ab14838d5dcc857de43781687b105d972941bd4a08e63d14b6485a3944a77c867c162f14eca9ef526170b26423a0d4a828a0b22d88cb34f99835233152dff + checksum: b7265b0cae099feb98e233dd518b54408fde01b9703535c9e9b84c24e9af6fff0fd9a61f0f7d7b24fb738151ad25a7f57210e83a5a2700cac38ee627f5b856d4 languageName: node linkType: hard @@ -7285,13 +7287,13 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/visitor-keys@npm:6.18.0": - version: 6.18.0 - resolution: "@typescript-eslint/visitor-keys@npm:6.18.0" +"@typescript-eslint/visitor-keys@npm:6.18.1": + version: 6.18.1 + resolution: "@typescript-eslint/visitor-keys@npm:6.18.1" dependencies: - "@typescript-eslint/types": 6.18.0 + "@typescript-eslint/types": 6.18.1 eslint-visitor-keys: ^3.4.1 - checksum: d6b1958867f3287c4e2c4f80633346a676060181e27ef69a1aad68634c62311738a3aad49e61c1d30d8e31800de146424ca8b33483d033132d90bf0c2f31cac8 + checksum: 4befc450fd459e9dc368c3da7066a4948946e8b24383bf0fbaacd059cbe69ff0f71cac4f6d5d1f99a523c1fb20d39bef907e522d2c8e8315a8ce4ce678a58540 languageName: node linkType: hard @@ -7476,6 +7478,19 @@ __metadata: languageName: node linkType: hard +"@wmfs/xml2csv@npm:^1.32.0": + version: 1.32.0 + resolution: "@wmfs/xml2csv@npm:1.32.0" + dependencies: + debug: 4.3.4 + dottie: 2.0.6 + fs-extra: 11.1.1 + lodash: 4.17.21 + sax: 1.2.4 + checksum: 4e9055f149d0b546344c9bd05fc0a2380c0a72da17561f73b1a4cf5d9cf0c55f9513f716d0a4d891963f949167650cf7edb33d8e547e3f57f84ec6593f1d06ad + languageName: node + linkType: hard + "@xmldom/xmldom@npm:^0.8.6, @xmldom/xmldom@npm:^0.8.8": version: 0.8.9 resolution: "@xmldom/xmldom@npm:0.8.9" @@ -10858,6 +10873,13 @@ __metadata: languageName: node linkType: hard +"dottie@npm:2.0.6": + version: 2.0.6 + resolution: "dottie@npm:2.0.6" + checksum: 4c778df9dc631a1108a32ef390916836814999a7411d10883f4151bd49c9c6934dc329b3f50fc7692849aa75ba87dba880fd54be501a3b39a6b9c23d6f772a09 + languageName: node + linkType: hard + "duck@npm:^0.1.12": version: 0.1.12 resolution: "duck@npm:0.1.12" @@ -12327,6 +12349,17 @@ __metadata: languageName: node linkType: hard +"fast-xml-parser@npm:^4.2.7": + version: 4.3.2 + resolution: "fast-xml-parser@npm:4.3.2" + dependencies: + strnum: ^1.0.5 + bin: + fxparser: src/cli/cli.js + checksum: d507ce2efa5fd13d0a5ba28bd76dd68f2fc30ad8748357c37b70f360d19417866d79e35a688af067d5bceaaa796033fa985206aef9692f7a421e1326b6e73309 + languageName: node + linkType: hard + "fastq@npm:^1.6.0": version: 1.15.0 resolution: "fastq@npm:1.15.0" @@ -12651,25 +12684,25 @@ __metadata: languageName: node linkType: hard -"fs-extra@npm:^10.0.0": - version: 10.1.0 - resolution: "fs-extra@npm:10.1.0" +"fs-extra@npm:11.1.1, fs-extra@npm:^11.0.0, fs-extra@npm:^11.1.0, fs-extra@npm:^11.1.1": + version: 11.1.1 + resolution: "fs-extra@npm:11.1.1" dependencies: graceful-fs: ^4.2.0 jsonfile: ^6.0.1 universalify: ^2.0.0 - checksum: dc94ab37096f813cc3ca12f0f1b5ad6744dfed9ed21e953d72530d103cea193c2f81584a39e9dee1bea36de5ee66805678c0dddc048e8af1427ac19c00fffc50 + checksum: fb883c68245b2d777fbc1f2082c9efb084eaa2bbf9fddaa366130d196c03608eebef7fb490541276429ee1ca99f317e2d73e96f5ca0999eefedf5a624ae1edfd languageName: node linkType: hard -"fs-extra@npm:^11.0.0, fs-extra@npm:^11.1.0, fs-extra@npm:^11.1.1": - version: 11.1.1 - resolution: "fs-extra@npm:11.1.1" +"fs-extra@npm:^10.0.0": + version: 10.1.0 + resolution: "fs-extra@npm:10.1.0" dependencies: graceful-fs: ^4.2.0 jsonfile: ^6.0.1 universalify: ^2.0.0 - checksum: fb883c68245b2d777fbc1f2082c9efb084eaa2bbf9fddaa366130d196c03608eebef7fb490541276429ee1ca99f317e2d73e96f5ca0999eefedf5a624ae1edfd + checksum: dc94ab37096f813cc3ca12f0f1b5ad6744dfed9ed21e953d72530d103cea193c2f81584a39e9dee1bea36de5ee66805678c0dddc048e8af1427ac19c00fffc50 languageName: node linkType: hard @@ -14143,10 +14176,10 @@ __metadata: languageName: node linkType: hard -"intl-tel-input@npm:18.3.4": - version: 18.3.4 - resolution: "intl-tel-input@npm:18.3.4" - checksum: a966c5f5956a8bb5822fe49f32dc1e2be6d694ca5a071bb3ce199fe147d7b772f67ae5cff6c38c0b6d5055fadd0da01541e45cb7ff698078da0b7769b867cade +"intl-tel-input@npm:18.3.5": + version: 18.3.5 + resolution: "intl-tel-input@npm:18.3.5" + checksum: 0a2ff31fc2999938ce1e1387ab538cd956aa2af824653773908b0cd95de96dfde5216d2993e2ee50b5eca1aba3e7b38f495633d9b8a9a505f44dcfcfec57575c languageName: node linkType: hard @@ -20699,7 +20732,7 @@ __metadata: languageName: node linkType: hard -"sax@npm:^1.2.4": +"sax@npm:1.2.4, sax@npm:^1.2.4": version: 1.2.4 resolution: "sax@npm:1.2.4" checksum: d3df7d32b897a2c2f28e941f732c71ba90e27c24f62ee918bd4d9a8cfb3553f2f81e5493c7f0be94a11c1911b643a9108f231dd6f60df3fa9586b5d2e3e9e1fe @@ -21889,6 +21922,13 @@ __metadata: languageName: node linkType: hard +"strnum@npm:^1.0.5": + version: 1.0.5 + resolution: "strnum@npm:1.0.5" + checksum: 651b2031db5da1bf4a77fdd2f116a8ac8055157c5420f5569f64879133825915ad461513e7202a16d7fec63c54fd822410d0962f8ca12385c4334891b9ae6dd2 + languageName: node + linkType: hard + "strong-log-transformer@npm:2.1.0, strong-log-transformer@npm:^2.1.0": version: 2.1.0 resolution: "strong-log-transformer@npm:2.1.0"