Skip to content

Commit

Permalink
[FEATURE] Configuration de l'oralisation par élève pour les écoles (P…
Browse files Browse the repository at this point in the history
  • Loading branch information
pix-service-auto-merge authored Oct 28, 2024
2 parents b3d5466 + 874644f commit 701cc8b
Show file tree
Hide file tree
Showing 31 changed files with 559 additions and 279 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { databaseBuffer } from '../../../database-buffer.js';
import { buildFeature } from '../../build-feature.js';
import { buildOrganizationLearner } from '../../build-organization-learner.js';

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

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

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

export { buildOrganizationLearnerFeature };
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
const TABLE_NAME = 'organization-learner-features';
const CONSTRAINT_NAME = 'organizationLearnerId_featureId_unique';

const up = async function (knex) {
return knex.schema.createTable(TABLE_NAME, function (table) {
table.bigIncrements().primary();
table.bigInteger('featureId').references('features.id').notNullable().comment('Feature identifier');
table
.bigInteger('organizationLearnerId')
.references('organization-learners.id')
.notNullable()
.comment('Identifier of the organization learner having the feature');
table.unique(['featureId', 'organizationLearnerId'], CONSTRAINT_NAME);
table.comment('Association table between organization-learners and features.');
});
};

const down = async function (knex) {
return knex.schema.dropTable(TABLE_NAME);
};

export { down, up };
23 changes: 23 additions & 0 deletions api/db/migrations/20241016094500_add-oralization-to-features.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// 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/DEV/pages/2153512965/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`
import { ORGANIZATION_FEATURE } from '../../src/shared/domain/constants.js';

const up = async function (knex) {
await knex('features').insert({
key: ORGANIZATION_FEATURE.ORALIZATION_MANAGED_BY_PRESCRIBER.key,
description: ORGANIZATION_FEATURE.ORALIZATION_MANAGED_BY_PRESCRIBER.description,
});
};

const down = async function (knex) {
await knex('features').where({ key: ORGANIZATION_FEATURE.ORALIZATION_MANAGED_BY_PRESCRIBER.key }).delete();
};

export { down, up };
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
const up = async function (knex) {
const feature = await knex.select('id').from('features').where({ key: 'ORALIZATION' }).first();
const organizationIdsSco1d = await knex.select('id').from('organizations').where({ type: 'SCO-1D' });

for await (const organization of organizationIdsSco1d) {
await knex('organization-features')
.insert({
organizationId: organization.id,
featureId: feature.id,
})
.onConflict()
.ignore();
}
};

const down = async function (knex) {
const [feature] = await knex.select('id').from('features').where({ key: 'ORALIZATION' }).limit(1);
const organizationIdsSco1d = await knex.select('id').from('organizations').where({ type: 'SCO-1D' });

for await (const organization of organizationIdsSco1d) {
await knex('organization-features').del().where({
organizationId: organization.id,
featureId: feature.id,
});
}
};

export { down, up };
2 changes: 2 additions & 0 deletions api/db/seeds/data/common/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ const FEATURE_MISSIONS_MANAGEMENT_ID = COMMON_OFFSET_ID + 4;
const FEATURE_LEARNER_IMPORT_ID = COMMON_OFFSET_ID + 5;
const FEATURE_CAN_REGISTER_FOR_A_COMPLEMENTARY_CERTIFICATION_ALONE_ID = COMMON_OFFSET_ID + 6;
const FEATURE_CAMPAIGN_EXTERNAL_ID = COMMON_OFFSET_ID + 7;
const FEATURE_ORALIZATION_ID = COMMON_OFFSET_ID + 8;

//ORGANIZATIONS
const SCO_MANAGING_ORGANIZATION_ID = COMMON_OFFSET_ID;
Expand Down Expand Up @@ -85,6 +86,7 @@ export {
FEATURE_LEARNER_IMPORT_ID,
FEATURE_MISSIONS_MANAGEMENT_ID,
FEATURE_MULTIPLE_SENDING_ASSESSMENT_ID,
FEATURE_ORALIZATION_ID,
FEATURE_PLACES_MANAGEMENT_ID,
IMPORT_FORMAT_GENERIC_ID,
IMPORT_FORMAT_ONDE_ID,
Expand Down
6 changes: 6 additions & 0 deletions api/db/seeds/data/common/feature-builder.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
FEATURE_LEARNER_IMPORT_ID,
FEATURE_MISSIONS_MANAGEMENT_ID,
FEATURE_MULTIPLE_SENDING_ASSESSMENT_ID,
FEATURE_ORALIZATION_ID,
FEATURE_PLACES_MANAGEMENT_ID,
} from './constants.js';

Expand Down Expand Up @@ -46,6 +47,11 @@ const featuresBuilder = async function ({ databaseBuilder }) {
key: CAMPAIGN_FEATURES.EXTERNAL_ID.key,
description: CAMPAIGN_FEATURES.EXTERNAL_ID.description,
});
databaseBuilder.factory.buildFeature({
id: FEATURE_ORALIZATION_ID,
key: ORGANIZATION_FEATURE.ORALIZATION_MANAGED_BY_PRESCRIBER.key,
description: ORGANIZATION_FEATURE.ORALIZATION_MANAGED_BY_PRESCRIBER.description,
});
await databaseBuilder.commit();
};

Expand Down
53 changes: 39 additions & 14 deletions api/db/seeds/data/common/organization-learner-import-formats.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,67 +7,92 @@ export const organizationLearnerImportFormat = async function ({ databaseBuilder
name: 'ONDE',
fileType: 'csv',
config: {
acceptedEncoding: ['iso-8859-1', 'utf8'],
unicityColumns: ['INE'],
headers: [
{
name: 'Nom élève',
required: true,
config: {
property: 'lastName',
validate: { type: 'string', required: true },
validate: {
type: 'string',
required: true,
},
},
required: true,
},
{
name: 'Prénom élève',
config: {
property: 'firstName',
validate: { type: 'string', required: true },
validate: {
type: 'string',
required: true,
},
},
required: true,
},
{
name: 'INE',
required: true,
config: {
validate: { type: 'string', required: true },
validate: {
type: 'string',
required: true,
},
},
required: true,
},
{
name: 'Cycle',
required: true,
config: {
validate: {
type: 'string',
expectedValues: ['CYCLE III'],
required: true,
expectedValues: ['CYCLE III'],
},
},
required: true,
},
{
name: 'Niveau',
required: true,
config: {
validate: {
type: 'string',
expectedValues: ['CM1', 'CM2'],
required: true,
expectedValues: ['CM1', 'CM2'],
},
},
required: true,
},
{
name: 'Libellé classe',
required: true,
config: {
validate: { type: 'string', required: true },
validate: {
type: 'string',
required: true,
},
displayable: {
position: 1,
name: IMPORT_KEY_FIELD.COMMON_DIVISION,
filterable: {
type: 'string',
},
},
},
required: true,
},
{
name: 'Date naissance',
config: {
validate: {
type: 'date',
format: 'YYYY-MM-DD',
required: true,
},
},
required: true,
config: { validate: { type: 'date', format: 'YYYY-MM-DD', required: true } },
},
],
unicityColumns: ['INE'],
acceptedEncoding: ['iso-8859-1', 'utf8'],
},
createdAt: new Date('2024-01-01'),
createdBy: REAL_PIX_SUPER_ADMIN_ID,
Expand Down
30 changes: 24 additions & 6 deletions api/db/seeds/data/team-1d/data-builder.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {
FEATURE_LEARNER_IMPORT_ID,
FEATURE_MISSIONS_MANAGEMENT_ID,
FEATURE_ORALIZATION_ID,
IMPORT_FORMAT_ONDE_ID,
USER_ID_ADMIN_ORGANIZATION,
USER_ID_MEMBER_ORGANIZATION,
Expand Down Expand Up @@ -52,6 +53,7 @@ async function _createSco1dOrganizations(databaseBuilder) {
memberIds: [USER_ID_MEMBER_ORGANIZATION],
features: [
{ id: FEATURE_MISSIONS_MANAGEMENT_ID },
{ id: FEATURE_ORALIZATION_ID },
{ id: FEATURE_LEARNER_IMPORT_ID, params: { organizationLearnerImportFormatId: IMPORT_FORMAT_ONDE_ID } },
],
});
Expand Down Expand Up @@ -94,14 +96,14 @@ async function _createSco1dOrganizations(databaseBuilder) {
});

// create class with namesakes
await databaseBuilder.factory.prescription.organizationLearners.buildOndeOrganizationLearner({
firstName: 'Bob',
const learner1 = await databaseBuilder.factory.prescription.organizationLearners.buildOndeOrganizationLearner({
firstName: 'Bob (oralisé)',
lastName: 'Le lapin',
division: 'CM1-B',
organizationId: TEAM_1D_ORGANIZATION_1_ID,
});
await databaseBuilder.factory.prescription.organizationLearners.buildOndeOrganizationLearner({
firstName: 'Bob',
const learner2 = await databaseBuilder.factory.prescription.organizationLearners.buildOndeOrganizationLearner({
firstName: 'Bob (oralisé)',
lastName: 'Le castor',
division: 'CM1-B',
organizationId: TEAM_1D_ORGANIZATION_1_ID,
Expand All @@ -112,8 +114,8 @@ async function _createSco1dOrganizations(databaseBuilder) {
division: 'CM1-B',
organizationId: TEAM_1D_ORGANIZATION_1_ID,
});
await databaseBuilder.factory.prescription.organizationLearners.buildOndeOrganizationLearner({
firstName: 'Bob',
const learner3 = await databaseBuilder.factory.prescription.organizationLearners.buildOndeOrganizationLearner({
firstName: 'Bob (oralisé)',
lastName: 'Le CObaye',
division: 'CM1-B',
organizationId: TEAM_1D_ORGANIZATION_1_ID,
Expand Down Expand Up @@ -143,10 +145,26 @@ async function _createSco1dOrganizations(databaseBuilder) {
adminIds: [TEAM_1D_USER_ID],
features: [
{ id: FEATURE_MISSIONS_MANAGEMENT_ID },
{ id: FEATURE_ORALIZATION_ID },
{ id: FEATURE_LEARNER_IMPORT_ID, params: { organizationLearnerImportFormatId: IMPORT_FORMAT_ONDE_ID } },
],
});

await databaseBuilder.factory.prescription.organizationLearners.buildOrganizationLearnerFeature({
featureId: FEATURE_ORALIZATION_ID,
organizationLearnerId: learner1.id,
});

await databaseBuilder.factory.prescription.organizationLearners.buildOrganizationLearnerFeature({
featureId: FEATURE_ORALIZATION_ID,
organizationLearnerId: learner2.id,
});

await databaseBuilder.factory.prescription.organizationLearners.buildOrganizationLearnerFeature({
featureId: FEATURE_ORALIZATION_ID,
organizationLearnerId: learner3.id,
});

await databaseBuilder.factory.buildSchool({
organizationId: TEAM_1D_ORGANIZATION_2_ID,
code: 'MAXIPIXOU',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,8 @@ export class OrganizationFeaturesDTO {
get hasLearnersImportFeature() {
return this.features.some((feature) => feature.name === ORGANIZATION_FEATURE.LEARNER_IMPORT.key);
}

get hasOralizationFeature() {
return this.features.some((feature) => feature.name === ORGANIZATION_FEATURE.ORALIZATION_MANAGED_BY_PRESCRIBER.key);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ class OrganizationForAdmin {
}
if (this.type === 'SCO-1D') {
this.features[ORGANIZATION_FEATURE.MISSIONS_MANAGEMENT.key] = { active: true, params: null };
this.features[ORGANIZATION_FEATURE.ORALIZATION_MANAGED_BY_PRESCRIBER.key] = { active: true, params: null };
this.features[ORGANIZATION_FEATURE.LEARNER_IMPORT.key] = {
active: true,
params: { name: ORGANIZATION_FEATURE.LEARNER_IMPORT.FORMAT.ONDE },
Expand Down
Loading

0 comments on commit 701cc8b

Please sign in to comment.