Skip to content

Commit

Permalink
[FEATURE] Sauvegarder la date de reconciliation (PIX-14392).
Browse files Browse the repository at this point in the history
  • Loading branch information
pix-service-auto-merge authored Sep 24, 2024
2 parents 542b5b3 + fe4f043 commit 4f9d33e
Show file tree
Hide file tree
Showing 26 changed files with 165 additions and 237 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,11 @@ const buildCertificationCandidate = function ({
prepaymentCode = null,
hasSeenCertificationInstructions = false,
accessibilityAdjustmentNeeded = false,
reconciliatedAt = null,
reconciledAt = null,
} = {}) {
sessionId = _.isUndefined(sessionId) ? buildSession().id : sessionId;
userId = _.isUndefined(userId) ? buildUser().id : userId;
reconciledAt = userId ? new Date('2020-01-02') : undefined;

const values = {
id,
Expand All @@ -57,7 +58,7 @@ const buildCertificationCandidate = function ({
prepaymentCode,
hasSeenCertificationInstructions,
accessibilityAdjustmentNeeded,
reconciliatedAt,
reconciledAt,
};

databaseBuffer.pushInsertable({
Expand Down Expand Up @@ -89,7 +90,7 @@ const buildCertificationCandidate = function ({
prepaymentCode,
hasSeenCertificationInstructions,
accessibilityAdjustmentNeeded,
reconciliatedAt,
reconciledAt,
};
};

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
const TABLE_NAME = 'certification-candidates';
const OLD_COLUMN_NAME = 'reconciliatedAt';
const NEW_COLUMN_NAME = 'reconciledAt';

const up = async function (knex) {
await knex.schema.table(TABLE_NAME, function (table) {
table.renameColumn(OLD_COLUMN_NAME, NEW_COLUMN_NAME);
});
};

const down = async function (knex) {
await knex.schema.table(TABLE_NAME, function (table) {
table.renameColumn(NEW_COLUMN_NAME, OLD_COLUMN_NAME);
});
};

export { down, up };
23 changes: 13 additions & 10 deletions api/db/seeds/data/common/tooling/session-tooling.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ async function createDraftScoSession({
databaseBuilder,
sessionId,
organizationId,
hasJoinSession: false,
hasJoinedSession: false,
configSession,
version,
});
Expand Down Expand Up @@ -169,7 +169,7 @@ async function createDraftSession({
const certificationCandidates = await _registerCandidatesToSession({
databaseBuilder,
sessionId,
hasJoinSession: false,
hasJoinedSession: false,
configSession,
certificationCenterId,
version,
Expand Down Expand Up @@ -398,7 +398,7 @@ async function createPublishedScoSession({
databaseBuilder,
sessionId,
organizationId,
hasJoinSession: true,
hasJoinedSession: true,
configSession,
});

Expand Down Expand Up @@ -521,7 +521,7 @@ async function createPublishedSession({
const certificationCandidates = await _registerCandidatesToSession({
databaseBuilder,
sessionId,
hasJoinSession: true,
hasJoinedSession: true,
configSession,
certificationCenterId,
version,
Expand Down Expand Up @@ -551,7 +551,7 @@ async function _registerOrganizationLearnersToSession({
databaseBuilder,
sessionId,
organizationId,
hasJoinSession,
hasJoinedSession,
configSession,
version,
}) {
Expand All @@ -566,7 +566,7 @@ async function _registerOrganizationLearnersToSession({
databaseBuilder,
sessionId,
extraTimePercentages,
hasJoinSession,
hasJoinedSession,
version,
);
}
Expand All @@ -579,7 +579,7 @@ function _addCertificationCandidatesToScoSession(
databaseBuilder,
sessionId,
extraTimePercentages,
hasJoinSession,
hasJoinedSession,
version,
) {
organizationLearners.forEach((organizationLearner, index) => {
Expand All @@ -597,7 +597,8 @@ function _addCertificationCandidatesToScoSession(
sessionId,
createdAt: new Date(),
extraTimePercentage: extraTimePercentages[index % extraTimePercentages.length],
userId: hasJoinSession ? organizationLearner.userId : null,
userId: hasJoinedSession ? organizationLearner.userId : null,
reconciledAt: hasJoinedSession ? new Date() : null,
organizationLearnerId: organizationLearner.id,
authorizedToStart: false,
billingMode: null,
Expand All @@ -623,7 +624,7 @@ function _hasLearnersToRegister(configSession) {
async function _registerCandidatesToSession({
databaseBuilder,
sessionId,
hasJoinSession,
hasJoinedSession,
configSession,
certificationCenterId,
version,
Expand Down Expand Up @@ -657,7 +658,7 @@ async function _registerCandidatesToSession({

for (let i = 0; i < configSession.candidatesToRegisterCount; i++) {
let userId = null;
if (hasJoinSession) {
if (hasJoinedSession) {
userId = databaseBuilder.factory.buildUser.withRawPassword({
firstName: `firstname${i}-${sessionId}`,
lastName: `lastname${i}-${sessionId}`,
Expand Down Expand Up @@ -685,6 +686,7 @@ async function _registerCandidatesToSession({
createdAt: configSession.sessionDate,
extraTimePercentage: randomExtraTimePercentage,
userId,
reconciledAt: hasJoinedSession ? new Date() : null,
organizationLearnerId: null,
authorizedToStart: false,
billingMode: randomBillingMode,
Expand Down Expand Up @@ -770,6 +772,7 @@ async function _registerSomeCandidatesToSession({ databaseBuilder, sessionId, co
createdAt: new Date(),
extraTimePercentage: randomExtraTimePercentage,
userId: hasJoinedSession ? userId : null,
reconciledAt: hasJoinedSession ? new Date() : null,
organizationLearnerId: null,
authorizedToStart: false,
billingMode: randomBillingMode,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { normalize } from '../../../shared/infrastructure/utils/string-utils.js';
import * as certificationCandidateSerializer from '../../shared/infrastructure/serializers/jsonapi/certification-candidate-serializer.js';
import { usecases } from '../domain/usecases/index.js';
import * as enrolledCandidateRepository from '../infrastructure/repositories/enrolled-candidate-repository.js';
import * as candidateSerializer from '../infrastructure/serializers/candidate-serializer.js';
import * as enrolledCandidateSerializer from '../infrastructure/serializers/enrolled-candidate-serializer.js';

Expand Down Expand Up @@ -54,12 +53,11 @@ const validateCertificationInstructions = async function (
) {
const certificationCandidateId = request.params.certificationCandidateId;

await usecases.candidateHasSeenCertificationInstructions({
const candidate = await usecases.candidateHasSeenCertificationInstructions({
certificationCandidateId,
});
const enrolledCandidate = await enrolledCandidateRepository.get({ id: certificationCandidateId });

return dependencies.certificationCandidateSerializer.serialize(enrolledCandidate);
return dependencies.certificationCandidateSerializer.serialize(candidate);
};

const certificationCandidateController = {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
/**
* @typedef {import ('./index.js').EnrolledCandidateRepository} EnrolledCandidateRepository
* @typedef {import ('../../domain/models/Candidate.js').Candidate} Candidate
*/

import { usecases } from '../../domain/usecases/index.js';

/**
* Candidate entry to a certification is a multi step process
* @param {Object} params
* @param {EnrolledCandidateRepository} params.enrolledCandidateRepository
* @returns {Promise<EnrolledCandidate>}
* @param {number} params.userId
* @param {number} params.sessionId
* @param {string} params.firstName
* @param {string} params.lastName
* @param {Date} params.birthdate
* @param {Function} params.normalizeStringFnc
* @returns {Promise<Candidate>}
*/
export const registerCandidateParticipation = async ({
userId,
Expand All @@ -17,7 +22,6 @@ export const registerCandidateParticipation = async ({
lastName,
birthdate,
normalizeStringFnc,
enrolledCandidateRepository,
}) => {
const candidate = await usecases.verifyCandidateIdentity({
userId,
Expand All @@ -28,12 +32,12 @@ export const registerCandidateParticipation = async ({
normalizeStringFnc,
});

if (!candidate.isLinkedToAUser()) {
await usecases.linkUserToCandidate({
userId,
candidate,
});
if (candidate.isLinkedToAUser()) {
return candidate;
}

return enrolledCandidateRepository.get({ id: candidate.id });
return usecases.reconcileCandidate({
userId,
candidate,
});
};
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import lodash from 'lodash';

import { normalize } from '../../../shared/infrastructure/utils/string-utils.js';
import { usecases } from '../domain/usecases/index.js';
import * as enrolledCandidateSerializer from '../infrastructure/serializers/enrolled-candidate-serializer.js';
import { serializeForParticipation } from '../infrastructure/serializers/candidate-serializer.js';
import * as sessionSerializer from '../infrastructure/serializers/session-serializer.js';
import { services } from './services/index.js';
const { trim } = lodash;
Expand Down Expand Up @@ -47,7 +47,7 @@ const createCandidateParticipation = async function (request, h) {
const lastName = trim(request.payload.data.attributes['last-name']);
const birthdate = request.payload.data.attributes['birthdate'];

const enrolledCandidate = await services.registerCandidateParticipation({
const candidate = await services.registerCandidateParticipation({
userId,
sessionId,
firstName,
Expand All @@ -56,8 +56,7 @@ const createCandidateParticipation = async function (request, h) {
normalizeStringFnc: normalize,
});

const serialized = await enrolledCandidateSerializer.serializeForParticipation(enrolledCandidate);
return h.response(serialized).created();
return h.response(serializeForParticipation(candidate)).created();
};

const sessionController = {
Expand Down
5 changes: 4 additions & 1 deletion api/src/certification/enrolment/domain/models/Candidate.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export class Candidate {
authorizedToStart = false,
sessionId,
userId,
reconciledAt,
organizationLearnerId,
billingMode,
prepaymentCode,
Expand Down Expand Up @@ -55,6 +56,7 @@ export class Candidate {
this.hasSeenCertificationInstructions = hasSeenCertificationInstructions;
this.subscriptions = subscriptions;
this.accessibilityAdjustmentNeeded = accessibilityAdjustmentNeeded;
this.reconciledAt = reconciledAt;
}

isLinkedToAUser() {
Expand All @@ -65,8 +67,9 @@ export class Candidate {
return this.userId === userId;
}

link(userId) {
reconcile(userId) {
this.userId = userId;
this.reconciledAt = new Date();
}

updateAccessibilityAdjustmentNeededStatus(newAdjustmentStatus) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
/**
* @typedef {import('../models/Subscription.js').Subscription} Subscription
* @typedef {import('../models/Candidate.js').Candidate} Candidate
*/
import _ from 'lodash';

import { SUBSCRIPTION_TYPES } from '../../../shared/domain/constants.js';

/**
* @deprecated please use Candidate model that has no differences with this model
* @see {Candidate} domain model
*/
export class EnrolledCandidate {
/**
* @param {Object} params
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
/**
* @typedef {import ('./index.js').CandidateRepository} CandidateRepository
* @typedef {import ('../models/Candidate.js').Candidate} Candidate
*/
import { CertificationCandidateNotFoundError } from '../errors.js';

/**
* @param {Object} params
* @param {number} params.certificationCandidateId
* @param {CandidateRepository} params.candidateRepository
* @returns {Candidate}
*/
const candidateHasSeenCertificationInstructions = async function ({ certificationCandidateId, candidateRepository }) {
const candidate = await candidateRepository.get({ certificationCandidateId });
Expand All @@ -15,8 +18,8 @@ const candidateHasSeenCertificationInstructions = async function ({ certificatio
}

candidate.validateCertificationInstructions();

await candidateRepository.update(candidate);
return candidate;
};

export { candidateHasSeenCertificationInstructions };
Original file line number Diff line number Diff line change
Expand Up @@ -16,32 +16,34 @@ import { UserNotAuthorizedToCertifyError } from '../../../../shared/domain/error
* @param {CandidateRepository} params.candidateRepository
* @param {PlacementProfileService} params.placementProfileService
*
* @returns {Promise<void>}
* @returns {Promise<Candidate>}
*/
export async function linkUserToCandidate({ userId, candidate, candidateRepository, placementProfileService }) {
export async function reconcileCandidate({ userId, candidate, candidateRepository, placementProfileService }) {
candidate.reconcile(userId);

if (candidate.hasCoreSubscription()) {
const placementProfile = await placementProfileService.getPlacementProfile({
userId,
limitDate: new Date(),
userId: candidate.userId,
limitDate: candidate.reconciledAt,
});

if (!placementProfile.isCertifiable()) {
throw new UserNotAuthorizedToCertifyError();
}
}

return _linkUser({ userId, candidate, candidateRepository });
await _saveReconcilement({ candidate, candidateRepository });
return candidate;
}

const _linkUser = withTransaction(
const _saveReconcilement = withTransaction(
/**
* @param {Object} params
* @param {number} params.userId
* @param {Candidate} params.candidate
* @param {CandidateRepository} params.candidateRepository
*/
async ({ userId, candidate, candidateRepository }) => {
candidate.link(userId);
async ({ candidate, candidateRepository }) => {
return candidateRepository.update(candidate);
},
);
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ async function _createValidCertificationCandidates({
subscriptions,
id: null,
userId: null,
reconciledAt: null,
organizationLearnerId: null,
createdAt: null,
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
* @typedef {import ('./index.js').SessionRepository} SessionRepository
* @typedef {import ('./index.js').UserRepository} UserRepository
* @typedef {import ('../models/Candidate.js').Candidate} Candidate
* @typedef {import ('../read-models/EnrolledCandidate.js').EnrolledCandidate} EnrolledCandidate
*/

import {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@ function adaptModelToDb(candidate) {
authorizedToStart: candidate.authorizedToStart,
sessionId: candidate.sessionId,
userId: candidate.userId,
reconciledAt: candidate.reconciledAt,
organizationLearnerId: candidate.organizationLearnerId,
billingMode: candidate.billingMode,
prepaymentCode: candidate.prepaymentCode,
Expand Down
Loading

0 comments on commit 4f9d33e

Please sign in to comment.