Skip to content

Commit

Permalink
Merge pull request #6383 from NMDSdevopsServiceAdm/feat/1543-delete-t…
Browse files Browse the repository at this point in the history
…raining-certificates-on-deletion-of-worker

Feat/1543 delete training certificates on deletion of worker
  • Loading branch information
duncanc19 authored Oct 10, 2024
2 parents c907158 + e508f51 commit b329a6b
Show file tree
Hide file tree
Showing 3 changed files with 116 additions and 2 deletions.
18 changes: 18 additions & 0 deletions backend/server/models/classes/worker.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ const WorkerProperties = require('./worker/workerProperties').WorkerPropertyMana
const JSON_DOCUMENT_TYPE = require('./worker/workerProperties').JSON_DOCUMENT;
const SEQUELIZE_DOCUMENT_TYPE = require('./worker/workerProperties').SEQUELIZE_DOCUMENT;

const TrainingCertificateRoute = require('../../routes/establishments/workerCertificate/trainingCertificate');

// WDF Calculator
const WdfCalculator = require('./wdfCalculator').WdfCalculator;

Expand Down Expand Up @@ -1150,6 +1152,8 @@ class Worker extends EntityValidator {
// TODO - to be confirmed
}

await this.deleteAllTrainingCertificatesAssociatedWithWorker(thisTransaction);

// always recalculate WDF - if not bulk upload (this._status)
if (this._status === null) {
await WdfCalculator.calculate(
Expand Down Expand Up @@ -1894,6 +1898,20 @@ class Worker extends EntityValidator {
throw err;
}
}

async deleteAllTrainingCertificatesAssociatedWithWorker(transaction) {
const trainingCertificates = await models.trainingCertificates.getAllTrainingCertificateRecordsForWorker(this._id);

if (!trainingCertificates.length) return;

const trainingCertificateUids = trainingCertificates.map((cert) => cert.uid);
const filesToDeleteFromS3 = trainingCertificates.map((cert) => {
return { Key: cert.key };
});

await models.trainingCertificates.deleteCertificate(trainingCertificateUids, transaction);
await TrainingCertificateRoute.deleteCertificatesFromS3(filesToDeleteFromS3);
}
}

module.exports.Worker = Worker;
Expand Down
11 changes: 10 additions & 1 deletion backend/server/models/trainingCertificates.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,11 +79,12 @@ module.exports = function (sequelize, DataTypes) {
});
};

TrainingCertificates.deleteCertificate = async function (uids) {
TrainingCertificates.deleteCertificate = async function (uids, transaction = null) {
return await this.destroy({
where: {
uid: uids,
},
...(transaction ? { transaction } : {}),
});
};

Expand All @@ -95,5 +96,13 @@ module.exports = function (sequelize, DataTypes) {
});
};

TrainingCertificates.getAllTrainingCertificateRecordsForWorker = async function (workerFk) {
return await this.findAll({
where: {
workerFk,
},
});
};

return TrainingCertificates;
};
89 changes: 88 additions & 1 deletion backend/server/test/unit/models/classes/worker.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ const expect = require('chai').expect;
const { build, fake, oneOf } = require('@jackfranklin/test-data-bot');
const sinon = require('sinon');

const models = require('../../../../models');
const Worker = require('../../../../models/classes/worker').Worker;
const WdfCalculator = require('../../../../models/classes/wdfCalculator');
const TrainingCertificateRoute = require('../../../../routes/establishments/workerCertificate/trainingCertificate');

const worker = new Worker();

Expand Down Expand Up @@ -428,4 +429,90 @@ describe('Worker Class', () => {
});
});
});

describe('deleteAllTrainingCertificatesAssociatedWithWorker()', async () => {
let mockWorker;
const trainingCertificatesReturnedFromDb = () => {
return [
{ uid: 'abc123', key: 'abc123/trainingCertificate/dasdsa12312' },
{ uid: 'def456', key: 'def456/trainingCertificate/deass12092' },
{ uid: 'ghi789', key: 'ghi789/trainingCertificate/da1412342' },
];
};

beforeEach(() => {
mockWorker = new Worker();
mockWorker._id = 12345;
});

afterEach(() => {
sinon.restore();
});

it('should call getAllTrainingCertificateRecordsForWorker with worker ID', async () => {
const getAllTrainingCertificateRecordsForWorkerSpy = sinon
.stub(models.trainingCertificates, 'getAllTrainingCertificateRecordsForWorker')
.resolves([]);

await mockWorker.deleteAllTrainingCertificatesAssociatedWithWorker();

expect(getAllTrainingCertificateRecordsForWorkerSpy.args[0][0]).to.equal(12345);
});

it('should not make DB or S3 deletion calls if no training certificates found', async () => {
const getAllTrainingCertificateRecordsForWorkerSpy = sinon
.stub(models.trainingCertificates, 'getAllTrainingCertificateRecordsForWorker')
.resolves([]);

const dbDeleteCertificateSpy = sinon.stub(models.trainingCertificates, 'deleteCertificate');
const s3DeleteCertificateSpy = sinon.stub(TrainingCertificateRoute, 'deleteCertificatesFromS3');

await mockWorker.deleteAllTrainingCertificatesAssociatedWithWorker();

expect(dbDeleteCertificateSpy.callCount).to.equal(0);
expect(s3DeleteCertificateSpy.callCount).to.equal(0);
});

it('should call deleteCertificate on DB model with uids returned from getAllTrainingCertificateRecordsForWorker and pass in transaction', async () => {
const trainingCertificates = trainingCertificatesReturnedFromDb();

const getAllTrainingCertificateRecordsForWorkerSpy = sinon
.stub(models.trainingCertificates, 'getAllTrainingCertificateRecordsForWorker')
.resolves(trainingCertificates);

const dbDeleteCertificateSpy = sinon.stub(models.trainingCertificates, 'deleteCertificate');
sinon.stub(TrainingCertificateRoute, 'deleteCertificatesFromS3');
const transaction = await models.sequelize.transaction();

await mockWorker.deleteAllTrainingCertificatesAssociatedWithWorker(transaction);

expect(dbDeleteCertificateSpy.args[0][0]).to.deep.equal([
trainingCertificates[0].uid,
trainingCertificates[1].uid,
trainingCertificates[2].uid,
]);

expect(dbDeleteCertificateSpy.args[0][1]).to.deep.equal(transaction);
});

it('should call deleteCertificatesFromS3 with keys returned from getAllTrainingCertificateRecordsForWorker', async () => {
const trainingCertificates = trainingCertificatesReturnedFromDb();

const getAllTrainingCertificateRecordsForWorkerSpy = sinon
.stub(models.trainingCertificates, 'getAllTrainingCertificateRecordsForWorker')
.resolves(trainingCertificates);

sinon.stub(models.trainingCertificates, 'deleteCertificate');
const s3DeleteCertificateSpy = sinon.stub(TrainingCertificateRoute, 'deleteCertificatesFromS3');
const transaction = await models.sequelize.transaction();

await mockWorker.deleteAllTrainingCertificatesAssociatedWithWorker(transaction);

expect(s3DeleteCertificateSpy.args[0][0]).to.deep.equal([
{ Key: trainingCertificates[0].key },
{ Key: trainingCertificates[1].key },
{ Key: trainingCertificates[2].key },
]);
});
});
});

0 comments on commit b329a6b

Please sign in to comment.