Skip to content

Commit

Permalink
[BUGFIX] Permettre la finalisation des sessions ayant à la fois des c…
Browse files Browse the repository at this point in the history
…ertifications complétés et une raison d'abandon (PIX-15524).

 #10759
  • Loading branch information
pix-service-auto-merge authored Dec 11, 2024
2 parents d560f15 + 1bbb86e commit 384ef16
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 75 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,11 @@ async function _removeAbortReasonFromCompletedCertificationCourses({
sessionCertificationCourse.isCompleted()
) {
sessionCertificationCourse.unabort();
await certificationCourseRepository.update({ certificationCourse: sessionCertificationCourse });
// do not use transaction so throwing error will not revert the session unabort
await certificationCourseRepository.update({
certificationCourse: sessionCertificationCourse,
noTransaction: true,
});
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import _ from 'lodash';

import { knex } from '../../../../../db/knex-database-connection.js';
import {
logErrorWithCorrelationIds,
logInfoWithCorrelationIds,
} from '../../../../../src/shared/infrastructure/monitoring-tools.js';
import { config } from '../../../../shared/config.js';
import { DomainTransaction } from '../../../../shared/domain/DomainTransaction.js';
import { NotFoundError } from '../../../../shared/domain/errors.js';
import { Assessment } from '../../../../shared/domain/models/index.js';
import {
logErrorWithCorrelationIds,
logInfoWithCorrelationIds,
} from '../../../../shared/infrastructure/monitoring-tools.js';
import { ComplementaryCertificationCourse } from '../../../session-management/domain/models/ComplementaryCertificationCourse.js';
import { CertificationCourse } from '../../domain/models/CertificationCourse.js';
import { CertificationIssueReport } from '../../domain/models/CertificationIssueReport.js';
Expand Down Expand Up @@ -202,13 +202,13 @@ async function findOneCertificationCourseByUserIdAndSessionId({ userId, sessionI
});
}

async function update({ certificationCourse }) {
const knexConn = DomainTransaction.getConnection();
async function update({ certificationCourse, noTransaction = false }) {
const knexConn = noTransaction ? knex : DomainTransaction.getConnection();

const certificationCourseData = _pickUpdatableProperties(certificationCourse);

const nbOfUpdatedCertificationCourses = await knexConn('certification-courses')
.update(certificationCourseData)
.update({ ...certificationCourseData, updatedAt: new Date() })
.where({ id: certificationCourseData.id });

if (nbOfUpdatedCertificationCourses === 0) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { SessionWithAbortReasonOnCompletedCertificationCourseError } from '../../../../../../src/certification/session-management/domain/errors.js';
import { usecases } from '../../../../../../src/certification/session-management/domain/usecases/index.js';
import { ABORT_REASONS } from '../../../../../../src/certification/shared/domain/models/CertificationCourse.js';
import { catchErr, databaseBuilder, expect, knex } from '../../../../../test-helper.js';

describe('Certification | Session Management | Integration | Domain | UseCase | Finalize Session ', function () {
context('When there is an abort reason for completed certification course', function () {
it('should throw an SessionWithAbortReasonOnCompletedCertificationCourseError error', async function () {
const certificationCourse = databaseBuilder.factory.buildCertificationCourse({
abortReason: ABORT_REASONS.CANDIDATE,
completedAt: new Date(),
});
await databaseBuilder.commit();
const certificationReports = [
{ certificationCourseId: certificationCourse.id, abortReason: ABORT_REASONS.CANDIDATE },
];

const err = await catchErr(usecases.finalizeSession)({
sessionId: certificationCourse.sessionId,
certificationReports,
});

expect(err).to.be.instanceOf(SessionWithAbortReasonOnCompletedCertificationCourseError);
const updatedCertificationCourse = await knex('certification-courses')
.where('id', certificationCourse.id)
.first();
expect(updatedCertificationCourse.abortReason).to.be.null;
});
});
});
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import {
SessionAlreadyFinalizedError,
SessionWithAbortReasonOnCompletedCertificationCourseError,
SessionWithMissingAbortReasonError,
SessionWithoutStartedCertificationError,
} from '../../../../../../src/certification/session-management/domain/errors.js';
Expand Down Expand Up @@ -108,44 +107,6 @@ describe('Unit | UseCase | finalize-session', function () {
});
});

context('When there is an abort reason for completed certification course', function () {
it('should throw an SessionWithAbortReasonOnCompletedCertificationCourseError error', async function () {
// given
const reportWithAbortReason = domainBuilder.buildCertificationReport({
abortReason: 'candidate',
certificationCourseId: 1234,
});
const certificationReports = [reportWithAbortReason];
const completedCertificationCourse = domainBuilder.buildCertificationCourse({
id: 1234,
abortReason: 'candidate',
completedAt: '2022-01-01',
});
sessionRepository.countUncompletedCertificationsAssessment.withArgs({ id: sessionId }).resolves(0);
certificationCourseRepository.findCertificationCoursesBySessionId
.withArgs({ sessionId })
.resolves([completedCertificationCourse]);

certificationCourseRepository.update.resolves(
domainBuilder.buildCertificationCourse({ ...completedCertificationCourse, abortReason: null }),
);

// when
const err = await catchErr(finalizeSession)({
sessionId,
examinerGlobalComment,
sessionRepository,
certificationReports,
certificationReportRepository,
certificationCourseRepository,
});

// then
expect(certificationCourseRepository.update).to.have.been.calledOnce;
expect(err).to.be.instanceOf(SessionWithAbortReasonOnCompletedCertificationCourseError);
});
});

context('When there is no abort reason for uncompleted certification course', function () {
it('should throw an SessionWithMissingAbortReasonError error', async function () {
// given
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -361,14 +361,15 @@ describe('Integration | Repository | Certification Course', function () {
});

describe('#update', function () {
let certificationCourse;
let certificationCourse, certificationCourseData;

beforeEach(async function () {
// given
const userId = databaseBuilder.factory.buildUser({}).id;
const certificationCourseData = databaseBuilder.factory.buildCertificationCourse({
certificationCourseData = databaseBuilder.factory.buildCertificationCourse({
userId,
isCancelled: false,
updatedAt: new Date('2020-12-01'),
});
certificationCourse = domainBuilder.buildCertificationCourse(certificationCourseData);
await databaseBuilder.commit();
Expand Down Expand Up @@ -408,36 +409,26 @@ describe('Integration | Repository | Certification Course', function () {

// then
const unpersistedUpdatedCertificationCourseDTO = unpersistedUpdatedCertificationCourse.toDTO();
const persistedUpdatedCertificationCourse = await certificationCourseRepository.get({
id: unpersistedUpdatedCertificationCourseDTO.id,
});
const persistedUpdatedCertificationCourseDTO = persistedUpdatedCertificationCourse.toDTO();
expect(persistedUpdatedCertificationCourse.getId()).to.equal(unpersistedUpdatedCertificationCourse.getId());
expect(persistedUpdatedCertificationCourseDTO.firstName).to.equal(
unpersistedUpdatedCertificationCourseDTO.firstName,
);
expect(persistedUpdatedCertificationCourseDTO.lastName).to.equal(
unpersistedUpdatedCertificationCourseDTO.lastName,
);
expect(persistedUpdatedCertificationCourseDTO.birthdate).to.equal(
unpersistedUpdatedCertificationCourseDTO.birthdate,
);
expect(persistedUpdatedCertificationCourseDTO.birthplace).to.equal(
unpersistedUpdatedCertificationCourseDTO.birthplace,
);
expect(persistedUpdatedCertificationCourseDTO.birthPostalCode).to.equal(
const updatedCertificationCourse = await knex('certification-courses')
.where('id', unpersistedUpdatedCertificationCourse.getId())
.first();
expect(updatedCertificationCourse.id).to.equal(unpersistedUpdatedCertificationCourse.getId());
expect(updatedCertificationCourse.firstName).to.equal(unpersistedUpdatedCertificationCourseDTO.firstName);
expect(updatedCertificationCourse.lastName).to.equal(unpersistedUpdatedCertificationCourseDTO.lastName);
expect(updatedCertificationCourse.birthdate).to.equal(unpersistedUpdatedCertificationCourseDTO.birthdate);
expect(updatedCertificationCourse.birthplace).to.equal(unpersistedUpdatedCertificationCourseDTO.birthplace);
expect(updatedCertificationCourse.birthPostalCode).to.equal(
unpersistedUpdatedCertificationCourseDTO.birthPostalCode,
);
expect(persistedUpdatedCertificationCourseDTO.birthINSEECode).to.equal(
expect(updatedCertificationCourse.birthINSEECode).to.equal(
unpersistedUpdatedCertificationCourseDTO.birthINSEECode,
);
expect(persistedUpdatedCertificationCourseDTO.birthCountry).to.equal(
unpersistedUpdatedCertificationCourseDTO.birthCountry,
);
expect(persistedUpdatedCertificationCourseDTO.sex).to.equal(unpersistedUpdatedCertificationCourseDTO.sex);
expect(persistedUpdatedCertificationCourseDTO.isCancelled).to.be.true;
expect(persistedUpdatedCertificationCourseDTO.completedAt).to.deep.equal(new Date('1999-12-31'));
expect(persistedUpdatedCertificationCourseDTO.isRejectedForFraud).to.be.true;
expect(updatedCertificationCourse.birthCountry).to.equal(unpersistedUpdatedCertificationCourseDTO.birthCountry);
expect(updatedCertificationCourse.sex).to.equal(unpersistedUpdatedCertificationCourseDTO.sex);
expect(updatedCertificationCourse.isCancelled).to.be.true;
expect(updatedCertificationCourse.completedAt).to.deep.equal(new Date('1999-12-31'));
expect(updatedCertificationCourse.isRejectedForFraud).to.be.true;
expect(updatedCertificationCourse.updatedAt).to.be.greaterThan(certificationCourseData.updatedAt);
});

it('should prevent other values to be updated', async function () {
Expand Down

0 comments on commit 384ef16

Please sign in to comment.