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

Migrate view bill runs page from legacy UI #925

Merged
merged 16 commits into from
Apr 23, 2024
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
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
2 changes: 1 addition & 1 deletion app/controllers/bill-runs-setup.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ async function create (request, h) {
try {
await CreateService.go(request.auth.credentials.user, results)

return h.redirect('/billing/batch/list')
return h.redirect('/system/bill-runs')
} catch (error) {
return Boom.badImplementation(error.message)
}
Expand Down
15 changes: 14 additions & 1 deletion app/controllers/bill-runs.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const Boom = require('@hapi/boom')

const CancelBillRunService = require('../services/bill-runs/cancel-bill-run.service.js')
const CreateBillRunValidator = require('../validators/create-bill-run.validator.js')
const IndexBillRunsService = require('../services/bill-runs/index-bill-runs.service.js')
const MatchDetailsService = require('../services/bill-runs/two-part-tariff/match-details.service.js')
const ReviewBillRunService = require('../services/bill-runs/two-part-tariff/review-bill-run.service.js')
const ReviewLicenceService = require('../services/bill-runs/two-part-tariff/review-licence.service.js')
Expand Down Expand Up @@ -47,6 +48,17 @@ async function create (request, h) {
}
}

async function index (request, h) {
const { page } = request.query

const pageData = await IndexBillRunsService.go(page)

return h.view('bill-runs/index.njk', {
activeNavBar: 'bill-runs',
...pageData
})
}

async function matchDetails (request, h) {
const { id: billRunId, licenceId, reviewChargeElementId } = request.params

Expand Down Expand Up @@ -102,7 +114,7 @@ async function submitCancel (request, h) {
// `cancel'.
await SubmitCancelBillRunService.go(id)

return h.redirect('/billing/batch/list')
return h.redirect('/system/bill-runs')
} catch (error) {
return Boom.badImplementation(error.message)
}
Expand Down Expand Up @@ -137,6 +149,7 @@ async function view (request, h) {
module.exports = {
cancel,
create,
index,
matchDetails,
review,
reviewLicence,
Expand Down
64 changes: 64 additions & 0 deletions app/presenters/bill-runs/index-bill-runs.presenter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
'use strict'

/**
* Formats the summary data for each bill run for use in the /bill-runs page
* @module IndexBillRunsPresenter
*/

const {
capitalize,
formatBillRunType,
formatLongDate,
formatMoney
} = require('../base.presenter.js')

/**
* Formats the summary data for each bill run for use in the /bill-runs page
*
* @param {module:BillRunModel[]} billRuns - The bill runs containing the data to be summarised for the view
*
* @returns {Object[]} Each bill run summary formatted for use in the `index.njk` template for `/bill-runs`
*/
function go (billRuns) {
return billRuns.map((billRun) => {
const {
batchType,
billRunNumber,
createdAt,
id,
netTotal,
numberOfBills,
region,
scheme,
summer,
status
} = billRun

const type = formatBillRunType(batchType, scheme, summer)
Cruikshanks marked this conversation as resolved.
Show resolved Hide resolved

return {
id,
createdAt: formatLongDate(createdAt),
link: _link(id, status),
number: billRunNumber,
numberOfBills,
region: capitalize(region),
scheme,
status,
total: formatMoney(netTotal, true),
type
}
})
}

function _link (billRunId, status) {
if (status === 'review') {
return `/system/bill-runs/${billRunId}/review`
}

return `/system/bill-runs/${billRunId}`
}

module.exports = {
go
}
13 changes: 13 additions & 0 deletions app/routes/bill-runs.routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,19 @@
const BillRunsController = require('../controllers/bill-runs.controller.js')

const routes = [
{
method: 'GET',
path: '/bill-runs',
handler: BillRunsController.index,
options: {
auth: {
access: {
scope: ['billing']
}
},
description: 'List all bill runs'
}
},
{
method: 'POST',
path: '/bill-runs',
Expand Down
64 changes: 64 additions & 0 deletions app/services/bill-runs/index-bill-runs.service.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
'use strict'

/**
* Orchestrates fetching and presenting the data needed for the /bill-runs page
* @module IndexBillRunsService
*/

const CheckBusyBillRunsService = require('./check-busy-bill-runs.service.js')
const FetchBillRunsService = require('./fetch-bill-runs.service.js')
const IndexBillRunsPresenter = require('../../presenters/bill-runs/index-bill-runs.presenter.js')
const PaginatorPresenter = require('../../presenters/paginator.presenter.js')

/**
* Orchestrates fetching and presenting the data needed for the /bill-runs page
*
* @param {string} page - the page number of bill runs to be viewed
*
* @returns {Promise<Object>} an object representing the `pageData` needed by the index bill run template. It contains
* summary details for each bill run for the page selected, the template's pagination control, the title and the
* status of any busy bill runs
*/
async function go (page) {
const selectedPageNumber = _selectedPageNumber(page)

// We expect the FetchBillRunsService to take longer to complete than CheckBusyBillRunsService. But running them
// together means we are only waiting as long as it takes FetchBillRunsService to complete rather than their combined
// time
const [fetchedBillRunResult, busyResult] = await Promise.all([
FetchBillRunsService.go(selectedPageNumber),
CheckBusyBillRunsService.go()
])

const billRuns = IndexBillRunsPresenter.go(fetchedBillRunResult.results)
const pagination = PaginatorPresenter.go(fetchedBillRunResult.total, selectedPageNumber, '/system/bill-runs')

const pageTitle = _pageTitle(pagination.numberOfPages, selectedPageNumber)

return {
billRuns,
busy: busyResult,
pageTitle,
pagination
}
}

function _pageTitle (numberOfPages, selectedPageNumber) {
if (numberOfPages === 1) {
return 'Bill runs'
}

return `Bill runs (page ${selectedPageNumber} of ${numberOfPages})`
}

function _selectedPageNumber (page) {
if (!page) {
return 1
}

return Number(page)
}

module.exports = {
go
}
2 changes: 1 addition & 1 deletion app/views/bill-runs/empty.njk
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
{{
govukBackLink({
text: 'Go back to bill runs',
href: '/billing/batch/list'
href: '/system/bill-runs'
})
}}
{% endblock %}
Expand Down
2 changes: 1 addition & 1 deletion app/views/bill-runs/errored.njk
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
{{
govukBackLink({
text: 'Go back to bill runs',
href: '/billing/batch/list'
href: '/system/bill-runs'
})
}}
{% endblock %}
Expand Down
132 changes: 132 additions & 0 deletions app/views/bill-runs/index.njk
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
{% extends 'layout.njk' %}
{% from "govuk/components/button/macro.njk" import govukButton %}
{% from "govuk/components/notification-banner/macro.njk" import govukNotificationBanner %}
{% from "govuk/components/pagination/macro.njk" import govukPagination %}
{% from "govuk/components/table/macro.njk" import govukTable %}

{% from "macros/bill-run-status-tag.njk" import statusTag %}

{% block content %}
<div class="govuk-grid-row">
<div class="govuk-grid-column-full">
{# Bill runs busy banner #}
{% if busy == 'both' %}
{{ govukNotificationBanner({
html: '<p class="govuk-notification-banner__heading">Bill runs are currently busy building and cancelling.</p>
<p class="govuk-body">Please wait for these bill runs to finish before creating another one.</p>'
}) }}
{% elif busy == 'building' %}
{{ govukNotificationBanner({
html: '<p class="govuk-notification-banner__heading">A bill run is currently building.</p>
<p class="govuk-body">Please wait for this bill run to finish building before creating another one.</p>'
}) }}
{% elif busy == 'cancelling' %}
{{ govukNotificationBanner({
html: '<p class="govuk-notification-banner__heading">A bill run is currently cancelling.</p>
<p class="govuk-body">Please wait for this bill run to finish cancelling before creating another one.</p>'
}) }}
{% endif %}

<h1 class="govuk-heading-xl">Bill runs</h1>

<p class="govuk-body">Create a supplementary, annual or two-part tariff bill run.</p>

{{ govukButton({
text: "Create a bill run",
href: "/system/bill-runs/setup"
}) }}

<hr class="govuk-section-break govuk-section-break--m govuk-section-break--visible">

</div>
</div>

<div class="govuk-grid-row govuk-!-margin-bottom-9">
<div class="govuk-grid-column-full">
{# Results #}
{% if billRuns|length == 0 %}
<p>No bill runs found.</p>
{% else %}
<h2 class="govuk-heading-l govuk-!-margin-top-6">View a bill run</h2>

<p class="govuk-body">Select date to see the details of a bill run.</p>

{% set tableRows = [] %}
{% for billRun in billRuns %}
{# Set an easier to use index #}
{% set rowIndex = loop.index0 %}


{# Generate the link to view the bill run #}
{% set viewLink %}
<a class="govuk-link" href="{{ billRun.link }}">{{ billRun.createdAt }} <span class="govuk-visually-hidden">View bill run {{ billRun.number }}</span></a>
{% if billRun.scheme == 'alcs' %}
<div class="govuk-body-s govuk-!-margin-0">Old charge scheme</div>
{% endif %}
{% endset %}

{% set billRunStatusTag %}
{{ statusTag(billRun.status, true) }}
{% endset %}

{% set tableRow = [
{
html: viewLink,
attributes: { 'data-test': 'date-created-' + rowIndex }
},
{
text: billRun.region,
attributes: { 'data-test': 'region-' + rowIndex }
},
{
text: billRun.type,
attributes: { 'data-test': 'bill-run-type-' + rowIndex }
},
{
text: billRun.number,
attributes: { 'data-test': 'bill-run-number-' + rowIndex },
format: 'numeric'
},
{
text: billRun.numberOfBills,
attributes: { 'data-test': 'number-of-bills-' + rowIndex },
format: 'numeric'
},
{
text: billRun.total,
attributes: { 'data-test': 'bill-run-total-' + rowIndex },
format: 'numeric'
},
{
html: billRunStatusTag,
attributes: { 'data-test': 'bill-run-status-' + rowIndex },
format: 'numeric'
}
] %}

{# Push our row into the table rows array #}
{% set tableRows = (tableRows.push(tableRow), tableRows) %}
{% endfor %}

{{ govukTable({
firstCellIsHeader: false,
attributes: { 'data-test': 'bill-runs'},
head: [
{ text: 'Date' },
{ text: 'Region' },
{ text: 'Run type' },
{ text: 'Number', format: 'numeric' },
{ text: 'Bills', format: 'numeric' },
{ text: 'Values', format: 'numeric' },
{ text: 'Status', format: 'numeric' }
],
rows: tableRows
}) }}

{% if pagination.numberOfPages > 1 %}
{{ govukPagination(pagination.component) }}
{% endif %}
{% endif %}
</div>
</div>
{% endblock %}
2 changes: 1 addition & 1 deletion app/views/bill-runs/review.njk
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
{# Back link #}
{{ govukBackLink({
text: 'Go back to bill runs',
href: '/billing/batch/list'
href: '/system/bill-runs'
}) }}
{% endblock %}

Expand Down
2 changes: 1 addition & 1 deletion app/views/bill-runs/setup/type.njk
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
{{
govukBackLink({
text: 'Go back to bill runs',
href: '/billing/batch/list'
href: '/system/bill-runs'
})
}}
{% endblock %}
Expand Down
2 changes: 1 addition & 1 deletion app/views/bill-runs/view.njk
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
{{
govukBackLink({
text: 'Go back to bill runs',
href: '/billing/batch/list'
href: '/system/bill-runs'
})
}}
{% endblock %}
Expand Down
2 changes: 1 addition & 1 deletion app/views/includes/nav-bar.njk
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
</li>
{% if auth.permission.billRuns %}
<li class="navbar__item">
<a class="navbar__link govuk-link--no-visited-state {{ 'navbar__link--active' if activeNavBar === 'bill-runs' }}" href="/billing/batch/list" id="nav-bill-runs">
<a class="navbar__link govuk-link--no-visited-state {{ 'navbar__link--active' if activeNavBar === 'bill-runs' }}" href="/system/bill-runs" id="nav-bill-runs">
Bill runs
</a>
</li>
Expand Down
Loading
Loading