Skip to content

Commit

Permalink
🚚 chore(api): move student certification to src
Browse files Browse the repository at this point in the history
  • Loading branch information
yaf committed Dec 27, 2024
1 parent bcfb00c commit 9bc3e26
Show file tree
Hide file tree
Showing 13 changed files with 375 additions and 369 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,6 @@ import * as divisionSerializer from '../../../src/prescription/campaign/infrastr
import * as certificationCenterMembershipSerializer from '../../../src/shared/infrastructure/serializers/jsonapi/certification-center-membership.serializer.js';
import { usecases as teamUsecases } from '../../../src/team/domain/usecases/index.js';
import { usecases } from '../../domain/usecases/index.js';
import * as studentCertificationSerializer from '../../infrastructure/serializers/jsonapi/student-certification-serializer.js';

const getStudents = async function (request) {
const certificationCenterId = request.params.certificationCenterId;
const sessionId = request.params.sessionId;

const { filter, page } = request.query;
if (filter.divisions && !Array.isArray(filter.divisions)) {
filter.divisions = [filter.divisions];
}

const { data, pagination } = await usecases.findStudentsForEnrolment({
certificationCenterId,
sessionId,
page,
filter,
});
return studentCertificationSerializer.serialize(data, pagination);
};

const getDivisions = async function (request) {
const certificationCenterId = request.params.certificationCenterId;
Expand Down Expand Up @@ -77,7 +58,6 @@ const certificationCenterController = {
createCertificationCenterMembershipByEmail,
findCertificationCenterMembershipsByCertificationCenter,
getDivisions,
getStudents,
updateReferer,
};

Expand Down
33 changes: 0 additions & 33 deletions api/lib/application/certification-centers/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -93,39 +93,6 @@ const register = async function (server) {
server.route([
...adminRoutes,
...certifRoutes,
{
method: 'GET',
path: '/api/certification-centers/{certificationCenterId}/sessions/{sessionId}/students',
config: {
validate: {
params: Joi.object({
certificationCenterId: identifiersType.certificationCenterId,
sessionId: identifiersType.sessionId,
}),
query: Joi.object({
filter: Joi.object({
divisions: Joi.array().items(Joi.string()),
}).default({}),
page: {
number: Joi.number().integer(),
size: Joi.number().integer(),
},
}),
},
pre: [
{
method: securityPreHandlers.checkUserIsMemberOfCertificationCenter,
assign: 'isMemberOfCertificationCenter',
},
],
handler: certificationCenterController.getStudents,
notes: [
'- **Cette route est restreinte aux utilisateurs authentifiés**\n' +
"- Récupération d'une liste d'élèves SCO à partir d'un identifiant de centre de certification",
],
tags: ['api', 'certification-center', 'students', 'session'],
},
},
{
method: 'GET',
path: '/api/certification-centers/{certificationCenterId}/divisions',
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { usecases } from '../domain/usecases/index.js';
import * as studentCertificationSerializer from '../infrastructure/serializers/student-certification-serializer.js';

const getStudents = async function (request) {
const certificationCenterId = request.params.certificationCenterId;
const sessionId = request.params.sessionId;

const { filter, page } = request.query;
if (filter.divisions && !Array.isArray(filter.divisions)) {
filter.divisions = [filter.divisions];
}

const { data, pagination } = await usecases.findStudentsForEnrolment({
certificationCenterId,
sessionId,
page,
filter,
});
return studentCertificationSerializer.serialize(data, pagination);
};

const certificationCenterController = { getStudents };

export { certificationCenterController };
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import Joi from 'joi';

import { securityPreHandlers } from '../../../shared/application/security-pre-handlers.js';
import { identifiersType } from '../../../shared/domain/types/identifiers-type.js';
import { certificationCenterController } from './certification-center-controller.js';

const register = async function (server) {
server.route([
{
method: 'GET',
path: '/api/certification-centers/{certificationCenterId}/sessions/{sessionId}/students',
config: {
validate: {
params: Joi.object({
certificationCenterId: identifiersType.certificationCenterId,
sessionId: identifiersType.sessionId,
}),
query: Joi.object({
filter: Joi.object({
divisions: Joi.array().items(Joi.string()),
}).default({}),
page: {
number: Joi.number().integer(),
size: Joi.number().integer(),
},
}),
},
pre: [
{
method: securityPreHandlers.checkUserIsMemberOfCertificationCenter,
assign: 'isMemberOfCertificationCenter',
},
],
handler: certificationCenterController.getStudents,
notes: [
'- **Cette route est restreinte aux utilisateurs authentifiés**\n' +
"- Récupération d'une liste d'élèves SCO à partir d'un identifiant de centre de certification",
],
tags: ['api', 'certification-center', 'students', 'session'],
},
},
]);
};

const name = 'certification-centers-api';
export { name, register };
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { NotFoundError } from '../../../src/shared/domain/errors.js';
import { StudentForEnrolment } from '../../../src/shared/domain/read-models/StudentForEnrolment.js';
import { NotFoundError } from '../../../../shared/domain/errors.js';
import { StudentForEnrolment } from '../../../../shared/domain/read-models/StudentForEnrolment.js';

const findStudentsForEnrolment = async function ({
certificationCenterId,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,104 +49,6 @@ describe('Acceptance | API | Certification Center', function () {
});
});

describe('GET /api/certification-centers/{certificationCenterId}/sessions/{sessionId}/students', function () {
let request;
const externalId = 'XXXX';

function _buildOrganizationLearnersWithConnectedUserRequest(user, certificationCenter, session) {
return {
method: 'GET',
url:
'/api/certification-centers/' +
certificationCenter.id +
'/sessions/' +
session.id +
'/students?page[size]=10&page[number]=1',
headers: { authorization: generateValidRequestAuthorizationHeader(user.id) },
};
}
function _buildOrganizationLearnersNotConnectedUserRequest(certificationCenter, session) {
return {
method: 'GET',
url:
'/api/certification-centers/' +
certificationCenter.id +
'/sessions/' +
session.id +
'/students?page[size]=10&page[number]=1',
};
}

context('when user is connected', function () {
it('should return 200 HTTP status', async function () {
// given
const { certificationCenter, user } = _buildUserWithCertificationCenterMemberShip(externalId);
const organization = databaseBuilder.factory.buildOrganization({ externalId, type: 'SCO' });
const session = databaseBuilder.factory.buildSession({ certificationCenterId: certificationCenter.id });
_buildOrganizationLearners(organization, { firstName: 'Laura', lastName: 'certifForEver', division: '2ndB' });
await databaseBuilder.commit();

const request = _buildOrganizationLearnersWithConnectedUserRequest(user, certificationCenter, session);

// when
const response = await server.inject(request);

// then
expect(response.statusCode).to.equal(200);
});

it('should return the organization learners asked', async function () {
// given
const { certificationCenter, user } = _buildUserWithCertificationCenterMemberShip(externalId);
const organization = databaseBuilder.factory.buildOrganization({ type: 'SCO', externalId });
const session = databaseBuilder.factory.buildSession({ certificationCenterId: certificationCenter.id });
_buildOrganizationLearners(
organization,
{ id: 1, division: '2ndB', firstName: 'Laura', lastName: 'Certif4Ever' },
{ id: 2, division: '2ndA', firstName: 'Laura', lastName: 'Booooo' },
{ id: 3, division: '2ndA', firstName: 'Laura', lastName: 'aaaaa' },
{ id: 4, division: '2ndA', firstName: 'Bart', lastName: 'Coucou' },
{ id: 5, division: '2ndA', firstName: 'Arthur', lastName: 'Coucou' },
);
await databaseBuilder.commit();

const request = _buildOrganizationLearnersWithConnectedUserRequest(user, certificationCenter, session);

// when
const response = await server.inject(request);

// then
expect(_.map(response.result.data, 'id')).to.deep.equal(['3', '2', '5', '4', '1']);
});
});

context('when user is not connected', function () {
it('should return 401 HTTP status code if user is not authenticated', async function () {
// given
_buildUserWithCertificationCenterMemberShip(externalId);
databaseBuilder.factory.buildOrganization({ externalId });
const certificationCenterWhereUserDoesNotHaveAccess = databaseBuilder.factory.buildCertificationCenter({
externalId,
});
const session = databaseBuilder.factory.buildSession({
certificationCenterId: certificationCenterWhereUserDoesNotHaveAccess.id,
});
await databaseBuilder.commit();

request = _buildOrganizationLearnersNotConnectedUserRequest(
certificationCenterWhereUserDoesNotHaveAccess,
session,
);

// when
const response = await server.inject(request);

// then
expect(response.statusCode).to.equal(401);
});
});
});

describe('GET /api/admin/certification-centers/{id}/certification-center-memberships', function () {
context('when certification center membership is linked to the certification center', function () {
it('should return 200 HTTP status', async function () {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
import _ from 'lodash';

import {
createServer,
databaseBuilder,
expect,
generateValidRequestAuthorizationHeader,
insertUserWithRoleSuperAdmin,
} from '../../../../test-helper.js';

describe('Acceptance | API | Certification Center', function () {
let server;

beforeEach(async function () {
server = await createServer();
await insertUserWithRoleSuperAdmin();
});

describe('GET /api/certification-centers/{certificationCenterId}/sessions/{sessionId}/students', function () {
let request;
const externalId = 'XXXX';

function _buildOrganizationLearnersWithConnectedUserRequest(user, certificationCenter, session) {
return {
method: 'GET',
url:
'/api/certification-centers/' +
certificationCenter.id +
'/sessions/' +
session.id +
'/students?page[size]=10&page[number]=1',
headers: { authorization: generateValidRequestAuthorizationHeader(user.id) },
};
}
function _buildOrganizationLearnersNotConnectedUserRequest(certificationCenter, session) {
return {
method: 'GET',
url:
'/api/certification-centers/' +
certificationCenter.id +
'/sessions/' +
session.id +
'/students?page[size]=10&page[number]=1',
};
}

context('when user is connected', function () {
it('should return 200 HTTP status', async function () {
// given
const { certificationCenter, user } = _buildUserWithCertificationCenterMemberShip(externalId);
const organization = databaseBuilder.factory.buildOrganization({ externalId, type: 'SCO' });
const session = databaseBuilder.factory.buildSession({ certificationCenterId: certificationCenter.id });
_buildOrganizationLearners(organization, { firstName: 'Laura', lastName: 'certifForEver', division: '2ndB' });
await databaseBuilder.commit();

const request = _buildOrganizationLearnersWithConnectedUserRequest(user, certificationCenter, session);

// when
const response = await server.inject(request);

// then
expect(response.statusCode).to.equal(200);
});

it('should return the organization learners asked', async function () {
// given
const { certificationCenter, user } = _buildUserWithCertificationCenterMemberShip(externalId);
const organization = databaseBuilder.factory.buildOrganization({ type: 'SCO', externalId });
const session = databaseBuilder.factory.buildSession({ certificationCenterId: certificationCenter.id });
_buildOrganizationLearners(
organization,
{ id: 1, division: '2ndB', firstName: 'Laura', lastName: 'Certif4Ever' },
{ id: 2, division: '2ndA', firstName: 'Laura', lastName: 'Booooo' },
{ id: 3, division: '2ndA', firstName: 'Laura', lastName: 'aaaaa' },
{ id: 4, division: '2ndA', firstName: 'Bart', lastName: 'Coucou' },
{ id: 5, division: '2ndA', firstName: 'Arthur', lastName: 'Coucou' },
);
await databaseBuilder.commit();

const request = _buildOrganizationLearnersWithConnectedUserRequest(user, certificationCenter, session);

// when
const response = await server.inject(request);

// then
expect(_.map(response.result.data, 'id')).to.deep.equal(['3', '2', '5', '4', '1']);
});
});

context('when user is not connected', function () {
it('should return 401 HTTP status code if user is not authenticated', async function () {
// given
_buildUserWithCertificationCenterMemberShip(externalId);
databaseBuilder.factory.buildOrganization({ externalId });
const certificationCenterWhereUserDoesNotHaveAccess = databaseBuilder.factory.buildCertificationCenter({
externalId,
});
const session = databaseBuilder.factory.buildSession({
certificationCenterId: certificationCenterWhereUserDoesNotHaveAccess.id,
});
await databaseBuilder.commit();

request = _buildOrganizationLearnersNotConnectedUserRequest(
certificationCenterWhereUserDoesNotHaveAccess,
session,
);

// when
const response = await server.inject(request);

// then
expect(response.statusCode).to.equal(401);
});
});
});

function _buildOrganizationLearners(organization, ...students) {
const AFTER_BEGINNING_OF_THE_2020_SCHOOL_YEAR = '2020-10-15';
return students.map((student) =>
databaseBuilder.factory.buildOrganizationLearner({
organizationId: organization.id,
...student,
updatedAt: AFTER_BEGINNING_OF_THE_2020_SCHOOL_YEAR,
}),
);
}

function _buildUserWithCertificationCenterMemberShip(certificationCenterExternalId) {
const user = databaseBuilder.factory.buildUser({});
const certificationCenter = databaseBuilder.factory.buildCertificationCenter({
externalId: certificationCenterExternalId,
type: 'SCO',
});
databaseBuilder.factory.buildCertificationCenterMembership({
certificationCenterId: certificationCenter.id,
userId: user.id,
});
return { user, certificationCenter };
}
});
Loading

0 comments on commit 9bc3e26

Please sign in to comment.