Skip to content

Commit

Permalink
[FEATURE] Permettre aux Orga de type AEFE de bénéficier du calcul de …
Browse files Browse the repository at this point in the history
…la certificabilité (Pix-9818)

 #7373
  • Loading branch information
pix-service-auto-merge authored Nov 3, 2023
2 parents d98147a + c892346 commit 5187377
Show file tree
Hide file tree
Showing 11 changed files with 151 additions and 136 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import customParseFormat from 'dayjs/plugin/customParseFormat.js';
dayjs.extend(customParseFormat);
import { getDivisionCertificationResultsCsv } from '../../infrastructure/utils/csv/certification-results/get-division-certification-results-csv.js';
import { getCertificationAttestationsPdf as certificationAttestationPdf } from '../../infrastructure/utils/pdf/certification-attestation-pdf.js';
import * as organizationForAdminSerializer from '../../infrastructure/serializers/jsonapi/organization-for-admin-serializer.js';
import * as organizationForAdminSerializer from '../../infrastructure/serializers/jsonapi/organizations-administration/organization-for-admin-serializer.js';

import { mapCertificabilityByLabel } from './helpers.js';
import * as csvSerializer from '../../infrastructure/serializers/csv/csv-serializer.js';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ class OrganizationForAdmin {
identityProviderForCampaigns,
enableMultipleSendingAssessment,
tags = [],
tagIds = [],
features = {},
} = {}) {
this.id = id;
Expand Down Expand Up @@ -63,6 +64,7 @@ class OrganizationForAdmin {
this.identityProviderForCampaigns = identityProviderForCampaigns;
this.enableMultipleSendingAssessment = enableMultipleSendingAssessment;
this.tags = tags;
this.tagIds = tagIds;
this.features = features;
if (this.type === 'SCO' && this.isManagingStudents) {
this.features[ORGANIZATION_FEATURE.COMPUTE_ORGANIZATION_LEARNER_CERTIFICABILITY.key] = true;
Expand Down Expand Up @@ -90,6 +92,8 @@ class OrganizationForAdmin {
}

updateWithDataProtectionOfficerAndTags(organization, dataProtectionOfficer = {}, tags = []) {
const isAEFE = Boolean(tags.find((tag) => tag.name === 'AEFE'));

if (organization.name) this.name = organization.name;
if (organization.type) this.type = organization.type;
if (organization.logoUrl) this.logoUrl = organization.logoUrl;
Expand All @@ -103,9 +107,8 @@ class OrganizationForAdmin {
this.updateIdentityProviderForCampaigns(organization.identityProviderForCampaigns);
this.dataProtectionOfficer.updateInformation(dataProtectionOfficer);
this.features[ORGANIZATION_FEATURE.MULTIPLE_SENDING_ASSESSMENT.key] = organization.enableMultipleSendingAssessment;
if (this.type === 'SCO') {
this.features[ORGANIZATION_FEATURE.COMPUTE_ORGANIZATION_LEARNER_CERTIFICABILITY.key] = this.isManagingStudents;
}
this.features[ORGANIZATION_FEATURE.COMPUTE_ORGANIZATION_LEARNER_CERTIFICABILITY.key] =
this.type === 'SCO' && (this.isManagingStudents || isAEFE);
this.tagsToAdd = differenceBy(tags, this.tags, 'id').map(({ id }) => ({ tagId: id, organizationId: this.id }));
this.tagsToRemove = differenceBy(this.tags, tags, 'id').map(({ id }) => ({ tagId: id, organizationId: this.id }));
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
const updateOrganizationInformation = async function ({
organization,
organizationForAdminRepository,
tagRepository,
domainTransaction,
}) {
const existingOrganization = await organizationForAdminRepository.get(organization.id, domainTransaction);
const tagsToUpdate = await tagRepository.findByIds(organization.tagIds, domainTransaction);

existingOrganization.updateWithDataProtectionOfficerAndTags(
organization,
organization.dataProtectionOfficer,
organization.tags,
tagsToUpdate,
);

await organizationForAdminRepository.update(existingOrganization, domainTransaction);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,9 @@ function _toDomain(rawOrganization) {
identityProviderForCampaigns: rawOrganization.identityProviderForCampaigns,
enableMultipleSendingAssessment: rawOrganization.enableMultipleSendingAssessment,
features: rawOrganization.features,
tags: rawOrganization.tags || [],
});

organization.tags = rawOrganization.tags || [];

return organization;
}

Expand Down Expand Up @@ -144,7 +143,7 @@ async function _disableFeatures(knexConn, features, organizationId) {
}

async function _addTags(knexConn, organizationTags) {
await knex('organization-tags').insert(organizationTags).onConflict(['tagId', 'organizationId']).ignore();
await knexConn('organization-tags').insert(organizationTags).onConflict(['tagId', 'organizationId']).ignore();
}

async function _removeTags(knexConn, organizationTags) {
Expand Down
8 changes: 7 additions & 1 deletion api/lib/infrastructure/repositories/tag-repository.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,10 @@ const findAll = async function () {
return rows.map((row) => new Tag(row));
};

export { create, findByName, findAll };
const findByIds = async function (tagIds, domainTransaction) {
const knexConn = domainTransaction.knexTransaction;
const rows = await knexConn('tags').whereIn('id', tagIds);
return rows.map((row) => new Tag(row));
};

export { create, findByName, findAll, findByIds };

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@ const serialize = function (organizations, meta) {
transform(record) {
const dataProtectionOfficer = record.dataProtectionOfficer;

record.dataProtectionOfficerFirstName = dataProtectionOfficer.firstName;
record.dataProtectionOfficerLastName = dataProtectionOfficer.lastName;
record.dataProtectionOfficerEmail = dataProtectionOfficer.email;

if (dataProtectionOfficer) {
record.dataProtectionOfficerFirstName = dataProtectionOfficer.firstName;
record.dataProtectionOfficerLastName = dataProtectionOfficer.lastName;
record.dataProtectionOfficerEmail = dataProtectionOfficer.email;
}
return record;
},
attributes: [
Expand Down Expand Up @@ -73,10 +74,10 @@ const deserialize = function (json) {
const attributes = json.data.attributes;
const relationships = json.data.relationships;

let tags = [];
let tagIds = [];
if (relationships && relationships.tags) {
tags = relationships.tags.data.map((tag) => {
return { id: parseInt(tag.id) };
tagIds = relationships.tags.data.map((tag) => {
return parseInt(tag.id);
});
}

Expand All @@ -98,7 +99,7 @@ const deserialize = function (json) {
dataProtectionOfficerLastName: attributes['data-protection-officer-last-name'],
dataProtectionOfficerEmail: attributes['data-protection-officer-email'],
enableMultipleSendingAssessment: attributes['enable-multiple-sending-assessment'],
tags,
tagIds,
});

return organization;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { expect, knex, domainBuilder, databaseBuilder, catchErr } from '../../..
import { AlreadyExistingEntityError } from '../../../../lib/domain/errors.js';
import { Tag } from '../../../../lib/domain/models/Tag.js';
import * as tagRepository from '../../../../lib/infrastructure/repositories/tag-repository.js';
import { DomainTransaction } from '../../../../lib/infrastructure/DomainTransaction.js';

describe('Integration | Repository | TagRepository', function () {
afterEach(async function () {
Expand Down Expand Up @@ -81,4 +82,28 @@ describe('Integration | Repository | TagRepository', function () {
expect(result).to.be.deep.equal(expectedResult);
});
});

describe('#findByIds', function () {
it('should return tagsByIds', async function () {
// given
const unknownId = 777777777;
const tag1 = new Tag({ id: 100000, name: 'PUBLIC' });
const tag2 = new Tag({ id: 100001, name: 'PRIVE' });

databaseBuilder.factory.buildTag(tag1);
databaseBuilder.factory.buildTag(tag2);

await databaseBuilder.commit();

const expectedResult = [tag1];

// when
const result = await DomainTransaction.execute(async (domainTransaction) =>
tagRepository.findByIds([tag1.id, unknownId], domainTransaction),
);

// then
expect(result).to.be.deep.equal(expectedResult);
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,84 @@ describe('Unit | Domain | Models | OrganizationForAdmin', function () {
).to.equal(true);
});

context('when updating AEFE tags', function () {
it('should enable compute organization learner certificability for SCO organization', function () {
// given
const givenOrganization = new OrganizationForAdmin({
isManagingStudents: false,
type: 'SCO',
features: {
[ORGANIZATION_FEATURE.COMPUTE_ORGANIZATION_LEARNER_CERTIFICABILITY.key]: false,
},
});

// when
givenOrganization.updateWithDataProtectionOfficerAndTags({}, {}, [{ name: 'AEFE', id: 1 }]);

// then
expect(
givenOrganization.features[ORGANIZATION_FEATURE.COMPUTE_ORGANIZATION_LEARNER_CERTIFICABILITY.key],
).to.equal(true);
});

it('should disable compute organization learner certificability on removing AEFE', function () {
// given
const givenOrganization = new OrganizationForAdmin({
isManagingStudents: false,
type: 'SCO',
features: {
[ORGANIZATION_FEATURE.COMPUTE_ORGANIZATION_LEARNER_CERTIFICABILITY.key]: true,
},
});

// when
givenOrganization.updateWithDataProtectionOfficerAndTags({});

// then
expect(
givenOrganization.features[ORGANIZATION_FEATURE.COMPUTE_ORGANIZATION_LEARNER_CERTIFICABILITY.key],
).to.equal(false);
});

it('should not enable compute organization learner certificability for SUP organization', function () {
// given
const givenOrganization = new OrganizationForAdmin({
isManagingStudents: false,
type: 'SUP',
features: {
[ORGANIZATION_FEATURE.COMPUTE_ORGANIZATION_LEARNER_CERTIFICABILITY.key]: false,
},
});

// when
givenOrganization.updateWithDataProtectionOfficerAndTags({}, {}, [{ name: 'AEFE', id: 1 }]);

// then
expect(
givenOrganization.features[ORGANIZATION_FEATURE.COMPUTE_ORGANIZATION_LEARNER_CERTIFICABILITY.key],
).to.equal(false);
});

it('should not enable compute organization learner certificability for PRO organization', function () {
// given
const givenOrganization = new OrganizationForAdmin({
isManagingStudents: false,
type: 'PRO',
features: {
[ORGANIZATION_FEATURE.COMPUTE_ORGANIZATION_LEARNER_CERTIFICABILITY.key]: false,
},
});

// when
givenOrganization.updateWithDataProtectionOfficerAndTags({}, {}, [{ name: 'AEFE', id: 1 }]);

// then
expect(
givenOrganization.features[ORGANIZATION_FEATURE.COMPUTE_ORGANIZATION_LEARNER_CERTIFICABILITY.key],
).to.equal(false);
});
});

it('should disable compute organization learner certificability when updating SCO organization isManagingStudents to false', function () {
// given
const givenOrganization = new OrganizationForAdmin({
Expand Down
Loading

0 comments on commit 5187377

Please sign in to comment.