Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create return logs for newly imported licences #1294

Merged
merged 39 commits into from
Sep 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
4170ee0
initial commit
robertparkinson Aug 29, 2024
96b3271
Merge branch 'main' into create-return-logs-for-new-licence
robertparkinson Aug 29, 2024
937528e
change logic for start date
robertparkinson Aug 30, 2024
e081d45
Merge branch 'main' into create-return-logs-for-new-licence
robertparkinson Sep 2, 2024
f3ce5c1
Merge branch 'main' into create-return-logs-for-new-licence
robertparkinson Sep 2, 2024
edddb18
Merge branch 'create-return-logs-for-new-licence' of github.com:DEFRA…
robertparkinson Sep 2, 2024
e91a8e2
merge from main
robertparkinson Sep 3, 2024
cc10655
merge from main
robertparkinson Sep 3, 2024
79e3e9b
merge conflicts
robertparkinson Sep 3, 2024
7abfb97
merge from main
robertparkinson Sep 3, 2024
173d672
Merge branch 'main' into create-return-logs-for-new-licence
robertparkinson Sep 4, 2024
c3cce54
refactor return log service and create licence return log service
robertparkinson Sep 10, 2024
a79b330
Merge branch 'create-return-logs-for-new-licence' of github.com:DEFRA…
robertparkinson Sep 10, 2024
60f888d
Merge branch 'main' into create-return-logs-for-new-licence
robertparkinson Sep 10, 2024
6683a05
Merge branch 'main' into create-return-logs-for-new-licence
robertparkinson Sep 10, 2024
7558cff
merge from main and add in call to return log creation
robertparkinson Sep 10, 2024
f8e00ce
resolve conflicts
robertparkinson Sep 10, 2024
64b2b55
Merge branch 'main' into create-return-logs-for-new-licence
robertparkinson Sep 11, 2024
d4c254b
remove console.log
robertparkinson Sep 11, 2024
70faa40
fix linting issues
robertparkinson Sep 11, 2024
5ed40a8
Merge branch 'main' into create-return-logs-for-new-licence
robertparkinson Sep 11, 2024
14ed51a
remove unused modifiers function
robertparkinson Sep 11, 2024
29e074c
Merge branch 'create-return-logs-for-new-licence' of github.com:DEFRA…
robertparkinson Sep 11, 2024
9832f5a
Merge branch 'main' into create-return-logs-for-new-licence
robertparkinson Sep 11, 2024
6431161
Merge branch 'create-return-logs-for-new-licence' of github.com:DEFRA…
robertparkinson Sep 11, 2024
10fc6cf
add updatedAt date
robertparkinson Sep 11, 2024
ea0c884
Merge branch 'main' into create-return-logs-for-new-licence
robertparkinson Sep 11, 2024
2a4b5c9
Merge branch 'main' into create-return-logs-for-new-licence
robertparkinson Sep 16, 2024
447cd81
address review comments
robertparkinson Sep 16, 2024
51bad2d
linting issues
robertparkinson Sep 16, 2024
3f44c08
address review comments
robertparkinson Sep 17, 2024
c1ffab0
Merge branch 'main' into create-return-logs-for-new-licence
robertparkinson Sep 17, 2024
fb2cad6
remove unused functions
robertparkinson Sep 17, 2024
d619175
Merge branch 'main' into create-return-logs-for-new-licence
robertparkinson Sep 17, 2024
cc949fa
Merge branch 'main' into create-return-logs-for-new-licence
robertparkinson Sep 17, 2024
dca4fa4
address review comments
robertparkinson Sep 18, 2024
d8bbd93
Merge branch 'main' into create-return-logs-for-new-licence
robertparkinson Sep 18, 2024
06dd803
Merge branch 'create-return-logs-for-new-licence' of github.com:DEFRA…
robertparkinson Sep 18, 2024
d480426
Merge branch 'main' into create-return-logs-for-new-licence
robertparkinson Sep 18, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions app/controllers/check.controller.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
'use strict'

/**
* Controller for /check endpoints
* @module CheckController
*/

const ProcessLicenceReturnLogsService = require('../services/jobs/return-logs/process-licence-return-logs.service.js')

const redirectStatusCode = 204

/**
* A test end point to create return logs for a given licence reference
*
* @param _request - the hapi request object
* @param h - the hapi response object
*
* @returns {Promise<object>} - A promise that resolves to an HTTP response object with a 204 status code
*/
async function returnLogsForLicence (_request, h) {
let licenceReference

if (h.request.payload !== null && h.request.payload.licenceReference) {
licenceReference = h.request.payload.licenceReference
} else {
return h.response().code(404)
}

ProcessLicenceReturnLogsService.go(licenceReference)

return h.response().code(redirectStatusCode)
}

module.exports = {
returnLogsForLicence
}
109 changes: 109 additions & 0 deletions app/lib/dates.lib.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
* @module DatesLib
*/

const { returnCycleDates } = require('./static-lookups.lib.js')

const february = 2
const lastDayOfFebruary = 28
const lastDayOfFebruaryLeapYear = 29
Expand Down Expand Up @@ -35,6 +37,106 @@ function formatStandardDateToISO (date) {
}
}

/**
* Formate the provided date in ISO format.
*
* @param {Date} date - a date object to be formatted
* @returns {Date} - the date formatted in YYYY-MM-DD.
*/
function formatDateObjectToISO (date) {
return date.toISOString().split('T')[0]
}

/**
* Get the due date of next provided cycle, either summer or winter and all year, formatted as YYYY-MM-DD
*
* @param {boolean} summer - true for summer, false for winter and all year.
* @returns {string} - the due date of the next cycle as an ISO string.
*/
function cycleDueDateAsISO (summer) {
return formatDateObjectToISO(cycleDueDate(summer))
}

/**
* Get the due date of next provided cycle, either summer or winter and all year
*
* @param {boolean} summer - true for summer, false for winter and all year.
* @returns {Date} - the due date of the next cycle.
*/
function cycleDueDate (summer) {
if (summer) {
return new Date(new Date().getFullYear() + 1,
returnCycleDates.summer.dueDate.month,
returnCycleDates.summer.dueDate.day
)
}

return new Date(new Date().getFullYear() + 1,
returnCycleDates.allYear.dueDate.month,
returnCycleDates.allYear.dueDate.day
)
}

/**
* Get the end date of next provided cycle, either summer or winter and all year, formatted as YYYY-MM-DD
*
* @param {boolean} summer - true for summer, false for winter and all year.
* @returns {string} - the end date of the next cycle as an ISO string.
*/
function cycleEndDateAsISO (summer) {
return formatDateObjectToISO(cycleEndDate(summer))
}

/**
* Get the end date of next provided cycle, either summer and winter or all year
*
* @param {boolean} summer - true for summer, false for winter and all year.
* @returns {Date} - the end date of the next cycle.
*/
function cycleEndDate (summer) {
if (summer) {
return new Date(new Date().getFullYear() + 1,
returnCycleDates.summer.endDate.month,
returnCycleDates.summer.endDate.day
)
}

return new Date(new Date().getFullYear() + 1,
returnCycleDates.allYear.endDate.month,
returnCycleDates.allYear.endDate.day
)
}

/**
* Get the start date of next provided cycle, either summer and winter and all year, formatted as YYYY-MM-DD
*
* @param {boolean} summer - true for summer, false for winter and all year.
* @returns {string} - the start date of the next cycle as an ISO string.
*/
function cycleStartDateAsISO (summer) {
return formatDateObjectToISO(cycleStartDate(summer))
}

/**
* Get the start date of next provided cycle, either summer or winter and all year
*
* @param {boolean} summer - true for summer, false for winter and all year.
* @returns {Date} - the start date of the next cycle.
*/
function cycleStartDate (summer) {
if (summer) {
return new Date(new Date().getFullYear(),
returnCycleDates.summer.startDate.month,
returnCycleDates.summer.startDate.day
)
}

return new Date(new Date().getFullYear(),
returnCycleDates.allYear.startDate.month,
returnCycleDates.allYear.startDate.day
)
}

/**
* Check if a date is valid or not by creating a date and checking it gives the time
*
Expand Down Expand Up @@ -104,7 +206,14 @@ function _isLeapYear (year) {
}

module.exports = {
formatDateObjectToISO,
formatStandardDateToISO,
cycleDueDate,
cycleDueDateAsISO,
cycleEndDate,
cycleEndDateAsISO,
cycleStartDate,
cycleStartDateAsISO,
isISODateFormat,
isValidDate
}
14 changes: 14 additions & 0 deletions app/lib/static-lookups.lib.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,19 @@ const organisationTypes = [
'publicLimitedCompany'
]

const returnCycleDates = {
allYear: {
dueDate: { day: 28, month: 3 },
endDate: { day: 31, month: 2 },
startDate: { day: 1, month: 3 }
},
summer: {
dueDate: { day: 28, month: 10 },
endDate: { day: 31, month: 9 },
startDate: { day: 1, month: 10 }
}
}

const returnRequirementFrequencies = {
day: 'daily',
week: 'weekly',
Expand Down Expand Up @@ -93,6 +106,7 @@ module.exports = {
companyTypes,
contactTypes,
organisationTypes,
returnCycleDates,
returnRequirementFrequencies,
returnRequirementReasons,
naldRegions,
Expand Down
2 changes: 2 additions & 0 deletions app/plugins/router.plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ const BillRoutes = require('../routes/bills.routes.js')
const BillRunRoutes = require('../routes/bill-runs.routes.js')
const BillRunSetupRoutes = require('../routes/bill-runs-setup.routes.js')
const BillingAccountRoutes = require('../routes/billing-accounts.routes.js')
const CheckRoutes = require('../routes/check.routes.js')
const DataRoutes = require('../routes/data.routes.js')
const FilterRoutesService = require('../services/plugins/filter-routes.service.js')
const HealthRoutes = require('../routes/health.routes.js')
Expand All @@ -37,6 +38,7 @@ const routes = [
...BillRunRoutes,
...BillRunSetupRoutes,
...BillingAccountRoutes,
...CheckRoutes,
...LicenceRoutes,
...JobRoutes,
...ReturnRequirementRoutes,
Expand Down
23 changes: 23 additions & 0 deletions app/routes/check.routes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
'use strict'

const CheckController = require('../controllers/check.controller.js')

const routes = [
{
method: 'POST',
path: '/check/licence-return-logs',
options: {
handler: CheckController.returnLogsForLicence,
app: {
excludeFromProd: true,
plainOutput: true
},
auth: false,
plugins: {
crumb: false
}
}
}
]

module.exports = routes
3 changes: 2 additions & 1 deletion app/services/import/legacy/process-licence.service.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

const LicenceStructureValidator = require('../../../validators/import/licence-structure.validator.js')
const PersistLicenceService = require('../persist-licence.service.js')
const ProcessLicenceReturnLogsService = require('../../jobs/return-logs/process-licence-return-logs.service.js')
const TransformCompaniesService = require('./transform-companies.service.js')
const TransformLicenceService = require('./transform-licence.service.js')
const TransformLicenceVersionPurposeConditionsService = require('./transform-licence-version-purpose-conditions.service.js')
Expand Down Expand Up @@ -44,7 +45,7 @@ async function go (licenceRef) {
const licenceId = await PersistLicenceService.go(transformedLicence, transformedCompanies)

if (wrlsLicenceId) {
// Process mod logs
await ProcessLicenceReturnLogsService.go(wrlsLicenceId)
}

calculateAndLogTimeTaken(startTime, 'Legacy licence import complete', { licenceId, licenceRef })
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
'use strict'

/**
* Fetches data needed for generating return logs
* @module FetchReturnLogsService
*/

const ReturnLogModel = require('../../../models/return-log.model.js')
const ReturnRequirementModel = require('../../../models/return-requirement.model.js')
const ReturnVersionModel = require('../../../models/return-version.model.js')

const { db } = require('../../../../db/db.js')
const { cycleEndDateAsISO, cycleStartDateAsISO, cycleStartDate } = require('../../../lib/dates.lib.js')

/**
* Given the licence reference this service returns the return requirements to be turned into return logs.
*
* @param {string} licenceReference - if provided only do the return log for that licence
*
* @returns {Promise<Array>} the array of return log payloads to be created in the database
*/
async function go (licenceReference) {
return _fetchReturnRequirements(licenceReference)
}

async function _fetchExternalIds (licenceReference) {
const externalIds = await ReturnLogModel.query()
.select([db.raw("concat(metadata->'nald'->>'regionCode', ':', return_reference) as externalid")])
.where('startDate', '>=', cycleStartDate(false))
.where('licenceRef', licenceReference)

const externalIdsArray = externalIds.map((item) => {
return item.externalid
})

return externalIdsArray
}

async function _fetchReturnRequirements (licenceReference) {
// pass in false to ge the all year start and end date to make sure we cover the entire year
const _cycleEndDate = cycleEndDateAsISO(false)
const _cycleStartDate = cycleStartDateAsISO(false)
const externalIds = await _fetchExternalIds(licenceReference)

return ReturnRequirementModel.query()
.whereNotIn('returnRequirements.externalId', externalIds)
.whereExists(_whereExistsClause(licenceReference, _cycleStartDate, _cycleEndDate))
.withGraphFetched('returnVersion')
.modifyGraph('returnVersion', (builder) => {
builder.select(['endDate',
'id',
'startDate',
'reason'])
})
.withGraphFetched('returnVersion.licence')
.modifyGraph('returnVersion.licence', (builder) => {
builder.select(['expiredDate',
'id',
'lapsedDate',
'licenceRef',
'revokedDate',
db.raw('regions->>\'historicalAreaCode\' as areacode')])
})
.withGraphFetched('returnVersion.licence.region')
.modifyGraph('returnVersion.licence.region', (builder) => {
builder.select(['id', 'naldRegionId'])
})
.withGraphFetched('returnRequirementPoints')
.modifyGraph('returnRequirementPoints', (builder) => {
builder.select(['description',
'ngr1',
'ngr2',
'ngr3',
'ngr4'])
})
.withGraphFetched('returnRequirementPurposes.primaryPurpose')
.modifyGraph('returnRequirementPurposes.primaryPurpose', (builder) => {
builder.select(['legacyId', 'description'])
})
.withGraphFetched('returnRequirementPurposes.secondaryPurpose')
.modifyGraph('returnRequirementPurposes.secondaryPurpose', (builder) => {
builder.select(['legacyId', 'description'])
})
.withGraphFetched('returnRequirementPurposes.purpose')
.modifyGraph('returnRequirementPurposes.purpose', (builder) => {
builder.select(['legacyId', 'description'])
})
}

function _whereExistsClause (licenceReference, cycleStartDate, cycleEndDate) {
const query = ReturnVersionModel.query().select(1)

query.select(1)
.innerJoinRelated('licence')
.where('licence.licenceRef', licenceReference)
.where('returnVersions.startDate', '<=', cycleEndDate)
.where('returnVersions.status', 'current')
.where((builder) => {
builder
.whereNull('returnVersions.endDate')
.orWhere('returnVersions.endDate', '>=', cycleStartDate)
})
.where((builder) => {
builder
.whereNull('licence.expiredDate')
.orWhere('licence.expiredDate', '>=', cycleStartDate)
})
.where((builder) => {
builder
.whereNull('licence.lapsedDate')
.orWhere('licence.lapsedDate', '>=', cycleStartDate)
})
.where((builder) => {
builder
.whereNull('licence.revokedDate')
.orWhere('licence.revokedDate', '>=', cycleStartDate)
})

query.whereColumn('returnVersions.id', 'returnRequirements.returnVersionId')

return query
}

module.exports = {
go
}
Loading
Loading