From 7edda701a9fe5a8c72dde2a669bee730224390bb Mon Sep 17 00:00:00 2001 From: P-Jeremy Date: Wed, 9 Oct 2024 17:12:35 +0200 Subject: [PATCH] WIP --- ...et-certification-candidate-subscription.js | 1 + ...ation-candidate-subscription-serializer.js | 2 +- .../application/subscription-route_test.js | 239 +++++++++++++++++- ...rtification-candidate-subscription_test.js | 7 +- ...-candidate-subscription-serializer_test.js | 17 +- 5 files changed, 238 insertions(+), 28 deletions(-) diff --git a/api/src/certification/enrolment/domain/usecases/get-certification-candidate-subscription.js b/api/src/certification/enrolment/domain/usecases/get-certification-candidate-subscription.js index a8c5ea0784d..0a8d735a7e1 100644 --- a/api/src/certification/enrolment/domain/usecases/get-certification-candidate-subscription.js +++ b/api/src/certification/enrolment/domain/usecases/get-certification-candidate-subscription.js @@ -31,6 +31,7 @@ const getCertificationCandidateSubscription = async function ({ let nonEligibleSubscription = null; const certifiableBadgeAcquisitions = await certificationBadgesService.findStillValidBadgeAcquisitions({ userId: certificationCandidate.userId, + limitDate: certificationCandidate.reconciledAt, }); if (center.isHabilitated(certificationCandidate.complementaryCertification.key)) { diff --git a/api/src/certification/enrolment/infrastructure/serializers/certification-candidate-subscription-serializer.js b/api/src/certification/enrolment/infrastructure/serializers/certification-candidate-subscription-serializer.js index fbc06d5e2f4..75ff7b8ba97 100644 --- a/api/src/certification/enrolment/infrastructure/serializers/certification-candidate-subscription-serializer.js +++ b/api/src/certification/enrolment/infrastructure/serializers/certification-candidate-subscription-serializer.js @@ -4,7 +4,7 @@ const { Serializer } = jsonapiSerializer; const serialize = function (certificationCandidateSubscription) { return new Serializer('certification-candidate-subscription', { - attributes: ['sessionId', 'eligibleSubscription', 'nonEligibleSubscription', 'sessionVersion'], + attributes: ['sessionId', 'eligibleSubscriptions', 'nonEligibleSubscription', 'sessionVersion'], }).serialize(certificationCandidateSubscription); }; diff --git a/api/tests/certification/enrolment/acceptance/application/subscription-route_test.js b/api/tests/certification/enrolment/acceptance/application/subscription-route_test.js index 5ae8939e3f1..8b159b231af 100644 --- a/api/tests/certification/enrolment/acceptance/application/subscription-route_test.js +++ b/api/tests/certification/enrolment/acceptance/application/subscription-route_test.js @@ -4,6 +4,8 @@ import { databaseBuilder, expect, generateValidRequestAuthorizationHeader, + learningContentBuilder, + mockLearningContent, } from '../../../../test-helper.js'; describe('Certification | Enrolment | Acceptance | Application | Routes | subscription', function () { @@ -11,29 +13,220 @@ describe('Certification | Enrolment | Acceptance | Application | Routes | subscr it('should return the certification candidate subscriptions', async function () { // given const server = await createServer(); + + const learningContent = learningContentBuilder.fromAreas([ + { + id: 'recvoGdo7z2z7pXWa', + title_i18n: { + fr: 'Information et données', + }, + color: 'jaffa', + code: '1', + competences: [ + { + id: 'recCompetence1', + name_i18n: { + fr: 'Mener une recherche et une veille d’information', + }, + index: '1.1', + origin: 'Pix', + areaId: 'recvoGdo7z2z7pXWa', + thematics: [ + { + id: 'recThemCompetence1', + tubes: [ + { + id: 'recTubeCompetence1', + skills: [ + { + id: 'skillId@web3', + name: '@web3', + status: 'actif', + level: 3, + }, + ], + }, + ], + }, + ], + }, + { + id: 'recCompetence2', + name_i18n: { + fr: 'Gérer les données', + }, + index: '1.2', + origin: 'Pix', + areaId: 'recvoGdo7z2z7pXWa', + thematics: [ + { + id: 'recThemCompetence2', + tubes: [ + { + id: 'recTubeCompetence2', + skills: [ + { + id: 'skillId@fichier3', + name: '@fichier3', + status: 'actif', + level: 3, + }, + ], + }, + ], + }, + ], + }, + { + id: 'recCompetence3', + name_i18n: { + fr: 'Traiter les données', + }, + index: '1.3', + origin: 'Pix', + areaId: 'recvoGdo7z2z7pXWa', + thematics: [ + { + id: 'recThemCompetence3', + tubes: [ + { + id: 'recTubeCompetence3', + skills: [ + { + id: 'skillId@tri3', + name: '@tri3', + status: 'actif', + level: 3, + }, + ], + }, + ], + }, + ], + }, + ], + }, + { + id: 'recDH19F7kKrfL3Ii', + title_i18n: { + fr: 'Communication et collaboration', + }, + color: 'jaffa', + code: '1', + competences: [ + { + id: 'recCompetence4', + name_i18n: { + fr: 'Intéragir', + }, + index: '2.1', + origin: 'Pix', + areaId: 'recDH19F7kKrfL3Ii', + thematics: [ + { + id: 'recThemCompetence4', + tubes: [ + { + id: 'recTubeCompetence4', + skills: [ + { + id: 'skillId@spam3', + name: '@spam3', + status: 'actif', + level: 3, + }, + ], + }, + ], + }, + ], + }, + { + id: 'recCompetence5', + name_i18n: { + fr: 'Partager et publier', + }, + index: '2.2', + origin: 'Pix', + areaId: 'recDH19F7kKrfL3Ii', + thematics: [ + { + id: 'recThemCompetence5', + tubes: [ + { + id: 'recTubeCompetence5', + skills: [ + { + id: 'skillId@vocRS3', + name: '@vocRS3', + status: 'actif', + level: 3, + }, + ], + }, + ], + }, + ], + }, + ], + }, + ]); + mockLearningContent(learningContent); + const userId = databaseBuilder.factory.buildUser().id; + + learningContent.skills.forEach(({ id: skillId, competenceId }) => { + databaseBuilder.factory.buildKnowledgeElement({ userId, earnedPix: 10, competenceId, skillId }); + }); + + const targetProfileId = databaseBuilder.factory.buildTargetProfile().id; + const badgeId = databaseBuilder.factory.buildBadge({ isCertifiable: true, targetProfileId }).id; + const campaignId = databaseBuilder.factory.buildCampaign({ + targetProfileId, + }).id; + const campaignParticipationId = databaseBuilder.factory.buildCampaignParticipation({ + campaignId, + isCertifiable: true, + userId, + }).id; + + learningContent.skills.forEach(({ id: skillId }) => { + databaseBuilder.factory.buildCampaignSkill({ + campaignId, + skillId, + }); + }); + + databaseBuilder.factory.buildBadgeCriterion({ + badgeId, + threshold: 75, + cappedTubes: JSON.stringify( + learningContent.tubes.map(({ id }) => ({ + id, + level: 8, + })), + ), + }); + const certificationCenter = databaseBuilder.factory.buildCertificationCenter(); const cleaComplementaryCertification = databaseBuilder.factory.buildComplementaryCertification({ key: ComplementaryCertificationKeys.CLEA, label: 'CléA Numérique', }); - const pixPlusDroitComplementaryCertification = databaseBuilder.factory.buildComplementaryCertification({ - key: ComplementaryCertificationKeys.PIX_PLUS_DROIT, - label: 'Pix+ Droit', - }); + databaseBuilder.factory.buildComplementaryCertificationHabilitation({ certificationCenterId: certificationCenter.id, complementaryCertificationId: cleaComplementaryCertification.id, }); - databaseBuilder.factory.buildComplementaryCertificationHabilitation({ - certificationCenterId: certificationCenter.id, - complementaryCertificationId: pixPlusDroitComplementaryCertification.id, - }); + const session = databaseBuilder.factory.buildSession({ certificationCenterId: certificationCenter.id, }); + const candidate = databaseBuilder.factory.buildCertificationCandidate({ sessionId: session.id, + userId, + reconciledAt: new Date('2021-01-01'), }); databaseBuilder.factory.buildCoreSubscription({ certificationCandidateId: candidate.id }); @@ -42,6 +235,19 @@ describe('Certification | Enrolment | Acceptance | Application | Routes | subscr certificationCandidateId: candidate.id, complementaryCertificationId: cleaComplementaryCertification.id, }); + + databaseBuilder.factory.buildComplementaryCertificationBadge({ + badgeId, + complementaryCertificationId: cleaComplementaryCertification.id, + }); + + databaseBuilder.factory.buildBadgeAcquisition({ + userId, + badgeId, + campaignParticipationId, + createdAt: new Date('2020-01-01'), + }); + await databaseBuilder.commit(); const options = { @@ -61,12 +267,17 @@ describe('Certification | Enrolment | Acceptance | Application | Routes | subscr attributes: { 'session-id': session.id, 'session-version': session.version, - 'eligible-subscription': null, - 'non-eligible-subscription': { - id: cleaComplementaryCertification.id, - label: 'CléA Numérique', - key: ComplementaryCertificationKeys.CLEA, - }, + 'eligible-subscriptions': [ + { + label: null, + type: 'CORE', + }, + { + label: 'CléA Numérique', + type: 'COMPLEMENTARY', + }, + ], + 'non-eligible-subscription': null, }, }); }); diff --git a/api/tests/certification/enrolment/unit/domain/usecases/get-certification-candidate-subscription_test.js b/api/tests/certification/enrolment/unit/domain/usecases/get-certification-candidate-subscription_test.js index 6bb33b4f1ed..29f51802903 100644 --- a/api/tests/certification/enrolment/unit/domain/usecases/get-certification-candidate-subscription_test.js +++ b/api/tests/certification/enrolment/unit/domain/usecases/get-certification-candidate-subscription_test.js @@ -28,6 +28,7 @@ describe('Certification | Enrolment | Unit | Domain | UseCase | get-certificatio userId, sessionId, subscriptions: [domainBuilder.buildCoreSubscription()], + reconciledAt: new Date('2024-10-09'), }; sessionRepository = { @@ -144,7 +145,7 @@ describe('Certification | Enrolment | Unit | Domain | UseCase | get-certificatio centerRepository.getById.withArgs({ id: 777 }).resolves(center); certificationBadgesService.findStillValidBadgeAcquisitions - .withArgs({ userId }) + .withArgs({ userId, limitDate: certificationCandidateData.reconciledAt }) .resolves([certifiableBadgeAcquisition]); // when @@ -219,7 +220,7 @@ describe('Certification | Enrolment | Unit | Domain | UseCase | get-certificatio centerRepository.getById.withArgs({ id: 777 }).resolves(center); certificationBadgesService.findStillValidBadgeAcquisitions - .withArgs({ userId }) + .withArgs({ userId, limitDate: certificationCandidateData.reconciledAt }) .resolves([certifiableBadgeAcquisition]); // when @@ -299,7 +300,7 @@ describe('Certification | Enrolment | Unit | Domain | UseCase | get-certificatio centerRepository.getById.withArgs({ id: 777 }).resolves(center); certificationBadgesService.findStillValidBadgeAcquisitions - .withArgs({ userId }) + .withArgs({ userId, limitDate: certificationCandidateData.reconciledAt }) .resolves([certifiableBadgeAcquisition]); // when diff --git a/api/tests/certification/enrolment/unit/infrastructure/serializers/certification-candidate-subscription-serializer_test.js b/api/tests/certification/enrolment/unit/infrastructure/serializers/certification-candidate-subscription-serializer_test.js index 270575275b1..11809c5ab78 100644 --- a/api/tests/certification/enrolment/unit/infrastructure/serializers/certification-candidate-subscription-serializer_test.js +++ b/api/tests/certification/enrolment/unit/infrastructure/serializers/certification-candidate-subscription-serializer_test.js @@ -7,12 +7,8 @@ describe('Certification | Enrolment | Unit | Serializer | certification-candidat const certificationCandidateSubscription = domainBuilder.buildCertificationCandidateSubscription({ id: 123, sessionId: 456, - eligibleSubscription: domainBuilder.buildComplementaryCertification({ - key: 'FIRST_COMPLEMENTARY', - label: 'First Complementary Certification', - }), + eligibleSubscriptions: [{ type: 'COMPLEMENTARY', label: 'First Complementary Certification' }], sessionVersion: 2, - nonEligibleSubscription: domainBuilder.buildComplementaryCertification({ key: 'SECOND_COMPLEMENTARY', label: 'Second Complementary Certification', @@ -24,11 +20,12 @@ describe('Certification | Enrolment | Unit | Serializer | certification-candidat id: '123', type: 'certification-candidate-subscriptions', attributes: { - 'eligible-subscription': { - id: 1, - key: 'FIRST_COMPLEMENTARY', - label: 'First Complementary Certification', - }, + 'eligible-subscriptions': [ + { + type: 'COMPLEMENTARY', + label: 'First Complementary Certification', + }, + ], 'non-eligible-subscription': { id: 1, key: 'SECOND_COMPLEMENTARY',