Skip to content

Commit

Permalink
ADJUST1-11 View additional days awarded. (#75)
Browse files Browse the repository at this point in the history
* ADJUST1-11 View additional days awarded.

* ADJUST11 linting.

* ADJUST1-11 View additional days titles.
  • Loading branch information
ldlharper authored Oct 16, 2023
1 parent 836d7bf commit 3e6f5c2
Show file tree
Hide file tree
Showing 11 changed files with 256 additions and 38 deletions.
6 changes: 6 additions & 0 deletions server/@types/AdaTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,11 @@ type AdasToReview = {
intercept: AdaIntercept
}

type AdasToView = {
awarded: AdasByDateCharged[]
totalAwarded: number
}

type PadasToReview = {
prospective: AdasByDateCharged[]
totalProspective: number
Expand All @@ -57,4 +62,5 @@ export {
AdaStatus,
ChargeStatus,
PadasToReview,
AdasToView,
}
23 changes: 23 additions & 0 deletions server/routes/additionalDaysAwardedRoutes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -182,4 +182,27 @@ export default class AdditionalDaysAwardedRoutes {
} as Message
return res.redirect(`/${nomsId}/success?message=${JSON.stringify(message)}`)
}

public view: RequestHandler = async (req, res): Promise<void> => {
const { caseloads, token, username } = res.locals.user
const { nomsId } = req.params
const prisonerDetail = await this.prisonerService.getPrisonerDetail(nomsId, caseloads, token)
const startOfSentenceEnvelope = await this.prisonerService.getStartOfSentenceEnvelope(
prisonerDetail.bookingId,
token,
)
const adas = await this.additionalDaysAwardedService.viewAdjustments(
nomsId,
startOfSentenceEnvelope,
username,
token,
)

return res.render('pages/adjustments/additional-days/view', {
model: {
prisonerDetail,
adas,
},
})
}
}
1 change: 1 addition & 0 deletions server/routes/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ export default function routes(service: Services): Router {
post('/:nomsId/additional-days/review-and-approve', additionalDaysAwardedRoutes.approve)
get('/:nomsId/additional-days/review-and-submit', additionalDaysAwardedRoutes.reviewAndSubmit)
post('/:nomsId/additional-days/review-and-submit', additionalDaysAwardedRoutes.submit)
get('/:nomsId/additional-days/view', additionalDaysAwardedRoutes.view)

get('/:nomsId/:adjustmentTypeUrl/view', adjustmentRoutes.view)
get('/:nomsId/:adjustmentTypeUrl/remove/:id', adjustmentRoutes.remove)
Expand Down
73 changes: 72 additions & 1 deletion server/services/additionalDaysAwardedService.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import AdditionalDaysAwardedService from './additionalDaysAwardedService'
import TokenStore from '../data/tokenStore'
import config from '../config'
import { AdjudicationSearchResponse, IndividualAdjudication } from '../@types/adjudications/adjudicationTypes'
import { AdaIntercept, AdasToReview, PadasToReview } from '../@types/AdaTypes'
import { AdaIntercept, AdasToReview, AdasToView, PadasToReview } from '../@types/AdaTypes'
import { Adjustment } from '../@types/adjustments/adjustmentsTypes'
import { PrisonApiPrisoner } from '../@types/prisonApi/prisonClientTypes'
import AdditionalDaysAwardedStoreService from './additionalDaysApprovalStoreService'
Expand Down Expand Up @@ -423,6 +423,77 @@ describe('Additional Days Added Service', () => {
} as AdasToReview)
})

it('View adjustments for adjudications awarded.', async () => {
const nomsId = 'AA1234A'
adjudicationsApi
.get('/adjudications/AA1234A/adjudications?size=1000', '')
.reply(200, threeAdjudicationsSearchResponse)
adjudicationsApi.get('/adjudications/AA1234A/charge/1525916', '').reply(200, adjudicationOne)
adjudicationsApi.get('/adjudications/AA1234A/charge/1525917', '').reply(200, adjudicationTwoConsecutiveToOne)
adjudicationsApi.get('/adjudications/AA1234A/charge/1525918', '').reply(200, adjudicationThreeConcurrentToOne)
adjustmentApi.get(`/adjustments?person=${nomsId}`).reply(200, [
{
id: 'c5b61b4e-8b47-4dfc-b88b-5eb58fc04691',
person: 'AA1234A',
bookingId: 1234,
adjustmentType: 'ADDITIONAL_DAYS_AWARDED',
fromDate: '2023-08-03',
days: 10,
additionalDaysAwarded: { adjudicationId: [1525916, 1525917, 1525918] },
},
])
const startOfSentenceEnvelope = new Date('2023-01-01')

const adasToView: AdasToView = await adaService.viewAdjustments(
nomsId,
startOfSentenceEnvelope,
'username',
token,
)

expect(adasToView).toEqual({
awarded: [
{
dateChargeProved: new Date('2023-08-03'),
charges: [
{
chargeNumber: 1525916,
dateChargeProved: new Date('2023-08-03'),
days: 5,
heardAt: 'Moorland (HMP & YOI)',
status: 'AWARDED_OR_PENDING',
toBeServed: 'Forthwith',
sequence: 15,
},
{
chargeNumber: 1525917,
dateChargeProved: new Date('2023-08-03'),
days: 5,
heardAt: 'Moorland (HMP & YOI)',
status: 'AWARDED_OR_PENDING',
toBeServed: 'Consecutive to 1525916',
sequence: 16,
consecutiveToSequence: 15,
},
{
chargeNumber: 1525918,
dateChargeProved: new Date('2023-08-03'),
days: 5,
heardAt: 'Moorland (HMP & YOI)',
status: 'AWARDED_OR_PENDING',
toBeServed: 'Concurrent',
sequence: 17,
},
],
total: 10,
status: 'AWARDED',
adjustmentId: 'c5b61b4e-8b47-4dfc-b88b-5eb58fc04691',
},
],
totalAwarded: 10,
} as AdasToView)
})

it('Get adjudication where adjustment has been quashed', async () => {
const nomsId = 'AA1234A'
adjudicationsApi
Expand Down
43 changes: 42 additions & 1 deletion server/services/additionalDaysAwardedService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,15 @@ import dayjs from 'dayjs'
import AdjudicationClient from '../api/adjudicationsClient'
import { AdjudicationSearchResponse, IndividualAdjudication, Sanction } from '../@types/adjudications/adjudicationTypes'
import { HmppsAuthClient } from '../data'
import { Ada, AdaIntercept, AdasByDateCharged, AdasToReview, ChargeStatus, PadasToReview } from '../@types/AdaTypes'
import {
Ada,
AdaIntercept,
AdasByDateCharged,
AdasToReview,
AdasToView,
ChargeStatus,
PadasToReview,
} from '../@types/AdaTypes'
import AdjustmentsClient from '../api/adjustmentsClient'
import { PrisonApiPrisoner } from '../@types/prisonApi/prisonClientTypes'
import { Adjustment } from '../@types/adjustments/adjustmentsTypes'
Expand Down Expand Up @@ -56,6 +64,39 @@ export default class AdditionalDaysAwardedService {
private readonly additionalDaysAwardedStoreService: AdditionalDaysAwardedStoreService,
) {}

public async viewAdjustments(
nomsId: string,
startOfSentenceEnvelope: Date,
username: string,
token: string,
): Promise<AdasToView> {
const allAdaAdjustments = (await new AdjustmentsClient(token).findByPerson(nomsId)).filter(
it => it.adjustmentType === 'ADDITIONAL_DAYS_AWARDED',
)
const existingAdasWithChargeIds = allAdaAdjustments.filter(it => it.additionalDaysAwarded)
const systemToken = await this.hmppsAuthClient.getSystemClientToken(username)
const adjudicationClient = new AdjudicationClient(systemToken)
const adjudications: AdjudicationSearchResponse = await adjudicationClient.getAdjudications(nomsId)
const individualAdjudications = await Promise.all(
adjudications.results.content.map(async it => {
return adjudicationClient.getAdjudication(nomsId, it.adjudicationNumber)
}),
)
const adas: Ada[] = this.getAdas(individualAdjudications, startOfSentenceEnvelope)
const awardedOrPending: AdasByDateCharged[] = this.getAdasByDateCharged(adas, 'AWARDED_OR_PENDING')
let { awarded } = this.filterAdasByMatchingAdjustment(awardedOrPending, existingAdasWithChargeIds)
const allProspective: AdasByDateCharged[] = this.getAdasByDateCharged(adas, 'PROSPECTIVE')
const { awarded: prospectiveAwarded } = this.filterAdasByMatchingAdjustment(
allProspective,
existingAdasWithChargeIds,
)

awarded = awarded.concat(prospectiveAwarded)
const totalAwarded: number = this.getTotalDays(awarded)

return { awarded, totalAwarded }
}

public async getAdasToApprove(
req: Request,
nomsId: string,
Expand Down
72 changes: 45 additions & 27 deletions server/views/macros/adaTable.njk
Original file line number Diff line number Diff line change
@@ -1,24 +1,36 @@
{% macro adaTable(tableId, adas, total, mainTitle, emptyTitle, checkboxes) %}
{% if adas | length %}
{% if mainTitle %}
<p>{{ mainTitle }}</p>
{#
This macro creates a table of ADAs. It has the following params
tableId: required, id of the table
adas: required, the data to display
total: required, the total number of days.
mainTitle: optional, title above table
emptyTitle: optional, displayed if table is empty
checkboxes: optional, defaults to false, does table have checkboxes
hideStatuses: optional, defaults to false , should the status of the ada be displayed
totalText: optional, defaults to 'Total' , the text displayed next to the total.
#}
{% macro adaTable(params) %}
{% if params.adas | length %}
{% if params.mainTitle %}
<p>{{ params.mainTitle }}</p>
{% endif %}
<table id="{{ tableId }}" class="govuk-table {{'govuk-!-margin-bottom-8' if not checkboxes else 'govuk-!-margin-bottom-2'}}">
<table id="{{ params.tableId }}" class="govuk-table {{'govuk-!-margin-bottom-8' if not params.checkboxes else 'govuk-!-margin-bottom-2'}}">
<thead class="govuk-table__head">
<tr class="govuk-table__row">
{% if checkboxes %}
{% if params.checkboxes %}
<th class="govuk-table__header" scope="col">
<span class="govuk-visually-hidden">Select adjudication</span>
</th>
{% endif %}
<th class="govuk-table__header" scope="col">Date charge proved</th>
<th class="govuk-table__header {{'govuk-!-width-two-fifths' if params.hideStatuses else 'govuk-!-width-one-fifth'}}" scope="col">Date charge proved</th>
<th class="govuk-table__header" scope="col">Charge details</th>
</tr>
</thead>
<tbody>
{% for ada in adas %}
{% for ada in params.adas %}
<tr class="govuk-table__row">
{% if checkboxes %}
{% if params.checkboxes %}
<td class="govuk-table__cell">
<div class="govuk-checkboxes__item govuk-checkboxes--small moj-multi-select__checkbox">
{% set isoDate = ada.dateChargeProved | date("YYYY-MM-DD") %}
Expand All @@ -30,17 +42,19 @@
</div>
</td>
{% endif %}
<td class="govuk-table__cell govuk-!-width-one-fifth">
<td class="govuk-table__cell">
{{ ada.dateChargeProved | date("DD MMM YYYY") }}
</td>
<td class="govuk-table__cell">
<table class="govuk-table">
<tr>
<th class="govuk-table__header govuk-!-width-one-fifth" scope="col">Charge number</th>
<th class="govuk-table__header {{'govuk-!-width-two-fifths' if params.hideStatuses else 'govuk-!-width-one-fifth'}}" scope="col">Charge number</th>
<th class="govuk-table__header govuk-!-width-one-quarter" scope="col">To be served</th>
<th class="govuk-table__header govuk-!-width-one-quarter" scope="col">Heard at</th>
<th class="govuk-table__header" scope="col">Status</th>
<th class="govuk-table__header govuk-!-text-align-centre" scope="col">Days</th>
{% if not params.hideStatuses %}
<th class="govuk-table__header" scope="col">Status</th>
{% endif %}
<th class="govuk-table__header govuk-!-text-align-right" scope="col">Days</th>
</tr>
{% for charge in ada.charges %}
<tr>
Expand All @@ -53,16 +67,18 @@
<td class="govuk-table__cell">
{{ charge.heardAt }}
</td>
<td class="govuk-table__cell">
{% if not checkboxes %}
<span class="moj-badge moj-badge--blue">{{ ada.status }}</span>
{% endif %}
{% if charge.status === 'PROSPECTIVE' %}
<span class="moj-badge moj-badge--purple">{{ charge.status }}</span>
{% endif %}
</td>
{% if not params.hideStatuses %}
<td class="govuk-table__cell">
{% if not params.checkboxes %}
<span class="moj-badge moj-badge--blue">{{ ada.status }}</span>
{% endif %}
{% if charge.status === 'PROSPECTIVE' %}
<span class="moj-badge moj-badge--purple">{{ charge.status }}</span>
{% endif %}
</td>
{% endif %}
<!-- Days -->
<td class="govuk-table__cell govuk-!-text-align-centre">{{ charge.days }}</td>
<td class="govuk-table__cell govuk-!-text-align-right">{{ charge.days }}</td>
</tr>
{% endfor %}
</table>
Expand All @@ -71,17 +87,19 @@
{% endfor %}
</tbody>

{% if not checkboxes %}
{% if not params.checkboxes %}
<tfoot>
<tr class="govuk-table__row">
<th class="govuk-table__cell govuk-!-text-align-left" scope="row" colspan="1">Total</th>
<td class="govuk-table__cell govuk-!-text-align-right govuk-!-padding-right-4">{{ total }}</td>
<th class="govuk-table__cell govuk-!-text-align-left" scope="row" colspan="1">
{{params.totalText if params.totalText else 'Total'}}
</th>
<td class="govuk-table__cell govuk-!-text-align-right">{{ params.total }}</td>
</tr>
</tfoot>
{% endif %}
</table>

{% if checkboxes %}
{% if params.checkboxes %}
<div class="govuk-form-group govuk-!-margin-bottom-4">
<div class="govuk-checkboxes govuk-checkboxes--small" data-module="govuk-checkboxes">
<div class="govuk-checkboxes__item">
Expand All @@ -92,6 +110,6 @@
</div>
{% endif %}
{% else %}
<p>{{ emptyTitle }}</p>
<p>{{ params.emptyTitle }}</p>
{% endif %}
{% endmacro %}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
{% from "../../../macros/adaTable.njk" import adaTable %}
{% from "govuk/components/button/macro.njk" import govukButton %}

{% set pageTitle = applicationName + " - Review additional days awarded" %}
{% set pageTitle = applicationName + " - Review adjustment information" %}
{% set mainClasses = "app-container govuk-body" %}

{% block content %}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
{% from "../../../macros/adaTable.njk" import adaTable %}
{% from "govuk/components/button/macro.njk" import govukButton %}

{% set pageTitle = applicationName + " - Review additional days awarded" %}
{% set pageTitle = applicationName + " - Review and approve ADAs" %}
{% set mainClasses = "app-container govuk-body" %}

{% block content %}
Expand Down Expand Up @@ -32,20 +32,43 @@

{% if adasToReview.intercept.type != 'FIRST_TIME'%}
<h2 class="govuk-heading-m">Awarded ADAs</h2>
{{ adaTable('awarded-adas', adasToReview.awarded, adasToReview.totalAwarded, 'Awarded ADAs will be included in the calculation.', model.prisonerDetail.firstName | title + ' ' + model.prisonerDetail.lastName | title + ' has no ADAs that are applicable to the current sentences.') }}
{{ adaTable({
tableId: 'awarded-adas',
adas: adasToReview.awarded,
total: adasToReview.totalAwarded,
mainTitle: 'Awarded ADAs will be included in the calculation.',
emptyTitle: model.prisonerDetail.firstName | title + ' ' + model.prisonerDetail.lastName | title + ' has no ADAs that are applicable to the current sentences.'
})
}}
{% endif %}

{% if adasToReview.suspended | length %}
<h2 class="govuk-heading-m">Suspended ADAs</h2>
{{ adaTable('suspended-adas', adasToReview.suspended, adasToReview.totalSuspended, 'Suspended ADAs will not be included in the calculation.') }}
{{ adaTable({
tableId: 'suspended-adas',
adas: adasToReview.suspended,
total: adasToReview.totalSuspended,
mainTitle: 'Suspended ADAs will not be included in the calculation.'
}) }}
{% endif %}

<h2 class="govuk-heading-m">Awarded ADAs pending approval</h2>
{{ adaTable('awaiting-approval-adas', adasToReview.awaitingApproval, adasToReview.totalAwaitingApproval, 'Once you have reviewed and approved the ADAs pending approval, they will be added to the sentence calculation.', 'No ADA records waiting for approval exist for this offender') }}
{{ adaTable({
tableId: 'awaiting-approval-adas',
adas: adasToReview.awaitingApproval,
total: adasToReview.totalAwaitingApproval,
mainTitle: 'Once you have reviewed and approved the ADAs pending approval, they will be added to the sentence calculation.',
emptyTitle: 'No ADA records waiting for approval exist for this offender'
}) }}

{% if adasToReview.quashed | length %}
<h2 class="govuk-heading-m">Review and approve quashed ADAs</h2>
{{ adaTable('quashed-approval-adas', adasToReview.quashed, adasToReview.totalQuashed, 'Once you have reviewed and approved the quashed ADAs, they will not be included in the sentence calculation') }}
{{ adaTable({
tableId: 'quashed-approval-adas',
adas: adasToReview.quashed,
total: adasToReview.totalQuashed,
mainTitle: 'Once you have reviewed and approved the quashed ADAs, they will not be included in the sentence calculation'
}) }}
{% endif %}

</div>
Expand Down
Loading

0 comments on commit 3e6f5c2

Please sign in to comment.