Skip to content

Commit

Permalink
Amend no returns message in view licence Returns tab (#1087)
Browse files Browse the repository at this point in the history
* View Licence Returns no return messages

When a licence has returns show the returns table.

When the licence does not have returns and or requirements then the messages show need to show different messages.
jonathangoulding authored Jun 13, 2024

Verified

This commit was signed with the committer’s verified signature. The key has expired.
addaleax Anna Henningsen
1 parent 177d0fe commit 3f05d48
Showing 9 changed files with 273 additions and 162 deletions.
26 changes: 22 additions & 4 deletions app/presenters/licences/view-licence-returns.presenter.js
Original file line number Diff line number Diff line change
@@ -5,19 +5,25 @@
* @module ViewLicenceReturnsPresenter
*/

const { formatLongDate } = require('../base.presenter')
const { formatLongDate } = require('../base.presenter.js')

/**
* Formats common data for the `/licences/{id}/*` view licence pages
*
* @param {module:ReturnLogModel[]} returnsData - The session for the return requirement journey
* @param {boolean} hasRequirements - If the licence has return versions then it has requirements
*
* @returns {Object} The data formatted for the view template
*/
function go (returnsData) {
const returns = _formatReturnToTableRow(returnsData.returns)
function go (returnsData, hasRequirements) {
const returns = _formatReturnToTableRow(returnsData)

const hasReturns = returns.length > 0

return {
activeTab: 'returns',
returns
returns,
noReturnsMessage: _noReturnsMessage(hasReturns, hasRequirements)
}
}

@@ -53,6 +59,18 @@ function _formatStatus (status) {
return 'NO STATUS'
}

function _noReturnsMessage (hasReturns, hasRequirements) {
if (!hasReturns && !hasRequirements) {
return 'No requirements for returns have been set up for this licence.'
}

if (hasRequirements && !hasReturns) {
return 'No returns for this licence.'
}

return null
}

module.exports = {
go
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
'use strict'

/**
* Determines if a licence has requirements
* @module DetermineLicenceHasReturnVersionsService
*/

const ReturnVersionModel = require('../../models/return-version.model.js')

/**
* Determines if a licence has requirements
*
* @param {string} licenceId - The UUID of the licence to determine if return versions exist
*
* @returns {Promise<Boolean>} true if the licence has return versions else false
*/
async function go (licenceId) {
const requirement = await _fetch(licenceId)

return !!requirement
}

async function _fetch (licenceId) {
return ReturnVersionModel.query()
.select([
'id'
])
.where('licenceId', licenceId)
.limit(1)
.first()
}

module.exports = {
go
}
15 changes: 10 additions & 5 deletions app/services/licences/view-licence-returns.service.js
Original file line number Diff line number Diff line change
@@ -5,23 +5,28 @@
* @module ViewLicenceSummaryService
*/

const FetchLicenceReturnsService = require('./fetch-licence-returns.service')
const ViewLicenceService = require('./view-licence.service')
const ViewLicenceReturnsPresenter = require('../../presenters/licences/view-licence-returns.presenter')
const PaginatorPresenter = require('../../presenters/paginator.presenter')
const DetermineLicenceHasReturnVersionsService = require('./determine-licence-has-return-versions.service.js')
const FetchLicenceReturnsService = require('./fetch-licence-returns.service.js')
const PaginatorPresenter = require('../../presenters/paginator.presenter.js')
const ViewLicenceReturnsPresenter = require('../../presenters/licences/view-licence-returns.presenter.js')
const ViewLicenceService = require('./view-licence.service.js')

/**
* Orchestrates fetching and presenting the data needed for the licence summary page
*
* @param {string} licenceId - The UUID of the licence
* @param {Object} auth - The auth object taken from `request.auth` containing user details
* @param {Object} page - The current page for the pagination service
*
* @returns {Promise<Object>} an object representing the `pageData` needed by the licence summary template.
*/
async function go (licenceId, auth, page) {
const commonData = await ViewLicenceService.go(licenceId, auth)

const hasRequirements = await DetermineLicenceHasReturnVersionsService.go(licenceId)

const returnsData = await FetchLicenceReturnsService.go(licenceId, page)
const pageData = ViewLicenceReturnsPresenter.go(returnsData)
const pageData = ViewLicenceReturnsPresenter.go(returnsData.returns, hasRequirements)

const pagination = PaginatorPresenter.go(returnsData.pagination.total, Number(page), `/system/licences/${licenceId}/returns`)

2 changes: 1 addition & 1 deletion app/services/licences/view-licence.service.js
Original file line number Diff line number Diff line change
@@ -12,7 +12,7 @@ const ViewLicencePresenter = require('../../presenters/licences/view-licence.pre
* Orchestrates fetching and presenting the data needed for the licence summary page
*
* @param {string} licenceId - The UUID of the licence
* @param {string} auth - Auth object
* @param {Object} auth - The auth object taken from `request.auth` containing user details
* @returns {Promise<Object>} an object representing the `pageData` needed by the licence summary template.
*/
async function go (licenceId, auth) {
78 changes: 49 additions & 29 deletions app/views/licences/tabs/returns.njk
Original file line number Diff line number Diff line change
@@ -19,36 +19,56 @@
{% endif %}
{% endmacro %}

<table class="govuk-table">
<h2 class="govuk-heading-l">Returns</h2>
{% if returns.length > 0 %}
<thead class="govuk-table__head">
<tr class="govuk-table__row">
<th scope="col" class="govuk-table__header">Return reference and dates</th>
<th scope="col" class="govuk-table__header">Purpose and description</th>
<th scope="col" class="govuk-table__header">Due date</th>
<th scope="col" class="govuk-table__header">Status</th>
</tr>
</thead>
<tbody class="govuk-table__body">
{% for return in returns %}
<tr class="govuk-table__row govuk-body-s">
<th class="govuk-table__cell">
<a href="/return/internal?returnId={{ return.id }}" class="govuk-link">{{ return.reference }} </a>
<p class="govuk-body-s"> {{ return.dates }}</p>
</th>
<td class="govuk-table__cell">{{ return.purpose }} <p class="govuk-body-s"> {{ return.description }}</p></td>
<td class="govuk-table__cell">{{ return.dueDate }}</td>
<td class="govuk-table__cell">{{ formatStatus(return.status) }}</td>
</tr>
{% endfor %}
</tbody>
{% else %}
<p>No returns found</p>
{% endif %}
</table>
<h2 class="govuk-heading-l">Returns</h2>

{% if noReturnsMessage %}
<p> {{ noReturnsMessage }} </p>
{% else %}

{% macro referenceColumn(return) %}
<a href="/return/internal?returnId={{ return.id }}" class="govuk-link">{{ return.reference }} </a>
<p class="govuk-body-s"> {{ return.dates }}</p>
{% endmacro %}

{% set returnRows = [] %}

{% for returnItem in returns %}
{% set returnRows = (returnRows.push([
{
html: referenceColumn(returnItem)
},
{
html: returnItem.purpose + "<p class=\"govuk-body-s\">" + returnItem.description + "</p>"
},
{
text: returnItem.dueDate
},
{
html: formatStatus(returnItem.status)
}
]), returnRows) %}
{% endfor %}

{{ govukTable({
head: [
{
text: 'Return reference and dates'
},
{
text: 'Purpose and description'
},
{
text: 'Due date'
},
{
text: 'Status'
}
],
rows: returnRows
}) }}
{% endif %}

{% if returns and pagination.numberOfPages > 1 %}
{% if pagination.numberOfPages > 1 %}
{{ govukPagination(pagination.component) }}
{% endif %}

35 changes: 8 additions & 27 deletions test/controllers/licences.controller.test.js
Original file line number Diff line number Diff line change
@@ -403,9 +403,15 @@ describe('Licences controller', () => {
}
})

describe('when a request is valid and has returns', () => {
describe('when a request is valid', () => {
beforeEach(async () => {
Sinon.stub(ViewLicenceReturnsService, 'go').resolves(_viewLicenceReturns())
Sinon.stub(ViewLicenceReturnsService, 'go').resolves({
activeTab: 'returns',
returns: [
{ id: 'returns-id' }
],
noReturnsMessage: null
})
})

it('returns the page successfully', async () => {
@@ -420,24 +426,6 @@ describe('Licences controller', () => {
expect(response.payload).to.contain('Status')
})
})

describe('when a request is valid and has NO returns', () => {
beforeEach(async () => {
Sinon.stub(ViewLicenceReturnsService, 'go').resolves({
activeTab: 'returns',
returns: []
})
})

it('returns the page successfully', async () => {
const response = await server.inject(options)

expect(response.statusCode).to.equal(200)
expect(response.payload).to.contain('Returns')
// Check the table titles
expect(response.payload).to.contain('No returns found')
})
})
})
})

@@ -474,13 +462,6 @@ function _viewLicenceContactDetails () {
}
}

function _viewLicenceReturns () {
return {
activeTab: 'returns',
returns: [{ id: 'returns-id' }]
}
}

function _viewLicenceSummary () {
return {
id: '7861814c-ca19-43f2-be11-3c612f0d744b',
150 changes: 81 additions & 69 deletions test/presenters/licences/view-licence-returns-presenter.test.js
Original file line number Diff line number Diff line change
@@ -8,21 +8,61 @@ const { describe, it, beforeEach } = exports.lab = Lab.script()
const { expect } = Code

// Thing under test
const ViewLicenceReturnsPresenter = require('../../../app/presenters/licences/view-licence-returns.presenter')
const ViewLicenceReturnsPresenter = require('../../../app/presenters/licences/view-licence-returns.presenter.js')

describe('View Licence returns presenter', () => {
let returnData
let returnsData
let hasRequirements

const returnItem = {
id: 'mock-id-1',
dueDate: '2012-11-28T00:00:00.000Z',
status: 'completed',
startDate: '2020/01/02',
endDate: '2020/02/01',
metadata: {
purposes: [
{
alias: 'SPRAY IRRIGATION',
primary: {
code: 'A',
description: 'Agriculture'
},
tertiary: {
code: '400',
description: 'Spray Irrigation - Direct'
},
secondary: {
code: 'AGR',
description: 'General Agriculture'
}
}
],
description: 'empty description'
},
returnReference: '1068'
}

beforeEach(() => {
returnData = _returnData()
hasRequirements = true
returnsData = [
{ ...returnItem },
{
...returnItem,
id: 'mock-id-2',
status: 'due',
returnReference: '1069'
}
]
})

describe('when provided with a populated licence', () => {
describe('when provided with returns data', () => {
it('correctly presents the data', () => {
const result = ViewLicenceReturnsPresenter.go(returnData)
const result = ViewLicenceReturnsPresenter.go(returnsData, hasRequirements)

expect(result).to.equal({
activeTab: 'returns',
noReturnsMessage: null,
returns: [
{
id: 'mock-id-1',
@@ -37,7 +77,7 @@ describe('View Licence returns presenter', () => {
id: 'mock-id-2',
reference: '1069',
purpose: 'SPRAY IRRIGATION',
dueDate: '28 November 2019',
dueDate: '28 November 2012',
status: 'OVERDUE',
dates: '2 January 2020 to 1 February 2020',
description: 'empty description'
@@ -46,67 +86,39 @@ describe('View Licence returns presenter', () => {
})
})
})
})

function _returnData () {
return {
returns: [
{
id: 'mock-id-1',
dueDate: '2012-11-28T00:00:00.000Z',
status: 'completed',
startDate: '2020/01/02',
endDate: '2020/02/01',
metadata: {
purposes: [
{
alias: 'SPRAY IRRIGATION',
primary: {
code: 'A',
description: 'Agriculture'
},
tertiary: {
code: '400',
description: 'Spray Irrigation - Direct'
},
secondary: {
code: 'AGR',
description: 'General Agriculture'
}
}
],
description: 'empty description'
},
returnReference: '1068'
},
{
id: 'mock-id-2',
dueDate: '2019-11-28T00:00:00.000Z',
status: 'due',
startDate: '2020/01/02',
endDate: '2020/02/01',
metadata: {
description: 'empty description',
purposes: [
{
alias: 'SPRAY IRRIGATION',
primary: {
code: 'A',
description: 'Agriculture'
},
tertiary: {
code: '400',
description: 'Spray Irrigation - Direct'
},
secondary: {
code: 'AGR',
description: 'General Agriculture'
}
}
]
},
returnReference: '1069'
}
]
}
}
describe('the "noReturnsMessage" property', () => {
describe('when a licence has returns and requirements', () => {
it('returns null', () => {
const result = ViewLicenceReturnsPresenter.go(returnsData, hasRequirements)

expect(result.noReturnsMessage).to.be.null()
})
})

describe('when a licence has NO returns and NO requirements', () => {
beforeEach(() => {
returnsData = []
hasRequirements = false
})

it('presents the No returns and No requirements message "No requirements for returns have been set up for this licence."', () => {
const result = ViewLicenceReturnsPresenter.go(returnsData, hasRequirements)

expect(result.noReturnsMessage).to.equal('No requirements for returns have been set up for this licence.')
})
})

describe('when a licence has returns but no requirements', () => {
beforeEach(() => {
returnsData = []
})

it('presents the returns but no requirements message "No returns for this licence."', () => {
const result = ViewLicenceReturnsPresenter.go(returnsData, hasRequirements)

expect(result.noReturnsMessage).to.equal('No returns for this licence.')
})
})
})
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
'use strict'

// Test framework dependencies
const Lab = require('@hapi/lab')
const Code = require('@hapi/code')

const { describe, it, beforeEach } = exports.lab = Lab.script()
const { expect } = Code

// Test helpers
const DatabaseSupport = require('../../support/database.js')
const ReturnVersionHelper = require('../../support/helpers/return-version.helper.js')

// Thing under test
const FetchLicenceHasRequirementsService =
require('../../../app/services/licences/determine-licence-has-return-versions.service.js')

describe('Fetch Licence Has Requirements service', () => {
const licenceId = 'e004c0c9-0316-42fc-a6e3-5ae9a271b3c6'

beforeEach(async () => {
await DatabaseSupport.clean()
})

describe('when the licence has return versions', () => {
beforeEach(async () => {
await ReturnVersionHelper.add({ licenceId })
})

it('returns true', async () => {
const result = await FetchLicenceHasRequirementsService.go(licenceId)

expect(result).to.be.true()
})
})

describe('when the licence does not have return versions', () => {
it('returns false', async () => {
const result = await FetchLicenceHasRequirementsService.go('ed3b9b1a-94e0-480c-8ad6-60e05f5fa9f4')

expect(result).to.be.false()
})
})
})
50 changes: 23 additions & 27 deletions test/services/licences/view-licence-returns.service.test.js
Original file line number Diff line number Diff line change
@@ -9,25 +9,39 @@ const { describe, it, beforeEach, afterEach } = exports.lab = Lab.script()
const { expect } = Code

// Things we need to stub
const ViewLicenceService = require('../../../app/services/licences/view-licence.service')
const PaginatorPresenter = require('../../../app/presenters/paginator.presenter')
const ViewLicenceReturnsPresenter = require('../../../app/presenters/licences/view-licence-returns.presenter')
const FetchLicenceReturnsService = require('../../../app/services/licences/fetch-licence-returns.service')
const DetermineLicenceHasReturnVersionsService = require('../../../app/services/licences/determine-licence-has-return-versions.service.js')
const FetchLicenceReturnsService = require('../../../app/services/licences/fetch-licence-returns.service.js')
const PaginatorPresenter = require('../../../app/presenters/paginator.presenter.js')
const ViewLicenceReturnsPresenter = require('../../../app/presenters/licences/view-licence-returns.presenter.js')
const ViewLicenceService = require('../../../app/services/licences/view-licence.service.js')

// Thing under test
const ViewLicenceReturnsService = require('../../../app/services/licences/view-licence-returns.service')
const ViewLicenceReturnsService = require('../../../app/services/licences/view-licence-returns.service.js')

describe('View Licence service returns', () => {
const testId = '2c80bd22-a005-4cf4-a2a2-73812a9861de'
const page = 1
const auth = {}
const pagination = { page }

beforeEach(() => {
Sinon.stub(FetchLicenceReturnsService, 'go').resolves(_returnsFetch())
beforeEach(async () => {
Sinon.stub(DetermineLicenceHasReturnVersionsService, 'go').returns(true)

Sinon.stub(FetchLicenceReturnsService, 'go').resolves({
pagination: { total: 1 },
returns: []
})

Sinon.stub(PaginatorPresenter, 'go').returns(pagination)
Sinon.stub(ViewLicenceReturnsPresenter, 'go').returns(_returnsPresenter())
Sinon.stub(ViewLicenceService, 'go').resolves(_licence())

Sinon.stub(ViewLicenceReturnsPresenter, 'go').returns({
returns: [],
activeTab: 'returns'
})

Sinon.stub(ViewLicenceService, 'go').resolves({
licenceName: 'fake licence'
})
})

afterEach(() => {
@@ -49,21 +63,3 @@ describe('View Licence service returns', () => {
})
})
})

function _licence () {
return { licenceName: 'fake licence' }
}

function _returnsFetch () {
return {
pagination: { total: 1 },
returns: []
}
}

function _returnsPresenter () {
return {
returns: [],
activeTab: 'returns'
}
}

0 comments on commit 3f05d48

Please sign in to comment.