diff --git a/api/lib/application/certification-centers/certification-center-controller.js b/api/lib/application/certification-centers/certification-center-controller.js index 4e861b5fcd1..61c95d131f0 100644 --- a/api/lib/application/certification-centers/certification-center-controller.js +++ b/api/lib/application/certification-centers/certification-center-controller.js @@ -2,23 +2,8 @@ import * as divisionSerializer from '../../../src/prescription/campaign/infrastr import * as certificationCenterMembershipSerializer from '../../../src/shared/infrastructure/serializers/jsonapi/certification-center-membership.serializer.js'; import { usecases as teamUsecases } from '../../../src/team/domain/usecases/index.js'; import { usecases } from '../../domain/usecases/index.js'; -import * as sessionSummarySerializer from '../../infrastructure/serializers/jsonapi/session-summary-serializer.js'; import * as studentCertificationSerializer from '../../infrastructure/serializers/jsonapi/student-certification-serializer.js'; -const findPaginatedSessionSummaries = async function (request) { - const certificationCenterId = request.params.id; - const userId = request.auth.credentials.userId; - const options = request.query; - - const { models: sessionSummaries, meta } = await usecases.findPaginatedCertificationCenterSessionSummaries({ - userId, - certificationCenterId, - page: options.page, - }); - - return sessionSummarySerializer.serialize(sessionSummaries, meta); -}; - const getStudents = async function (request) { const certificationCenterId = request.params.certificationCenterId; const sessionId = request.params.sessionId; @@ -91,7 +76,6 @@ const updateReferer = async function (request, h) { const certificationCenterController = { createCertificationCenterMembershipByEmail, findCertificationCenterMembershipsByCertificationCenter, - findPaginatedSessionSummaries, getDivisions, getStudents, updateReferer, diff --git a/api/lib/application/certification-centers/index.js b/api/lib/application/certification-centers/index.js index dd61886e854..4a8f3546825 100644 --- a/api/lib/application/certification-centers/index.js +++ b/api/lib/application/certification-centers/index.js @@ -149,29 +149,6 @@ const register = async function (server) { tags: ['api', 'certification-center', 'students', 'session'], }, }, - { - method: 'GET', - path: '/api/certification-centers/{id}/session-summaries', - config: { - validate: { - params: Joi.object({ - id: identifiersType.certificationCenterId, - }), - query: Joi.object({ - page: Joi.object({ - number: Joi.number().integer().empty('').allow(null).optional(), - size: Joi.number().integer().empty('').allow(null).optional(), - }).default({}), - }), - }, - handler: certificationCenterController.findPaginatedSessionSummaries, - tags: ['api', 'certification-center'], - notes: [ - '- **Cette route est restreinte aux utilisateurs authentifiés**\n', - '- Elle retourne les sessions rattachées au centre de certification.', - ], - }, - }, ]); }; diff --git a/api/src/certification/session-management/application/certification-centers-session-summaries-controller.js b/api/src/certification/session-management/application/certification-centers-session-summaries-controller.js new file mode 100644 index 00000000000..77023038ccb --- /dev/null +++ b/api/src/certification/session-management/application/certification-centers-session-summaries-controller.js @@ -0,0 +1,22 @@ +import { usecases } from '../domain/usecases/index.js'; +import * as sessionSummarySerializer from '../infrastructure/serializers/session-summary-serializer.js'; + +const findPaginatedSessionSummaries = async function (request) { + const certificationCenterId = request.params.id; + const userId = request.auth.credentials.userId; + const options = request.query; + + const { models: sessionSummaries, meta } = await usecases.findPaginatedCertificationCenterSessionSummaries({ + userId, + certificationCenterId, + page: options.page, + }); + + return sessionSummarySerializer.serialize(sessionSummaries, meta); +}; + +const certificationCenterController = { + findPaginatedSessionSummaries, +}; + +export { certificationCenterController }; diff --git a/api/src/certification/session-management/application/certification-centers-session-summaries-route.js b/api/src/certification/session-management/application/certification-centers-session-summaries-route.js new file mode 100644 index 00000000000..d977d4bb875 --- /dev/null +++ b/api/src/certification/session-management/application/certification-centers-session-summaries-route.js @@ -0,0 +1,35 @@ +import Joi from 'joi'; + +import { certificationCenterController } from '../../../../src/certification/session-management/application/certification-centers-session-summaries-controller.js'; +import { identifiersType } from '../../../shared/domain/types/identifiers-type.js'; + +const register = async function (server) { + server.route([ + { + method: 'GET', + path: '/api/certification-centers/{id}/session-summaries', + config: { + validate: { + params: Joi.object({ + id: identifiersType.certificationCenterId, + }), + query: Joi.object({ + page: Joi.object({ + number: Joi.number().integer().empty('').allow(null).optional(), + size: Joi.number().integer().empty('').allow(null).optional(), + }).default({}), + }), + }, + handler: certificationCenterController.findPaginatedSessionSummaries, + tags: ['api', 'certification-center'], + notes: [ + '- **Cette route est restreinte aux utilisateurs authentifiés**\n', + '- Elle retourne les sessions rattachées au centre de certification.', + ], + }, + }, + ]); +}; + +const name = 'session-summaries-api'; +export { name, register }; diff --git a/api/lib/domain/usecases/find-paginated-certification-center-session-summaries.js b/api/src/certification/session-management/domain/usecases/find-paginated-certification-center-session-summaries.js similarity index 88% rename from api/lib/domain/usecases/find-paginated-certification-center-session-summaries.js rename to api/src/certification/session-management/domain/usecases/find-paginated-certification-center-session-summaries.js index dab3b2ba87c..cf20ac81e58 100644 --- a/api/lib/domain/usecases/find-paginated-certification-center-session-summaries.js +++ b/api/src/certification/session-management/domain/usecases/find-paginated-certification-center-session-summaries.js @@ -1,4 +1,4 @@ -import { ForbiddenAccess } from '../../../src/shared/domain/errors.js'; +import { ForbiddenAccess } from '../../../../../src/shared/domain/errors.js'; const findPaginatedCertificationCenterSessionSummaries = async function ({ userId, diff --git a/api/src/certification/session-management/domain/usecases/index.js b/api/src/certification/session-management/domain/usecases/index.js index 13574d23a43..33c23f5e923 100644 --- a/api/src/certification/session-management/domain/usecases/index.js +++ b/api/src/certification/session-management/domain/usecases/index.js @@ -4,6 +4,7 @@ import { fileURLToPath } from 'node:url'; import { pickChallengeService } from '../../../../../src/evaluation/domain/services/pick-challenge-service.js'; import * as flashAlgorithmService from '../../../../certification/flash-certification/domain/services/algorithm-methods/flash.js'; +import * as userRepository from '../../../../identity-access-management/infrastructure/repositories/user.repository.js'; import * as placementProfileService from '../../../../shared/domain/services/placement-profile-service.js'; import { injectDependencies } from '../../../../shared/infrastructure/utils/dependency-injection.js'; import { importNamedExportsFromDirectory } from '../../../../shared/infrastructure/utils/import-named-exports-from-directory.js'; @@ -23,6 +24,7 @@ import { cpfExportRepository, flashAlgorithmConfigurationRepository, sessionRepositories, + sessionSummaryRepository, sharedCompetenceMarkRepository, } from '../../infrastructure/repositories/index.js'; import { cpfExportsStorage } from '../../infrastructure/storage/cpf-exports-storage.js'; @@ -68,6 +70,7 @@ import * as sessionPublicationService from '../services/session-publication-serv * @typedef {import('../../../shared/domain/services/certification-cpf-service.js')} CertificationCpfService * @typedef {import('../../infrastructure/repositories/index.js').CertificationCandidateRepository} CertificationCandidateRepository * @typedef {import('../../infrastructure/repositories/index.js').CertificationCompanionAlertRepository} CertificationCompanionAlertRepository + * @typedef {import('../../../../identity-access-management/infrastructure/repositories/user.respository.js').UserRepository} UserRepository **/ /** @@ -96,6 +99,7 @@ import * as sessionPublicationService from '../services/session-publication-serv * @typedef {complementaryCertificationCourseResultRepository} ComplementaryCertificationCourseResultRepository * @typedef {sessionJuryCommentRepository} SessionJuryCommentRepository * @typedef {sessionRepository} SessionRepository + * @typedef {sessionSummaryRepository} SessionSummaryRepository * @typedef {certificationReportRepository} CertificationReportRepository * @typedef {certificationCpfCountryRepository} CertificationCpfCountryRepository * @typedef {certificationCpfCityRepository} CertificationCpfCityRepository @@ -111,9 +115,11 @@ import * as sessionPublicationService from '../services/session-publication-serv * @typedef {cpfExportRepository} CpfExportRepository * @typedef {certificationCandidateRepository} CertificationCandidateRepository * @typedef {certificationCompanionAlertRepository} CertificationCompanionAlertRepository + * @typedef {userRepository} UserRepository **/ const dependencies = { ...sessionRepositories, + sessionSummaryRepository, assessmentRepository, assessmentResultRepository, answerRepository, @@ -135,6 +141,7 @@ const dependencies = { pickChallengeService, sessionPublicationService, sharedSessionRepository, + userRepository, }; const path = dirname(fileURLToPath(import.meta.url)); diff --git a/api/src/certification/session-management/infrastructure/repositories/index.js b/api/src/certification/session-management/infrastructure/repositories/index.js index 30ef2047445..f3ec77be661 100644 --- a/api/src/certification/session-management/infrastructure/repositories/index.js +++ b/api/src/certification/session-management/infrastructure/repositories/index.js @@ -32,6 +32,7 @@ import * as sessionForInvigilatorKitRepository from './session-for-invigilator-k import * as sessionForSupervisingRepository from './session-for-supervising-repository.js'; import * as sessionJuryCommentRepository from './session-jury-comment-repository.js'; import * as sessionRepository from './session-repository.js'; +import * as sessionSummaryRepository from './session-summary-repository.js'; import * as supervisorAccessRepository from './supervisor-access-repository.js'; import * as v3CertificationCourseDetailsForAdministrationRepository from './v3-certification-course-details-for-administration-repository.js'; @@ -53,6 +54,7 @@ import * as v3CertificationCourseDetailsForAdministrationRepository from './v3-c * @typedef {certificationIssueReportRepository} CertificationIssueReportRepository * @typedef {sessionForSupervisingRepository} SessionForSupervisingRepository * @typedef {sessionJuryCommentRepository} SessionJuryCommentRepository + * @typedef {sessionSummaryRepository} SessionSummaryRepository * @typedef {sessionRepository} SessionRepository * @typedef {supervisorAccessRepository} SupervisorAccessRepository * @typedef {certificationReportRepository} CertificationReportRepository @@ -88,6 +90,7 @@ const repositoriesWithoutInjectedDependencies = { sessionForInvigilatorKitRepository, issueReportCategoryRepository, sessionRepository, + sessionSummaryRepository, sessionForSupervisingRepository, sessionJuryCommentRepository, certificationRepository, @@ -126,5 +129,6 @@ export { cpfExportRepository, flashAlgorithmConfigurationRepository, sessionRepositories, + sessionSummaryRepository, sharedCompetenceMarkRepository, }; diff --git a/api/lib/infrastructure/serializers/jsonapi/session-summary-serializer.js b/api/src/certification/session-management/infrastructure/serializers/session-summary-serializer.js similarity index 100% rename from api/lib/infrastructure/serializers/jsonapi/session-summary-serializer.js rename to api/src/certification/session-management/infrastructure/serializers/session-summary-serializer.js diff --git a/api/src/certification/session-management/routes.js b/api/src/certification/session-management/routes.js index f3645bf4b6a..7ccab6e0594 100644 --- a/api/src/certification/session-management/routes.js +++ b/api/src/certification/session-management/routes.js @@ -1,5 +1,6 @@ import * as cancellation from './application/cancellation-route.js'; import * as certificationCandidate from './application/certification-candidate-route.js'; +import * as sessionSummaries from './application/certification-centers-session-summaries-route.js'; import * as certificationCourse from './application/certification-course-route.js'; import * as certificationDetails from './application/certification-details-route.js'; import * as certificationIssueReport from './application/certification-issue-report-route.js'; @@ -36,6 +37,7 @@ const certificationSessionRoutes = [ juryCertification, juryComment, session, + sessionSummaries, sessionForSupervising, sessionLiveAlert, sessionPublication, diff --git a/api/tests/certification/session-management/unit/application/certification-centers-session-summaries-controller.test.js b/api/tests/certification/session-management/unit/application/certification-centers-session-summaries-controller.test.js new file mode 100644 index 00000000000..dfa10fbefa5 --- /dev/null +++ b/api/tests/certification/session-management/unit/application/certification-centers-session-summaries-controller.test.js @@ -0,0 +1,78 @@ +import { certificationCenterController } from '../../../../../src/certification/session-management/application/certification-centers-session-summaries-controller.js'; +import { usecases } from '../../../../../src/certification/session-management/domain/usecases/index.js'; +import { domainBuilder, expect, hFake, sinon } from '../../../../test-helper.js'; + +describe('Unit | Controller | certifications-center-controller', function () { + describe('#findPaginatedSessionSummaries', function () { + beforeEach(function () { + sinon.stub(usecases, 'findPaginatedCertificationCenterSessionSummaries'); + }); + + it('should return a list of JSON API session summaries with pagination information', async function () { + // given + const request = { + params: { id: 456 }, + auth: { credentials: { userId: 123 } }, + query: { + page: { + number: 1, + size: 10, + }, + }, + }; + const sessionSummary = domainBuilder.buildSessionSummary.created({ + id: 1, + address: 'ici', + room: 'la-bas', + date: '2020-01-01', + time: '16:00', + examiner: 'Moi', + enrolledCandidatesCount: 5, + effectiveCandidatesCount: 4, + }); + usecases.findPaginatedCertificationCenterSessionSummaries + .withArgs({ + userId: 123, + certificationCenterId: 456, + page: { number: 1, size: 10 }, + }) + .resolves({ + models: [sessionSummary], + meta: { page: 1, pageSize: 10, itemsCount: 1, pagesCount: 1, hasSessions: true }, + }); + + // when + const serializedSessionSummaries = await certificationCenterController.findPaginatedSessionSummaries( + request, + hFake, + ); + + // then + expect(serializedSessionSummaries).to.deep.equal({ + data: [ + { + id: '1', + type: 'session-summaries', + attributes: { + address: 'ici', + room: 'la-bas', + date: '2020-01-01', + time: '16:00', + examiner: 'Moi', + 'effective-candidates-count': 4, + 'enrolled-candidates-count': 5, + status: 'created', + }, + }, + ], + meta: { + hasSessions: true, + itemsCount: 1, + page: 1, + pageSize: 10, + pagesCount: 1, + }, + }); + }); + }); +}); diff --git a/api/tests/certification/session-management/unit/application/certification-centers-session-summaries-route.test.js b/api/tests/certification/session-management/unit/application/certification-centers-session-summaries-route.test.js new file mode 100644 index 00000000000..097ae9ce33c --- /dev/null +++ b/api/tests/certification/session-management/unit/application/certification-centers-session-summaries-route.test.js @@ -0,0 +1,21 @@ +import { certificationCenterController } from '../../../../../src/certification/session-management/application/certification-centers-session-summaries-controller.js'; +import * as moduleUnderTest from '../../../../../src/certification/session-management/application/certification-centers-session-summaries-route.js'; +import { expect, HttpTestServer, sinon } from '../../../../test-helper.js'; + +describe('Certification | Session-management | Unit | Application | Routes | session-summaries', function () { + describe('GET /api/certification-centers/{certificationCenterId}/session-summaries', function () { + it('should return 200', async function () { + // given + sinon.stub(certificationCenterController, 'findPaginatedSessionSummaries').returns('ok'); + const httpTestServer = new HttpTestServer(); + await httpTestServer.register(moduleUnderTest); + + // when + const response = await httpTestServer.request('GET', '/api/certification-centers/123/session-summaries'); + + // then + expect(response.statusCode).to.equal(200); + sinon.assert.calledOnce(certificationCenterController.findPaginatedSessionSummaries); + }); + }); +}); diff --git a/api/tests/unit/domain/usecases/find-paginated-certification-center-session-summaries_test.js b/api/tests/certification/session-management/unit/domain/usecases/find-paginated-certification-center-session-summaries_test.js similarity index 92% rename from api/tests/unit/domain/usecases/find-paginated-certification-center-session-summaries_test.js rename to api/tests/certification/session-management/unit/domain/usecases/find-paginated-certification-center-session-summaries_test.js index 277047675cd..18e3b31e003 100644 --- a/api/tests/unit/domain/usecases/find-paginated-certification-center-session-summaries_test.js +++ b/api/tests/certification/session-management/unit/domain/usecases/find-paginated-certification-center-session-summaries_test.js @@ -1,6 +1,6 @@ -import { findPaginatedCertificationCenterSessionSummaries } from '../../../../lib/domain/usecases/find-paginated-certification-center-session-summaries.js'; -import { ForbiddenAccess } from '../../../../src/shared/domain/errors.js'; -import { catchErr, domainBuilder, expect, sinon } from '../../../test-helper.js'; +import { findPaginatedCertificationCenterSessionSummaries } from '../../../../../../src/certification/session-management/domain/usecases/find-paginated-certification-center-session-summaries.js'; +import { ForbiddenAccess } from '../../../../../../src/shared/domain/errors.js'; +import { catchErr, domainBuilder, expect, sinon } from '../../../../../test-helper.js'; describe('Unit | Domain | Use Cases | find-paginated-certification-center-session-summaries', function () { const sessionSummaryRepository = { diff --git a/api/tests/unit/infrastructure/serializers/jsonapi/session-summary-serializer_test.js b/api/tests/certification/session-management/unit/infrastructure/serializers/session-summary-serializer_test.js similarity index 83% rename from api/tests/unit/infrastructure/serializers/jsonapi/session-summary-serializer_test.js rename to api/tests/certification/session-management/unit/infrastructure/serializers/session-summary-serializer_test.js index e31accb4e44..19301abc027 100644 --- a/api/tests/unit/infrastructure/serializers/jsonapi/session-summary-serializer_test.js +++ b/api/tests/certification/session-management/unit/infrastructure/serializers/session-summary-serializer_test.js @@ -1,5 +1,5 @@ -import * as serializer from '../../../../../lib/infrastructure/serializers/jsonapi/session-summary-serializer.js'; -import { domainBuilder, expect } from '../../../../test-helper.js'; +import * as serializer from '../../../../../../src/certification/session-management/infrastructure/serializers/session-summary-serializer.js'; +import { domainBuilder, expect } from '../../../../../test-helper.js'; describe('Unit | Serializer | JSONAPI | session-summary-serializer', function () { describe('#serialize()', function () { diff --git a/api/tests/unit/application/certification-centers/certification-center-controller_test.js b/api/tests/unit/application/certification-centers/certification-center-controller_test.js index 50972e57d3c..14ed71d70f2 100644 --- a/api/tests/unit/application/certification-centers/certification-center-controller_test.js +++ b/api/tests/unit/application/certification-centers/certification-center-controller_test.js @@ -182,79 +182,6 @@ describe('Unit | Controller | certifications-center-controller', function () { }); }); - describe('#findPaginatedSessionSummaries', function () { - beforeEach(function () { - sinon.stub(usecases, 'findPaginatedCertificationCenterSessionSummaries'); - }); - - it('should return a list of JSON API session summaries with pagination information', async function () { - // given - const request = { - params: { id: 456 }, - auth: { credentials: { userId: 123 } }, - query: { - page: { - number: 1, - size: 10, - }, - }, - }; - const sessionSummary = domainBuilder.buildSessionSummary.created({ - id: 1, - address: 'ici', - room: 'la-bas', - date: '2020-01-01', - time: '16:00', - examiner: 'Moi', - enrolledCandidatesCount: 5, - effectiveCandidatesCount: 4, - }); - usecases.findPaginatedCertificationCenterSessionSummaries - .withArgs({ - userId: 123, - certificationCenterId: 456, - page: { number: 1, size: 10 }, - }) - .resolves({ - models: [sessionSummary], - meta: { page: 1, pageSize: 10, itemsCount: 1, pagesCount: 1, hasSessions: true }, - }); - - // when - const serializedSessionSummaries = await certificationCenterController.findPaginatedSessionSummaries( - request, - hFake, - ); - - // then - expect(serializedSessionSummaries).to.deep.equal({ - data: [ - { - id: '1', - type: 'session-summaries', - attributes: { - address: 'ici', - room: 'la-bas', - date: '2020-01-01', - time: '16:00', - examiner: 'Moi', - 'effective-candidates-count': 4, - 'enrolled-candidates-count': 5, - status: 'created', - }, - }, - ], - meta: { - hasSessions: true, - itemsCount: 1, - page: 1, - pageSize: 10, - pagesCount: 1, - }, - }); - }); - }); - describe('#updateReferer', function () { it('should call updateCertificationCenterReferer usecase and return 204', async function () { // given diff --git a/api/tests/unit/application/certification-centers/index_test.js b/api/tests/unit/application/certification-centers/index_test.js index 40a136f8abc..80e1c78afc1 100644 --- a/api/tests/unit/application/certification-centers/index_test.js +++ b/api/tests/unit/application/certification-centers/index_test.js @@ -272,20 +272,4 @@ describe('Unit | Router | certification-center-router', function () { expect(result.statusCode).to.equal(400); }); }); - - describe('GET /api/certification-centers/{certificationCenterId}/session-summaries', function () { - it('should return 200', async function () { - // given - sinon.stub(certificationCenterController, 'findPaginatedSessionSummaries').returns('ok'); - const httpTestServer = new HttpTestServer(); - await httpTestServer.register(moduleUnderTest); - - // when - const response = await httpTestServer.request('GET', '/api/certification-centers/123/session-summaries'); - - // then - expect(response.statusCode).to.equal(200); - sinon.assert.calledOnce(certificationCenterController.findPaginatedSessionSummaries); - }); - }); });