diff --git a/__tests__/unit/PlanSnapshot.amendmentSubmissions.spec.js b/__tests__/unit/PlanSnapshot.amendmentSubmissions.spec.js new file mode 100644 index 00000000..4eb9f400 --- /dev/null +++ b/__tests__/unit/PlanSnapshot.amendmentSubmissions.spec.js @@ -0,0 +1,111 @@ +import { describe, expect, it, vi, beforeAll } from 'vitest'; + +beforeAll(() => { + process.env.SSO_URL = process.env.SSO_URL || 'https://sso.example.com'; +}); +vi.mock('../../src/libs/db2/model/amendmenttype.js', () => ({ + default: { + find: vi.fn().mockResolvedValue([ + { id: 1, description: 'Minor Amendment' }, + { id: 2, description: 'Mandatory Amendment' }, + ]), + }, +})); + +describe('PlanSnapshot.fetchAmendmentSubmissions', () => { + it('pairs a mandatory amendment with its later approval', async () => { + const snapshots = [ + { + id: 1, + plan_id: 1444, + version: 1, + status_id: 12, + created_at: '2021-06-17T23:43:07.837Z', + snapshot: { statusId: 12, amendmentTypeId: null }, + given_name: 'Jason', + family_name: 'Caswell', + }, + { + id: 2, + plan_id: 1444, + version: 2, + status_id: 22, + created_at: '2024-02-22T23:38:15.337Z', + snapshot: { statusId: 22, amendmentTypeId: 2 }, + given_name: 'Taylor', + family_name: 'Grafton', + }, + { + id: 3, + plan_id: 1444, + version: 3, + status_id: 12, + created_at: '2024-05-30T23:00:48.697Z', + snapshot: { statusId: 12, amendmentTypeId: 2 }, + given_name: 'Tara', + family_name: 'Bogh', + }, + ]; + const query = { + leftJoin: vi.fn().mockReturnThis(), + select: vi.fn().mockReturnThis(), + where: vi.fn().mockReturnThis(), + orderBy: vi.fn().mockReturnThis(), + execute: vi.fn().mockResolvedValue(snapshots), + }; + const db = { selectFrom: vi.fn().mockReturnValue(query) }; + const { default: PlanSnapshot } = await import('../../src/libs/db2/model/plansnapshot.ts'); + + const result = await PlanSnapshot.fetchAmendmentSubmissions(db, 1444); + + expect(result[1]).toMatchObject({ + createdAt: '2024-02-22T23:38:15.337Z', + submittedBy: 'Taylor Grafton', + approvedAt: '2024-05-30T23:00:48.697Z', + approvedBy: 'Tara Bogh', + }); + }); + + it('does not pair a mandatory amendment with an earlier approval', async () => { + const snapshots = [ + { + id: 1, + plan_id: 1444, + version: 1, + status_id: 12, + created_at: '2021-06-17T23:43:07.837Z', + snapshot: { statusId: 12, amendmentTypeId: null }, + given_name: 'Jason', + family_name: 'Caswell', + }, + { + id: 2, + plan_id: 1444, + version: 2, + status_id: 22, + created_at: '2024-02-22T23:38:15.337Z', + snapshot: { statusId: 22, amendmentTypeId: 2 }, + given_name: 'Taylor', + family_name: 'Grafton', + }, + ]; + const query = { + leftJoin: vi.fn().mockReturnThis(), + select: vi.fn().mockReturnThis(), + where: vi.fn().mockReturnThis(), + orderBy: vi.fn().mockReturnThis(), + execute: vi.fn().mockResolvedValue(snapshots), + }; + const db = { selectFrom: vi.fn().mockReturnValue(query) }; + const { default: PlanSnapshot } = await import('../../src/libs/db2/model/plansnapshot.ts'); + + const result = await PlanSnapshot.fetchAmendmentSubmissions(db, 1444); + + expect(result[1]).toMatchObject({ + createdAt: '2024-02-22T23:38:15.337Z', + submittedBy: 'Taylor Grafton', + approvedAt: null, + approvedBy: null, + }); + }); +}); diff --git a/src/libs/db2/model/plansnapshot.ts b/src/libs/db2/model/plansnapshot.ts index e7e186cb..daa2f29a 100644 --- a/src/libs/db2/model/plansnapshot.ts +++ b/src/libs/db2/model/plansnapshot.ts @@ -94,7 +94,7 @@ export default class PlanSnapshot extends KyselyModel { 'user_account.given_name', ]) .where('plan_snapshot.plan_id', '=', planId) - .orderBy('plan_snapshot.created_at', 'desc'); + .orderBy('plan_snapshot.created_at', 'asc'); if (startDate) query = query.where('plan_snapshot.created_at', '<=', startDate); const results = await query.execute(); const response: any[] = []; @@ -102,7 +102,7 @@ export default class PlanSnapshot extends KyselyModel { let lastMinorAmendment: number | null = null; for (let index = 0; index < results.length; index++) { const row: any = results[index]; - const nextRow: any = results[index + 1]; + const previousRow: any = results[index - 1]; row.isCurrentLegalVersion = false; if (row.snapshot?.amendmentTypeId === 4) { response.push({ @@ -130,7 +130,7 @@ export default class PlanSnapshot extends KyselyModel { amendmentType: amendmentTypeArray[1], snapshot: row.snapshot, }); - } else if (row.status_id === 22 || (row.status_id === 23 && nextRow?.status_id !== 21)) { + } else if (row.status_id === 22 || (row.status_id === 23 && previousRow?.status_id !== 21)) { lastMandatoryAmendment = response.length; response.push({ id: row.id, @@ -175,10 +175,10 @@ export default class PlanSnapshot extends KyselyModel { } } } - const responseSorted = response.reverse(); - const currentLegalVersion = responseSorted.find( - (resp: any) => Plan.legalStatuses.indexOf(resp.snapshot.statusId) !== -1, - ); + const responseSorted = response; + const currentLegalVersion = [...responseSorted] + .reverse() + .find((resp: any) => Plan.legalStatuses.indexOf(resp.snapshot.statusId) !== -1); if (currentLegalVersion) currentLegalVersion.isCurrentLegalVersion = true; return responseSorted; }