Skip to content

Commit

Permalink
feat(api): add additionInfos on csv profile collection line
Browse files Browse the repository at this point in the history
  • Loading branch information
lionelB authored and xav-car committed Sep 23, 2024
1 parent 116fe8b commit 149fd7d
Show file tree
Hide file tree
Showing 6 changed files with 287 additions and 50 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,23 @@ const startWritingCampaignProfilesCollectionResultsToStream = async function ({
campaignParticipationRepository,
organizationRepository,
placementProfileService,
organizationFeatureApi,
organizationLearnerImportFormatRepository,
}) {
const campaign = await campaignRepository.get(campaignId);
const translate = i18n.__;
let additionalHeaders = [];

if (!campaign.isProfilesCollection()) {
throw new CampaignTypeError();
}

const organizationFeatures = await organizationFeatureApi.getAllFeaturesFromOrganization(campaign.organizationId);
if (organizationFeatures.hasLearnersImportFeature) {
const importFormat = await organizationLearnerImportFormatRepository.get(campaign.organizationId);
additionalHeaders = importFormat.exportableColumns;
}

const [allPixCompetences, organization, campaignParticipationResultDatas] = await Promise.all([
competenceRepository.listPixCompetencesOnly({ locale: i18n.getLocale() }),
organizationRepository.get(campaign.organizationId),
Expand All @@ -36,6 +45,7 @@ const startWritingCampaignProfilesCollectionResultsToStream = async function ({
campaign,
allPixCompetences,
translate,
additionalHeaders,
);

// No return/await here, we need the writing to continue in the background
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,22 @@ import * as csvSerializer from '../../../../../shared/infrastructure/serializers
const EMPTY_ARRAY = [];

class CampaignProfilesCollectionResultLine {
constructor(campaign, organization, campaignParticipationResult, competences, placementProfile, translate) {
constructor({
campaign,
organization,
campaignParticipationResult,
competences,
placementProfile,
translate,
additionalHeaders,
}) {
this.organization = organization;
this.campaign = campaign;
this.campaignParticipationResult = campaignParticipationResult;
this.competences = competences;
this.placementProfile = placementProfile;
this.translate = translate;
this.additionalHeaders = additionalHeaders;

this.notShared = translate('campaign-export.common.not-available');
}
Expand All @@ -25,6 +34,7 @@ class CampaignProfilesCollectionResultLine {
this.campaign.name,
this.campaignParticipationResult.participantLastName,
this.campaignParticipationResult.participantFirstName,
...this.#makeAdditionalInfos(),
...this._getGroupColumn(),
...this._getDivisionColumn(),
...this._getStudentNumberColumn(),
Expand All @@ -40,6 +50,12 @@ class CampaignProfilesCollectionResultLine {
return csvSerializer.serializeLine(line);
}

#makeAdditionalInfos() {
if (!this.additionalHeaders) return [];

return this.additionalHeaders.map((header) => this.campaignParticipationResult.additionalInfos[header.columnName])
}

_getDivisionColumn() {
if (this.organization.isSco && this.organization.isManagingStudents) {
return [this.campaignParticipationResult.division || ''];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,14 @@ import { PromiseUtils } from '../../../../../shared/infrastructure/utils/promise
import { CampaignProfilesCollectionResultLine } from '../../exports/campaigns/campaign-profiles-collection-result-line.js';

class CampaignProfilesCollectionExport {
constructor(outputStream, organization, campaign, competences, translate) {
constructor({ outputStream, organization, campaign, competences, translate, additionalHeaders = [] }) {
this.stream = outputStream;
this.organization = organization;
this.campaign = campaign;
this.idPixLabel = campaign.idPixLabel;
this.competences = competences;
this.translate = translate;
this.additionalHeaders = additionalHeaders;
}

export(
Expand Down Expand Up @@ -50,13 +51,16 @@ class CampaignProfilesCollectionExport {
const displayGroup = this.organization.isSup && this.organization.isManagingStudents;
const displayDivision = this.organization.isSco && this.organization.isManagingStudents;

const extraHeaders = this.additionalHeaders.map((header) => header.columnName);

const header = [
this.translate('campaign-export.common.organization-name'),
this.translate('campaign-export.common.campaign-id'),
this.translate('campaign-export.common.campaign-code'),
this.translate('campaign-export.common.campaign-name'),
this.translate('campaign-export.common.participant-lastname'),
this.translate('campaign-export.common.participant-firstname'),
...extraHeaders,
displayGroup && this.translate('campaign-export.common.participant-group'),
displayDivision && this.translate('campaign-export.common.participant-division'),
displayStudentNumber && this.translate('campaign-export.common.participant-student-number'),
Expand Down Expand Up @@ -101,14 +105,15 @@ class CampaignProfilesCollectionExport {
return sameUserId && sameDate;
});

const line = new CampaignProfilesCollectionResultLine(
this.campaign,
this.organization,
campaignParticipationResultData,
this.competences,
const line = new CampaignProfilesCollectionResultLine({
campaign: this.campaign,
organization: this.organization,
campaignParticipationResult: campaignParticipationResultData,
additionalHeaders: this.additionalHeaders,
competences: this.competences,
placementProfile,
this.translate,
);
translate: this.translate,
});

return line.toCsvLine();
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,11 @@ import * as userRepository from '../../../../../../src/identity-access-managemen
import { startWritingCampaignProfilesCollectionResultsToStream } from '../../../../../../src/prescription/campaign/domain/usecases/start-writing-campaign-profiles-collection-results-to-stream.js';
import * as campaignParticipationRepository from '../../../../../../src/prescription/campaign-participation/infrastructure/repositories/campaign-participation-repository.js';
import { CampaignParticipationStatuses } from '../../../../../../src/prescription/shared/domain/constants.js';
import { MAX_REACHABLE_LEVEL, MAX_REACHABLE_PIX_BY_COMPETENCE } from '../../../../../../src/shared/domain/constants.js';
import {
MAX_REACHABLE_LEVEL,
MAX_REACHABLE_PIX_BY_COMPETENCE,
ORGANIZATION_FEATURE,
} from '../../../../../../src/shared/domain/constants.js';
import * as placementProfileService from '../../../../../../src/shared/domain/services/placement-profile-service.js';
import * as competenceRepository from '../../../../../../src/shared/infrastructure/repositories/competence-repository.js';
import * as organizationRepository from '../../../../../../src/shared/infrastructure/repositories/organization-repository.js';
Expand Down Expand Up @@ -188,6 +192,74 @@ describe('Integration | Domain | Use Cases | start-writing-profiles-collection-c
`"Observatoire de Pix";${campaign.id};"QWERTY456";"'@Campagne de Test N°2";"'=Bono";"'@Jean";"'+Mon mail pro";"Non";"NA";"NA";"NA";"NA";"NA";"NA";"NA";"NA"`,
);
});

context('extra columns', function () {
beforeEach(async function () {
// Import Configuration
const importConfig = {
name: 'MY_TEST_EXPORT',
fileType: 'csv',
config: {
acceptedEncoding: ['utf-8'],
unicityColumns: ['my_column1'],
validationRules: {
formats: [
{ name: 'my_column1', type: 'string' },
{ name: 'my_column2', type: 'string' },
],
},
headers: [
{ name: 'my_column1', required: true, property: 'lastName' },
{ name: 'my_column2', required: true, property: 'firstName' },
{ name: 'hobby', required: true, config: { exportable: true } },
],
},
};
const feature = databaseBuilder.factory.buildFeature({
key: ORGANIZATION_FEATURE.LEARNER_IMPORT.key,
});
const organizationLearnerImportFormatId =
databaseBuilder.factory.buildOrganizationLearnerImportFormat(importConfig).id;

databaseBuilder.factory.buildOrganizationFeature({
featureId: feature.id,
organizationId: organization.id,
params: { organizationLearnerImportFormatId },
});
participant = databaseBuilder.factory.buildUser();
organizationLearner = databaseBuilder.factory.prescription.organizationLearners.buildOrganizationLearner({
firstName: '@Jean',
lastName: '=Bono',
organizationId: organization.id,
userId: participant.id,
attributes: { hobby: 'genky', sleep: '8h' },
});
await databaseBuilder.commit();
});
it('should return extra columns', async function () {
startWritingCampaignProfilesCollectionResultsToStream({
campaignId: campaign.id,
writableStream,
i18n,
campaignRepository,
userRepository,
competenceRepository,
organizationRepository,
campaignParticipationRepository,
placementProfileService,
});

const csv = await csvPromise;
const cells = csv.split('\n');

expect(cells[0]).to.be.equals(
'\uFEFF"Nom de l\'organisation";"ID Campagne";"Code";"Nom de la campagne";"Nom du Participant";"Prénom du Participant";"hobby";"Mail Perso";"Envoi (O/N)";"Date de l\'envoi";"Nombre de pix total";"Certifiable (O/N)";"Nombre de compétences certifiables";"Niveau pour la compétence ";"Nombre de pix pour la compétence ";"Niveau pour la compétence ";"Nombre de pix pour la compétence "',
);
expect(cells[1]).to.be.equals(
`"Observatoire de Pix";${campaign.id};"QWERTY456";"'@Campagne de Test N°2";"'=Bono";"'@Jean";"genky";"'+Mon mail pro";"Oui";2019-03-01;52;"Non";2;1;12;5;40`,
);
});
});
});

context('When the organization is PRO', function () {
Expand Down
Loading

0 comments on commit 149fd7d

Please sign in to comment.