Skip to content

Commit

Permalink
feat(api): get features of organization learner
Browse files Browse the repository at this point in the history
  • Loading branch information
aurelie-crouillebois committed Nov 6, 2024
1 parent 526a151 commit 9e6ad23
Show file tree
Hide file tree
Showing 11 changed files with 132 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,24 @@ const buildOrganizationLearnerFeature = function ({
});
};

export { buildOrganizationLearnerFeature };
const buildOrganizationLearnerFeatureWithFeatureKey = function ({
id = databaseBuffer.getNextId(),
organizationLearnerId,
featureKey,
} = {}) {
organizationLearnerId = organizationLearnerId === undefined ? buildOrganizationLearner().id : organizationLearnerId;
const featureId = buildFeature({ key: featureKey }).id;

const values = {
id,
organizationLearnerId,
featureId,
};

return databaseBuffer.pushInsertable({
tableName: 'organization-learner-features',
values,
});
};

export { buildOrganizationLearnerFeature, buildOrganizationLearnerFeatureWithFeatureKey };
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Make sure you properly test your migration, especially DDL (Data Definition Language)
// ! If the target table is large, and the migration take more than 20 minutes, the deployment will fail !

// You can design and test your migration to avoid this by following this guide
// https://1024pix.atlassian.net/wiki/spaces/EDTDT/pages/3849323922/Cr+er+une+migration

// If your migrations target `answers` or `knowledge-elements`
// contact @team-captains, because automatic migrations are not active on `pix-datawarehouse-production`
// this may prevent data replication to succeed the day after your migration is deployed on `pix-api-production`
const TABLE_NAME = 'organization-learner-features';
const COLUMN_NAME = 'organizationLearnerId';

const up = async function (knex) {
await knex.schema.table(TABLE_NAME, function (table) {
table.index(COLUMN_NAME);
});
};

const down = async function (knex) {
await knex.schema.table(TABLE_NAME, function (table) {
table.dropIndex(COLUMN_NAME);
});
};

export { down, up };
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
export class OrganizationLearner {
constructor({ id, firstName, lastName, organizationId, ...attributes }) {
constructor({ id, firstName, lastName, features, organizationId, ...attributes }) {
this.id = id;
this.firstName = firstName;
this.lastName = lastName;
this.division = attributes['Libellé classe'];
this.features = features;
this.organizationId = organizationId;
this.division = attributes['Libellé classe'];
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ class OrganizationLearner {
organizationId,
certifiableAtFromLearner,
userId,
features,
} = {}) {
this.id = id;
this.firstName = firstName;
Expand All @@ -27,6 +28,7 @@ class OrganizationLearner {
this.authenticationMethods = authenticationMethods;
this.organizationId = organizationId;
this.userId = userId;
this.features = features;

this._buildCertificability({
isCertifiableFromCampaign,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ async function get({ organizationLearnerId }) {
'subquery.isCertifiableFromCampaign',
'subquery.certifiableAtFromCampaign',
knex.raw('array_remove(ARRAY_AGG("identityProvider"), NULL) AS "authenticationMethods"'),
knex.raw('array_remove(ARRAY_AGG(features.key), NULL) as features'),
'users.email',
'users.username',
)
Expand All @@ -55,6 +56,12 @@ async function get({ organizationLearnerId }) {
.leftJoin('subquery', 'subquery.organizationLearnerId', 'view-active-organization-learners.id')
.leftJoin('authentication-methods', 'authentication-methods.userId', 'view-active-organization-learners.userId')
.leftJoin('users', 'view-active-organization-learners.userId', 'users.id')
.leftJoin(
'organization-learner-features',
'view-active-organization-learners.id',
'organization-learner-features.organizationLearnerId',
)
.leftJoin('features', 'organization-learner-features.featureId', 'features.id')
.groupBy(
'view-active-organization-learners.id',
'view-active-organization-learners.firstName',
Expand Down
12 changes: 11 additions & 1 deletion api/src/school/domain/models/OrganizationLearner.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,19 @@
class OrganizationLearner {
constructor({ id, lastName, firstName, division, organizationId, completedMissionIds, startedMissionIds } = {}) {
constructor({
id,
lastName,
firstName,
division,
features,
organizationId,
completedMissionIds,
startedMissionIds,
} = {}) {
this.id = id;
this.lastName = lastName;
this.firstName = firstName;
this.division = division;
this.features = features || [];
this.organizationId = organizationId;
this.completedMissionIds = completedMissionIds;
this.startedMissionIds = startedMissionIds;
Expand Down
12 changes: 11 additions & 1 deletion api/src/school/domain/read-models/OrganizationLearnerDTO.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,22 @@
class OrganizationLearnerDTO {
constructor({ id, displayName, firstName, division, organizationId, startedMissionIds, completedMissionIds } = {}) {
constructor({
id,
displayName,
firstName,
division,
organizationId,
startedMissionIds,
completedMissionIds,
features,
} = {}) {
this.id = id;
this.displayName = displayName;
this.firstName = firstName;
this.division = division;
this.organizationId = organizationId;
this.startedMissionIds = startedMissionIds;
this.completedMissionIds = completedMissionIds;
this.features = features;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,15 @@ import { Serializer } from 'jsonapi-serializer';

const serialize = function (organizationLearner) {
return new Serializer('organizationLearner', {
attributes: ['firstName', 'displayName', 'division', 'organizationId', 'completedMissionIds', 'startedMissionIds'],
attributes: [
'firstName',
'displayName',
'division',
'organizationId',
'completedMissionIds',
'startedMissionIds',
'features',
],
transform: function (organizationLearner) {
return {
...organizationLearner,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,23 @@ describe('Integration | Infrastructure | Repository | Organization Learner', fun
expect(organizationLearner.email).to.equal('[email protected]');
expect(organizationLearner.username).to.equal('sassouk');
expect(organizationLearner.organizationId).to.equal(organizationId);
expect(organizationLearner.features).to.be.empty;
});

it("Should return organization learner's features", async function () {
const organizationLearnerId = databaseBuilder.factory.buildOrganizationLearner().id;
databaseBuilder.factory.prescription.organizationLearners.buildOrganizationLearnerFeatureWithFeatureKey({
organizationLearnerId,
featureKey: 'ORALIZATION',
});
databaseBuilder.factory.prescription.organizationLearners.buildOrganizationLearnerFeatureWithFeatureKey({
organizationLearnerId,
featureKey: 'BLA',
});
await databaseBuilder.commit();

const organizationLearner = await organizationLearnerRepository.get({ organizationLearnerId });
expect(organizationLearner.features).to.deep.equal(['ORALIZATION', 'BLA']);
});

it('Should return the organization learner with a given ID', async function () {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,30 @@ describe('Integration | Usecase | get-organization-learner-with-completed-missio
);
});

it('should return organization learner with features', async function () {
const organizationLearner =
databaseBuilder.factory.prescription.organizationLearners.buildOndeOrganizationLearner();
databaseBuilder.factory.prescription.organizationLearners.buildOrganizationLearnerFeatureWithFeatureKey({
organizationLearnerId: organizationLearner.id,
featureKey: 'ORALIZATION',
});
await databaseBuilder.commit();

const result = await usecases.getOrganizationLearnerWithMissionIdsByState({
organizationLearnerId: organizationLearner.id,
});

expect(result).to.deep.equal(
new OrganizationLearner({
...organizationLearner,
division: organizationLearner.attributes['Libellé classe'],
completedMissionIds: [],
startedMissionIds: [],
features: ['ORALIZATION'],
}),
);
});

it('should return only the good organization learner', async function () {
const organizationLearner =
databaseBuilder.factory.prescription.organizationLearners.buildOndeOrganizationLearner();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ describe('Unit | Controller | organization-learner-controller', function () {
organizationId: '345',
completedMissionIds: ['rec12344', 'rec435'],
startedMissionIds: undefined,
features: ['ORALIZATION'],
}),
);
const id = 4356;
Expand All @@ -33,6 +34,7 @@ describe('Unit | Controller | organization-learner-controller', function () {
'display-name': undefined,
division: 'CM2',
'organization-id': '345',
features: ['ORALIZATION'],
},
id: '4356',
type: 'organizationLearners',
Expand Down

0 comments on commit 9e6ad23

Please sign in to comment.