@proconnect-gouv/proconnect.identite 1.2.0 → 1.3.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 +8 -0
- package/README.md +0 -2
- package/dist/data/certification/categories-juridiques-sources.d.ts +8 -0
- package/dist/data/certification/categories-juridiques-sources.d.ts.map +1 -0
- package/dist/data/certification/categories-juridiques-sources.js +743 -0
- package/dist/data/certification/index.d.ts +1 -0
- package/dist/data/certification/index.d.ts.map +1 -1
- package/dist/data/certification/index.js +1 -0
- package/dist/errors/index.d.ts +0 -9
- package/dist/errors/index.d.ts.map +1 -1
- package/dist/errors/index.js +0 -18
- package/dist/managers/certification/certification-score.d.ts +11 -1
- package/dist/managers/certification/certification-score.d.ts.map +1 -1
- package/dist/managers/certification/certification-score.js +17 -8
- 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/process-certification-dirigeant.d.ts +80 -0
- package/dist/managers/certification/process-certification-dirigeant.d.ts.map +1 -0
- package/dist/managers/certification/process-certification-dirigeant.js +121 -0
- package/dist/managers/organization/adapters/api_entreprise.d.ts +2 -1
- package/dist/managers/organization/adapters/api_entreprise.d.ts.map +1 -1
- package/dist/managers/organization/adapters/api_entreprise.js +3 -1
- package/dist/managers/organization/force-join-organization.d.ts +1 -1
- package/dist/managers/organization/force-join-organization.d.ts.map +1 -1
- package/dist/managers/organization/force-join-organization.js +3 -4
- package/dist/managers/user/assign-user-verification-type-to-domain.d.ts.map +1 -1
- package/dist/managers/user/assign-user-verification-type-to-domain.js +6 -6
- package/dist/repositories/organization/find-by-user-id.d.ts +1 -1
- package/dist/repositories/organization/get-users-by-organization.d.ts +1 -1
- package/dist/repositories/organization/link-user-to-organization.d.ts +1 -1
- package/dist/repositories/organization/upsert.d.ts.map +1 -1
- package/dist/repositories/organization/upsert.js +8 -3
- package/dist/repositories/user/update-user-organization-link.d.ts +1 -1
- package/dist/services/organization/index.d.ts +1 -0
- package/dist/services/organization/index.d.ts.map +1 -1
- package/dist/services/organization/index.js +1 -0
- package/dist/services/organization/is-entreprise-unipersonnelle.d.ts +3 -3
- package/dist/services/organization/is-entreprise-unipersonnelle.d.ts.map +1 -1
- package/dist/services/organization/is-entreprise-unipersonnelle.js +4 -4
- package/dist/services/organization/is-organization-covered-by-certification-dirigeant.d.ts +3 -0
- package/dist/services/organization/is-organization-covered-by-certification-dirigeant.d.ts.map +1 -0
- package/dist/services/organization/is-organization-covered-by-certification-dirigeant.js +2 -0
- package/dist/services/organization/is-public-service.d.ts.map +1 -1
- package/dist/services/organization/is-public-service.js +16 -6
- package/dist/services/organization/is-syndicat-communal.d.ts.map +1 -1
- package/dist/services/organization/is-syndicat-communal.js +1 -0
- package/dist/types/franceconnect.d.ts.map +1 -1
- package/dist/types/franceconnect.js +2 -2
- package/dist/types/{dirigeant.d.ts → identity-vector.d.ts} +2 -1
- package/dist/types/identity-vector.d.ts.map +1 -0
- package/dist/types/{dirigeant.js → identity-vector.js} +8 -0
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +1 -1
- package/dist/types/organization-info.d.ts +2 -1
- package/dist/types/organization-info.d.ts.map +1 -1
- package/dist/types/organization-info.js +1 -0
- package/dist/types/organization.d.ts +1 -0
- package/dist/types/organization.d.ts.map +1 -1
- package/dist/types/user-organization-link.d.ts +31 -24
- package/dist/types/user-organization-link.d.ts.map +1 -1
- package/dist/types/user-organization-link.js +15 -8
- package/package.json +2 -2
- package/src/data/certification/categories-juridiques-sources.ts +811 -0
- package/src/data/certification/index.ts +1 -0
- package/src/errors/index.ts +0 -21
- package/src/managers/certification/certification-score.test.ts +69 -33
- package/src/managers/certification/certification-score.ts +20 -9
- package/src/managers/certification/index.ts +1 -1
- package/src/managers/certification/{is-organization-dirigeant.test.ts → process-certification-dirigeant.test.ts} +62 -64
- package/src/managers/certification/{is-organization-dirigeant.ts → process-certification-dirigeant.ts} +115 -74
- package/src/managers/organization/adapters/api_entreprise.test.ts.snapshot +4 -0
- package/src/managers/organization/adapters/api_entreprise.ts +3 -0
- package/src/managers/organization/force-join-organization.ts +3 -6
- package/src/managers/organization/get-organization-info.test.ts.snapshot +3 -0
- package/src/managers/organization/mark-domain-as-verified.test.ts +1 -1
- package/src/managers/user/assign-user-verification-type-to-domain.ts +6 -6
- package/src/repositories/organization/find-by-id.test.ts +1 -0
- package/src/repositories/organization/find-by-user-id.test.ts.snapshot +3 -0
- package/src/repositories/organization/get-by-id.test.ts +1 -0
- package/src/repositories/organization/link-user-to-organization.test.ts +3 -2
- package/src/repositories/organization/link-user-to-organization.test.ts.snapshot +2 -2
- package/src/repositories/organization/upsert.ts +8 -1
- package/src/repositories/organization/upset.test.ts +2 -0
- package/src/services/organization/index.ts +1 -0
- package/src/services/organization/is-entreprise-unipersonnelle.ts +5 -5
- package/src/services/organization/is-organization-covered-by-certification-dirigeant.test.ts +43 -0
- package/src/services/organization/is-organization-covered-by-certification-dirigeant.ts +9 -0
- package/src/services/organization/is-public-service.test.ts +1 -1
- package/src/services/organization/is-public-service.ts +20 -7
- package/src/services/organization/is-syndicat-communal.ts +1 -0
- package/src/types/franceconnect.ts +6 -7
- package/src/types/{dirigeant.ts → identity-vector.ts} +9 -0
- package/src/types/index.ts +1 -1
- package/src/types/organization-info.ts +1 -0
- package/src/types/organization.ts +1 -0
- package/src/types/user-organization-link.ts +17 -11
- package/tsconfig.lib.tsbuildinfo +1 -1
- package/dist/managers/certification/is-organization-dirigeant.d.ts +0 -45
- package/dist/managers/certification/is-organization-dirigeant.d.ts.map +0 -1
- package/dist/managers/certification/is-organization-dirigeant.js +0 -97
- package/dist/types/dirigeant.d.ts.map +0 -1
package/src/errors/index.ts
CHANGED
|
@@ -1,12 +1,5 @@
|
|
|
1
1
|
//
|
|
2
2
|
|
|
3
|
-
export class InvalidCertificationError extends Error {
|
|
4
|
-
constructor(message?: string, options?: ErrorOptions) {
|
|
5
|
-
super(message, options);
|
|
6
|
-
this.name = "InvalidCertificationError";
|
|
7
|
-
}
|
|
8
|
-
}
|
|
9
|
-
|
|
10
3
|
export class InvalidSiretError extends Error {
|
|
11
4
|
constructor(message?: string, options?: ErrorOptions) {
|
|
12
5
|
super(message, options);
|
|
@@ -21,13 +14,6 @@ export class NotFoundError extends Error {
|
|
|
21
14
|
}
|
|
22
15
|
}
|
|
23
16
|
|
|
24
|
-
export class OrganizationNotActiveError extends Error {
|
|
25
|
-
constructor(message?: string, options?: ErrorOptions) {
|
|
26
|
-
super(message, options);
|
|
27
|
-
this.name = "OrganizationNotActiveError";
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
17
|
export class OrganizationNotFoundError extends Error {
|
|
32
18
|
constructor(message?: string, options?: ErrorOptions) {
|
|
33
19
|
super(message, options);
|
|
@@ -41,10 +27,3 @@ export class UserNotFoundError extends Error {
|
|
|
41
27
|
this.name = "UserNotFoundError";
|
|
42
28
|
}
|
|
43
29
|
}
|
|
44
|
-
|
|
45
|
-
export class ModerationNotFoundError extends Error {
|
|
46
|
-
constructor(message?: string, options?: ErrorOptions) {
|
|
47
|
-
super(message, options);
|
|
48
|
-
this.name = "ModerationNotFoundError";
|
|
49
|
-
}
|
|
50
|
-
}
|
|
@@ -9,7 +9,7 @@ import { certificationScore } from "./certification-score.js";
|
|
|
9
9
|
describe("certification scoring", () => {
|
|
10
10
|
it("perfect match - all 5 criteria", () => {
|
|
11
11
|
// All criteria match: family name, first name, gender, birthdate, birthplace
|
|
12
|
-
assert.
|
|
12
|
+
assert.deepStrictEqual(
|
|
13
13
|
certificationScore(
|
|
14
14
|
{
|
|
15
15
|
birthcountry: null,
|
|
@@ -28,13 +28,19 @@ describe("certification scoring", () => {
|
|
|
28
28
|
given_name: "Stéphane",
|
|
29
29
|
},
|
|
30
30
|
),
|
|
31
|
-
|
|
31
|
+
new Set([
|
|
32
|
+
"family_name",
|
|
33
|
+
"first_name",
|
|
34
|
+
"gender",
|
|
35
|
+
"birth_date",
|
|
36
|
+
"birth_place",
|
|
37
|
+
]),
|
|
32
38
|
);
|
|
33
39
|
});
|
|
34
40
|
|
|
35
41
|
it("family name mismatch", () => {
|
|
36
|
-
// Different family name =
|
|
37
|
-
assert.
|
|
42
|
+
// Different family name = missing family_name
|
|
43
|
+
assert.deepStrictEqual(
|
|
38
44
|
certificationScore(
|
|
39
45
|
{
|
|
40
46
|
birthcountry: null,
|
|
@@ -53,13 +59,13 @@ describe("certification scoring", () => {
|
|
|
53
59
|
given_name: "Stéphane",
|
|
54
60
|
},
|
|
55
61
|
),
|
|
56
|
-
|
|
62
|
+
new Set(["first_name", "gender", "birth_date", "birth_place"]),
|
|
57
63
|
);
|
|
58
64
|
});
|
|
59
65
|
|
|
60
66
|
it("different birthdate", () => {
|
|
61
|
-
// Different birthdate =
|
|
62
|
-
assert.
|
|
67
|
+
// Different birthdate = missing birth_date
|
|
68
|
+
assert.deepStrictEqual(
|
|
63
69
|
certificationScore(
|
|
64
70
|
{
|
|
65
71
|
birthcountry: null,
|
|
@@ -78,13 +84,13 @@ describe("certification scoring", () => {
|
|
|
78
84
|
given_name: "Stéphane",
|
|
79
85
|
},
|
|
80
86
|
),
|
|
81
|
-
|
|
87
|
+
new Set(["family_name", "first_name", "gender", "birth_place"]),
|
|
82
88
|
);
|
|
83
89
|
});
|
|
84
90
|
|
|
85
91
|
it("different birthplace", () => {
|
|
86
|
-
// Different birthplace =
|
|
87
|
-
assert.
|
|
92
|
+
// Different birthplace = missing birth_place
|
|
93
|
+
assert.deepStrictEqual(
|
|
88
94
|
certificationScore(
|
|
89
95
|
{
|
|
90
96
|
birthcountry: null,
|
|
@@ -103,13 +109,13 @@ describe("certification scoring", () => {
|
|
|
103
109
|
given_name: "Stéphane",
|
|
104
110
|
},
|
|
105
111
|
),
|
|
106
|
-
|
|
112
|
+
new Set(["family_name", "first_name", "gender", "birth_date"]),
|
|
107
113
|
);
|
|
108
114
|
});
|
|
109
115
|
|
|
110
116
|
it("swapped first and family names", () => {
|
|
111
|
-
// Both names don't match =
|
|
112
|
-
assert.
|
|
117
|
+
// Both names don't match = missing both name criteria
|
|
118
|
+
assert.deepStrictEqual(
|
|
113
119
|
certificationScore(
|
|
114
120
|
{
|
|
115
121
|
birthcountry: null,
|
|
@@ -128,13 +134,13 @@ describe("certification scoring", () => {
|
|
|
128
134
|
given_name: "Stéphane",
|
|
129
135
|
},
|
|
130
136
|
),
|
|
131
|
-
|
|
137
|
+
new Set(["gender", "birth_date", "birth_place"]),
|
|
132
138
|
);
|
|
133
139
|
});
|
|
134
140
|
|
|
135
141
|
it("different gender still matches when source gender is null", () => {
|
|
136
|
-
// Gender is null in source = still gets
|
|
137
|
-
assert.
|
|
142
|
+
// Gender is null in source = still gets gender match
|
|
143
|
+
assert.deepStrictEqual(
|
|
138
144
|
certificationScore(
|
|
139
145
|
{
|
|
140
146
|
birthcountry: null,
|
|
@@ -153,13 +159,19 @@ describe("certification scoring", () => {
|
|
|
153
159
|
given_name: "Stéphane",
|
|
154
160
|
},
|
|
155
161
|
),
|
|
156
|
-
|
|
162
|
+
new Set([
|
|
163
|
+
"family_name",
|
|
164
|
+
"first_name",
|
|
165
|
+
"gender",
|
|
166
|
+
"birth_date",
|
|
167
|
+
"birth_place",
|
|
168
|
+
]),
|
|
157
169
|
);
|
|
158
170
|
});
|
|
159
171
|
|
|
160
172
|
it("different gender when source has gender", () => {
|
|
161
|
-
// Different gender =
|
|
162
|
-
assert.
|
|
173
|
+
// Different gender = missing gender
|
|
174
|
+
assert.deepStrictEqual(
|
|
163
175
|
certificationScore(
|
|
164
176
|
{
|
|
165
177
|
birthcountry: null,
|
|
@@ -178,13 +190,13 @@ describe("certification scoring", () => {
|
|
|
178
190
|
given_name: "Stéphane",
|
|
179
191
|
},
|
|
180
192
|
),
|
|
181
|
-
|
|
193
|
+
new Set(["family_name", "first_name", "birth_date", "birth_place"]),
|
|
182
194
|
);
|
|
183
195
|
});
|
|
184
196
|
|
|
185
197
|
it("matches first name with hyphen normalization", () => {
|
|
186
|
-
// Jean-Pierre and Jean
|
|
187
|
-
assert.
|
|
198
|
+
// Jean-Pierre and Jean Marc should match (first name is "Jean")
|
|
199
|
+
assert.deepStrictEqual(
|
|
188
200
|
certificationScore(
|
|
189
201
|
{
|
|
190
202
|
birthcountry: null,
|
|
@@ -203,13 +215,19 @@ describe("certification scoring", () => {
|
|
|
203
215
|
given_name: "Jean Marc",
|
|
204
216
|
},
|
|
205
217
|
),
|
|
206
|
-
|
|
218
|
+
new Set([
|
|
219
|
+
"family_name",
|
|
220
|
+
"first_name",
|
|
221
|
+
"gender",
|
|
222
|
+
"birth_date",
|
|
223
|
+
"birth_place",
|
|
224
|
+
]),
|
|
207
225
|
);
|
|
208
226
|
});
|
|
209
227
|
|
|
210
228
|
it("birthplace with commune code conversion", () => {
|
|
211
229
|
// 75050 should convert to 92050
|
|
212
|
-
assert.
|
|
230
|
+
assert.deepStrictEqual(
|
|
213
231
|
certificationScore(
|
|
214
232
|
{
|
|
215
233
|
birthcountry: null,
|
|
@@ -228,13 +246,19 @@ describe("certification scoring", () => {
|
|
|
228
246
|
given_name: "Stéphane",
|
|
229
247
|
},
|
|
230
248
|
),
|
|
231
|
-
|
|
249
|
+
new Set([
|
|
250
|
+
"family_name",
|
|
251
|
+
"first_name",
|
|
252
|
+
"gender",
|
|
253
|
+
"birth_date",
|
|
254
|
+
"birth_place",
|
|
255
|
+
]),
|
|
232
256
|
);
|
|
233
257
|
});
|
|
234
258
|
|
|
235
259
|
it("null birthplace in source still matches", () => {
|
|
236
|
-
// Null birthplace in source = still gets
|
|
237
|
-
assert.
|
|
260
|
+
// Null birthplace in source = still gets birth_place match
|
|
261
|
+
assert.deepStrictEqual(
|
|
238
262
|
certificationScore(
|
|
239
263
|
{
|
|
240
264
|
birthcountry: null,
|
|
@@ -253,13 +277,19 @@ describe("certification scoring", () => {
|
|
|
253
277
|
given_name: "Stéphane",
|
|
254
278
|
},
|
|
255
279
|
),
|
|
256
|
-
|
|
280
|
+
new Set([
|
|
281
|
+
"family_name",
|
|
282
|
+
"first_name",
|
|
283
|
+
"gender",
|
|
284
|
+
"birth_date",
|
|
285
|
+
"birth_place",
|
|
286
|
+
]),
|
|
257
287
|
);
|
|
258
288
|
});
|
|
259
289
|
|
|
260
290
|
it("foreign person with matching country", () => {
|
|
261
291
|
// For foreigners, check country code
|
|
262
|
-
assert.
|
|
292
|
+
assert.deepStrictEqual(
|
|
263
293
|
certificationScore(
|
|
264
294
|
{
|
|
265
295
|
birthcountry: "99136",
|
|
@@ -278,13 +308,19 @@ describe("certification scoring", () => {
|
|
|
278
308
|
given_name: "Patrick",
|
|
279
309
|
},
|
|
280
310
|
),
|
|
281
|
-
|
|
311
|
+
new Set([
|
|
312
|
+
"family_name",
|
|
313
|
+
"first_name",
|
|
314
|
+
"gender",
|
|
315
|
+
"birth_date",
|
|
316
|
+
"birth_country",
|
|
317
|
+
]),
|
|
282
318
|
);
|
|
283
319
|
});
|
|
284
320
|
|
|
285
321
|
it("foreign person with different country", () => {
|
|
286
|
-
// Different country =
|
|
287
|
-
assert.
|
|
322
|
+
// Different country = missing birth_country
|
|
323
|
+
assert.deepStrictEqual(
|
|
288
324
|
certificationScore(
|
|
289
325
|
{
|
|
290
326
|
birthcountry: "99136", // Ireland
|
|
@@ -303,7 +339,7 @@ describe("certification scoring", () => {
|
|
|
303
339
|
given_name: "Patrick",
|
|
304
340
|
},
|
|
305
341
|
),
|
|
306
|
-
|
|
342
|
+
new Set(["family_name", "first_name", "gender", "birth_date"]),
|
|
307
343
|
);
|
|
308
344
|
});
|
|
309
345
|
});
|
|
@@ -1,11 +1,22 @@
|
|
|
1
1
|
//
|
|
2
2
|
|
|
3
3
|
import type { IdentityVector } from "#src/types";
|
|
4
|
+
import z from "zod/v4";
|
|
4
5
|
import { convertCommuneCode } from "./birthplace-conversion.js";
|
|
5
6
|
import { extractFirstName, normalizeText } from "./normalize.js";
|
|
6
7
|
|
|
7
8
|
//
|
|
8
9
|
|
|
10
|
+
export const MatchCriteria = z.enum([
|
|
11
|
+
"birth_country",
|
|
12
|
+
"birth_date",
|
|
13
|
+
"birth_place",
|
|
14
|
+
"family_name",
|
|
15
|
+
"first_name",
|
|
16
|
+
"gender",
|
|
17
|
+
]);
|
|
18
|
+
export type MatchCriteria = z.output<typeof MatchCriteria>;
|
|
19
|
+
|
|
9
20
|
/**
|
|
10
21
|
* Calculates a certification score between identity from FranceConnect (IdentitePivot)
|
|
11
22
|
* and executive identity from business registries (SourceDirigeant).
|
|
@@ -28,8 +39,8 @@ import { extractFirstName, normalizeText } from "./normalize.js";
|
|
|
28
39
|
export function certificationScore(
|
|
29
40
|
identitePivot: IdentityVector,
|
|
30
41
|
sourceDirigeant: IdentityVector,
|
|
31
|
-
)
|
|
32
|
-
|
|
42
|
+
) {
|
|
43
|
+
const matches = new Set<MatchCriteria>();
|
|
33
44
|
|
|
34
45
|
// 1. Family name match (after normalization)
|
|
35
46
|
const normalizedFamilyNamePivot = normalizeText(identitePivot.family_name);
|
|
@@ -40,7 +51,7 @@ export function certificationScore(
|
|
|
40
51
|
normalizedFamilyNameSource &&
|
|
41
52
|
normalizedFamilyNamePivot === normalizedFamilyNameSource
|
|
42
53
|
) {
|
|
43
|
-
|
|
54
|
+
matches.add(MatchCriteria.enum.family_name);
|
|
44
55
|
}
|
|
45
56
|
|
|
46
57
|
// 2. First name match (first name only, after normalization)
|
|
@@ -48,7 +59,7 @@ export function certificationScore(
|
|
|
48
59
|
const firstNameSource = extractFirstName(sourceDirigeant.given_name);
|
|
49
60
|
|
|
50
61
|
if (firstNamePivot && firstNameSource && firstNamePivot === firstNameSource) {
|
|
51
|
-
|
|
62
|
+
matches.add(MatchCriteria.enum.first_name);
|
|
52
63
|
}
|
|
53
64
|
|
|
54
65
|
// 3. Gender match (match or absent in source)
|
|
@@ -56,7 +67,7 @@ export function certificationScore(
|
|
|
56
67
|
!sourceDirigeant.gender ||
|
|
57
68
|
identitePivot.gender === sourceDirigeant.gender
|
|
58
69
|
) {
|
|
59
|
-
|
|
70
|
+
matches.add(MatchCriteria.enum.gender);
|
|
60
71
|
}
|
|
61
72
|
|
|
62
73
|
// 4. Birth date match (exact match)
|
|
@@ -65,7 +76,7 @@ export function certificationScore(
|
|
|
65
76
|
sourceDirigeant.birthdate &&
|
|
66
77
|
identitePivot.birthdate.getTime() === sourceDirigeant.birthdate.getTime()
|
|
67
78
|
) {
|
|
68
|
-
|
|
79
|
+
matches.add(MatchCriteria.enum.birth_date);
|
|
69
80
|
}
|
|
70
81
|
|
|
71
82
|
// 5. Birth place match (different logic for French vs foreigners)
|
|
@@ -79,7 +90,7 @@ export function certificationScore(
|
|
|
79
90
|
|
|
80
91
|
// Match if equal or if source has no commune data
|
|
81
92
|
if (!communeSource || (communePivot && communePivot === communeSource)) {
|
|
82
|
-
|
|
93
|
+
matches.add(MatchCriteria.enum.birth_place);
|
|
83
94
|
}
|
|
84
95
|
} else {
|
|
85
96
|
// For foreigners: check country code (with conversion if needed from RNE)
|
|
@@ -89,9 +100,9 @@ export function certificationScore(
|
|
|
89
100
|
sourceDirigeant.birthcountry &&
|
|
90
101
|
identitePivot.birthcountry === sourceDirigeant.birthcountry
|
|
91
102
|
) {
|
|
92
|
-
|
|
103
|
+
matches.add(MatchCriteria.enum.birth_country);
|
|
93
104
|
}
|
|
94
105
|
}
|
|
95
106
|
|
|
96
|
-
return
|
|
107
|
+
return matches;
|
|
97
108
|
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
//
|
|
2
2
|
|
|
3
|
-
import { InvalidCertificationError, NotFoundError } from "#src/errors";
|
|
4
3
|
import { IdentityVectorSchema } from "#src/types";
|
|
5
4
|
import {
|
|
6
5
|
LiElJonsonFranceConnectUserInfo,
|
|
@@ -24,13 +23,13 @@ import {
|
|
|
24
23
|
} from "@proconnect-gouv/proconnect.registre_national_entreprises/testing/seed";
|
|
25
24
|
import assert from "node:assert/strict";
|
|
26
25
|
import { describe, it } from "node:test";
|
|
27
|
-
import {
|
|
26
|
+
import { processCertificationDirigeantFactory } from "./process-certification-dirigeant.js";
|
|
28
27
|
|
|
29
28
|
//
|
|
30
29
|
|
|
31
|
-
describe("
|
|
30
|
+
describe("processCertificationDirigeantFactory", () => {
|
|
32
31
|
it("should recognize a user as executive of a auto-entrepreneur", async () => {
|
|
33
|
-
const
|
|
32
|
+
const processCertificationDirigeant = processCertificationDirigeantFactory({
|
|
34
33
|
ApiEntrepriseInfogreffeRepository: {
|
|
35
34
|
findMandatairesSociauxBySiren: () => Promise.reject(new Error("💣")),
|
|
36
35
|
},
|
|
@@ -40,22 +39,27 @@ describe("isOrganizationDirigeantFactory", () => {
|
|
|
40
39
|
InseeApiRepository: {
|
|
41
40
|
findBySiren: () => Promise.resolve(RogalDornEstablishment),
|
|
42
41
|
},
|
|
43
|
-
FranceConnectApiRepository: {
|
|
44
|
-
getFranceConnectUserInfo: () =>
|
|
45
|
-
Promise.resolve(RogalDornFranceConnectUserInfo),
|
|
46
|
-
},
|
|
47
42
|
});
|
|
48
43
|
|
|
49
|
-
const
|
|
44
|
+
const certificationDirigeantResult = await processCertificationDirigeant(
|
|
45
|
+
rogal_dorn_org_info,
|
|
46
|
+
RogalDornFranceConnectUserInfo,
|
|
47
|
+
);
|
|
50
48
|
|
|
51
|
-
assert.deepEqual(
|
|
49
|
+
assert.deepEqual(certificationDirigeantResult, {
|
|
52
50
|
cause: "exact_match",
|
|
53
51
|
details: {
|
|
54
52
|
dirigeant: {
|
|
55
53
|
...IdentityVectorSchema.parse(RogalDornFranceConnectUserInfo),
|
|
56
54
|
birthplace: null, // INSEE adapter returns null for foreigners
|
|
57
55
|
},
|
|
58
|
-
|
|
56
|
+
matches: new Set([
|
|
57
|
+
"family_name",
|
|
58
|
+
"first_name",
|
|
59
|
+
"gender",
|
|
60
|
+
"birth_date",
|
|
61
|
+
"birth_country",
|
|
62
|
+
]),
|
|
59
63
|
identity: IdentityVectorSchema.parse(RogalDornFranceConnectUserInfo),
|
|
60
64
|
source: "api.insee.fr/api-sirene/private",
|
|
61
65
|
},
|
|
@@ -64,7 +68,7 @@ describe("isOrganizationDirigeantFactory", () => {
|
|
|
64
68
|
});
|
|
65
69
|
|
|
66
70
|
it("should not match another mandataire", async () => {
|
|
67
|
-
const
|
|
71
|
+
const processCertificationDirigeant = processCertificationDirigeantFactory({
|
|
68
72
|
ApiEntrepriseInfogreffeRepository: {
|
|
69
73
|
findMandatairesSociauxBySiren: () => Promise.reject(new Error("💣")),
|
|
70
74
|
},
|
|
@@ -74,22 +78,21 @@ describe("isOrganizationDirigeantFactory", () => {
|
|
|
74
78
|
InseeApiRepository: {
|
|
75
79
|
findBySiren: () => Promise.resolve(LiElJonsonEstablishment),
|
|
76
80
|
},
|
|
77
|
-
FranceConnectApiRepository: {
|
|
78
|
-
getFranceConnectUserInfo: () =>
|
|
79
|
-
Promise.resolve(RogalDornFranceConnectUserInfo),
|
|
80
|
-
},
|
|
81
81
|
});
|
|
82
82
|
|
|
83
|
-
const
|
|
83
|
+
const certificationDirigeantResult = await processCertificationDirigeant(
|
|
84
|
+
rogal_dorn_org_info,
|
|
85
|
+
RogalDornFranceConnectUserInfo,
|
|
86
|
+
);
|
|
84
87
|
|
|
85
|
-
assert.deepEqual(
|
|
88
|
+
assert.deepEqual(certificationDirigeantResult, {
|
|
86
89
|
cause: "below_threshold",
|
|
87
90
|
details: {
|
|
88
91
|
dirigeant: {
|
|
89
92
|
...IdentityVectorSchema.parse(LiElJonsonFranceConnectUserInfo),
|
|
90
93
|
birthcountry: null, // INSEE adapter returns null for French people
|
|
91
94
|
},
|
|
92
|
-
|
|
95
|
+
matches: new Set(["gender"]),
|
|
93
96
|
identity: IdentityVectorSchema.parse(RogalDornFranceConnectUserInfo),
|
|
94
97
|
source: "api.insee.fr/api-sirene/private",
|
|
95
98
|
},
|
|
@@ -98,7 +101,7 @@ describe("isOrganizationDirigeantFactory", () => {
|
|
|
98
101
|
});
|
|
99
102
|
|
|
100
103
|
it("should match Rogal Dorn among the executive of Papillon in RNE", async () => {
|
|
101
|
-
const
|
|
104
|
+
const processCertificationDirigeant = processCertificationDirigeantFactory({
|
|
102
105
|
ApiEntrepriseInfogreffeRepository: {
|
|
103
106
|
findMandatairesSociauxBySiren: () => Promise.reject(new Error("💣")),
|
|
104
107
|
},
|
|
@@ -109,22 +112,27 @@ describe("isOrganizationDirigeantFactory", () => {
|
|
|
109
112
|
InseeApiRepository: {
|
|
110
113
|
findBySiren: () => Promise.reject(new Error("💣")),
|
|
111
114
|
},
|
|
112
|
-
FranceConnectApiRepository: {
|
|
113
|
-
getFranceConnectUserInfo: () =>
|
|
114
|
-
Promise.resolve(RogalDornFranceConnectUserInfo),
|
|
115
|
-
},
|
|
116
115
|
});
|
|
117
116
|
|
|
118
|
-
const
|
|
117
|
+
const certificationDirigeantResult = await processCertificationDirigeant(
|
|
118
|
+
papillon_org_info,
|
|
119
|
+
RogalDornFranceConnectUserInfo,
|
|
120
|
+
);
|
|
119
121
|
|
|
120
|
-
assert.deepEqual(
|
|
122
|
+
assert.deepEqual(certificationDirigeantResult, {
|
|
121
123
|
cause: "exact_match",
|
|
122
124
|
details: {
|
|
123
125
|
dirigeant: {
|
|
124
126
|
...IdentityVectorSchema.parse(RogalDornFranceConnectUserInfo),
|
|
125
127
|
birthplace: null, // RNE adapter returns null for foreigners
|
|
126
128
|
},
|
|
127
|
-
|
|
129
|
+
matches: new Set([
|
|
130
|
+
"family_name",
|
|
131
|
+
"first_name",
|
|
132
|
+
"gender",
|
|
133
|
+
"birth_date",
|
|
134
|
+
"birth_country",
|
|
135
|
+
]),
|
|
128
136
|
identity: IdentityVectorSchema.parse(RogalDornFranceConnectUserInfo),
|
|
129
137
|
source: "registre-national-entreprises.inpi.fr/api",
|
|
130
138
|
},
|
|
@@ -133,7 +141,7 @@ describe("isOrganizationDirigeantFactory", () => {
|
|
|
133
141
|
});
|
|
134
142
|
|
|
135
143
|
it("should match Rogal Dorn among the executive of Papillon in Infogreffe", async () => {
|
|
136
|
-
const
|
|
144
|
+
const processCertificationDirigeant = processCertificationDirigeantFactory({
|
|
137
145
|
ApiEntrepriseInfogreffeRepository: {
|
|
138
146
|
findMandatairesSociauxBySiren: () =>
|
|
139
147
|
Promise.resolve([UlysseToriMandataire, RogalDornMandataire]),
|
|
@@ -144,15 +152,14 @@ describe("isOrganizationDirigeantFactory", () => {
|
|
|
144
152
|
InseeApiRepository: {
|
|
145
153
|
findBySiren: () => Promise.reject(new Error("💣")),
|
|
146
154
|
},
|
|
147
|
-
FranceConnectApiRepository: {
|
|
148
|
-
getFranceConnectUserInfo: () =>
|
|
149
|
-
Promise.resolve(RogalDornFranceConnectUserInfo),
|
|
150
|
-
},
|
|
151
155
|
});
|
|
152
156
|
|
|
153
|
-
const
|
|
157
|
+
const certificationDirigeantResult = await processCertificationDirigeant(
|
|
158
|
+
papillon_org_info,
|
|
159
|
+
RogalDornFranceConnectUserInfo,
|
|
160
|
+
);
|
|
154
161
|
|
|
155
|
-
assert.deepEqual(
|
|
162
|
+
assert.deepEqual(certificationDirigeantResult, {
|
|
156
163
|
cause: "exact_match",
|
|
157
164
|
details: {
|
|
158
165
|
dirigeant: {
|
|
@@ -160,7 +167,13 @@ describe("isOrganizationDirigeantFactory", () => {
|
|
|
160
167
|
birthplace: null, // API Entreprise adapter doesn't provide birthplace
|
|
161
168
|
gender: null, // API Entreprise adapter doesn't provide gender
|
|
162
169
|
},
|
|
163
|
-
|
|
170
|
+
matches: new Set([
|
|
171
|
+
"family_name",
|
|
172
|
+
"first_name",
|
|
173
|
+
"gender",
|
|
174
|
+
"birth_date",
|
|
175
|
+
"birth_country",
|
|
176
|
+
]),
|
|
164
177
|
identity: IdentityVectorSchema.parse(RogalDornFranceConnectUserInfo),
|
|
165
178
|
source:
|
|
166
179
|
"entreprise.api.gouv.fr/v3/infogreffe/rcs/unites_legales/{siren}/mandataires_sociaux",
|
|
@@ -169,48 +182,33 @@ describe("isOrganizationDirigeantFactory", () => {
|
|
|
169
182
|
});
|
|
170
183
|
});
|
|
171
184
|
|
|
172
|
-
it("❎ fail with no
|
|
173
|
-
const
|
|
185
|
+
it("❎ fail with no mandataires", async () => {
|
|
186
|
+
const processCertificationDirigeant = processCertificationDirigeantFactory({
|
|
174
187
|
ApiEntrepriseInfogreffeRepository: {
|
|
175
188
|
findMandatairesSociauxBySiren: () => Promise.reject(new Error("💣")),
|
|
176
189
|
},
|
|
177
190
|
RegistreNationalEntreprisesApiRepository: {
|
|
178
|
-
findPouvoirsBySiren: () => Promise.
|
|
191
|
+
findPouvoirsBySiren: () => Promise.resolve([]),
|
|
179
192
|
},
|
|
180
193
|
InseeApiRepository: {
|
|
181
194
|
findBySiren: () => Promise.reject(new Error("💣")),
|
|
182
195
|
},
|
|
183
|
-
FranceConnectApiRepository: {
|
|
184
|
-
getFranceConnectUserInfo: () => Promise.resolve(undefined),
|
|
185
|
-
},
|
|
186
196
|
});
|
|
187
197
|
|
|
188
|
-
await
|
|
189
|
-
|
|
190
|
-
|
|
198
|
+
const certificationDirigeantResult = await processCertificationDirigeant(
|
|
199
|
+
papillon_org_info,
|
|
200
|
+
LiElJonsonFranceConnectUserInfo,
|
|
191
201
|
);
|
|
192
|
-
});
|
|
193
202
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
},
|
|
202
|
-
InseeApiRepository: {
|
|
203
|
-
findBySiren: () => Promise.reject(new Error("💣")),
|
|
204
|
-
},
|
|
205
|
-
FranceConnectApiRepository: {
|
|
206
|
-
getFranceConnectUserInfo: () =>
|
|
207
|
-
Promise.resolve(LiElJonsonFranceConnectUserInfo),
|
|
203
|
+
assert.deepEqual(certificationDirigeantResult, {
|
|
204
|
+
cause: "no_candidates",
|
|
205
|
+
details: {
|
|
206
|
+
dirigeant: undefined,
|
|
207
|
+
identity: IdentityVectorSchema.parse(LiElJonsonFranceConnectUserInfo),
|
|
208
|
+
matches: new Set(),
|
|
209
|
+
source: "registre-national-entreprises.inpi.fr/api",
|
|
208
210
|
},
|
|
211
|
+
ok: false,
|
|
209
212
|
});
|
|
210
|
-
|
|
211
|
-
await assert.rejects(
|
|
212
|
-
isOrganizationDirigeant(papillon_org_info, 1),
|
|
213
|
-
new InvalidCertificationError("No candidates found"),
|
|
214
|
-
);
|
|
215
213
|
});
|
|
216
214
|
});
|