Skip to content

Commit

Permalink
✨ feat(junior) show ORALIZATION information on junior students
Browse files Browse the repository at this point in the history
page

Co-authored-by: rouxxi <[email protected]>
Co-authored-by: Aurelie Crouillebois <[email protected]>
  • Loading branch information
3 people committed Oct 18, 2024
1 parent 888a3ae commit faa0314
Show file tree
Hide file tree
Showing 16 changed files with 277 additions and 41 deletions.
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import _ from 'lodash';

import { databaseBuffer } from '../../../database-buffer.js';
import { buildOrganizationLearner } from '../../build-organization-learner.js';
import { buildFeature } from '../../build-feature.js';
import { buildOrganizationLearner } from '../../build-organization-learner.js';

const buildOrganizationLearnerFeature = function ({
id = databaseBuffer.getNextId(),
Expand Down
2 changes: 1 addition & 1 deletion api/db/seeds/data/common/feature-builder.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import {
FEATURE_COMPUTE_ORGANIZATION_LEARNER_CERTIFICABILITY_ID,
FEATURE_LEARNER_IMPORT_ID,
FEATURE_MISSIONS_MANAGEMENT_ID,
FEATURE_ORALIZATION_ID,
FEATURE_MULTIPLE_SENDING_ASSESSMENT_ID,
FEATURE_ORALIZATION_ID,
FEATURE_PLACES_MANAGEMENT_ID,
} from './constants.js';

Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { ORGANIZATION_FEATURE } from '../../../../shared/domain/constants.js';

const findPaginatedFilteredParticipants = async function ({
organizationId,
filters,
Expand All @@ -7,15 +9,13 @@ const findPaginatedFilteredParticipants = async function ({
organizationParticipantRepository,
organizationLearnerImportFormatRepository,
organizationFeaturesAPI,
organizationLearnerFeatureRepository,
}) {
const organizationFeatures = await organizationFeaturesAPI.getAllFeaturesFromOrganization(organizationId);

if (organizationFeatures.hasLearnersImportFeature) {
const importFormat = await organizationLearnerImportFormatRepository.get(organizationId);

// TODO récupérer le featureId qui nous intéresse, pour l'oralization activé
// TODO Branger le organizationLearnerFeatureRepository pour récupérer les organizationLearners concerné par la feature

const { organizationParticipants, meta } =
await organizationParticipantRepository.findPaginatedFilteredImportedParticipants({
organizationId,
Expand All @@ -26,23 +26,62 @@ const findPaginatedFilteredParticipants = async function ({
page,
});

// TODO Si oralization activée pour l'orga, décorer la liste des organizationPArticipants avec l'info

meta.headingCustomColumns = importFormat.columnsToDisplay;
if (organizationFeatures.hasOralizationFeature) {
meta.headingCustomColumns.push('ORALIZATION');
}
meta.customFilters = importFormat.filtersToDisplay;

if (organizationFeatures.hasOralizationFeature) {
return await _addOralizationInformations({
organizationId,
meta,
organizationParticipants,
organizationLearnerFeatureRepository,
});
}
return { organizationParticipants, meta };
} else {
return organizationParticipantRepository.findPaginatedFilteredParticipants({
organizationId,
filters,
sort,
page,
});
}

return organizationParticipantRepository.findPaginatedFilteredParticipants({
organizationId,
filters,
sort,
page,
});
};

async function _addOralizationInformations({
organizationId,
meta,
organizationParticipants,
organizationLearnerFeatureRepository,
}) {
meta.headingCustomColumns.push('ORALIZATION');
return {
meta,
organizationParticipants: await _addOralizationInformationToParticipants({
organizationId,
organizationParticipants,
organizationLearnerFeatureRepository,
}),
};
}

async function _addOralizationInformationToParticipants({
organizationId,
organizationParticipants,
organizationLearnerFeatureRepository,
}) {
const learnersWithOralizationFeature = await organizationLearnerFeatureRepository.getLearnersByFeature({
organizationId,
featureKey: ORGANIZATION_FEATURE.ORALIZATION,
});
return organizationParticipants?.map((participant) => {
const hasOralization = learnersWithOralizationFeature.some(
(learnerWithOralization) => learnerWithOralization.id === participant.id,
);
participant.extraColumns['ORALIZATION'] = hasOralization;

return participant;
});
}

export { findPaginatedFilteredParticipants };
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import * as groupRepository from '../../../campaign/infrastructure/repositories/
import * as organizationLearnerImportFormatRepository from '../../../learner-management/infrastructure/repositories/organization-learner-import-format-repository.js';
import { repositories } from '../../infrastructure/repositories/index.js';
import * as organizationLearnerActivityRepository from '../../infrastructure/repositories/organization-learner-activity-repository.js';
import * as organizationLearnerFeatureRepository from '../../infrastructure/repositories/organization-learner-feature-repository.js';
import * as organizationParticipantRepository from '../../infrastructure/repositories/organization-participant-repository.js';
import * as registrationOrganizationLearnerRepository from '../../infrastructure/repositories/registration-organization-learner-repository.js';
import * as scoOrganizationParticipantRepository from '../../infrastructure/repositories/sco-organization-participant-repository.js';
Expand All @@ -34,6 +35,7 @@ const dependencies = {
organizationParticipantRepository,
organizationLearnerActivityRepository,
organizationLearnerRepository: repositories.organizationLearnerRepository,
organizationLearnerFeatureRepository,
organizationLearnerImportFormatRepository,
organizationFeaturesAPI,
campaignRepository,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
import { DomainTransaction } from '../../../../../lib/infrastructure/DomainTransaction.js';
import { OrganizationLearner } from '../../domain/read-models/OrganizationLearner.js';

async function getLearnersByFeature({ organizationId, featureId }) {
async function getLearnersByFeature({ organizationId, featureKey }) {
const knexConn = DomainTransaction.getConnection();
const rawOrganizationLearnerFeatures = await knexConn
.select('*')
.from('organization-learner-features')
.join('organization-learners', 'organization-learners.id', 'organization-learner-features.organizationLearnerId')
.where({ featureId, organizationId });
.select('organization-learners.*')
.from('organization-learners')
.join(
'organization-learner-features',
'organization-learner-features.organizationLearnerId',
'organization-learners.id',
)
.join('features', 'features.id', 'organization-learner-features.featureId')
.where({ key: featureKey, organizationId });

return rawOrganizationLearnerFeatures.map(
(rawOrganizationLearnerFeature) => new OrganizationLearner(rawOrganizationLearnerFeature),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ describe('Unit | Organizational Entities | application | API | OrganizationFeatu
expect(organizationFeature.hasLearnersImportFeature).to.be.false;
});
});

describe('#hasOralizationFeature', function () {
it('should return true', function () {
const organizationFeature = new OrganizationFeaturesDTO({
Expand Down
Original file line number Diff line number Diff line change
@@ -1,27 +1,39 @@
import * as organizationLearnerFeatureRepository from '../../../../../src/prescription/organization-learner/infrastructure/repositories/organization-learner-feature-repository.js';
import { OrganizationLearner } from '../../../../../src/prescription/organization-learner/domain/read-models/OrganizationLearner.js';

import { expect, databaseBuilder, domainBuilder } from '../../../../test-helper.js';
import * as organizationLearnerFeatureRepository from '../../../../../src/prescription/organization-learner/infrastructure/repositories/organization-learner-feature-repository.js';
import { databaseBuilder, expect } from '../../../../test-helper.js';

describe('Prescription | OrganizationLearner | Integration | Infrastructure | OrganizationLearnerFeatureRepository', function () {
describe('#getLearnerByFeature', function () {
it('returns empty array when feature is unknown', async function () {
const organizationId = databaseBuilder.factory.buildOrganization().id;
const featureKey = 'AN_UNKNOWN_FEATURE';

await databaseBuilder.commit();

const result = await organizationLearnerFeatureRepository.getLearnersByFeature({ organizationId, featureKey });

expect(result).to.deep.equal([]);
});

it('returns empty array when no learner', async function () {
const organizationId = databaseBuilder.factory.buildOrganization().id;
const featureId = databaseBuilder.factory.buildFeature({ key: 'A_FEATURE' }).id;
const featureKey = 'A_FEATURE';
const featureId = databaseBuilder.factory.buildFeature({ key: featureKey }).id;
databaseBuilder.factory.buildOrganizationFeature({ organizationId, featureId });

await databaseBuilder.commit();

const result = await organizationLearnerFeatureRepository.getLearnersByFeature({ organizationId, featureId });
const result = await organizationLearnerFeatureRepository.getLearnersByFeature({ organizationId, featureKey });

expect(result).to.deep.equal([]);
});

it('returns learner that have linked feature', async function () {
const organizationId = databaseBuilder.factory.buildOrganization().id;
const otherOrganizationId = databaseBuilder.factory.buildOrganization().id;
const featureKey = 'A_FEATURE';

const featureId = databaseBuilder.factory.buildFeature({ key: 'A_FEATURE' }).id;
const featureId = databaseBuilder.factory.buildFeature({ key: featureKey }).id;
const otherFeatureId = databaseBuilder.factory.buildFeature({ key: 'OTHER_FEATURE' }).id;

databaseBuilder.factory.buildOrganizationFeature({ organizationId, featureId });
Expand Down Expand Up @@ -51,7 +63,7 @@ describe('Prescription | OrganizationLearner | Integration | Infrastructure | Or

const learner = new OrganizationLearner({ ...organizationLearner });

const result = await organizationLearnerFeatureRepository.getLearnersByFeature({ organizationId, featureId });
const result = await organizationLearnerFeatureRepository.getLearnersByFeature({ organizationId, featureKey });

expect(result).to.deep.equal([learner]);
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { OrganizationParticipant } from '../../../../../../src/prescription/organization-learner/domain/read-models/OrganizationParticipant.js';
import { findPaginatedFilteredParticipants } from '../../../../../../src/prescription/organization-learner/domain/usecases/find-paginated-filtered-participants.js';
import { expect, sinon } from '../../../../../test-helper.js';
import { domainBuilder, expect, sinon } from '../../../../../test-helper.js';

describe('Unit | UseCases | find-paginated-participants', function () {
let organizationId,
Expand All @@ -12,7 +13,8 @@ describe('Unit | UseCases | find-paginated-participants', function () {
extraColumns,
organizationLearnerImportFormatRepository,
organizationParticipantRepository,
organizationFeaturesAPI;
organizationFeaturesAPI,
organizationLearnerFeatureRepository;

beforeEach(function () {
organizationId = Symbol('organizationId');
Expand All @@ -36,6 +38,10 @@ describe('Unit | UseCases | find-paginated-participants', function () {
organizationFeaturesAPI = {
getAllFeaturesFromOrganization: sinon.stub(),
};

organizationLearnerFeatureRepository = {
getLearnersByFeature: sinon.stub(),
};
});

it('should call findPaginatedFilteredParticipants when import not enabled', async function () {
Expand Down Expand Up @@ -122,10 +128,77 @@ describe('Unit | UseCases | find-paginated-participants', function () {
sort,
organizationParticipantRepository,
organizationLearnerImportFormatRepository,
organizationLearnerFeatureRepository,
organizationFeaturesAPI,
});

expect(result.meta.headingCustomColumns).to.be.deep.equals(['ORALIZATION']);
});
it('should add oralization value to participants', async function () {
// given
organizationFeaturesAPI.getAllFeaturesFromOrganization
.withArgs(organizationId)
.resolves({ hasLearnersImportFeature: true, hasOralizationFeature: true });

organizationLearnerImportFormatRepository.get
.withArgs(organizationId)
.resolves({ columnsToDisplay: [], extraColumns, filtersToDisplay });
const learnerWithOralization = domainBuilder.buildOrganizationLearner({ id: 1 });

const participantWithOralization = new OrganizationParticipant({
id: learnerWithOralization.id,
FAKE_COLUMN: 'fake value',
});
const participantWithoutOralization = new OrganizationParticipant({
id: 2,
FAKE_COLUMN: 'fake value',
});
organizationParticipantRepository.findPaginatedFilteredImportedParticipants.resolves({
organizationParticipants: [participantWithOralization, participantWithoutOralization],
meta: {},
});
organizationLearnerFeatureRepository.getLearnersByFeature.resolves([learnerWithOralization]);

// when
const result = await findPaginatedFilteredParticipants({
organizationId,
filters,
extraFilters,
page,
sort,
organizationParticipantRepository,
organizationLearnerImportFormatRepository,
organizationFeaturesAPI,
organizationLearnerFeatureRepository,
});

// then
expect(
organizationParticipantRepository.findPaginatedFilteredImportedParticipants,
).to.have.been.calledWithExactly({
organizationId,
extraColumns,
page,
sort,
filters,
extraFilters,
});

const expectedParticipantWithOralization = new OrganizationParticipant({
id: participantWithOralization.id,
FAKE_COLUMN: 'fake value',
ORALIZATION: true,
});
const expectedParticipantWithoutOralization = new OrganizationParticipant({
id: participantWithoutOralization.id,
FAKE_COLUMN: 'fake value',
ORALIZATION: false,
});

expect(result.organizationParticipants).to.have.deep.members([
expectedParticipantWithOralization,
expectedParticipantWithoutOralization,
]);
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { OrganizationParticipant } from '../../../../src/prescription/organization-learner/domain/read-models/OrganizationParticipant.js';

function buildOrganizationParticipant({
id = 345,
firstName = 'first-name',
lastName = 'last-name',
participationCount = 0,
lastParticipationDate = null,
campaignName = null,
campaignType = null,
participationStatus = null,
isCertifiableFromCampaign = false,
certifiableAtFromCampaign = false,
isCertifiableFromLearner = false,
certifiableAtFromLearner = false,
extraColumns,
} = {}) {
return new OrganizationParticipant({
id,
firstName,
lastName,
participationCount,
lastParticipationDate,
campaignName,
campaignType,
participationStatus,
isCertifiableFromCampaign,
certifiableAtFromCampaign,
isCertifiableFromLearner,
certifiableAtFromLearner,
...extraColumns,
});
}

export { buildOrganizationParticipant };
Loading

0 comments on commit faa0314

Please sign in to comment.