Skip to content

Commit

Permalink
feat(api): update batch usecase with external api
Browse files Browse the repository at this point in the history
  • Loading branch information
xav-car committed Nov 29, 2024
1 parent ed758df commit c6b770e
Show file tree
Hide file tree
Showing 6 changed files with 73 additions and 12 deletions.
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
class OrganizationFeature {
constructor({ featureId, organizationId, params }) {
#deleteLearner;
constructor({ featureId, organizationId, params, deleteLearner }) {
this.featureId = parseInt(featureId, 10);
this.organizationId = parseInt(organizationId, 10);
this.params = params ? JSON.parse(params) : null;

this.#deleteLearner = deleteLearner === 'Y';
}

get deleteLearner() {
return this.#deleteLearner;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,31 +28,43 @@ const organizationFeatureCsvHeader = {
name: 'Params',
isRequired: false,
}),
new CsvColumn({
property: 'deleteLearner',
name: 'Delete Learner',
isRequired: false,
}),
],
};

export const addOrganizationFeatureInBatch = withTransaction(
/**
* @param {Object} params - A parameter object.
* @param {Number} params.userId - user connected performing action
* @param {Number} params.userId - user connected performing the action
* @param {string} params.filePath - path of csv file wich contains organizations and params.
* @param {OrganizationFeatureRepository} params.organizationFeatureRepository - organizationRepository to use.
* @param {Object} params.dependencies
* @returns {Promise<void>}
*/
async ({ filePath, organizationFeatureRepository }) => {
async ({ userId, filePath, organizationFeatureRepository, learnersApi }) => {
const stream = createReadStream(filePath);
const buffer = await getDataBuffer(stream);

const csvParser = new CsvParser(buffer, organizationFeatureCsvHeader);
const csvData = csvParser.parse();
const data = csvData.map(({ featureId, organizationId, params }) => {
const data = csvData.map(({ featureId, organizationId, params, deleteLearner }) => {
try {
return new OrganizationFeature({ featureId, organizationId, params: params });
return new OrganizationFeature({ featureId, organizationId, params, deleteLearner });
} catch (err) {
throw new FeatureParamsNotProcessable();
}
});

data.forEach(async ({ organizationId, deleteLearner }) => {
if (deleteLearner) {
await learnersApi.deleteOrganizationLearnerBeforeImportFeature({ userId, organizationId });
}
});

return organizationFeatureRepository.saveInBatch(data);
},
);
4 changes: 3 additions & 1 deletion api/src/organizational-entities/domain/usecases/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { dirname, join } from 'node:path';
import { fileURLToPath } from 'node:url';

import * as organizationTagRepository from '../../../../lib/infrastructure/repositories/organization-tag-repository.js';
import * as learnersApi from '../../../prescription/learner-management/application/api/learners-api.js';
import * as schoolRepository from '../../../school/infrastructure/repositories/school-repository.js';
import { injectDependencies } from '../../../shared/infrastructure/utils/dependency-injection.js';
import { importNamedExportsFromDirectory } from '../../../shared/infrastructure/utils/import-named-exports-from-directory.js';
Expand All @@ -12,10 +13,10 @@ import * as dataProtectionOfficerRepository from '../../infrastructure/repositor
import * as organizationFeatureRepository from '../../infrastructure/repositories/organization-feature-repository.js';
import { organizationForAdminRepository } from '../../infrastructure/repositories/organization-for-admin.repository.js';
import { tagRepository } from '../../infrastructure/repositories/tag.repository.js';

const path = dirname(fileURLToPath(import.meta.url));

/**
* @typedef {import ('../../../prescription/learner-management/application/api/learners-api.js')} learnersApi
* @typedef {import ('../../infrastructure/repositories/certification-center.repository.js')} CertificationCenterRepository
* @typedef {import ('../../infrastructure/repositories/certification-center-for-admin-repository.js')} CertificationCenterForAdminRepository
* @typedef {import ('../../infrastructure/repositories/complementary-certification-habilitation-repository.js')} ComplementaryCertificationHabilitationRepository
Expand All @@ -34,6 +35,7 @@ const repositories = {
organizationForAdminRepository,
organizationFeatureRepository,
schoolRepository,
learnersApi,
organizationTagRepository,
tagRepository,
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@ import { domainBuilder, expect, hFake, sinon } from '../../../../test-helper.js'

describe('Unit | Organizational Entities | Application | Controller | Admin | organization', function () {
describe('#addOrganizationFeatureInBatch', function () {
let filePath, request;
let filePath, request, userId;

beforeEach(function () {
userId = Symbol('userId');
filePath = Symbol('filePath');
request = { payload: { path: filePath } };
request = { payload: { path: filePath }, auth: { credentials: { userId } } };
sinon.stub(usecases, 'addOrganizationFeatureInBatch').resolves();
});

Expand All @@ -24,6 +25,7 @@ describe('Unit | Organizational Entities | Application | Controller | Admin | or

// then
expect(usecases.addOrganizationFeatureInBatch).to.have.been.calledWithExactly({
userId,
filePath,
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,24 @@ describe('Unit | Organizational Entities | Domain | Model | OrganizationFeature'
//when
organizationFeature = new OrganizationFeature({ featureId, organizationId, params });
// then
expect(organizationFeature).to.deep.equal({ featureId: 1, organizationId: 2, params: { id: 3 } });
expect(organizationFeature).to.deep.equal({
featureId: 1,
organizationId: 2,
params: { id: 3 },
deletedLearner: false,
});
});

it('should activate learner deletion given params', function () {
//when
organizationFeature = new OrganizationFeature({ featureId, organizationId, params, deletedLearner: 'Y' });
// then
expect(organizationFeature).to.deep.equal({
featureId: 1,
organizationId: 2,
params: { id: 3 },
deletedLearner: true,
});
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,20 @@ import { DomainTransaction } from '../../../../../src/shared/domain/DomainTransa
import { catchErr, createTempFile, expect, removeTempFile, sinon } from '../../../../test-helper.js';

describe('Unit | Domain | UseCases | add-organization-feature-in-batch', function () {
let organizationFeatureRepository, featureId, filePath, csvData;
let organizationFeatureRepository, learnersApi, featureId, filePath, csvData, userId;

beforeEach(function () {
sinon.stub(DomainTransaction, 'execute').callsFake((callback) => {
return callback();
});

userId = Symbol('userId');
featureId = 1;
csvData = [
new OrganizationFeature({ featureId, organizationId: 123, params: `{ "id": 123 }` }),
new OrganizationFeature({ featureId, organizationId: 456, params: `{ "id": 123 }` }),
];

learnersApi = { deleteOrganizationLearnerBeforeImportFeature: sinon.stub() };
organizationFeatureRepository = {
saveInBatch: sinon.stub(),
};
Expand All @@ -37,9 +38,29 @@ describe('Unit | Domain | UseCases | add-organization-feature-in-batch', functio
`,
);
// when
await addOrganizationFeatureInBatch({ filePath, organizationFeatureRepository });
await addOrganizationFeatureInBatch({ filePath, organizationFeatureRepository, learnersApi });

expect(organizationFeatureRepository.saveInBatch).to.have.been.calledOnceWithExactly(csvData);
expect(learnersApi.deleteOrganizationLearnerBeforeImportFeature.called).to.be.false;
});

it('should call call learner api with correct paramaters', async function () {
// given
filePath = await createTempFile(
'test.csv',
`Feature ID;Organization ID;Params;Delete Learner
${featureId};123;{"id": 123};
${featureId};456;{"id": 123};Y
`,
);
// when
await addOrganizationFeatureInBatch({ userId, filePath, organizationFeatureRepository, learnersApi });

expect(organizationFeatureRepository.saveInBatch).to.have.been.calledOnceWithExactly(csvData);
expect(learnersApi.deleteOrganizationLearnerBeforeImportFeature).to.have.been.calledOnceWithExactly({
userId,
organizationId: 456,
});
});

it('should throw a FeatureParamsNotProcessable error', async function () {
Expand Down

0 comments on commit c6b770e

Please sign in to comment.