Skip to content

Commit 9a68790

Browse files
l-schererachorein
andauthored
feat: 1092 bo liste agrements (#1193)
## Ticket(s) lié(s) 1092 ## Description BO Liste agrement --------- Co-authored-by: Anselme <anselme@chorein.fr>
1 parent a3e4654 commit 9a68790

File tree

44 files changed

+950
-64
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+950
-64
lines changed

.talismanrc

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ fileignoreconfig:
6565
checksum: ab7a0f54777521ceb0cf4f2f253cc6f804e24ad7e27015eb9d66961366510a12
6666
- filename: packages/backend/src/__tests__/usagers/authentification.test.ts
6767
checksum: c15d2aeea878e0da568caa3a14d4dc58287fad8ee1cd6d026626c38870e8bc47
68+
- filename: packages/backend/src/admin/agrements/agrements.service.ts
69+
checksum: 8f4c20086189fa2e89ff078120488bd868a0370b6f6cbd737b93def3b82c4c15
6870
- filename: packages/backend/src/config.js
6971
checksum: 5e974a98e40b4f10974b9e57127b8b71e4abef208494d69218b17b3721453ada
7072
- filename: packages/backend/src/controllers/__tests__/bo-user/accept-cgu.test.js
@@ -185,6 +187,8 @@ fileignoreconfig:
185187
checksum: 2ba032561adc4ef237463114e8761fb3f7a754e062f0d192f7b38d31f80763b7
186188
- filename: packages/frontend-bo/src/assets/Download.svg
187189
checksum: 2845f88f98040035bf7e9434a9bd5fe5cb8d0dd28fd1d765dd9c6a0b440e49f7
190+
- filename: packages/frontend-bo/src/components/agrements/liste.vue
191+
checksum: 6b798d2ae581064a525ebcd10b7a4ba940a2cfad2c920c2ec186e2e93674a8c3
188192
- filename: packages/frontend-bo/src/components/connexion/email/validateToken.client.vue
189193
checksum: 595435cdea445525554cb0d703a53cf277127a3c0ad39c02502f865cb9fc5dd0
190194
- filename: packages/frontend-bo/src/components/demandes-sejour/DefaultTable.vue
@@ -309,14 +313,16 @@ fileignoreconfig:
309313
checksum: 0c60a5a9f3321ab3c36025bdeb35663395586d5bca3d21984fdbe5997b46c6eb
310314
- filename: packages/migrations/src/scripts/reset-s3.js
311315
checksum: 7b52636c4c49bf85a592f649f8fbf653e0203b390f4f9d220fe3ae4da06422a7
316+
- filename: packages/shared-bridge/src/dto/paginationQueryDto.ts
317+
checksum: 171d7cf0f68b404e3b648fcb9d7b3e36891da049bad2ede67007d0c03661145a
312318
- filename: packages/shared-bridge/src/constantes/file.ts
313319
checksum: dded09b86eeb4c664e493ff12b023d20914b18ac5c9a98ac7e60235daec3927d
314320
- filename: packages/shared-bridge/src/utils/request.ts
315321
checksum: c29fc1527b710e177395fabd040b7e3cdd44b429b21d504ba6f192faf1cd861a
316322
- filename: packages/shared-ui/src/components/DsfrMultiselectV2.vue
317323
checksum: 1de96bc77280e61537e5c573a8116d32a8d2793eb073f89080cc66f8a389ce73
318324
- filename: packages/shared-ui/src/components/Table/DsfrDataTableV2.vue
319-
checksum: 0333a8dd3d87ab118f5896b079f89423f9e465208c68bebed045a83350ce24d6
325+
checksum: 3a7b2bfad20888628a8300ef771cdf322d0ccbf3e9043eb7995b78877045d765
320326
- filename: packages/shared-ui/src/components/Toaster.vue
321327
checksum: 83bcf77f5b7763c7f6bc272366174a0780fec328462c6ca4bc29ef144e2c37de
322328
- filename: packages/shared-ui/src/composables/useToaster.ts
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
import request from "supertest";
2+
3+
import app from "../../app";
4+
import { buildAgrementFixture } from "../helper/fixtures/agrementsFixture";
5+
import { createAgrement } from "../helper/fixtures/agrementsHelper";
6+
import { createOrganisme } from "../helper/fixtures/organismeHelper";
7+
import {
8+
createAdminUser,
9+
createUsagersUser,
10+
} from "../helper/fixtures/userHelper";
11+
import {
12+
createTestContainer,
13+
removeTestContainer,
14+
} from "../helper/testContainer";
15+
16+
let authUser = { id: 1, role: "admin" };
17+
let authUser2 = { id: 2, role: "admin" };
18+
let authUserBo = { territoireCode: "IDF" };
19+
20+
jest.mock("../../middlewares/common/checkJWT", () => {
21+
return async (req, res, next) => {
22+
req.decoded = authUserBo;
23+
next();
24+
};
25+
});
26+
27+
beforeAll(async () => await createTestContainer());
28+
afterAll(async () => await removeTestContainer());
29+
30+
afterEach(() => {
31+
jest.clearAllMocks();
32+
});
33+
34+
describe("GET /agrements/list/", () => {
35+
it("devrait retourner une liste d'agréments avec succès", async () => {
36+
authUser = await createUsagersUser();
37+
const organismeId1 = await createOrganisme({ userId: authUser.id });
38+
const agrementData = await buildAgrementFixture({
39+
organismeId: organismeId1,
40+
});
41+
const agrementId1 = await createAgrement({
42+
agrement: agrementData,
43+
organismeId: organismeId1,
44+
});
45+
authUser2 = await createUsagersUser();
46+
const organismeId2 = await createOrganisme({ userId: authUser2.id });
47+
const agrementData2 = await buildAgrementFixture({
48+
organismeId: organismeId2,
49+
});
50+
const agrementId2 = await createAgrement({
51+
agrement: agrementData2,
52+
organismeId: organismeId2,
53+
});
54+
authUserBo = await createAdminUser({ territoireCode: "IDF" });
55+
const response = await request(app).get(`/admin/agrements/list/`);
56+
57+
expect(response.status).toBe(200);
58+
expect(response.body.agrements).toBeDefined();
59+
expect(response.body.agrements.length).toBe(2);
60+
expect(response.body.agrements[0].id).toEqual(agrementId1);
61+
expect(response.body.agrements[1].id).toEqual(agrementId2);
62+
});
63+
64+
it("devrait retourner un seul agréments filtré avec succès", async () => {
65+
authUser = await createUsagersUser();
66+
const organismeId1 = await createOrganisme({ userId: authUser.id });
67+
const agrementData = await buildAgrementFixture({
68+
organismeId: organismeId1,
69+
});
70+
await createAgrement({
71+
agrement: agrementData,
72+
organismeId: organismeId1,
73+
});
74+
authUser2 = await createUsagersUser();
75+
const organismeId2 = await createOrganisme({ userId: authUser2.id });
76+
const agrementData2 = await buildAgrementFixture({
77+
organismeId: organismeId2,
78+
});
79+
await createAgrement({
80+
agrement: agrementData2,
81+
organismeId: organismeId2,
82+
});
83+
authUserBo = await createAdminUser({ territoireCode: "IDF" });
84+
const response = await request(app).get(
85+
`/admin/agrements/list?limit=1&offset=0&search={"numero":"${agrementData.numero}"}`,
86+
);
87+
88+
expect(response.status).toBe(200);
89+
expect(response.body.agrements).toBeDefined();
90+
expect(response.body.agrements.length).toBe(1);
91+
expect(response.body.agrements[0].numero).toEqual(agrementData.numero);
92+
});
93+
});

packages/backend/src/__tests__/helper/fixtures/agrementsFixture.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ export async function buildAgrementFixture({
7373
dateVerifCompleture: new Date("2024-12-05"),
7474
immatriculation: "123-AB-456",
7575
motivations: "Motivation de test",
76+
numero: "AGR-2024-0001",
7677
organismeId,
7778
protocoleEvacUrg: "Procédure OK",
7879
protocoleInfoFamille: "Information envoyée",

packages/backend/src/__tests__/helper/fixtures/userHelper.ts

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,24 @@
11
import { UsersRepository as AdminUsersRepository } from "../../../repositories/admin/Users";
22
import { UsersRepository as UsagerUsersRepository } from "../../../repositories/usagers/Users";
3-
import { create as createBoUserService } from "../../../services/BoUser";
3+
import {
4+
create as createBoUserService,
5+
readOneByMail as readOneByMailBoUserService,
6+
} from "../../../services/BoUser";
47
import { registerByEmail as createFrontUserService } from "../../../services/User";
58

69
export const createAdminUser = async (user = {}) => {
10+
const timestamp = Date.now();
711
const fixture = {
8-
email: "user1@example.com",
12+
email: `userbo${timestamp}@example.com`,
913
nom: "Nom1",
1014
prenom: "Prenom1",
11-
roles: ["eig", "DemandeSejour_Lecture", "DemandeSejour_Ecriture"],
15+
roles: ["DemandeSejour_Lecture", "DemandeSejour_Ecriture"],
1216
territoireCode: "FRA",
1317
...user,
1418
};
15-
return await createBoUserService(fixture);
19+
await createBoUserService(fixture);
20+
const result = await readOneByMailBoUserService(fixture.email);
21+
return result;
1622
};
1723

1824
export const createUsagersUser = async (user = {}) => {
@@ -21,7 +27,7 @@ export const createUsagersUser = async (user = {}) => {
2127
email: `frontuser${timestamp}@example.com`,
2228
nom: "FrontNom",
2329
prenom: "FrontPrenom",
24-
siret: `123456789012${timestamp.toString().slice(-2)}`,
30+
siret: `${timestamp.toString().slice(-2)}123456789012`,
2531
telephone: "0102030405",
2632
terCode: "FRA",
2733
...user,
@@ -57,5 +63,5 @@ export const createAdminUserValide = async (user = {}) => {
5763
...user,
5864
};
5965
const result = await AdminUsersRepository.create({ user: fixture });
60-
return result.user;
66+
return result;
6167
};

packages/backend/src/__tests__/usagers/authentification.test.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,6 @@ describe("POST /authentication/email/register", () => {
4848
.post("/authentication/email/register")
4949
.send(payload);
5050

51-
console.log("Response body:", response.body);
5251
expect(response.status).toBe(400);
5352
expect(response.body.name).toBe("SiretNotFound");
5453
});

packages/backend/src/__tests__/usagers/territoire.test.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ describe("GET /territoire/getByAgrementRegionUser", () => {
4040
const territoireId = await createTerritoire({
4141
territoireCode: "IDF",
4242
});
43-
console.log("Territoire ID simulé :", territoireId);
4443
const response = await request(app).get(
4544
`/territoire/get-by-agrement-region-user`,
4645
);
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import type { AgrementAdminRoutes } from "@vao/shared-bridge";
2+
import type { NextFunction } from "express";
3+
4+
import type { RouteRequest, RouteResponse } from "../../types/request";
5+
import logger from "../../utils/logger";
6+
import { AgrementService } from "./agrements.service";
7+
8+
const log = logger(module.filename);
9+
10+
export const AgrementController = {
11+
async getList(
12+
req: RouteRequest<AgrementAdminRoutes["GetList"]>,
13+
res: RouteResponse<AgrementAdminRoutes["GetList"]>,
14+
next: NextFunction,
15+
) {
16+
log.i("IN");
17+
const regionCode = String(req.decoded?.territoireCode);
18+
try {
19+
const { count, result } = await AgrementService.getListAgrements({
20+
queryParams: req.validatedQuery!,
21+
regionCode,
22+
});
23+
res.json({ agrements: result, count });
24+
} catch (error) {
25+
log.w("DONE with error");
26+
next(error);
27+
}
28+
},
29+
};
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import { AgrementDto } from "@vao/shared-bridge";
2+
import { PaginationQueryDto } from "@vao/shared-bridge/src/dto/paginationQueryDto";
3+
4+
import { processQuery } from "../../helpers/queryParams";
5+
import { AgrementEntity } from "../../shared/agrements/agrements.entity";
6+
import { AgrementsMapper } from "../../shared/agrements/agrements.mapper";
7+
import Logger from "../../utils/logger";
8+
import { getPool } from "../../utils/pgpool";
9+
10+
const log = Logger(module.filename);
11+
// ------------------------------------------------------------
12+
// 🏗️ Repository Admin
13+
// ------------------------------------------------------------
14+
export const AgrementsRepository = {
15+
/**
16+
* Récupère une liste d'agréments par région d'obtention
17+
*/
18+
async getByRegionObtention({
19+
regionCode,
20+
criterias,
21+
queryParams,
22+
}: {
23+
regionCode: string;
24+
criterias: Array<Record<string, any>>;
25+
queryParams: PaginationQueryDto & {
26+
name?: string;
27+
numero?: string;
28+
siret?: string;
29+
statut?: string;
30+
};
31+
}): Promise<{ count: number; result: AgrementDto[] }> {
32+
log.i("getByRegionObtention - IN");
33+
const query = () => `
34+
SELECT
35+
agr.*,
36+
pm.siret,
37+
pm.raison_sociale,
38+
pp.prenom,
39+
pp.nom_usage,
40+
pp.siret
41+
FROM front.agrements agr
42+
INNER JOIN front.organismes o ON o.id = agr.organisme_id
43+
LEFT JOIN front.personne_morale pm ON pm.organisme_id = o.id AND pm.current = true
44+
LEFT JOIN front.personne_physique pp ON pp.organisme_id = o.id AND pp.current = true
45+
WHERE agr.region_obtention = $1
46+
`;
47+
48+
const paginatedQuery = processQuery(
49+
query,
50+
[regionCode],
51+
criterias ?? {},
52+
queryParams,
53+
);
54+
const response = await Promise.all([
55+
getPool().query(paginatedQuery.query, paginatedQuery.params),
56+
getPool().query(
57+
paginatedQuery.countQuery,
58+
paginatedQuery.countQueryParams,
59+
),
60+
]);
61+
const agrements = [];
62+
for (const row of response[0].rows) {
63+
const agrement = AgrementsMapper.toModel(row as AgrementEntity);
64+
agrements.push(agrement);
65+
}
66+
log.i("getByRegionObtention - DONE");
67+
68+
return {
69+
count: parseInt(response[1].rows[0].total, 10),
70+
result: agrements,
71+
};
72+
},
73+
};
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { AgrementAdminRoutesSchema } from "@vao/shared-bridge";
2+
import express from "express";
3+
4+
import boCheckJWT from "../../middlewares/bo-check-JWT";
5+
import checkPermissionBOAgrement from "../../middlewares/checkPermissionBOAgrement";
6+
import { requestValidatorMiddleware } from "../../middlewares/requestValidatorMiddleware";
7+
import { AgrementController } from "./agrements.controller";
8+
9+
const router = express.Router();
10+
11+
router.get(
12+
"/list/",
13+
boCheckJWT,
14+
requestValidatorMiddleware(AgrementAdminRoutesSchema["GetList"]),
15+
checkPermissionBOAgrement,
16+
AgrementController.getList,
17+
);
18+
19+
export default router;

0 commit comments

Comments
 (0)