diff --git a/certif/app/controllers/authenticated/sessions/details/parameters.js b/certif/app/controllers/authenticated/sessions/details/parameters.js
index 9458f8d1ae1..7af9f040e48 100644
--- a/certif/app/controllers/authenticated/sessions/details/parameters.js
+++ b/certif/app/controllers/authenticated/sessions/details/parameters.js
@@ -19,6 +19,13 @@ export default class SessionParametersController extends Controller {
return this.certificationCandidates.some(({ isLinked }) => isLinked);
}
+ get isSessionFinalizationTemporarilyBlocked() {
+ return (
+ this.certificationCandidates.some((candidate) => candidate.hasOnlyComplementarySubscription) &&
+ this.sessionManagement.version === 3
+ );
+ }
+
@action
async showSessionIdTooltip() {
await navigator.clipboard.writeText(this.session.id);
diff --git a/certif/app/models/certification-candidate.js b/certif/app/models/certification-candidate.js
index 1fa637571c6..bc914a5afe1 100644
--- a/certif/app/models/certification-candidate.js
+++ b/certif/app/models/certification-candidate.js
@@ -58,4 +58,10 @@ export default class CertificationCandidate extends Model {
const hasCleaSubscription = this.subscriptions.some((sub) => sub.isClea(centerHabilitations));
return hasCoreSubscription && hasCleaSubscription;
}
+
+ get hasOnlyComplementarySubscription() {
+ const hasCoreSubscription = this.subscriptions.some((sub) => sub.isCore);
+ const hasComplementarySubscription = this.subscriptions.some((sub) => sub.isComplementary);
+ return !hasCoreSubscription && hasComplementarySubscription;
+ }
}
diff --git a/certif/app/models/subscription.js b/certif/app/models/subscription.js
index 92a556a044f..0670a79d6d9 100644
--- a/certif/app/models/subscription.js
+++ b/certif/app/models/subscription.js
@@ -17,6 +17,10 @@ export default class SubscriptionModel extends Model {
return this.type === SUBSCRIPTION_TYPES.CORE;
}
+ get isComplementary() {
+ return this.type === SUBSCRIPTION_TYPES.COMPLEMENTARY;
+ }
+
isClea(centerHabilitations) {
const matchingHabilitation = centerHabilitations.find(
(habilitation) => habilitation.id === this.complementaryCertificationId,
diff --git a/certif/app/templates/authenticated/sessions/details/parameters.hbs b/certif/app/templates/authenticated/sessions/details/parameters.hbs
index 2cfe2bf28e1..a9fcb481083 100644
--- a/certif/app/templates/authenticated/sessions/details/parameters.hbs
+++ b/certif/app/templates/authenticated/sessions/details/parameters.hbs
@@ -129,14 +129,20 @@
{{t "common.actions.update"}}
{{#if this.sessionHasStarted}}
- {{#if this.sessionManagement.isFinalized}}
+ {{#if this.isSessionFinalizationTemporarilyBlocked}}
- {{t "pages.sessions.detail.parameters.finalization-info"}}
+ {{t "pages.sessions.detail.parameters.finalization.temporarily-blocked"}}
{{else}}
-
- {{t "pages.sessions.detail.parameters.actions.finalizing"}}
-
+ {{#if this.sessionManagement.isFinalized}}
+
+ {{t "pages.sessions.detail.parameters.finalization-info"}}
+
+ {{else}}
+
+ {{t "pages.sessions.detail.parameters.actions.finalizing"}}
+
+ {{/if}}
{{/if}}
{{/if}}
diff --git a/certif/tests/acceptance/session-details-parameters-test.js b/certif/tests/acceptance/session-details-parameters-test.js
index b7977fd0c90..b510adcf49e 100644
--- a/certif/tests/acceptance/session-details-parameters-test.js
+++ b/certif/tests/acceptance/session-details-parameters-test.js
@@ -4,6 +4,7 @@ import setupMirage from 'ember-cli-mirage/test-support/setup-mirage';
import { setupIntl } from 'ember-intl/test-support';
import { setupApplicationTest } from 'ember-qunit';
import { CREATED, FINALIZED } from 'pix-certif/models/session-management';
+import { SUBSCRIPTION_TYPES } from 'pix-certif/models/subscription';
import { module, test } from 'qunit';
import { authenticateSession } from '../helpers/test-init';
@@ -85,6 +86,64 @@ module('Acceptance | Session Details Parameters', function (hooks) {
.exists();
});
+ module('when the session version is 3 and candidates have been enrolled for a complementary course', function () {
+ test('it should temporarily block the finalise button', async function (assert) {
+ // given
+ const allowedCertificationCenterAccess = server.create('allowed-certification-center-access', {
+ isAccessBlockedCollege: false,
+ isAccessBlockedLycee: false,
+ isAccessBlockedAEFE: false,
+ isAccessBlockedAgri: false,
+ isV3Pilot: true,
+ habilitations: [
+ {
+ id: 123,
+ label: 'Pix+Droit',
+ },
+ ],
+ });
+ certificationPointOfContact = server.create('certification-point-of-contact', {
+ firstName: 'Buffy',
+ lastName: 'Summers',
+ allowedCertificationCenterAccesses: [allowedCertificationCenterAccess],
+ pixCertifTermsOfServiceAccepted: true,
+ });
+ await authenticateSession(certificationPointOfContact.id);
+ const sessionCreated = server.create('session-enrolment', {
+ id: 123,
+ status: CREATED,
+ certificationCenterId: allowedCertificationCenterAccess.id,
+ });
+ const complementarySubscription = server.create('subscription', {
+ type: SUBSCRIPTION_TYPES.COMPLEMENTARY,
+ complementaryCertificationId: 123,
+ });
+ server.create('certification-candidate', {
+ isLinked: true,
+ subscriptions: [complementarySubscription],
+ sessionId: sessionCreated.id,
+ });
+ server.create('session-management', {
+ id: sessionCreated.id,
+ status: CREATED,
+ version: 3,
+ });
+
+ // when
+ const screen = await visit(`/sessions/${sessionCreated.id}`);
+
+ // then
+ assert.dom(screen.queryByRole('button', { name: 'Finaliser la session' })).doesNotExist();
+ assert
+ .dom(
+ screen.getByText(
+ 'Cette session ne peut pas être finalisée pour le moment. Les équipes de Pix travaillent au déblocage de la finalisation.',
+ ),
+ )
+ .exists();
+ });
+ });
+
module('when the session is not finalized', function () {
module('when the session is CREATED', function () {
test('it should not display the finalize button if no candidate has joined the session', async function (assert) {
diff --git a/certif/tests/unit/models/certification-candidate-test.js b/certif/tests/unit/models/certification-candidate-test.js
index 958ad238c3a..1236d50b61e 100644
--- a/certif/tests/unit/models/certification-candidate-test.js
+++ b/certif/tests/unit/models/certification-candidate-test.js
@@ -222,6 +222,80 @@ module('Unit | Model | certification-candidate', function (hooks) {
});
});
+ module('#get hasOnlyComplementarySubscription', function () {
+ module('when candidate has only one complementary subscription', function () {
+ test('should return true', function (assert) {
+ // given
+ // when
+ const store = this.owner.lookup('service:store');
+ const habilitations = [
+ {
+ id: 123,
+ label: 'Certif Pix+Droit',
+ key: 'DROIT',
+ },
+ ];
+ const complementarySubscription = store.createRecord('subscription', {
+ type: SUBSCRIPTION_TYPES.COMPLEMENTARY,
+ complementaryCertificationId: habilitations[0].id,
+ });
+ const candidate = store.createRecord('certification-candidate', {
+ subscriptions: [complementarySubscription],
+ });
+
+ // then
+ assert.true(candidate.hasOnlyComplementarySubscription);
+ });
+ });
+
+ module('when candidate has a core subscription', function () {
+ test('should return false', function (assert) {
+ // given
+ // when
+ const store = this.owner.lookup('service:store');
+ const coreSubscription = store.createRecord('subscription', {
+ type: SUBSCRIPTION_TYPES.CORE,
+ complementaryCertificationId: null,
+ });
+ const candidate = store.createRecord('certification-candidate', {
+ subscriptions: [coreSubscription],
+ });
+
+ // then
+ assert.false(candidate.hasOnlyComplementarySubscription);
+ });
+ });
+
+ module('when candidate has a clea subscription', function () {
+ test('should return false', function (assert) {
+ // given
+ // when
+ const habilitations = [
+ {
+ id: 123,
+ label: 'Certif CLEA',
+ key: COMPLEMENTARY_KEYS.CLEA,
+ },
+ ];
+ const store = this.owner.lookup('service:store');
+ const coreSubscription = store.createRecord('subscription', {
+ type: SUBSCRIPTION_TYPES.CORE,
+ complementaryCertificationId: null,
+ });
+ const cleaSubscription = store.createRecord('subscription', {
+ type: SUBSCRIPTION_TYPES.COMPLEMENTARY,
+ complementaryCertificationId: habilitations[0].id,
+ });
+ const candidate = store.createRecord('certification-candidate', {
+ subscriptions: [coreSubscription, cleaSubscription],
+ });
+
+ // then
+ assert.false(candidate.hasOnlyComplementarySubscription);
+ });
+ });
+ });
+
function _pickModelData(certificationCandidate) {
return pick(certificationCandidate, [
'firstName',
diff --git a/certif/tests/unit/models/subscription-test.js b/certif/tests/unit/models/subscription-test.js
index 018aee157a5..28fcf4cdfa2 100644
--- a/certif/tests/unit/models/subscription-test.js
+++ b/certif/tests/unit/models/subscription-test.js
@@ -109,4 +109,47 @@ module('Unit | Model | subscription', function (hooks) {
assert.false(isCore);
});
});
+
+ module('get isComplementary', function () {
+ module('when subscription is COMPLEMENTARY', function () {
+ test('it should return true', function (assert) {
+ // given
+ const store = this.owner.lookup('service:store');
+ const habilitations = [
+ {
+ id: 123,
+ label: 'Pix+Droit',
+ key: 'DROIT',
+ },
+ ];
+ const complementarySubscription = store.createRecord('subscription', {
+ type: SUBSCRIPTION_TYPES.COMPLEMENTARY,
+ complementaryCertificationId: habilitations[0].id,
+ });
+
+ // when
+ const isComplementary = complementarySubscription.isComplementary;
+
+ // then
+ assert.true(isComplementary);
+ });
+ });
+
+ module('when subscription is not COMPLEMENTARY', function () {
+ test('it should return false', function (assert) {
+ // given
+ const store = this.owner.lookup('service:store');
+ const coreSubscription = store.createRecord('subscription', {
+ type: SUBSCRIPTION_TYPES.CORE,
+ complementaryCertificationId: null,
+ });
+
+ // when
+ const isComplementary = coreSubscription.isComplementary;
+
+ // then
+ assert.false(isComplementary);
+ });
+ });
+ });
});
diff --git a/certif/translations/en.json b/certif/translations/en.json
index 366d00716ba..d5beb99ac46 100644
--- a/certif/translations/en.json
+++ b/certif/translations/en.json
@@ -702,6 +702,9 @@
"finalizing": "Finalise the session",
"update": "Edit the details for session {sessionId}"
},
+ "finalization": {
+ "temporarily-blocked": "This session cannot be finalised at the moment. The Pix teams are working to unblock the finalization."
+ },
"finalization-info": "The finalisation information for the session has already been transmitted to Pix.",
"password": {
"copy-password": "Copy the invigilator’s session password",
diff --git a/certif/translations/fr.json b/certif/translations/fr.json
index fdd2a17ee0e..9cb8dfddceb 100644
--- a/certif/translations/fr.json
+++ b/certif/translations/fr.json
@@ -702,6 +702,9 @@
"finalizing": "Finaliser la session",
"update": "Modifier les informations de la session {sessionId}"
},
+ "finalization": {
+ "temporarily-blocked": "Cette session ne peut pas être finalisée pour le moment. Les équipes de Pix travaillent au déblocage de la finalisation."
+ },
"finalization-info": "Les informations de finalisation de la session ont déjà été transmises aux équipes de Pix.",
"password": {
"copy-password": "Copier le mot de passe de session pour le surveillant",