Skip to content

Commit

Permalink
Code to call the new endpoint - getReleaseDatesForACalcReqId (#701)
Browse files Browse the repository at this point in the history
* Code to call the new endpoint - getReleaseDatesForACalcReqId

* Add missed file for getReleaseDatesForACalcReqId

* Update package.json to use the latest calc card design

* Update package-lock.json to fix npm error [Error in desc]

npm error `npm ci` can only install packages when your package.json and package-lock.json or npm-shrinkwrap.json are in sync. Please update your lock file with `npm install` before continuing.
npm error
npm error Invalid: lock file's hmpps-court-cases-release-dates-design@2.3.6 does not satisfy hmpps-court-cases-release-dates-design@2.5.0

* Update ViewRouteSentenceAndOffenceViewModel to generateAdjustmentArray as required by PrintNotificationSlip

* PrintNotificationSlip Page design elements

* Updated Routes and ReleaseDateType in CalculationSummaryDatesCardModel

* Updating test cases to assert for the length

* Scenario to cover custodial term

* Relocating files to printNotification partials to correct folder - Re-structuring

* Correcting path typo

* Addressing as per code review comments

* Tests to cover the sentence length (Terms)
  • Loading branch information
FaizJD030 authored May 17, 2024
1 parent 7b9a415 commit 6803392
Show file tree
Hide file tree
Showing 22 changed files with 1,128 additions and 47 deletions.
116 changes: 116 additions & 0 deletions assets/scss/_print.scss
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,120 @@
.no-print {
display: none;
}

@page {

size: A4 portrait;
margin-left: 1cm;
margin-right: 1cm;
margin-bottom: 1.5cm;
margin-top: 1.5cm;


h1, h2, h3, h4, h5 {
page-break-after: avoid;
}

table, figure, dl {
page-break-inside: avoid;
}

.dont-break {
page-break-inside: avoid;
}

}

footer {
display: none;
}

.offender-title {
text-align: center;
font-family: Arial, Helvetica, sans-serif;
font-size: 10px;
margin-bottom: 2px;
}

.establishment-title {
text-align: center;
font-family: Arial, Helvetica, sans-serif;
font-size: 10px;
margin-bottom: 2px;
}

.govuk-grid-row {
margin-right: 0px;
margin-left: 0px;
}

.govuk-grid-column-full {
margin-right: 0px;
margin-left: 0px;
}

.print-width-container {
max-width: 21cm;
margin-right: 0px;
margin-left: 0px;
margin-top: 0px;
}
.print-button {
display: none;
}
.notification-slip {
width: 21cm;
margin-bottom: 0px;
padding-top: 0px;
padding-right: 0px;
padding-bottom: 0px;
padding-left: 0px;
border-top-width: 0px;
border-right-width: 0px;
border-bottom-width: 0px;
border-left-width: 0px;
border-top-style: none;
border-right-style: none;
border-bottom-style: none;
border-left-style: none;
border-image-source: initial;
border-image-slice: initial;
border-image-width: initial;
border-image-outset: initial;
border-image-repeat: initial;
break-inside: avoid;
}

.govuk-body {
font-size: 14pt;
line-height: 1.3;
}

.govuk-table {
font-size: 14pt;
line-height: 1;
}

.govuk-summary-list {
font-size: 14pt;
line-height: 1;
}

.notification-slip .notification-slip-establishment {
text-align: right;
font-weight: normal;
margin-bottom: 0px;
}

.govuk-heading-xl {
margin-bottom: 30px;
}

.govuk-heading-l {
margin-bottom: 30px;
}

.notification-slip .govuk-summary-list__key {
width: 250px;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ export type CalculationPrisonerDetails = components['schemas']['PrisonerDetails'
export type LatestCalculation = components['schemas']['LatestCalculation']
export type DateTypeDefinition = components['schemas']['DateTypeDefinition']
export type NomisCalculationSummary = components['schemas']['NomisCalculationSummary']
export type ReleaseDatesAndCalculationContext = components['schemas']['ReleaseDatesAndCalculationContext']
export type SentenceAndOffenceWithReleaseArrangements =
components['schemas']['SentenceAndOffenceWithReleaseArrangements']
export type OffenderOffence = components['schemas']['OffenderOffence']
4 changes: 4 additions & 0 deletions server/@types/calculateReleaseDates/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1169,6 +1169,10 @@ export interface components {
comment?: string
releaseDates: components['schemas']['DetailedDate'][]
}
ReleaseDatesAndCalculationContext: {
calculation: components['schemas']['CalculationContext']
dates: components['schemas']['DetailedDate'][]
}
/** @description Calculation breakdown details */
CalculationBreakdown: {
concurrentSentences: components['schemas']['ConcurrentSentenceBreakdown'][]
Expand Down
7 changes: 7 additions & 0 deletions server/api/calculateReleaseDatesApiClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
LatestCalculation,
ManualEntryRequest,
NomisCalculationSummary,
ReleaseDatesAndCalculationContext,
SentenceAndOffenceWithReleaseArrangements,
SubmitCalculationRequest,
ValidationMessage,
Expand Down Expand Up @@ -317,4 +318,10 @@ export default class CalculateReleaseDatesApiClient {
path: `/calculation/nomis-calculation-summary/${offenderSentCalcId}`,
}) as Promise<NomisCalculationSummary>
}

getReleaseDatesForACalcReqId(calcReqId: number): Promise<ReleaseDatesAndCalculationContext> {
return this.restClient.get({
path: `/calculation/release-dates/${calcReqId}`,
}) as Promise<ReleaseDatesAndCalculationContext>
}
}
17 changes: 17 additions & 0 deletions server/models/PrintNotificationSlipViewModel.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import PrisonerContextViewModel from './PrisonerContextViewModel'
import ViewRouteSentenceAndOffenceViewModel from './ViewRouteSentenceAndOffenceViewModel'

export default class PrintNotificationSlipViewModel extends PrisonerContextViewModel {
constructor(
public model: ViewRouteSentenceAndOffenceViewModel,
public calculationRequestId: number,
public nomsId: string,
public calculationDate: string,
public keyDatesArray: { date: string; description: string }[],
public fromPage: string,
public pageType: string,
public calculationReason: string,
) {
super(model.prisonerDetail)
}
}
108 changes: 108 additions & 0 deletions server/models/ViewRouteSentenceAndOffenceViewModel.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -201,4 +201,112 @@ describe('ViewRouteSentenceAndOffenceViewModel', () => {
expect(model.getMultipleOffencesToASentence()).toStrictEqual([])
})
})
it('should generate adjustments array correctly', () => {
const stubbedAdjustments = {
bookingAdjustments: [
{
active: true,
fromDate: '2022-01-01',
toDate: '2022-01-08',
numberOfDays: 8,
type: 'ADDITIONAL_DAYS_AWARDED',
},
{ active: true, fromDate: '2022-02-01', toDate: '2022-01-08', numberOfDays: 8, type: 'UNLAWFULLY_AT_LARGE' },
{
active: true,
fromDate: '2022-03-01',
toDate: '2022-01-08',
numberOfDays: 8,
type: 'RESTORED_ADDITIONAL_DAYS_AWARDED',
},
],
sentenceAdjustments: [
{ active: true, fromDate: '2022-05-01', toDate: '2024-03-03', numberOfDays: 3, type: 'REMAND' },
{ active: true, fromDate: '2022-06-01', toDate: '2024-03-19', numberOfDays: 15, type: 'TAGGED_BAIL' },
{ active: true, fromDate: '2022-07-01', toDate: '2024-03-19', numberOfDays: 15, type: 'UNUSED_REMAND' },
{
active: true,
fromDate: '2022-08-01',
toDate: '2024-03-19',
numberOfDays: 15,
type: 'RECALL_SENTENCE_TAGGED_BAIL',
},
{
active: true,
fromDate: '2022-09-01',
toDate: '2024-03-19',
numberOfDays: 15,
type: 'RECALL_SENTENCE_REMAND',
},
],
}
const model = new ViewRouteSentenceAndOffenceViewModel(
stubbedPrisonerData,
stubbedUserInput,
[],
stubbedAdjustments as AnalyzedPrisonApiBookingAndSentenceAdjustments,
false,
stubbedReturnToCustodyDate,
null,
)
const adjustmentsArray = model.generateAdjustmentsRows()
expect(adjustmentsArray).toStrictEqual([
{
adjustmentName: 'Recall remand',
adjustmentType: 'deducted',
adjustmentFrom: '2022-09-01',
adjustmentTo: '2024-03-19',
adjustmentDays: 15,
},
{
adjustmentName: 'Recall tagged bail',
adjustmentType: 'deducted',
adjustmentFrom: '2022-08-01',
adjustmentTo: '2024-03-19',
adjustmentDays: 15,
},
{
adjustmentName: 'Unused remand',
adjustmentType: 'deducted',
adjustmentFrom: '2022-07-01',
adjustmentTo: '2024-03-19',
adjustmentDays: 15,
},
{
adjustmentName: 'Tagged bail',
adjustmentType: 'deducted',
adjustmentFrom: '2022-06-01',
adjustmentTo: '2024-03-19',
adjustmentDays: 15,
},
{
adjustmentName: 'Remand',
adjustmentType: 'deducted',
adjustmentFrom: '2022-05-01',
adjustmentTo: '2024-03-03',
adjustmentDays: 3,
},
{
adjustmentName: 'Restored additional days awarded (RADA)',
adjustmentType: 'deducted',
adjustmentFrom: '2022-03-01',
adjustmentTo: '2022-01-08',
adjustmentDays: 8,
},
{
adjustmentName: 'Unlawfully at large',
adjustmentType: 'added',
adjustmentFrom: '2022-02-01',
adjustmentTo: '2022-01-08',
adjustmentDays: 8,
},
{
adjustmentName: 'Additional days awarded (ADA)',
adjustmentType: 'added',
adjustmentFrom: '2022-01-01',
adjustmentTo: '2022-01-08',
adjustmentDays: 8,
},
])
})
})
31 changes: 31 additions & 0 deletions server/models/ViewRouteSentenceAndOffenceViewModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,4 +97,35 @@ export default class ViewRouteSentenceAndOffenceViewModel {
})
return Object.keys(duplicates).map(key => [duplicates[key].caseSequence, duplicates[key].lineSequence])
}

generateAdjustmentsRows() {
const adjustmentsRows = []

const pushAdjustmentDetails = (adjustmentType, adjustmentName, addOrDeduct) => {
if (this.adjustments[adjustmentType].aggregate !== 0) {
this.adjustments[adjustmentType].details.forEach(adjustment => {
adjustmentsRows.push({
adjustmentName,
adjustmentType: addOrDeduct,
adjustmentFrom: adjustment.from,
adjustmentTo: adjustment.to,
adjustmentDays: adjustment.days,
})
})
}
}

pushAdjustmentDetails('recallSentenceRemand', 'Recall remand', 'deducted')
pushAdjustmentDetails('remand', 'Remand', 'deducted')
pushAdjustmentDetails('recallSentenceTaggedBail', 'Recall tagged bail', 'deducted')
pushAdjustmentDetails('taggedBail', 'Tagged bail', 'deducted')
pushAdjustmentDetails('restoredAdditionalDaysAwarded', 'Restored additional days awarded (RADA)', 'deducted')
pushAdjustmentDetails('unusedRemand', 'Unused remand', 'deducted')
pushAdjustmentDetails('additionalDaysAwarded', 'Additional days awarded (ADA)', 'added')
pushAdjustmentDetails('unlawfullyAtLarge', 'Unlawfully at large', 'added')

adjustmentsRows.sort((a, b) => new Date(b.adjustmentFrom).getTime() - new Date(a.adjustmentFrom).getTime())

return adjustmentsRows
}
}
21 changes: 5 additions & 16 deletions server/routes/calculationRoutes.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -572,6 +572,7 @@ describe('Calculation routes tests', () => {
const backToDpsLink = $('[data-qa=back-to-dps-search-link]').first()
const courtCaseAndReleaseDatesLink = $('[data-qa=ccard-overview-link]').first()
const prisonerProfileLink = $('[data-qa=prisoner-profile-link]').first()
const prisonerNotificationSlipLink = $('[data-qa=prisoner-notification-slip-link]').first()

expect(backToDpsLink.length).toStrictEqual(1)
expect(backToDpsLink.text()).toStrictEqual('DPS homepage')
Expand All @@ -583,6 +584,10 @@ describe('Calculation routes tests', () => {
'http://localhost:3100/prisoner/A1234AA/overview',
)

expect(prisonerNotificationSlipLink.attr('href')).toStrictEqual(
'/calculation/A1234AA/summary/123456/printNotificationSlip?fromPage=calculation',
)

expect(prisonerProfileLink.length).toStrictEqual(1)
expect(prisonerProfileLink.text()).toStrictEqual('Prisoner profile')
expect(prisonerProfileLink.attr('href')).toStrictEqual('http://localhost:3000/dps/prisoner/A1234AA')
Expand Down Expand Up @@ -633,22 +638,6 @@ describe('Calculation routes tests', () => {
})
return request(app).get('/calculation/A1234AB/complete/123456').expect(404).expect('Content-Type', /html/)
})
it('GET /calculation/:nomsId/summary/:calculationRequestId/print should return a printable page about the calculation requested', () => {
prisonerService.getPrisonerDetail.mockResolvedValue(stubbedPrisonerData)
calculateReleaseDatesService.getResultsWithBreakdownAndAdjustments.mockResolvedValue(
stubbedResultsWithBreakdownAndAdjustments,
)
return request(app)
.get('/calculation/A1234AB/summary/123456/print')
.expect(200)
.expect('Content-Type', /html/)
.expect(res => {
expect(res.text).toContain('Anon Nobody')
expect(res.text).toMatch(/<script src="\/assets\/print.js"><\/script>/)
expect(res.text).toMatch(/Dates for/)
expectMiniProfile(res.text, expectedMiniProfile)
})
})

it('POST /calculation/:nomsId/summary/:calculationRequestId should redirect if an error is thrown', () => {
const error = {
Expand Down
9 changes: 8 additions & 1 deletion server/routes/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,10 @@ export default function Index({
const calculationRoutes = () => {
get('/calculation/:nomsId/summary/:calculationRequestId', calculationAccessRoutes.calculationSummary)
post('/calculation/:nomsId/summary/:calculationRequestId', calculationAccessRoutes.submitCalculationSummary)
get('/calculation/:nomsId/summary/:calculationRequestId/print', calculationAccessRoutes.printCalculationSummary)
get(
'/calculation/:nomsId/summary/:calculationRequestId/printNotificationSlip',
viewAccessRoutes.printNotificationSlip,
)
get('/calculation/:nomsId/complete/:calculationRequestId', calculationAccessRoutes.complete)
}

Expand All @@ -152,6 +155,10 @@ export default function Index({
get('/view/:nomsId/nomis-calculation-summary/:offenderSentCalculationId', viewAccessRoutes.nomisCalculationSummary)
get('/view/:nomsId/calculation-summary/:calculationRequestId', viewAccessRoutes.calculationSummary)
get('/view/:nomsId/calculation-summary/:calculationRequestId/print', viewAccessRoutes.printCalculationSummary)
get(
'/view/:nomsId/calculation-summary/:calculationRequestId/printNotificationSlip',
viewAccessRoutes.printNotificationSlip,
)
}

const otherRoutes = () => {
Expand Down
Loading

0 comments on commit 6803392

Please sign in to comment.