@proconnect-gouv/proconnect.identite 1.1.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -0
- package/dist/data/certification/commune-code-conversion.d.ts +13 -0
- package/dist/data/certification/commune-code-conversion.d.ts.map +1 -0
- package/dist/data/certification/commune-code-conversion.js +5188 -0
- package/dist/data/certification/country-iso-to-cog.d.ts +12 -0
- package/dist/data/certification/country-iso-to-cog.d.ts.map +1 -0
- package/dist/data/certification/country-iso-to-cog.js +438 -0
- package/dist/data/certification/index.d.ts +3 -0
- package/dist/data/certification/index.d.ts.map +1 -0
- package/dist/data/certification/index.js +3 -0
- package/dist/{mappers/certification/index.d.ts → managers/certification/adapters/api_entreprise.d.ts} +2 -2
- package/dist/managers/certification/adapters/api_entreprise.d.ts.map +1 -0
- package/dist/managers/certification/adapters/api_entreprise.js +14 -0
- package/dist/managers/certification/adapters/franceconnect.d.ts +3 -0
- package/dist/managers/certification/adapters/franceconnect.d.ts.map +1 -0
- package/dist/managers/certification/adapters/franceconnect.js +15 -0
- package/dist/managers/certification/adapters/insee.d.ts +4 -0
- package/dist/managers/certification/adapters/insee.d.ts.map +1 -0
- package/dist/managers/certification/adapters/insee.js +29 -0
- package/dist/managers/certification/adapters/rne.d.ts +4 -0
- package/dist/managers/certification/adapters/rne.d.ts.map +1 -0
- package/dist/managers/certification/adapters/rne.js +45 -0
- package/dist/managers/certification/birthplace-conversion.d.ts +27 -0
- package/dist/managers/certification/birthplace-conversion.d.ts.map +1 -0
- package/dist/managers/certification/birthplace-conversion.js +45 -0
- package/dist/managers/certification/certification-score.d.ts +22 -0
- package/dist/managers/certification/certification-score.d.ts.map +1 -0
- package/dist/managers/certification/certification-score.js +72 -0
- package/dist/managers/certification/index.d.ts +1 -1
- package/dist/managers/certification/index.d.ts.map +1 -1
- package/dist/managers/certification/index.js +1 -1
- package/dist/managers/certification/is-organization-dirigeant.d.ts +38 -8
- package/dist/managers/certification/is-organization-dirigeant.d.ts.map +1 -1
- package/dist/managers/certification/is-organization-dirigeant.js +89 -52
- package/dist/managers/certification/normalize.d.ts +21 -0
- package/dist/managers/certification/normalize.d.ts.map +1 -0
- package/dist/managers/certification/normalize.js +64 -0
- package/dist/managers/franceconnect/openid-client.d.ts +1 -0
- package/dist/managers/franceconnect/openid-client.d.ts.map +1 -1
- package/dist/managers/organization/adapters/api_entreprise.d.ts +25 -0
- package/dist/managers/organization/adapters/api_entreprise.d.ts.map +1 -0
- package/dist/{mappers/organization/from-siret.js → managers/organization/adapters/api_entreprise.js} +25 -2
- package/dist/managers/organization/get-organization-info.d.ts.map +1 -1
- package/dist/managers/organization/get-organization-info.js +3 -3
- package/dist/repositories/organization/upsert.d.ts +1 -1
- package/dist/repositories/organization/upsert.d.ts.map +1 -1
- package/dist/repositories/organization/upsert.js +26 -1
- package/dist/repositories/user/get-franceconnect-user-info.d.ts +1 -0
- package/dist/repositories/user/get-franceconnect-user-info.d.ts.map +1 -1
- package/dist/repositories/user/upsert-franceconnect-userinfo.d.ts +1 -0
- package/dist/repositories/user/upsert-franceconnect-userinfo.d.ts.map +1 -1
- package/dist/services/organization/is-syndicat-communal.d.ts.map +1 -1
- package/dist/services/organization/is-syndicat-communal.js +2 -0
- package/dist/types/dirigeant.d.ts +5 -0
- package/dist/types/dirigeant.d.ts.map +1 -1
- package/dist/types/dirigeant.js +2 -0
- package/dist/types/franceconnect.d.ts +2 -0
- package/dist/types/franceconnect.d.ts.map +1 -1
- package/dist/types/franceconnect.js +1 -0
- package/dist/types/organization.d.ts +2 -2
- package/dist/types/organization.d.ts.map +1 -1
- package/package.json +6 -6
- package/src/data/certification/commune-code-conversion.ts +5189 -0
- package/src/data/certification/country-iso-to-cog.ts +439 -0
- package/src/data/certification/index.ts +4 -0
- package/src/managers/certification/adapters/api_entreprise.test.ts +68 -0
- package/src/managers/certification/adapters/api_entreprise.test.ts.snapshot +109 -0
- package/src/{mappers/certification/index.ts → managers/certification/adapters/api_entreprise.ts} +7 -4
- package/src/managers/certification/adapters/franceconnect.ts +21 -0
- package/src/managers/certification/adapters/insee.test.ts +18 -0
- package/src/managers/certification/adapters/insee.test.ts.snapshot +21 -0
- package/src/managers/certification/adapters/insee.ts +39 -0
- package/src/managers/certification/adapters/rne.test.ts +276 -0
- package/src/managers/certification/adapters/rne.ts +64 -0
- package/src/managers/certification/birthplace-conversion.test.ts +76 -0
- package/src/managers/certification/birthplace-conversion.ts +58 -0
- package/src/managers/certification/certification-score.test.ts +309 -0
- package/src/managers/certification/certification-score.ts +97 -0
- package/src/managers/certification/index.ts +1 -1
- package/src/managers/certification/is-organization-dirigeant.test.ts +139 -48
- package/src/managers/certification/is-organization-dirigeant.ts +132 -106
- package/src/managers/certification/normalize.test.ts +71 -0
- package/src/managers/certification/normalize.ts +72 -0
- package/src/managers/organization/adapters/api_entreprise.test.ts +31 -0
- package/src/{mappers/organization/from-siret.test.ts.snapshot → managers/organization/adapters/api_entreprise.test.ts.snapshot} +26 -3
- package/src/{mappers/organization/from-siret.ts → managers/organization/adapters/api_entreprise.ts} +53 -3
- package/src/managers/organization/get-organization-info.test.ts +1 -1
- package/src/managers/organization/get-organization-info.ts +3 -3
- package/src/repositories/organization/upsert.ts +69 -19
- package/src/repositories/user/get-franceconnect-user-info.test.ts +1 -0
- package/src/repositories/user/upsert-franceconnect-userinfo.test.ts +2 -0
- package/src/services/organization/is-syndicat-communal.ts +2 -0
- package/src/types/dirigeant.ts +3 -0
- package/src/types/franceconnect.ts +1 -0
- package/src/types/organization.ts +2 -2
- package/testing/seed/franceconnect/index.ts +12 -9
- package/testing/seed/organizations/index.ts +34 -0
- package/tsconfig.json +5 -2
- package/tsconfig.lib.tsbuildinfo +1 -1
- package/dist/managers/certification/distance.d.ts +0 -4
- package/dist/managers/certification/distance.d.ts.map +0 -1
- package/dist/managers/certification/distance.js +0 -16
- package/dist/mappers/certification/index.d.ts.map +0 -1
- package/dist/mappers/certification/index.js +0 -11
- package/dist/mappers/index.d.ts +0 -2
- package/dist/mappers/index.d.ts.map +0 -1
- package/dist/mappers/index.js +0 -2
- package/dist/mappers/organization/from-siret.d.ts +0 -5
- package/dist/mappers/organization/from-siret.d.ts.map +0 -1
- package/dist/mappers/organization/index.d.ts +0 -2
- package/dist/mappers/organization/index.d.ts.map +0 -1
- package/dist/mappers/organization/index.js +0 -2
- package/src/managers/certification/distance.test.ts +0 -109
- package/src/managers/certification/distance.ts +0 -41
- package/src/mappers/index.ts +0 -3
- package/src/mappers/organization/from-siret.test.ts +0 -26
- package/src/mappers/organization/index.ts +0 -3
- package/testing/seed/insee/index.ts +0 -22
- package/testing/seed/mandataires/index.ts +0 -32
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
//
|
|
2
|
+
import { COMMUNE_CODE_CONVERSION, COUNTRY_ISO_TO_COG, } from "#src/data/certification";
|
|
3
|
+
/**
|
|
4
|
+
* Converts a commune code to a canonical representation,
|
|
5
|
+
* ensuring consistency across historical and current versions.
|
|
6
|
+
* If the code is not in the conversion table, returns the original code.
|
|
7
|
+
*
|
|
8
|
+
* @param communeCode - The commune code to convert (format: XXXXX or 2AXXX or 2BXXX)
|
|
9
|
+
* @returns The converted code, or the original if no conversion is needed
|
|
10
|
+
*/
|
|
11
|
+
export function convertCommuneCode(communeCode) {
|
|
12
|
+
if (!communeCode)
|
|
13
|
+
return null;
|
|
14
|
+
// Check if the code needs conversion
|
|
15
|
+
const converted = COMMUNE_CODE_CONVERSION[communeCode];
|
|
16
|
+
return converted || communeCode;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Converts an ISO 3166 country code (2 or 3-letter) to COG format (5-digit).
|
|
20
|
+
*
|
|
21
|
+
* @param iso3166Code - The ISO 3166 country code (e.g., "IRL", "FRA")
|
|
22
|
+
* @returns The COG code (e.g., "99136"), or null if not found
|
|
23
|
+
*/
|
|
24
|
+
export function convertCountryIsoToCog(iso3166Code) {
|
|
25
|
+
if (!iso3166Code)
|
|
26
|
+
return null;
|
|
27
|
+
const cogCode = COUNTRY_ISO_TO_COG[iso3166Code.toUpperCase()];
|
|
28
|
+
return cogCode || null;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Validates if a birthplace code has the correct COG format.
|
|
32
|
+
* Valid formats:
|
|
33
|
+
* - 5 digits (e.g., "75001")
|
|
34
|
+
* - 2A or 2B + 3 digits (e.g., "2A001", "2B042" for Corsica)
|
|
35
|
+
*
|
|
36
|
+
* @param birthplaceCode - The birthplace code to validate
|
|
37
|
+
* @returns true if the format is valid, false otherwise
|
|
38
|
+
*/
|
|
39
|
+
export function isValidBirthplaceFormat(birthplaceCode) {
|
|
40
|
+
if (!birthplaceCode)
|
|
41
|
+
return false;
|
|
42
|
+
// Match either 5 digits or 2A/2B + 3 digits
|
|
43
|
+
const validFormat = /^(\d{5}|2[AB]\d{3})$/;
|
|
44
|
+
return validFormat.test(birthplaceCode);
|
|
45
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { IdentityVector } from "#src/types";
|
|
2
|
+
/**
|
|
3
|
+
* Calculates a certification score between identity from FranceConnect (IdentitePivot)
|
|
4
|
+
* and executive identity from business registries (SourceDirigeant).
|
|
5
|
+
*
|
|
6
|
+
* The scoring system awards 1 point for each matching criterion:
|
|
7
|
+
* - Family name (after normalization): 1 point
|
|
8
|
+
* - First name (first name only, after normalization): 1 point
|
|
9
|
+
* - Gender (match or absent in source): 1 point
|
|
10
|
+
* - Birth date (exact match): 1 point
|
|
11
|
+
* - Birth place:
|
|
12
|
+
* - For French (birthcountry = 99100 or null): commune match or absent in source: 1 point
|
|
13
|
+
* - For foreigners: country match: 1 point
|
|
14
|
+
*
|
|
15
|
+
* Maximum score: 5 points (required for certification)
|
|
16
|
+
*
|
|
17
|
+
* @param identitePivot - Identity from FranceConnect
|
|
18
|
+
* @param sourceDirigeant - Executive identity from business registry
|
|
19
|
+
* @returns Score from 0 to 5
|
|
20
|
+
*/
|
|
21
|
+
export declare function certificationScore(identitePivot: IdentityVector, sourceDirigeant: IdentityVector): number;
|
|
22
|
+
//# sourceMappingURL=certification-score.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"certification-score.d.ts","sourceRoot":"","sources":["../../../src/managers/certification/certification-score.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAMjD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,kBAAkB,CAChC,aAAa,EAAE,cAAc,EAC7B,eAAe,EAAE,cAAc,GAC9B,MAAM,CAkER"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
//
|
|
2
|
+
import { convertCommuneCode } from "./birthplace-conversion.js";
|
|
3
|
+
import { extractFirstName, normalizeText } from "./normalize.js";
|
|
4
|
+
//
|
|
5
|
+
/**
|
|
6
|
+
* Calculates a certification score between identity from FranceConnect (IdentitePivot)
|
|
7
|
+
* and executive identity from business registries (SourceDirigeant).
|
|
8
|
+
*
|
|
9
|
+
* The scoring system awards 1 point for each matching criterion:
|
|
10
|
+
* - Family name (after normalization): 1 point
|
|
11
|
+
* - First name (first name only, after normalization): 1 point
|
|
12
|
+
* - Gender (match or absent in source): 1 point
|
|
13
|
+
* - Birth date (exact match): 1 point
|
|
14
|
+
* - Birth place:
|
|
15
|
+
* - For French (birthcountry = 99100 or null): commune match or absent in source: 1 point
|
|
16
|
+
* - For foreigners: country match: 1 point
|
|
17
|
+
*
|
|
18
|
+
* Maximum score: 5 points (required for certification)
|
|
19
|
+
*
|
|
20
|
+
* @param identitePivot - Identity from FranceConnect
|
|
21
|
+
* @param sourceDirigeant - Executive identity from business registry
|
|
22
|
+
* @returns Score from 0 to 5
|
|
23
|
+
*/
|
|
24
|
+
export function certificationScore(identitePivot, sourceDirigeant) {
|
|
25
|
+
let score = 0;
|
|
26
|
+
// 1. Family name match (after normalization)
|
|
27
|
+
const normalizedFamilyNamePivot = normalizeText(identitePivot.family_name);
|
|
28
|
+
const normalizedFamilyNameSource = normalizeText(sourceDirigeant.family_name);
|
|
29
|
+
if (normalizedFamilyNamePivot &&
|
|
30
|
+
normalizedFamilyNameSource &&
|
|
31
|
+
normalizedFamilyNamePivot === normalizedFamilyNameSource) {
|
|
32
|
+
score += 1;
|
|
33
|
+
}
|
|
34
|
+
// 2. First name match (first name only, after normalization)
|
|
35
|
+
const firstNamePivot = extractFirstName(identitePivot.given_name);
|
|
36
|
+
const firstNameSource = extractFirstName(sourceDirigeant.given_name);
|
|
37
|
+
if (firstNamePivot && firstNameSource && firstNamePivot === firstNameSource) {
|
|
38
|
+
score += 1;
|
|
39
|
+
}
|
|
40
|
+
// 3. Gender match (match or absent in source)
|
|
41
|
+
if (!sourceDirigeant.gender ||
|
|
42
|
+
identitePivot.gender === sourceDirigeant.gender) {
|
|
43
|
+
score += 1;
|
|
44
|
+
}
|
|
45
|
+
// 4. Birth date match (exact match)
|
|
46
|
+
if (identitePivot.birthdate &&
|
|
47
|
+
sourceDirigeant.birthdate &&
|
|
48
|
+
identitePivot.birthdate.getTime() === sourceDirigeant.birthdate.getTime()) {
|
|
49
|
+
score += 1;
|
|
50
|
+
}
|
|
51
|
+
// 5. Birth place match (different logic for French vs foreigners)
|
|
52
|
+
const isFrench = !identitePivot.birthcountry || identitePivot.birthcountry === "99100";
|
|
53
|
+
if (isFrench) {
|
|
54
|
+
// For French: check commune code (with conversion)
|
|
55
|
+
const communePivot = convertCommuneCode(identitePivot.birthplace);
|
|
56
|
+
const communeSource = convertCommuneCode(sourceDirigeant.birthplace);
|
|
57
|
+
// Match if equal or if source has no commune data
|
|
58
|
+
if (!communeSource || (communePivot && communePivot === communeSource)) {
|
|
59
|
+
score += 1;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
// For foreigners: check country code (with conversion if needed from RNE)
|
|
64
|
+
// Both should already be in COG format (99XXX)
|
|
65
|
+
if (identitePivot.birthcountry &&
|
|
66
|
+
sourceDirigeant.birthcountry &&
|
|
67
|
+
identitePivot.birthcountry === sourceDirigeant.birthcountry) {
|
|
68
|
+
score += 1;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return score;
|
|
72
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/managers/certification/index.ts"],"names":[],"mappings":"AAEA,cAAc,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/managers/certification/index.ts"],"names":[],"mappings":"AAEA,cAAc,0BAA0B,CAAC;AACzC,cAAc,gCAAgC,CAAC"}
|
|
@@ -1,15 +1,45 @@
|
|
|
1
1
|
import type { GetFranceConnectUserInfoHandler } from "#src/repositories/user";
|
|
2
|
-
import type {
|
|
3
|
-
import type {
|
|
2
|
+
import type { Organization } from "#src/types";
|
|
3
|
+
import type { ApiEntrepriseInfogreffeRepository } from "@proconnect-gouv/proconnect.api_entreprise/api";
|
|
4
|
+
import type { FindUniteLegaleBySirenHandler } from "@proconnect-gouv/proconnect.insee/api";
|
|
5
|
+
import type { FindPouvoirsBySirenHandler } from "@proconnect-gouv/proconnect.registre_national_entreprises/api";
|
|
4
6
|
type IsOrganizationExecutiveFactoryFactoryConfig = {
|
|
5
|
-
ApiEntrepriseInfogreffeRepository: ApiEntrepriseInfogreffeRepository
|
|
6
|
-
ApiEntrepriseInseeRepository: Pick<ApiEntrepriseInseeRepository, "findBySiret">;
|
|
7
|
+
ApiEntrepriseInfogreffeRepository: Pick<ApiEntrepriseInfogreffeRepository, "findMandatairesSociauxBySiren">;
|
|
7
8
|
EQUALITY_THRESHOLD?: number;
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
FranceConnectApiRepository: {
|
|
10
|
+
getFranceConnectUserInfo: GetFranceConnectUserInfoHandler;
|
|
11
|
+
};
|
|
12
|
+
InseeApiRepository: {
|
|
13
|
+
findBySiren: FindUniteLegaleBySirenHandler;
|
|
14
|
+
};
|
|
15
|
+
RegistreNationalEntreprisesApiRepository: {
|
|
16
|
+
findPouvoirsBySiren: FindPouvoirsBySirenHandler;
|
|
17
|
+
};
|
|
11
18
|
};
|
|
12
|
-
export declare function isOrganizationDirigeantFactory(config: IsOrganizationExecutiveFactoryFactoryConfig): (
|
|
19
|
+
export declare function isOrganizationDirigeantFactory(config: IsOrganizationExecutiveFactoryFactoryConfig): (organization: Organization, user_id: number) => Promise<{
|
|
20
|
+
details: {
|
|
21
|
+
identity: {
|
|
22
|
+
birthcountry: string | null;
|
|
23
|
+
birthdate: Date | null;
|
|
24
|
+
birthplace: string | null;
|
|
25
|
+
family_name: string | null;
|
|
26
|
+
gender: "male" | "female" | null;
|
|
27
|
+
given_name: string | null;
|
|
28
|
+
};
|
|
29
|
+
source: "api.insee.fr/api-sirene/private" | "entreprise.api.gouv.fr/v3/infogreffe/rcs/unites_legales/{siren}/mandataires_sociaux" | "registre-national-entreprises.inpi.fr/api";
|
|
30
|
+
dirigeant: {
|
|
31
|
+
birthcountry: string | null;
|
|
32
|
+
birthdate: Date | null;
|
|
33
|
+
birthplace: string | null;
|
|
34
|
+
family_name: string | null;
|
|
35
|
+
gender: "male" | "female" | null;
|
|
36
|
+
given_name: string | null;
|
|
37
|
+
};
|
|
38
|
+
score: number;
|
|
39
|
+
};
|
|
40
|
+
cause: "exact_match" | "close_match" | "below_threshold";
|
|
41
|
+
ok: boolean;
|
|
42
|
+
}>;
|
|
13
43
|
export type IsOrganizationDirigeantHandler = ReturnType<typeof isOrganizationDirigeantFactory>;
|
|
14
44
|
export {};
|
|
15
45
|
//# sourceMappingURL=is-organization-dirigeant.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"is-organization-dirigeant.d.ts","sourceRoot":"","sources":["../../../src/managers/certification/is-organization-dirigeant.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"is-organization-dirigeant.d.ts","sourceRoot":"","sources":["../../../src/managers/certification/is-organization-dirigeant.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,+BAA+B,EAAE,MAAM,wBAAwB,CAAC;AAC9E,OAAO,KAAK,EAAkB,YAAY,EAAE,MAAM,YAAY,CAAC;AAC/D,OAAO,KAAK,EAAE,iCAAiC,EAAE,MAAM,gDAAgD,CAAC;AACxG,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,uCAAuC,CAAC;AAC3F,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,+DAA+D,CAAC;AAWhH,KAAK,2CAA2C,GAAG;IACjD,iCAAiC,EAAE,IAAI,CACrC,iCAAiC,EACjC,+BAA+B,CAChC,CAAC;IACF,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,0BAA0B,EAAE;QAC1B,wBAAwB,EAAE,+BAA+B,CAAC;KAC3D,CAAC;IACF,kBAAkB,EAAE;QAAE,WAAW,EAAE,6BAA6B,CAAA;KAAE,CAAC;IACnE,wCAAwC,EAAE;QACxC,mBAAmB,EAAE,0BAA0B,CAAC;KACjD,CAAC;CACH,CAAC;AAqCF,wBAAgB,8BAA8B,CAC5C,MAAM,EAAE,2CAA2C,IAKjD,cAAc,YAAY,EAC1B,SAAS,MAAM;;;;;;;;;;;;;;;;;;;;;;;GA2ClB;AAED,MAAM,MAAM,8BAA8B,GAAG,UAAU,CACrD,OAAO,8BAA8B,CACtC,CAAC"}
|
|
@@ -1,60 +1,97 @@
|
|
|
1
1
|
//
|
|
2
|
-
import { NotFoundError } from "#src/errors";
|
|
3
|
-
import {
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
import
|
|
7
|
-
import
|
|
2
|
+
import { InvalidCertificationError, NotFoundError } from "#src/errors";
|
|
3
|
+
import { match } from "ts-pattern";
|
|
4
|
+
import z from "zod/v4";
|
|
5
|
+
import * as ApiEntreprise from "./adapters/api_entreprise.js";
|
|
6
|
+
import * as FranceConnect from "./adapters/franceconnect.js";
|
|
7
|
+
import * as INSEE from "./adapters/insee.js";
|
|
8
|
+
import * as RNE from "./adapters/rne.js";
|
|
9
|
+
import { certificationScore } from "./certification-score.js";
|
|
8
10
|
//
|
|
11
|
+
async function getMandatairesSociaux({ RegistreNationalEntreprisesApiRepository, ApiEntrepriseInfogreffeRepository, }, siren) {
|
|
12
|
+
try {
|
|
13
|
+
const pouvoirs = await RegistreNationalEntreprisesApiRepository.findPouvoirsBySiren(siren);
|
|
14
|
+
const dirigeants = pouvoirs.map(RNE.toIdentityVector);
|
|
15
|
+
return {
|
|
16
|
+
dirigeants,
|
|
17
|
+
source: SourceDirigeant.enum["registre-national-entreprises.inpi.fr/api"],
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
const mandataires = await ApiEntrepriseInfogreffeRepository.findMandatairesSociauxBySiren(siren);
|
|
22
|
+
const dirigeants = mandataires.map(ApiEntreprise.toIdentityVector);
|
|
23
|
+
return {
|
|
24
|
+
dirigeants,
|
|
25
|
+
source: SourceDirigeant.enum["entreprise.api.gouv.fr/v3/infogreffe/rcs/unites_legales/{siren}/mandataires_sociaux"],
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
}
|
|
9
29
|
export function isOrganizationDirigeantFactory(config) {
|
|
10
|
-
const {
|
|
11
|
-
return async function isOrganizationDirigeant(
|
|
12
|
-
const
|
|
13
|
-
const franceconnectUserInfo = await getFranceConnectUserInfo(user_id);
|
|
30
|
+
const { InseeApiRepository, FranceConnectApiRepository } = config;
|
|
31
|
+
return async function isOrganizationDirigeant(organization, user_id) {
|
|
32
|
+
const siren = organization.siret.substring(0, 9);
|
|
33
|
+
const franceconnectUserInfo = await FranceConnectApiRepository.getFranceConnectUserInfo(user_id);
|
|
14
34
|
if (!franceconnectUserInfo) {
|
|
15
35
|
throw new NotFoundError("FranceConnect UserInfo not found");
|
|
16
36
|
}
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
const birthdate = formatBirthdate(String(uniteLegale?.dateNaissanceUniteLegale));
|
|
40
|
-
return [
|
|
41
|
-
{
|
|
42
|
-
birthplace: uniteLegale?.codeCommuneNaissanceUniteLegale ?? null,
|
|
43
|
-
birthdate: isNaN(birthdate.getTime()) ? null : birthdate,
|
|
44
|
-
family_name: uniteLegale?.nomUniteLegale ?? null,
|
|
45
|
-
given_name: [
|
|
46
|
-
uniteLegale?.prenom1UniteLegale,
|
|
47
|
-
uniteLegale?.prenom2UniteLegale,
|
|
48
|
-
uniteLegale?.prenom3UniteLegale,
|
|
49
|
-
uniteLegale?.prenom4UniteLegale,
|
|
50
|
-
]
|
|
51
|
-
.filter(Boolean)
|
|
52
|
-
.join(" "),
|
|
37
|
+
const identity = FranceConnect.toIdentityVector(franceconnectUserInfo);
|
|
38
|
+
const prefered_source = organization.cached_libelle_categorie_juridique ===
|
|
39
|
+
"Entrepreneur individuel"
|
|
40
|
+
? SourceDirigeant.enum["api.insee.fr/api-sirene/private"]
|
|
41
|
+
: SourceDirigeant.enum["registre-national-entreprises.inpi.fr/api"];
|
|
42
|
+
const { dirigeants, source } = await match(prefered_source)
|
|
43
|
+
.with("api.insee.fr/api-sirene/private", async () => ({
|
|
44
|
+
dirigeants: await InseeApiRepository.findBySiren(siren)
|
|
45
|
+
.then(INSEE.toIdentityVector)
|
|
46
|
+
.then((vector) => [vector]),
|
|
47
|
+
source: SourceDirigeant.enum["api.insee.fr/api-sirene/private"],
|
|
48
|
+
}))
|
|
49
|
+
.with("registre-national-entreprises.inpi.fr/api", () => getMandatairesSociaux(config, siren))
|
|
50
|
+
.exhaustive();
|
|
51
|
+
const result = match_identity_to_dirigeant(identity, dirigeants);
|
|
52
|
+
if (result.kind === "no_candidates")
|
|
53
|
+
throw new InvalidCertificationError("No candidates found");
|
|
54
|
+
return {
|
|
55
|
+
details: {
|
|
56
|
+
...result.closest,
|
|
57
|
+
identity,
|
|
58
|
+
source,
|
|
53
59
|
},
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
+
cause: result.kind,
|
|
61
|
+
ok: result.kind === "exact_match",
|
|
62
|
+
};
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
const SourceDirigeant = z.enum([
|
|
66
|
+
"api.insee.fr/api-sirene/private",
|
|
67
|
+
"entreprise.api.gouv.fr/v3/infogreffe/rcs/unites_legales/{siren}/mandataires_sociaux",
|
|
68
|
+
"registre-national-entreprises.inpi.fr/api",
|
|
69
|
+
]);
|
|
70
|
+
function match_identity_to_dirigeant(identity, dirigeants) {
|
|
71
|
+
if (dirigeants.length === 0)
|
|
72
|
+
return { kind: "no_candidates" };
|
|
73
|
+
const [closest] = dirigeants
|
|
74
|
+
.map((dirigeant) => ({
|
|
75
|
+
dirigeant,
|
|
76
|
+
score: certificationScore(identity, dirigeant),
|
|
77
|
+
}))
|
|
78
|
+
.toSorted((a, b) => b.score - a.score); // Sort by score descending (higher is better)
|
|
79
|
+
// According to the specification, only score of 5 (perfect match) is certified
|
|
80
|
+
return match(closest.score)
|
|
81
|
+
.with(5, () => ({
|
|
82
|
+
kind: "exact_match",
|
|
83
|
+
closest,
|
|
84
|
+
}))
|
|
85
|
+
.with(4, () => ({
|
|
86
|
+
kind: "close_match",
|
|
87
|
+
closest,
|
|
88
|
+
}))
|
|
89
|
+
.with(3, () => ({
|
|
90
|
+
kind: "close_match",
|
|
91
|
+
closest,
|
|
92
|
+
}))
|
|
93
|
+
.otherwise(() => ({
|
|
94
|
+
kind: "below_threshold",
|
|
95
|
+
closest,
|
|
96
|
+
}));
|
|
60
97
|
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Normalizes text for identity matching:
|
|
3
|
+
* - Convert to uppercase
|
|
4
|
+
* - Replace accented characters with their simple versions
|
|
5
|
+
* - Replace special characters (including ' and -) with spaces
|
|
6
|
+
* - Remove multiple consecutive spaces
|
|
7
|
+
* - Trim leading and trailing spaces
|
|
8
|
+
*
|
|
9
|
+
* @param text - The text to normalize
|
|
10
|
+
* @returns The normalized text
|
|
11
|
+
*/
|
|
12
|
+
export declare function normalizeText(text: string | null | undefined): string;
|
|
13
|
+
/**
|
|
14
|
+
* Extracts the first name from a normalized full name string.
|
|
15
|
+
* The first name is the part before the first space.
|
|
16
|
+
*
|
|
17
|
+
* @param givenName - The full given name (may contain multiple names)
|
|
18
|
+
* @returns The first name only
|
|
19
|
+
*/
|
|
20
|
+
export declare function extractFirstName(givenName: string | null | undefined): string;
|
|
21
|
+
//# sourceMappingURL=normalize.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"normalize.d.ts","sourceRoot":"","sources":["../../../src/managers/certification/normalize.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CA2CrE;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAM7E"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
//
|
|
2
|
+
/**
|
|
3
|
+
* Normalizes text for identity matching:
|
|
4
|
+
* - Convert to uppercase
|
|
5
|
+
* - Replace accented characters with their simple versions
|
|
6
|
+
* - Replace special characters (including ' and -) with spaces
|
|
7
|
+
* - Remove multiple consecutive spaces
|
|
8
|
+
* - Trim leading and trailing spaces
|
|
9
|
+
*
|
|
10
|
+
* @param text - The text to normalize
|
|
11
|
+
* @returns The normalized text
|
|
12
|
+
*/
|
|
13
|
+
export function normalizeText(text) {
|
|
14
|
+
if (!text)
|
|
15
|
+
return "";
|
|
16
|
+
// Convert to uppercase
|
|
17
|
+
let normalized = text.toUpperCase();
|
|
18
|
+
// Replace accented characters with their simple versions
|
|
19
|
+
const accentMap = {
|
|
20
|
+
À: "A",
|
|
21
|
+
Â: "A",
|
|
22
|
+
Ä: "A",
|
|
23
|
+
Ç: "C",
|
|
24
|
+
É: "E",
|
|
25
|
+
È: "E",
|
|
26
|
+
Ê: "E",
|
|
27
|
+
Ë: "E",
|
|
28
|
+
Î: "I",
|
|
29
|
+
Ï: "I",
|
|
30
|
+
Ô: "O",
|
|
31
|
+
Ö: "O",
|
|
32
|
+
Ù: "U",
|
|
33
|
+
Û: "U",
|
|
34
|
+
Ü: "U",
|
|
35
|
+
Ÿ: "Y",
|
|
36
|
+
Æ: "AE",
|
|
37
|
+
Œ: "OE",
|
|
38
|
+
};
|
|
39
|
+
for (const [accented, simple] of Object.entries(accentMap)) {
|
|
40
|
+
normalized = normalized.replaceAll(accented, simple);
|
|
41
|
+
}
|
|
42
|
+
// Replace special characters (including ' and -) with spaces
|
|
43
|
+
// Keep only letters, digits, and spaces
|
|
44
|
+
normalized = normalized.replace(/[^A-Z0-9 ]/g, " ");
|
|
45
|
+
// Remove multiple consecutive spaces
|
|
46
|
+
normalized = normalized.replace(/\s+/g, " ");
|
|
47
|
+
// Trim leading and trailing spaces
|
|
48
|
+
normalized = normalized.trim();
|
|
49
|
+
return normalized;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Extracts the first name from a normalized full name string.
|
|
53
|
+
* The first name is the part before the first space.
|
|
54
|
+
*
|
|
55
|
+
* @param givenName - The full given name (may contain multiple names)
|
|
56
|
+
* @returns The first name only
|
|
57
|
+
*/
|
|
58
|
+
export function extractFirstName(givenName) {
|
|
59
|
+
if (!givenName)
|
|
60
|
+
return "";
|
|
61
|
+
const normalized = normalizeText(givenName);
|
|
62
|
+
const parts = normalized.split(" ");
|
|
63
|
+
return parts[0] || "";
|
|
64
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"openid-client.d.ts","sourceRoot":"","sources":["../../../src/managers/franceconnect/openid-client.ts"],"names":[],"mappings":"AAMA,OAAO,EAUL,KAAK,cAAc,EACpB,MAAM,eAAe,CAAC;AAKvB,MAAM,MAAM,gCAAgC,GAAG;IAC7C,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC;IAClC,MAAM,EAAE,GAAG,CAAC;CACb,CAAC;AAEF,wBAAgB,oCAAoC,CAClD,MAAM,EAAE,gCAAgC,wDAYzC;AAED,MAAM,MAAM,oCAAoC,GAAG,UAAU,CAC3D,OAAO,oCAAoC,CAC5C,CAAC;AAEF,wBAAgB,gBAAgB;;;EAK/B;AAED,wBAAgB,kCAAkC,CAChD,gBAAgB,EAAE,oCAAoC,EACtD,UAAU,EAAE;IACV,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;CACf,IAG0C,OAAO,MAAM,EAAE,OAAO,MAAM,kBAaxE;AAED,wBAAgB,2BAA2B,CACzC,gBAAgB,EAAE,oCAAoC,IAEX,YAAY;IACrD,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,GAAG,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;CACvB
|
|
1
|
+
{"version":3,"file":"openid-client.d.ts","sourceRoot":"","sources":["../../../src/managers/franceconnect/openid-client.ts"],"names":[],"mappings":"AAMA,OAAO,EAUL,KAAK,cAAc,EACpB,MAAM,eAAe,CAAC;AAKvB,MAAM,MAAM,gCAAgC,GAAG;IAC7C,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC;IAClC,MAAM,EAAE,GAAG,CAAC;CACb,CAAC;AAEF,wBAAgB,oCAAoC,CAClD,MAAM,EAAE,gCAAgC,wDAYzC;AAED,MAAM,MAAM,oCAAoC,GAAG,UAAU,CAC3D,OAAO,oCAAoC,CAC5C,CAAC;AAEF,wBAAgB,gBAAgB;;;EAK/B;AAED,wBAAgB,kCAAkC,CAChD,gBAAgB,EAAE,oCAAoC,EACtD,UAAU,EAAE;IACV,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;CACf,IAG0C,OAAO,MAAM,EAAE,OAAO,MAAM,kBAaxE;AAED,wBAAgB,2BAA2B,CACzC,gBAAgB,EAAE,oCAAoC,IAEX,YAAY;IACrD,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,GAAG,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;CACvB;;;;;;;;;;;;GA0BF;AAED,wBAAgB,wCAAwC,CACtD,gBAAgB,EAAE,oCAAoC,IAGpD,eAAe,MAAM,EACrB,0BAA0B,MAAM,EAChC,OAAO,MAAM,kBAShB"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import "#src/types";
|
|
2
|
+
import { type OrganizationInfo } from "#src/types";
|
|
3
|
+
import type { InseeSireneEstablishmentSiretResponseData } from "@proconnect-gouv/proconnect.api_entreprise/types";
|
|
4
|
+
export declare function toOrganizationInfo(siretData: InseeSireneEstablishmentSiretResponseData): OrganizationInfo;
|
|
5
|
+
export declare function toPartialOrganization(organization_info: OrganizationInfo): {
|
|
6
|
+
cached_activite_principale: string;
|
|
7
|
+
cached_adresse: string;
|
|
8
|
+
cached_categorie_juridique: string;
|
|
9
|
+
cached_code_officiel_geographique: string;
|
|
10
|
+
cached_code_postal: string | null;
|
|
11
|
+
cached_enseigne: string;
|
|
12
|
+
cached_est_active: boolean;
|
|
13
|
+
cached_est_diffusible: boolean;
|
|
14
|
+
cached_etat_administratif: string;
|
|
15
|
+
cached_libelle_activite_principale: string;
|
|
16
|
+
cached_libelle_categorie_juridique: string;
|
|
17
|
+
cached_libelle_tranche_effectif: string;
|
|
18
|
+
cached_libelle: string;
|
|
19
|
+
cached_nom_complet: string;
|
|
20
|
+
cached_statut_diffusion: "diffusible" | "partiellement_diffusible" | "non_diffusible";
|
|
21
|
+
cached_tranche_effectifs_unite_legale: string | null;
|
|
22
|
+
cached_tranche_effectifs: "NN" | "00" | "01" | "02" | "03" | "11" | "12" | "21" | "22" | "31" | "32" | "41" | "42" | "51" | "52" | "53" | null;
|
|
23
|
+
siret: string;
|
|
24
|
+
};
|
|
25
|
+
//# sourceMappingURL=api_entreprise.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api_entreprise.d.ts","sourceRoot":"","sources":["../../../../src/managers/organization/adapters/api_entreprise.ts"],"names":[],"mappings":"AAEA,OAAO,YAAY,CAAC;AACpB,OAAO,EAGL,KAAK,gBAAgB,EACtB,MAAM,YAAY,CAAC;AAOpB,OAAO,KAAK,EAAE,yCAAyC,EAAE,MAAM,kDAAkD,CAAC;AAKlH,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,yCAAyC,GACnD,gBAAgB,CAyDlB;AAED,wBAAgB,qBAAqB,CAAC,iBAAiB,EAAE,gBAAgB;;;;;;;;;;;;;;;;;;;EA4CxE"}
|
package/dist/{mappers/organization/from-siret.js → managers/organization/adapters/api_entreprise.js}
RENAMED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
//
|
|
2
2
|
import "#src/types";
|
|
3
|
-
import { OrganizationInfoSchema } from "#src/types";
|
|
3
|
+
import { OrganizationInfoSchema, } from "#src/types";
|
|
4
4
|
import { formatAddress, formatMainActivity, formatNomComplet, libelleFromCodeEffectif, } from "@proconnect-gouv/proconnect.api_entreprise/formatters";
|
|
5
5
|
import { capitalize } from "lodash-es";
|
|
6
6
|
//
|
|
7
|
-
export function
|
|
7
|
+
export function toOrganizationInfo(siretData) {
|
|
8
8
|
const isPartiallyNonDiffusible = siretData.status_diffusion === "partiellement_diffusible";
|
|
9
9
|
const enseigne = siretData.enseigne ?? "";
|
|
10
10
|
const nomComplet = isPartiallyNonDiffusible
|
|
@@ -49,3 +49,26 @@ export function fromSiret(siretData) {
|
|
|
49
49
|
trancheEffectifsUniteLegale,
|
|
50
50
|
});
|
|
51
51
|
}
|
|
52
|
+
export function toPartialOrganization(organization_info) {
|
|
53
|
+
const { activitePrincipale: cached_activite_principale, adresse: cached_adresse, categorieJuridique: cached_categorie_juridique, codeOfficielGeographique: cached_code_officiel_geographique, codePostal: cached_code_postal, enseigne: cached_enseigne, estActive: cached_est_active, estDiffusible: cached_est_diffusible, etatAdministratif: cached_etat_administratif, libelle: cached_libelle, libelleActivitePrincipale: cached_libelle_activite_principale, libelleCategorieJuridique: cached_libelle_categorie_juridique, libelleTrancheEffectif: cached_libelle_tranche_effectif, nomComplet: cached_nom_complet, siret, statutDiffusion: cached_statut_diffusion, trancheEffectifs: cached_tranche_effectifs, trancheEffectifsUniteLegale: cached_tranche_effectifs_unite_legale, } = organization_info;
|
|
54
|
+
return {
|
|
55
|
+
cached_activite_principale,
|
|
56
|
+
cached_adresse,
|
|
57
|
+
cached_categorie_juridique,
|
|
58
|
+
cached_code_officiel_geographique,
|
|
59
|
+
cached_code_postal,
|
|
60
|
+
cached_enseigne,
|
|
61
|
+
cached_est_active,
|
|
62
|
+
cached_est_diffusible,
|
|
63
|
+
cached_etat_administratif,
|
|
64
|
+
cached_libelle_activite_principale,
|
|
65
|
+
cached_libelle_categorie_juridique,
|
|
66
|
+
cached_libelle_tranche_effectif,
|
|
67
|
+
cached_libelle,
|
|
68
|
+
cached_nom_complet,
|
|
69
|
+
cached_statut_diffusion,
|
|
70
|
+
cached_tranche_effectifs_unite_legale,
|
|
71
|
+
cached_tranche_effectifs,
|
|
72
|
+
siret,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"get-organization-info.d.ts","sourceRoot":"","sources":["../../../src/managers/organization/get-organization-info.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"get-organization-info.d.ts","sourceRoot":"","sources":["../../../src/managers/organization/get-organization-info.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,YAAY,CAAC;AACnD,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,gDAAgD,CAAC;AASnG,wBAAgB,0BAA0B,CACxC,MAAM,EAAE,4BAA4B,IAKlC,cAAc,MAAM,KACnB,OAAO,CAAC,gBAAgB,CAAC,CAiC7B;AAED,MAAM,MAAM,0BAA0B,GAAG,UAAU,CACjD,OAAO,0BAA0B,CAClC,CAAC"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
//
|
|
2
2
|
import { InvalidSiretError, NotFoundError } from "#src/errors";
|
|
3
|
-
import { OrganizationInfoMapper } from "#src/mappers";
|
|
4
3
|
import {} from "#src/types";
|
|
5
4
|
import { ApiEntrepriseConnectionError, ApiEntrepriseInvalidSiret, } from "@proconnect-gouv/proconnect.api_entreprise/types";
|
|
5
|
+
import * as ApiEntreprise from "./adapters/api_entreprise.js";
|
|
6
6
|
//
|
|
7
7
|
export function getOrganizationInfoFactory(config) {
|
|
8
8
|
const { findBySiren, findBySiret } = config;
|
|
@@ -10,10 +10,10 @@ export function getOrganizationInfoFactory(config) {
|
|
|
10
10
|
try {
|
|
11
11
|
let establishment;
|
|
12
12
|
if (siretOrSiren.match(/^\d{14}$/)) {
|
|
13
|
-
establishment =
|
|
13
|
+
establishment = ApiEntreprise.toOrganizationInfo(await findBySiret(siretOrSiren));
|
|
14
14
|
}
|
|
15
15
|
else if (siretOrSiren.match(/^\d{9}$/)) {
|
|
16
|
-
establishment =
|
|
16
|
+
establishment = ApiEntreprise.toOrganizationInfo(await findBySiren(siretOrSiren));
|
|
17
17
|
}
|
|
18
18
|
else {
|
|
19
19
|
throw new InvalidSiretError();
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { DatabaseContext, Organization, OrganizationInfo } from "#src/types";
|
|
2
|
-
export declare function upsertFactory({ pg }: DatabaseContext): ({ siret, organizationInfo
|
|
2
|
+
export declare function upsertFactory({ pg }: DatabaseContext): ({ siret, organizationInfo, }: {
|
|
3
3
|
siret: string;
|
|
4
4
|
organizationInfo: OrganizationInfo;
|
|
5
5
|
}) => Promise<Organization>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"upsert.d.ts","sourceRoot":"","sources":["../../../src/repositories/organization/upsert.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,eAAe,EACf,YAAY,EACZ,gBAAgB,EACjB,MAAM,YAAY,CAAC;AAKpB,wBAAgB,aAAa,CAAC,EAAE,EAAE,EAAE,EAAE,eAAe,IACtB,
|
|
1
|
+
{"version":3,"file":"upsert.d.ts","sourceRoot":"","sources":["../../../src/repositories/organization/upsert.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,eAAe,EACf,YAAY,EACZ,gBAAgB,EACjB,MAAM,YAAY,CAAC;AAKpB,wBAAgB,aAAa,CAAC,EAAE,EAAE,EAAE,EAAE,eAAe,IACtB,8BAG1B;IACD,KAAK,EAAE,MAAM,CAAC;IACd,gBAAgB,EAAE,gBAAgB,CAAC;CACpC,2BA2HF;AAED,MAAM,MAAM,aAAa,GAAG,UAAU,CAAC,OAAO,aAAa,CAAC,CAAC"}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
//
|
|
2
2
|
//
|
|
3
3
|
export function upsertFactory({ pg }) {
|
|
4
|
-
return async function upsert({ siret, organizationInfo
|
|
4
|
+
return async function upsert({ siret, organizationInfo, }) {
|
|
5
|
+
const { cached_libelle, cached_nom_complet, cached_enseigne, cached_tranche_effectifs, cached_tranche_effectifs_unite_legale, cached_libelle_tranche_effectif, cached_etat_administratif, cached_est_active, cached_statut_diffusion, cached_est_diffusible, cached_adresse, cached_code_postal, cached_code_officiel_geographique, cached_activite_principale, cached_libelle_activite_principale, cached_categorie_juridique, cached_libelle_categorie_juridique, } = toPartialOrganization(organizationInfo);
|
|
5
6
|
const { rows } = await pg.query(`
|
|
6
7
|
INSERT INTO organizations
|
|
7
8
|
(
|
|
@@ -101,3 +102,27 @@ export function upsertFactory({ pg }) {
|
|
|
101
102
|
return rows.shift();
|
|
102
103
|
};
|
|
103
104
|
}
|
|
105
|
+
//
|
|
106
|
+
function toPartialOrganization(organization_info) {
|
|
107
|
+
const { activitePrincipale: cached_activite_principale, adresse: cached_adresse, categorieJuridique: cached_categorie_juridique, codeOfficielGeographique: cached_code_officiel_geographique, codePostal: cached_code_postal, enseigne: cached_enseigne, estActive: cached_est_active, estDiffusible: cached_est_diffusible, etatAdministratif: cached_etat_administratif, libelle: cached_libelle, libelleActivitePrincipale: cached_libelle_activite_principale, libelleCategorieJuridique: cached_libelle_categorie_juridique, libelleTrancheEffectif: cached_libelle_tranche_effectif, nomComplet: cached_nom_complet, siret, statutDiffusion: cached_statut_diffusion, trancheEffectifs: cached_tranche_effectifs, trancheEffectifsUniteLegale: cached_tranche_effectifs_unite_legale, } = organization_info;
|
|
108
|
+
return {
|
|
109
|
+
cached_activite_principale,
|
|
110
|
+
cached_adresse,
|
|
111
|
+
cached_categorie_juridique,
|
|
112
|
+
cached_code_officiel_geographique,
|
|
113
|
+
cached_code_postal,
|
|
114
|
+
cached_enseigne,
|
|
115
|
+
cached_est_active,
|
|
116
|
+
cached_est_diffusible,
|
|
117
|
+
cached_etat_administratif,
|
|
118
|
+
cached_libelle_activite_principale,
|
|
119
|
+
cached_libelle_categorie_juridique,
|
|
120
|
+
cached_libelle_tranche_effectif,
|
|
121
|
+
cached_libelle,
|
|
122
|
+
cached_nom_complet,
|
|
123
|
+
cached_statut_diffusion,
|
|
124
|
+
cached_tranche_effectifs_unite_legale,
|
|
125
|
+
cached_tranche_effectifs,
|
|
126
|
+
siret,
|
|
127
|
+
};
|
|
128
|
+
}
|