Skip to content

Commit

Permalink
Man 309 links to previous orders (#294)
Browse files Browse the repository at this point in the history
* MAN-309 - add new page

* MAN-309 - add card elements

* MAN-309 - add new e2e test

* MAN-309 - update e2e test

* MAN-309 - update route url
  • Loading branch information
achimber-moj authored Jan 30, 2025
1 parent fc89ba4 commit ebfc76e
Show file tree
Hide file tree
Showing 16 changed files with 490 additions and 7 deletions.
4 changes: 2 additions & 2 deletions integration_tests/e2e/sentence/previous-orders.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ context('Sentence', () => {

cy.get('p')
.eq(0)
.within(() => cy.get('a').invoke('attr', 'href').should('equal', '/case/X000001/handoff/delius'))
.within(() => cy.get('a').invoke('attr', 'href').should('equal', '/case/X000001/sentence/previous-orders/3'))
cy.get('p')
.eq(0)
.within(() => cy.get('a').should('contain.text', 'CJA - Std Determinate Custody (16 Months)'))
Expand All @@ -18,7 +18,7 @@ context('Sentence', () => {

cy.get('p')
.eq(1)
.within(() => cy.get('a').invoke('attr', 'href').should('equal', '/case/X000001/handoff/delius'))
.within(() => cy.get('a').invoke('attr', 'href').should('equal', '/case/X000001/sentence/previous-orders/2'))
cy.get('p')
.eq(1)
.within(() => cy.get('a').should('contain.text', 'CJA - Std Determinate Custody (12 Months)'))
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import Page from '../../../pages'
import PreviousOrderPage from '../../../pages/sentence/previous-orders/previous-order'

context('Sentence', () => {
it('Previous order page is rendered', () => {
cy.visit('/case/X000001/sentence/previous-orders/3')

const page = Page.verifyOnPage(PreviousOrderPage)
const breadCrumbElement = '.govuk-breadcrumbs__list-item'

page.assertTextElementAtIndex('h2', 0, 'Previous orders')

page.assertAnchorElementAtIndex(breadCrumbElement, 0, '/case')
page.assertTextAtAnchorElementAtIndex(breadCrumbElement, 0, 'My cases')

page.assertAnchorElementAtIndex(breadCrumbElement, 1, '/case/X000001')
page.assertTextAtAnchorElementAtIndex(breadCrumbElement, 1, 'Caroline Wolff')

page.assertAnchorElementAtIndex(breadCrumbElement, 2, '/case/X000001/sentence')
page.assertTextAtAnchorElementAtIndex(breadCrumbElement, 2, 'Sentence')

page.assertAnchorElementAtIndex(breadCrumbElement, 3, '/case/X000001/sentence/previous-orders')
page.assertTextAtAnchorElementAtIndex(breadCrumbElement, 3, 'Previous orders')

page.assertTextElementAtIndex('h2', 1, 'CJA - Std Determinate Custody (16 Months)')

page.assertPageElementAtIndexWithin('section', 0, 'h2', 0, 'Offence')
page.assertPageElementAtIndexWithin('section', 0, 'dt', 0, 'Main offence')
page.assertPageElementAtIndexWithin('section', 0, 'dt', 1, 'Offence date')
page.assertPageElementAtIndexWithin('section', 0, 'dt', 2, 'Notes')
page.assertPageElementAtIndexWithin('section', 0, 'dt', 3, 'Additional offences')
page.assertPageElementAtIndexWithin('section', 0, 'dd', 0, 'Speeding (1 count)')
page.assertPageElementAtIndexWithin('section', 0, 'dd', 1, '20 January 2024')
page.assertPageElementAtIndexWithin('section', 0, 'dd', 2, 'My note')
page.assertPageElementAtIndexWithin('section', 0, 'dd', 3, 'Burglary (2 count)')

page.assertPageElementAtIndexWithin('section', 1, 'h2', 0, 'Conviction')
page.assertPageElementAtIndexWithin('section', 1, 'dt', 0, 'Sentencing court')
page.assertPageElementAtIndexWithin('section', 1, 'dt', 1, 'Responsible court')
page.assertPageElementAtIndexWithin('section', 1, 'dt', 2, 'Conviction date')
page.assertPageElementAtIndexWithin('section', 1, 'dt', 3, 'Additional sentences')
page.assertPageElementAtIndexWithin('section', 1, 'dd', 0, 'Hull Court')
page.assertPageElementAtIndexWithin('section', 1, 'dd', 1, 'Birmingham Court')
page.assertPageElementAtIndexWithin('section', 1, 'dd', 2, '20 March 2024')
page.assertPageElementAtIndexWithin('section', 1, 'dd', 3, 'Disqualified from Driving')

page.assertPageElementAtIndexWithin('section', 2, 'h2', 0, 'Sentence')
page.assertPageElementAtIndexWithin('section', 2, 'dt', 0, 'Order')
page.assertPageElementAtIndexWithin('section', 2, 'dt', 1, 'Sentence start date')
page.assertPageElementAtIndexWithin('section', 2, 'dt', 2, 'Sentence end date')
page.assertPageElementAtIndexWithin('section', 2, 'dt', 3, 'Terminated date')
page.assertPageElementAtIndexWithin('section', 2, 'dt', 4, 'Termination reason')
page.assertPageElementAtIndexWithin('section', 2, 'dt', 5, 'Court documents')
page.assertPageElementAtIndexWithin('section', 2, 'dd', 0, '12 month community order')
page.assertPageElementAtIndexWithin('section', 2, 'dd', 1, '1 February 2024')
page.assertPageElementAtIndexWithin('section', 2, 'dd', 2, '1 November 2024')
page.assertPageElementAtIndexWithin('section', 2, 'dd', 3, '31 January 2025')
page.assertPageElementAtIndexWithin('section', 2, 'dd', 4, '11 months elapsed (of 12 months)')
page.assertPageElementAtIndexWithin('section', 2, 'dd', 5, 'Pre-sentence report')
})
})
10 changes: 10 additions & 0 deletions integration_tests/pages/page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,16 @@ export default abstract class Page {
.within(() => cy.get('a').invoke('attr', 'href').should('equal', value))
}

assertTextElementAtIndex = (element: string, index: number, value: string) => {
cy.get(element).eq(index).should('contain.text', value)
}

assertTextAtAnchorElementAtIndex = (element: string, index: number, value: string) => {
cy.get(element)
.eq(index)
.within(() => cy.contains(value))
}

assertAnchorElementAtIndexWithin = (element: string, index: number, anchorIndex: number, value: string) => {
cy.get(element)
.eq(index)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import Page from '../../page'

export default class PreviousOrderPage extends Page {
constructor() {
super('Previous orders')
}
}
5 changes: 5 additions & 0 deletions server/data/masApiClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { CaseAccess, UserAccess } from './model/caseAccess'
import { LicenceConditionNoteDetails } from './model/licenceConditionNoteDetails'
import { AppointmentRequestBody, ActivityLogRequestBody } from '../@types'
import { RequirementNoteDetails } from './model/requirementNoteDetails'
import { PreviousOrderDetail } from './model/previousOrderDetail'

export default class MasApiClient extends RestClient {
constructor(token: string) {
Expand Down Expand Up @@ -50,6 +51,10 @@ export default class MasApiClient extends RestClient {
return this.get({ path: `/sentence/${crn}/previous-orders`, handle404: false })
}

async getSentencePreviousOrder(crn: string, eventNumber: string): Promise<PreviousOrderDetail | null> {
return this.get({ path: `/sentence/${crn}/previous-orders/${eventNumber}`, handle404: false })
}

async getSentenceOffences(crn: string, eventNumber: string): Promise<Offences | null> {
return this.get({ path: `/sentence/${crn}/offences/${eventNumber}`, handle404: false })
}
Expand Down
8 changes: 8 additions & 0 deletions server/data/model/previousOrderDetail.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { Name } from './common'
import { Sentence } from './sentenceDetails'

export interface PreviousOrderDetail {
name: Name
title: string
sentence: Sentence
}
1 change: 1 addition & 0 deletions server/data/model/previousOrderHistory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export interface PreviousOrderHistory {
}

export interface PreviousOrder {
eventNumber: string
title: string
description: string
terminationDate: string
Expand Down
1 change: 1 addition & 0 deletions server/data/model/sentenceDetails.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export interface Sentence {
unpaidWorkProgress: string
licenceConditions: LicenceCondition[]
}

export interface OffenceDetails {
eventNumber: string
offence: Offence
Expand Down
23 changes: 23 additions & 0 deletions server/routes/sentence.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,29 @@ export default function sentenceRoutes(router: Router, { hmppsAuthClient }: Serv
})
})

get('/case/:crn/sentence/previous-orders/:eventNumber', async (req, res, _next) => {
const { crn, eventNumber } = req.params
const token = await hmppsAuthClient.getSystemClientToken(res.locals.user.username)

await auditService.sendAuditMessage({
action: 'VIEW_MAS_SENTENCE_PREVIOUS_ORDER',
who: res.locals.user.username,
subjectId: crn,
subjectType: 'CRN',
correlationId: v4(),
service: 'hmpps-manage-people-on-probation-ui',
})

const masClient = new MasApiClient(token)

const previousOrderDetail = await masClient.getSentencePreviousOrder(crn, eventNumber)

res.render('pages/sentence/previous-orders/previous-order', {
previousOrderDetail,
crn,
})
})

get('/case/:crn/sentence/offences/:eventNumber', async (req, res, _next) => {
const { crn, eventNumber } = req.params
const token = await hmppsAuthClient.getSystemClientToken(res.locals.user.username)
Expand Down
62 changes: 62 additions & 0 deletions server/views/pages/sentence/_conviction.njk
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
{% set hasAdditionalSentences = sentence.conviction.additionalSentences and sentence.conviction.additionalSentences.length > 0 %}
{% set additionalSentences %}
{% for additionalSentence in sentence.conviction.additionalSentences %}
{% set detailsHtml %}
{{ govukSummaryList({
rows: [
{
key: { text: 'Sentence' },
value: { text: additionalSentence.description }
},
{
key: { text: 'Value' },
value: { text: additionalSentence.value }
} if additionalSentence.value,
{
key: { text: 'Length' },
value: { text: additionalSentence.length }
} if additionalSentence.length,
{
key: { text: 'Notes' },
value: { html: additionalSentence.notes | nl2br if additionalSentence.notes else 'No notes' }
}
]
}) }}
{% endset %}
{{ govukDetails({
classes: 'govuk-!-margin-bottom-1',
summaryText: additionalSentence.description,
html: detailsHtml
}) }}
{% endfor %}
{% endset %}

{% set conviction %}
{{ govukSummaryList({
rows: [
{
key: { text: "Sentencing court" },
value: { html: sentence.conviction.sentencingCourt | nl2br if sentence.conviction.sentencingCourt else 'No court details' }
},
{
key: { text: "Responsible court" },
value: { html: sentence.conviction.responsibleCourt | nl2br if sentence.conviction.responsibleCourt else 'No court details' }
},
{
key: { text: "Conviction date" },
value: { html: sentence.conviction.convictionDate | dateWithYear | nl2br if sentence.conviction.convictionDate else 'No conviction date' }
},
{
key: { text: "Additional sentences" },
value: { html: additionalSentences if hasAdditionalSentences else 'No additional sentences' }
}
]
}) }}
{% endset %}

{{ appSummaryCard({
attributes: {'data-qa': 'convictionCard'},
titleText: 'Conviction',
classes: 'govuk-!-margin-bottom-6 app-summary-card--large-title',
html: conviction
}) }}
42 changes: 42 additions & 0 deletions server/views/pages/sentence/_sentence-offence.njk
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
{% set hasAdditionalOffences = sentence.offenceDetails.additionalOffences and sentence.offenceDetails.additionalOffences.length > 0 %}
{% set additionalOffences %}
{% if hasAdditionalOffences %}
<ol class="govuk-list{% if sentence.offenceDetails.additionalOffences > 1 %} govuk-list--number{% endif %}">
{% for additionalOffence in sentence.offenceDetails.additionalOffences %}
<li>{{ additionalOffence.description }} ({{ additionalOffence.count }} count)</li>
{% endfor %}
</ol>

<a href="/case/{{ crn }}/sentence/offences/{{ sentence.offenceDetails.eventNumber }}">View additional offence details</a>
{% endif %}
{% endset %}

{% set offence %}
{{ govukSummaryList({
rows: [
{
key: { text: "Main offence" },
value: { html: sentence.offenceDetails.offence.description + ' (' + sentence.offenceDetails.offence.count + ' count)' }
},
{
key: { text: "Offence date" },
value: { html: sentence.offenceDetails.dateOfOffence | dateWithYear }
},
{
key: { text: "Notes" },
value: { html: sentence.offenceDetails.notes | nl2br if sentence.offenceDetails.notes else 'No notes' }
},
{
key: { text: "Additional offences" },
value: { html: additionalOffences if hasAdditionalOffences else 'No additional offences' }
}
]
}) }}
{% endset %}

{{ appSummaryCard({
attributes: {'data-qa': 'offenceCard'},
titleText: 'Offence',
classes: 'govuk-!-margin-bottom-6 app-summary-card--large-title',
html: offence
}) }}
55 changes: 55 additions & 0 deletions server/views/pages/sentence/_sentence.njk
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
{% set hasCourtDocuments = sentence.courtDocuments and sentence.courtDocuments.length > 0 %}
{% set courtDocuments %}
<ul class="govuk-list govuk-!-margin-top-0">
{% for doc in sentence.courtDocuments %}
<li>
<a href="personal-details/documents/{{ doc.id }}/download" download="{{ doc.documentName }}">{{ doc.documentName }}</a><br>
<span class="govuk-!-font-size-16">
{% if doc.lastSaved %}
Last updated {{ doc.lastSaved | dateWithYearShortMonth }}
{% else %}
Unavailable
{% endif %}
</span>
</li>
{% endfor %}
</ul>
{% endset %}

{% set sentence %}
{{ govukSummaryList({
rows: [
{
key: { text: "Order" },
value: { html: sentence.order.description | nl2br if sentence.order.description else 'No order details' }
},
{
key: { text: "Sentence start date" },
value: { html: sentence.order.startDate | dateWithYear | nl2br if sentence.order.startDate else 'No start date details' }
},
{
key: { text: "Sentence end date" },
value: { html: sentence.order.releaseDate | dateWithYear | nl2br if sentence.order.releaseDate else 'No release date details' }
},
{
key: { text: "Terminated date" },
value: { html: sentence.order.endDate | dateWithYear | nl2br if sentence.order.endDate else 'No end date details' }
},
{
key: { text: "Termination reason" },
value: { html: sentence.order.startDate | monthsOrDaysElapsed + ' elapsed (of ' + sentence.order.length + ' months)' | nl2br if sentence.order.startDate else 'No details' }
},
{
key: { text: "Court documents" },
value: { html: '<span data-qa="courtDocumentsValue">' + courtDocuments if hasCourtDocuments else 'No court documents' + '</span>' }
}
]
}) }}
{% endset %}

{{ appSummaryCard({
attributes: {'data-qa': 'sentenceCard'},
titleText: 'Sentence',
classes: 'govuk-!-margin-bottom-6 app-summary-card--large-title',
html: sentence
}) }}
2 changes: 1 addition & 1 deletion server/views/pages/sentence/previous-orders.njk
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@

{% for order in previousOrderHistory.previousOrders %}
<p class="govuk-heading-s govuk-!-margin-bottom-0">
<a class="govuk-link govuk-link--no-visited-state" href="/case/{{ crn }}/handoff/delius">
<a class="govuk-link govuk-link--no-visited-state" href="/case/{{ crn }}/sentence/previous-orders/{{ order.eventNumber }}">
{{ order.title }}
</a>
</p>
Expand Down
41 changes: 41 additions & 0 deletions server/views/pages/sentence/previous-orders/previous-order.njk
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
{% extends "../../../partials/layout.njk" %}
{% set headerPersonName = previousOrderDetail.name.forename + ' ' + previousOrderDetail.name.surname %}

{% block beforeContent %}
{{ govukBreadcrumbs({
items: [
{
text: "My cases",
href: "/case"
},
{
text: headerPersonName,
href: "/case/" + crn,
attributes: { "data-ai-id": "breadcrumbPersonNameLink" }
},
{
text: "Sentence",
href: "/case/" + crn + "/sentence"
},
{
text: "Previous orders",
href: "/case/" + crn + "/sentence/previous-orders"
}
]
}) }}
{% endblock %}
{% block content %}
<div class="govuk-!-margin-bottom-0">
<h2 class="govuk-caption-l" data-qa="pageHeading">Previous orders</h2>
</div>

{% set sentence = previousOrderDetail.sentence %}
{% if sentence %}
<h2 class="govuk-heading-m govuk-!-margin-bottom-4">
{{ previousOrderDetail.title }}
</h2>
{% include '../_sentence-offence.njk' %}
{% include '../_conviction.njk' %}
{% include '../_sentence.njk' %}
{% endif %}
{% endblock %}
Loading

0 comments on commit ebfc76e

Please sign in to comment.