From 7c863e39bb3584708dd531d473611ec5a1b3ef75 Mon Sep 17 00:00:00 2001 From: Robert Parkinson Date: Fri, 11 Oct 2024 09:49:27 +0100 Subject: [PATCH] Return log start and end dates to be determined using the correct cycle dates (#1397) https://eaflood.atlassian.net/browse/WATER-4543 As part of the work to replace the legacy system NALD we need to generate return logs. This PR updates the logic around how the start, end and due dates are calculated based on the time of the year the request is being made. This is mostly for new licences that have been imported or for when licences are ended and will need new return logs created. --- app/lib/dates.lib.js | 66 +++++++++------ test/lib/dates.lib.test.js | 81 ++++++++++++++++--- .../fetch-return-requirements.service.test.js | 12 ++- .../generate-return-logs.service.test.js | 67 ++++++++++----- 4 files changed, 165 insertions(+), 61 deletions(-) diff --git a/app/lib/dates.lib.js b/app/lib/dates.lib.js index 859aa33839..6670e8c6ea 100644 --- a/app/lib/dates.lib.js +++ b/app/lib/dates.lib.js @@ -64,17 +64,23 @@ function cycleDueDateAsISO (summer) { * @returns {Date} - the due date of the next cycle. */ function cycleDueDate (summer) { + const today = new Date() + const year = today.getFullYear() + const month = today.getMonth() + if (summer) { - return new Date(new Date().getFullYear() + 1, - returnCycleDates.summer.dueDate.month, - returnCycleDates.summer.dueDate.day - ) + if (month > returnCycleDates.summer.endDate.month) { + return new Date(year + 1, returnCycleDates.summer.dueDate.month, returnCycleDates.summer.dueDate.day) + } + + return new Date(year, returnCycleDates.summer.dueDate.month, returnCycleDates.summer.dueDate.day) + } + + if (month > returnCycleDates.allYear.endDate.month) { + return new Date(year + 1, returnCycleDates.allYear.dueDate.month, returnCycleDates.allYear.dueDate.day) } - return new Date(new Date().getFullYear() + 1, - returnCycleDates.allYear.dueDate.month, - returnCycleDates.allYear.dueDate.day - ) + return new Date(year, returnCycleDates.allYear.dueDate.month, returnCycleDates.allYear.dueDate.day) } /** @@ -94,17 +100,23 @@ function cycleEndDateAsISO (summer) { * @returns {Date} - the end date of the next cycle. */ function cycleEndDate (summer) { + const today = new Date() + const year = today.getFullYear() + const month = today.getMonth() + if (summer) { - return new Date(new Date().getFullYear() + 1, - returnCycleDates.summer.endDate.month, - returnCycleDates.summer.endDate.day - ) + if (month > returnCycleDates.summer.endDate.month) { + return new Date(year + 1, returnCycleDates.summer.endDate.month, returnCycleDates.summer.endDate.day) + } + + return new Date(year, returnCycleDates.summer.endDate.month, returnCycleDates.summer.endDate.day) } - return new Date(new Date().getFullYear() + 1, - returnCycleDates.allYear.endDate.month, - returnCycleDates.allYear.endDate.day - ) + if (month > returnCycleDates.allYear.endDate.month) { + return new Date(year + 1, returnCycleDates.allYear.endDate.month, returnCycleDates.allYear.endDate.day) + } + + return new Date(year, returnCycleDates.allYear.endDate.month, returnCycleDates.allYear.endDate.day) } /** @@ -124,17 +136,23 @@ function cycleStartDateAsISO (summer) { * @returns {Date} - the start date of the next cycle. */ function cycleStartDate (summer) { + const today = new Date() + const year = today.getFullYear() + const month = today.getMonth() + if (summer) { - return new Date(new Date().getFullYear(), - returnCycleDates.summer.startDate.month, - returnCycleDates.summer.startDate.day - ) + if (month < returnCycleDates.summer.startDate.month) { + return new Date(year - 1, returnCycleDates.summer.startDate.month, returnCycleDates.summer.startDate.day) + } + + return new Date(year, returnCycleDates.summer.startDate.month, returnCycleDates.summer.startDate.day) + } + + if (month < returnCycleDates.allYear.startDate.month) { + return new Date(year - 1, returnCycleDates.allYear.startDate.month, returnCycleDates.allYear.startDate.day) } - return new Date(new Date().getFullYear(), - returnCycleDates.allYear.startDate.month, - returnCycleDates.allYear.startDate.day - ) + return new Date(year, returnCycleDates.allYear.startDate.month, returnCycleDates.allYear.startDate.day) } /** diff --git a/test/lib/dates.lib.test.js b/test/lib/dates.lib.test.js index c7e9afe712..1638a292ff 100644 --- a/test/lib/dates.lib.test.js +++ b/test/lib/dates.lib.test.js @@ -7,10 +7,15 @@ const Code = require('@hapi/code') const { describe, it, beforeEach } = exports.lab = Lab.script() const { expect } = Code +const { returnCycleDates } = require('../../app/lib/static-lookups.lib.js') + // Thing under test const DateLib = require('../../app/lib/dates.lib.js') describe('Dates lib', () => { + const today = new Date() + const month = today.getMonth() + let expectedDate let summer @@ -95,7 +100,11 @@ describe('Dates lib', () => { beforeEach(() => { summer = true - expectedDate = new Date(new Date().getFullYear() + 1, 10, 28) + if (month > returnCycleDates.summer.endDate.month) { + expectedDate = new Date(new Date().getFullYear() + 1, 10, 28) + } else { + expectedDate = new Date(new Date().getFullYear(), 10, 28) + } }) it('should return the due date for the current summer cycle', () => { @@ -109,7 +118,11 @@ describe('Dates lib', () => { beforeEach(() => { summer = false - expectedDate = new Date(new Date().getFullYear() + 1, 3, 28) + if (month > returnCycleDates.allYear.endDate.month) { + expectedDate = new Date(new Date().getFullYear() + 1, 3, 28) + } else { + expectedDate = new Date(new Date().getFullYear(), 3, 28) + } }) it('should return the due date of the current winter and all year cycle', () => { @@ -125,7 +138,11 @@ describe('Dates lib', () => { beforeEach(() => { summer = true - expectedDate = new Date(new Date().getFullYear() + 1, 10, 28).toISOString().split('T')[0] + if (month > returnCycleDates.summer.endDate.month) { + expectedDate = new Date(new Date().getFullYear() + 1, 10, 28).toISOString().split('T')[0] + } else { + expectedDate = new Date(new Date().getFullYear(), 10, 28).toISOString().split('T')[0] + } }) it('should return the due date for the current summer cycle formatted as YYYY-MM-DD', () => { @@ -139,7 +156,11 @@ describe('Dates lib', () => { beforeEach(() => { summer = false - expectedDate = new Date(new Date().getFullYear() + 1, 3, 28).toISOString().split('T')[0] + if (month > returnCycleDates.allYear.endDate.month) { + expectedDate = new Date(new Date().getFullYear() + 1, 3, 28).toISOString().split('T')[0] + } else { + expectedDate = new Date(new Date().getFullYear(), 3, 28).toISOString().split('T')[0] + } }) it('should return the due date of the current winter and all year cycle formatted as YYYY-MM-DD', () => { @@ -155,7 +176,11 @@ describe('Dates lib', () => { beforeEach(() => { summer = true - expectedDate = new Date(new Date().getFullYear() + 1, 9, 31) + if (month > returnCycleDates.summer.endDate.month) { + expectedDate = new Date(new Date().getFullYear() + 1, 9, 31) + } else { + expectedDate = new Date(new Date().getFullYear(), 9, 31) + } }) it('should return the due date for the current summer cycle', () => { @@ -169,7 +194,11 @@ describe('Dates lib', () => { beforeEach(() => { summer = false - expectedDate = new Date(new Date().getFullYear() + 1, 2, 31) + if (month > returnCycleDates.allYear.endDate.month) { + expectedDate = new Date(new Date().getFullYear() + 1, 2, 31) + } else { + expectedDate = new Date(new Date().getFullYear(), 2, 31) + } }) it('should return the due date of the current winter and all year cycle', () => { @@ -185,7 +214,11 @@ describe('Dates lib', () => { beforeEach(() => { summer = true - expectedDate = new Date(new Date().getFullYear() + 1, 9, 31).toISOString().split('T')[0] + if (month > returnCycleDates.summer.endDate.month) { + expectedDate = new Date(new Date().getFullYear() + 1, 9, 31).toISOString().split('T')[0] + } else { + expectedDate = new Date(new Date().getFullYear(), 9, 31).toISOString().split('T')[0] + } }) it('should return the due date for the current summer cycle formatted as YYYY-MM-DD', () => { @@ -199,7 +232,11 @@ describe('Dates lib', () => { beforeEach(() => { summer = false - expectedDate = new Date(new Date().getFullYear() + 1, 2, 31).toISOString().split('T')[0] + if (month > returnCycleDates.allYear.endDate.month) { + expectedDate = new Date(new Date().getFullYear() + 1, 2, 31).toISOString().split('T')[0] + } else { + expectedDate = new Date(new Date().getFullYear(), 2, 31).toISOString().split('T')[0] + } }) it('should return the due date of the current winter and all year cycle formatted as YYYY-MM-DD', () => { @@ -215,10 +252,14 @@ describe('Dates lib', () => { beforeEach(() => { summer = true - expectedDate = new Date(new Date().getFullYear(), 10, 1) + if (month < returnCycleDates.summer.startDate.month) { + expectedDate = new Date(new Date().getFullYear() - 1, 10, 1) + } else { + expectedDate = new Date(new Date().getFullYear(), 10, 1) + } }) - it('should return the due date for the current summer cycle', () => { + it('should return the start date for the current summer cycle', () => { const result = DateLib.cycleStartDate(summer) expect(result).to.equal(expectedDate) @@ -229,7 +270,11 @@ describe('Dates lib', () => { beforeEach(() => { summer = false - expectedDate = new Date(new Date().getFullYear(), 3, 1) + if (month < returnCycleDates.allYear.startDate.month) { + expectedDate = new Date(new Date().getFullYear() - 1, 3, 1) + } else { + expectedDate = new Date(new Date().getFullYear(), 3, 1) + } }) it('should return the due date of the current winter and all year cycle', () => { @@ -245,10 +290,14 @@ describe('Dates lib', () => { beforeEach(() => { summer = true - expectedDate = new Date(new Date().getFullYear(), 10, 1).toISOString().split('T')[0] + if (month < returnCycleDates.summer.startDate.month) { + expectedDate = new Date(new Date().getFullYear() - 1, 10, 1).toISOString().split('T')[0] + } else { + expectedDate = new Date(new Date().getFullYear(), 10, 1).toISOString().split('T')[0] + } }) - it('should return the due date for the current summer cycle formatted as YYYY-MM-DD', () => { + it('should return the start date for the current summer cycle formatted as YYYY-MM-DD', () => { const result = DateLib.cycleStartDateAsISO(summer) expect(result).to.equal(expectedDate) @@ -259,6 +308,12 @@ describe('Dates lib', () => { beforeEach(() => { summer = false + if (month < returnCycleDates.allYear.startDate.month) { + expectedDate = new Date(new Date().getFullYear() - 1, 3, 1).toISOString().split('T')[0] + } else { + expectedDate = new Date(new Date().getFullYear(), 3, 1).toISOString().split('T')[0] + } + expectedDate = new Date(new Date().getFullYear(), 3, 1).toISOString().split('T')[0] }) diff --git a/test/services/jobs/return-logs/fetch-return-requirements.service.test.js b/test/services/jobs/return-logs/fetch-return-requirements.service.test.js index 2262b9c53b..0b755e6b7c 100644 --- a/test/services/jobs/return-logs/fetch-return-requirements.service.test.js +++ b/test/services/jobs/return-logs/fetch-return-requirements.service.test.js @@ -8,6 +8,8 @@ const { describe, it, before } = exports.lab = Lab.script() const { expect } = Code // Test helpers +const { returnCycleDates } = require('../../../../app/lib/static-lookups.lib.js') +const { formatDateObjectToISO } = require('../../../../app/lib/dates.lib.js') const LicenceHelper = require('../../../support/helpers/licence.helper.js') const PointHelper = require('../../../support/helpers/point.helper.js') const PrimaryPurposeHelper = require('../../../support/helpers/primary-purpose.helper.js') @@ -23,6 +25,9 @@ const SecondaryPurposeHelper = require('../../../support/helpers/secondary-purpo const FetchReturnRequirementsService = require('../../../../app/services/jobs/return-logs/fetch-return-requirements.service.js') describe('Fetch return logs service', () => { + const today = new Date() + const month = today.getMonth() + const year = today.getFullYear() const summerReturns = [] const allYearReturns = [] @@ -44,7 +49,11 @@ describe('Fetch return logs service', () => { let revokedDate let secondaryPurpose let secondaryPurpose2 - let startDate + let startDate = formatDateObjectToISO(new Date(year, 11, 1)) + + if (month < returnCycleDates.summer.startDate.month) { + startDate = formatDateObjectToISO(new Date(year - 1, 11, 1)) + } describe('when summer is false, one return requirement and a licenceRef provided', () => { before(async () => { @@ -774,7 +783,6 @@ describe('Fetch return logs service', () => { describe('when summer is true, the return version start date is after the cycle start date, one return requirement and a licenceRef provided', () => { before(async () => { - startDate = new Date(new Date().getFullYear(), 11, 1).toISOString().split('T')[0] primaryPurpose = PrimaryPurposeHelper.select() purpose = PurposeHelper.select() secondaryPurpose = SecondaryPurposeHelper.select() diff --git a/test/services/jobs/return-logs/generate-return-logs.service.test.js b/test/services/jobs/return-logs/generate-return-logs.service.test.js index 6b1c54e2ca..494af9f9d5 100644 --- a/test/services/jobs/return-logs/generate-return-logs.service.test.js +++ b/test/services/jobs/return-logs/generate-return-logs.service.test.js @@ -9,6 +9,7 @@ const { describe, it, before, after } = exports.lab = Lab.script() const { expect } = Code // Test helpers +const { returnCycleDates } = require('../../../../app/lib/static-lookups.lib.js') const { formatDateObjectToISO } = require('../../../../app/lib/dates.lib.js') const FetchReturnCycleService = require('../../../../app/services/jobs/return-logs/fetch-return-cycle.service.js') const FetchReturnRequirementsService = require('../../../../app/services/jobs/return-logs/fetch-return-requirements.service.js') @@ -28,20 +29,15 @@ const SecondaryPurposeHelper = require('../../../support/helpers/secondary-purpo const GenerateReturnLogsService = require('../../../../app/services/jobs/return-logs/generate-return-logs.service.js') describe('Generate return logs service', () => { - const allYearDueDate = new Date(new Date().getFullYear() + 1, 3, 28).toISOString().split('T')[0] - const summerDueDate = new Date(new Date().getFullYear() + 1, 10, 28).toISOString().split('T')[0] - const allYearEndDate = new Date(new Date().getFullYear() + 1, 2, 31).toISOString().split('T')[0] - const summerEndDate = new Date(new Date().getFullYear() + 1, 9, 31).toISOString().split('T')[0] - const allYearStartDate = new Date(new Date().getFullYear(), 3, 1).toISOString().split('T')[0] - const summerStartDate = new Date(new Date().getFullYear(), 10, 1).toISOString().split('T')[0] - const summerReturns = [] - const allYearReturns = [] - const allYearReturnCycleId = 'c095d75e-0e0d-4fe4-b048-150457f3871b' - const summerReturnCycleId = 'd095d75e-0e0d-4fe4-b048-150457f3871f' - const today = formatDateObjectToISO(new Date()) + const today = new Date() + const month = today.getMonth() + const year = today.getFullYear() + let allYearDueDate = formatDateObjectToISO(new Date(year, 3, 28)) + let allYearEndDate = formatDateObjectToISO(new Date(year, 2, 31)) + let allYearStartDate = formatDateObjectToISO(new Date(year, 3, 1)) let expiredDate - let lapsedDate + let lapsedDate = formatDateObjectToISO(new Date(year, 8, 30)) let licence let point let point2 @@ -59,14 +55,43 @@ describe('Generate return logs service', () => { let revokedDate let secondaryPurpose let secondaryPurpose2 - let startDate + let startDate = formatDateObjectToISO(new Date(year, 11, 1)) let summer + let summerDueDate = formatDateObjectToISO(new Date(year, 10, 28)) + let summerEndDate = formatDateObjectToISO(new Date(year, 9, 31)) + let summerStartDate = formatDateObjectToISO(new Date(year, 10, 1)) + + if (month > returnCycleDates.allYear.endDate.month) { + allYearDueDate = formatDateObjectToISO(new Date(year + 1, 3, 28)) + allYearEndDate = formatDateObjectToISO(new Date(year + 1, 2, 31)) + } + + if (month > returnCycleDates.summer.endDate.month) { + summerDueDate = formatDateObjectToISO(new Date(year + 1, 10, 28)) + summerEndDate = formatDateObjectToISO(new Date(year + 1, 9, 31)) + lapsedDate = formatDateObjectToISO(new Date(year + 1, 8, 30)) + } + + if (month < returnCycleDates.summer.startDate.month) { + summerStartDate = formatDateObjectToISO(new Date(year - 1, 10, 1)) + startDate = formatDateObjectToISO(new Date(year - 1, 11, 1)) + } + + if (month < returnCycleDates.allYear.startDate.month) { + allYearStartDate = formatDateObjectToISO(new Date(year - 1, 3, 1)) + } + + const summerReturns = [] + const allYearReturns = [] + const allYearReturnCycleId = 'c095d75e-0e0d-4fe4-b048-150457f3871b' + const summerReturnCycleId = 'd095d75e-0e0d-4fe4-b048-150457f3871f' + const todayAsIso = formatDateObjectToISO(new Date()) describe('when return cycle exists', () => { before(async () => { Sinon.stub(FetchReturnCycleService, 'go') - .withArgs(today, false).returns(allYearReturnCycleId) - .withArgs(today, true).returns(summerReturnCycleId) + .withArgs(todayAsIso, false).returns(allYearReturnCycleId) + .withArgs(todayAsIso, true).returns(summerReturnCycleId) }) describe('when summer is false', () => { @@ -296,7 +321,7 @@ describe('Generate return logs service', () => { describe('there is an expired date, one return requirement and a licenceRef provided', () => { before(async () => { - expiredDate = new Date(new Date().getFullYear() + 1, 1, 31).toISOString().split('T')[0] + expiredDate = new Date(year + 1, 1, 31).toISOString().split('T')[0] region = RegionHelper.select() licence = await LicenceHelper.add({ expiredDate, regionId: region.id }) returnVersion = await ReturnVersionHelper.add({ licenceId: licence.id }) @@ -376,7 +401,7 @@ describe('Generate return logs service', () => { describe('there is an expired date after the end of the cycle, one return requirement and a licenceRef provided', () => { before(async () => { - expiredDate = new Date(new Date().getFullYear() + 1, 3, 31).toISOString().split('T')[0] + expiredDate = new Date(year + 1, 3, 31).toISOString().split('T')[0] region = RegionHelper.select() licence = await LicenceHelper.add({ expiredDate, regionId: region.id }) returnVersion = await ReturnVersionHelper.add({ licenceId: licence.id }) @@ -698,7 +723,6 @@ describe('Generate return logs service', () => { describe('there is a lapsed date, one return requirement and a licenceRef provided', () => { before(async () => { - lapsedDate = new Date(new Date().getFullYear() + 1, 8, 31).toISOString().split('T')[0] region = RegionHelper.select() licence = await LicenceHelper.add({ lapsedDate, regionId: region.id }) returnVersion = await ReturnVersionHelper.add({ licenceId: licence.id }) @@ -778,7 +802,7 @@ describe('Generate return logs service', () => { describe('there is a revoked date that is after the cycle, one return requirement and a licenceRef provided', () => { before(async () => { - revokedDate = new Date(new Date().getFullYear() + 1, 10, 31).toISOString().split('T')[0] + revokedDate = new Date(year + 1, 10, 31).toISOString().split('T')[0] region = RegionHelper.select() licence = await LicenceHelper.add({ revokedDate, regionId: region.id }) returnVersion = await ReturnVersionHelper.add({ licenceId: licence.id }) @@ -858,7 +882,6 @@ describe('Generate return logs service', () => { describe('the return version start date is after the cycle start date, one return requirement and a licenceRef provided', () => { before(async () => { - startDate = new Date(new Date().getFullYear(), 11, 1).toISOString().split('T')[0] region = RegionHelper.select() licence = await LicenceHelper.add({ regionId: region.id }) returnVersion = await ReturnVersionHelper.add({ licenceId: licence.id, startDate }) @@ -960,8 +983,8 @@ describe('Generate return logs service', () => { describe('when return cycle does not exist', () => { before(async () => { Sinon.stub(FetchReturnCycleService, 'go') - .withArgs(today, false).returns(undefined) - .withArgs(today, true).returns(undefined) + .withArgs(todayAsIso, false).returns(undefined) + .withArgs(todayAsIso, true).returns(undefined) Sinon.stub(GenerateReturnCycleService, 'go') .withArgs(false).returns(allYearReturnCycleId) .withArgs(true).returns(summerReturnCycleId)