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

CDPS-59 - Staff Contacts component #56

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all 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
3 changes: 1 addition & 2 deletions assets/scss/components/_alerts.scss
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
font-weight: 300;
text-align: center;
line-height: 1;
min-width: 100px;
}

@media print {
Expand Down Expand Up @@ -40,7 +39,7 @@
gap: 15px;

li {
padding: 0 5px;
padding: 0 10px;
margin-bottom: 0;
background-color: govuk-colour('white');
}
Expand Down
2 changes: 2 additions & 0 deletions helm_deploy/values-dev.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ generic-service:
DPS_HOME_PAGE_URL: "https://digital-dev.prison.service.justice.gov.uk"
PRISONER_SEARCH_API_URL: "https://prisoner-offender-search-dev.prison.service.justice.gov.uk"
PRISON_API_URL: "https://api-dev.prison.service.justice.gov.uk"
ALLOCATION_MANAGER_ENDPOINT_URL: "https://allocation-manager-staging.apps.live-1.cloud-platform.service.justice.gov.uk"
KEYWORKER_API_URL: "https://keyworker-api-dev.prison.service.justice.gov.uk"

generic-prometheus-alerts:
alertSeverity: digital-prison-service-dev
Expand Down
9 changes: 9 additions & 0 deletions integration_tests/e2e/overviewPage.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -148,4 +148,13 @@ context('SignIn', () => {
overviewPage.schedule().evening().item(1).should('include.text', 'VLB - Test')
})
})

context('Staff contacts', () => {
it('Displays the offender staff contact details', () => {
cy.task('stubDpsOverviewPage')
cy.signIn()
const overviewPage = Page.verifyOnPage(OverviewPage)
overviewPage.staffContacts().should('exist')
})
})
})
2 changes: 2 additions & 0 deletions integration_tests/pages/overviewPage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ export default class OverviewPage extends Page {

personalDetails = (): PageElement => cy.get('[data-qa=personal-details]')

staffContacts = (): PageElement => cy.get('[data-qa=staff-contacts]')

schedule = () => ({
morning: () => ({
column: (): PageElement => cy.get('[data-qa=morning-schedule]'),
Expand Down
16 changes: 16 additions & 0 deletions server/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,22 @@ export default {
agent: new AgentConfig(Number(get('PRISONER_SEARCH_API_TIMEOUT_DEADLINE', 20000))),
},
dpsHomePageUrl: get('DPS_HOME_PAGE_URL', 'http://localhost:3001', requiredInProduction),
allocationManager: {
url: process.env.ALLOCATION_MANAGER_ENDPOINT_URL || '',
timeout: {
response: Number(get('ALLOCATION_MANAGER_API_TIMEOUT_SECONDS', 20000)),
deadline: Number(get('ALLOCATION_MANAGER_API_TIMEOUT_SECONDS', 20000)),
},
agent: new AgentConfig(Number(get('ALLOCATION_MANAGER_API_TIMEOUT_DEADLINE', 20000))),
},
keyworker: {
url: process.env.KEYWORKER_API_URL || 'http://localhost:8081/',
timeout: {
response: Number(get('KEYWORKER_API_TIMEOUT_SECONDS', 20000)),
deadline: Number(get('AKEYWORKER_API_TIMEOUT_SECONDS', 20000)),
},
agent: new AgentConfig(Number(get('KEYWORKER_API_TIMEOUT_DEADLINE', 20000))),
},
},
domain: get('INGRESS_URL', 'http://localhost:3000', requiredInProduction),
localMockData: get('LOCAL_MOCK_DATA', false),
Expand Down
19 changes: 19 additions & 0 deletions server/data/allocationManagerApiClient.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import RestClient from './restClient'
import config from '../config'
import { Pom } from '../interfaces/pom'

export default class AllocationManagerClient {
restClient: RestClient

constructor(token: string) {
this.restClient = new RestClient('Allocation Manager API', config.apis.allocationManager, token)
}

async getPomByOffenderNo(offenderNumber: string): Promise<Pom> {
try {
return await this.restClient.get<Pom>({ path: `/api/allocation/${offenderNumber}` })
} catch (error) {
return error
}
}
}
5 changes: 5 additions & 0 deletions server/data/interfaces/allocationManagerClient.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { Pom } from '../../interfaces/pom'

export default interface AllocationManagerClient {
getPomByOffenderNo(prisonerNumber: string): Promise<Pom>
}
5 changes: 5 additions & 0 deletions server/data/interfaces/keyWorkerClient.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { KeyWorker } from '../../interfaces/keyWorker'

export default interface KeyWorkerClient {
getOffendersKeyWorker(prisonerNumber: string): Promise<KeyWorker>
}
4 changes: 4 additions & 0 deletions server/data/interfaces/prisonApiClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import { AdjudicationSummary } from '../../interfaces/adjudicationSummary'
import { VisitSummary } from '../../interfaces/visitSummary'
import { VisitBalances } from '../../interfaces/visitBalances'
import { Assessment } from '../../interfaces/assessment'
import { OffenderContacts } from '../../interfaces/staffContacts'
import { CaseNote } from '../../interfaces/caseNote'
import { ScheduledEvent } from '../../interfaces/scheduledEvent'

export interface PrisonApiClient {
Expand All @@ -17,5 +19,7 @@ export interface PrisonApiClient {
getVisitSummary(bookingId: number): Promise<VisitSummary>
getVisitBalances(prisonerNumber: string): Promise<VisitBalances>
getAssessments(bookingId: number): Promise<Assessment[]>
getOffenderContacts(bookingId: number): Promise<OffenderContacts>
getCaseNoteSummaryByTypes(params: object): Promise<CaseNote[]>
getEventsScheduledForToday(bookingId: number): Promise<ScheduledEvent[]>
}
22 changes: 22 additions & 0 deletions server/data/keyWorkersApiClient.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import RestClient from './restClient'
import config from '../config'
import { KeyWorker } from '../interfaces/keyWorker'

export default class KeyWorkerClient {
restClient: RestClient

caseLoadId: string

constructor(token: string, caseLoadId: string) {
this.restClient = new RestClient('KeyWorkers API', config.apis.keyworker, token)
this.caseLoadId = caseLoadId
}

async getOffendersKeyWorker(offenderNumber: string): Promise<KeyWorker> {
try {
return await this.restClient.get<KeyWorker>({ path: `/key-worker/${this.caseLoadId}/offender/${offenderNumber}` })
} catch (error) {
return error
}
}
}
12 changes: 12 additions & 0 deletions server/data/localMockData/keyWorker.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { KeyWorker } from '../../interfaces/keyWorker'

export const keyWorkerMock: KeyWorker = {
staffId: 3532453,
firstName: 'Dave',
lastName: 'Stevens',
email: '1@1.com',
}

export default {
keyWorkerMock,
}
10 changes: 10 additions & 0 deletions server/data/localMockData/pom.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { Pom } from '../../interfaces/pom'

export const pomMock: Pom = {
primary_pom: { staff_id: 485887, name: 'MARKE, ANDY' },
secondary_pom: { staff_id: 485829, name: 'HUDSON, ANDY' },
}

export default {
pomMock,
}
16 changes: 16 additions & 0 deletions server/data/localMockData/staffContacts.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { convertToTitleCase } from '../../utils/utils'
import { keyWorkerMock } from './keyWorker'

export const StaffContactsMock = {
keyWorker: {
name: `${convertToTitleCase(keyWorkerMock.firstName)} ${convertToTitleCase(keyWorkerMock.lastName)}`,
lastSession: '',
},
prisonOffenderManager: 'Andy Marke',
coworkingPrisonOffenderManager: 'Andy Hudson',
communityOffenderManager: 'Not assigned',
}

export default {
StaffContactsMock,
}
19 changes: 19 additions & 0 deletions server/data/prisonApiClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ import { AdjudicationSummary } from '../interfaces/adjudicationSummary'
import { VisitSummary } from '../interfaces/visitSummary'
import { VisitBalances } from '../interfaces/visitBalances'
import { Assessment } from '../interfaces/assessment'
import { OffenderContacts } from '../interfaces/staffContacts'
import { mapToQueryString } from '../utils/utils'
import { CaseNote } from '../interfaces/caseNote'
import { ScheduledEvent } from '../interfaces/scheduledEvent'
import dummyScheduledEvents from './localMockData/eventsForToday'

Expand Down Expand Up @@ -91,4 +94,20 @@ export default class PrisonApiRestClient implements PrisonApiClient {
dummyScheduledEvents,
)
}

async getOffenderContacts(bookingId: number): Promise<OffenderContacts> {
try {
return await this.restClient.get<OffenderContacts>({ path: `/api/bookings/${bookingId}/contacts` })
} catch (error) {
return error
}
}

async getCaseNoteSummaryByTypes(params: object): Promise<CaseNote[]> {
try {
return await this.restClient.get<CaseNote[]>({ path: `/api/case-notes/summary?${mapToQueryString(params)}` })
} catch (error) {
return error
}
}
}
7 changes: 7 additions & 0 deletions server/interfaces/caseNote.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export type CaseNote = {
bookingId: number
caseNoteType: string
caseNoteSubType: string
numCaseNotes: number
latestCaseNote: string
}
6 changes: 6 additions & 0 deletions server/interfaces/keyWorker.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export interface KeyWorker {
staffId: number
firstName: string
lastName: string
email: string
}
4 changes: 4 additions & 0 deletions server/interfaces/pom.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export interface Pom {
primary_pom: { staff_id: number; name: string }
secondary_pom: { staff_id: number; name: string }
}
38 changes: 38 additions & 0 deletions server/interfaces/staffContacts.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
export interface StaffContacts {
keyWorker: KeyWorkerUI
prisonOffenderManager: string
coworkingPrisonOffenderManager: string
communityOffenderManager: string
}

export interface KeyWorkerUI {
name: string
lastSession: string
}

export interface OffenderContact {
lastName: string
firstName: string
middleName: string
contactType: string
contactTypeDescription: string
relationship: string
relationshipDescription: string
commentText: string
emergencyContact: boolean
nextOfKin: boolean
relationshipId: number
personId: number
activeFlag: boolean
expiryDate: string
approvedVisitorFlag: boolean
canBeContactedFlag: boolean
awareOfChargesFlag: boolean
contactRootOffenderId: number
bookingId: number
createDateTime: string
}

export interface OffenderContacts {
otherContacts: OffenderContact[]
}
12 changes: 9 additions & 3 deletions server/routes/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ import PrisonerSearchClient from '../data/prisonerSearchClient'

import { mapHeaderData } from '../mappers/headerMappers'
import { PageConfig } from '../interfaces/pageConfig'
import AllocationManagerClient from '../data/allocationManagerApiClient'
import KeyWorkersClient from '../data/keyWorkersApiClient'
import { convertToTitleCase } from '../utils/utils'

// eslint-disable-next-line @typescript-eslint/no-unused-vars
export default function routes(service: Services): Router {
Expand All @@ -27,10 +30,13 @@ export default function routes(service: Services): Router {

get('/prisoner/:prisonerNumber', async (req, res, next) => {
const prisonerSearchClient = new PrisonerSearchClient(res.locals.clientToken)
const prisonApiClient = new PrisonApiRestClient(res.locals.clientToken)
const allocationManagerClient = new AllocationManagerClient(res.locals.clientToken)
const keyWorkersClient = new KeyWorkersClient(res.locals.clientToken, res.locals.user.activeCaseLoadId)

const prisonerData: Prisoner = await prisonerSearchClient.getPrisonerDetails(req.params.prisonerNumber)

const prisonApi = new PrisonApiRestClient(res.locals.clientToken)
const overviewPageService = new OverviewPageService(prisonApi)
const overviewPageService = new OverviewPageService(prisonApiClient, allocationManagerClient, keyWorkersClient)
const overviewPageData = await overviewPageService.get(prisonerData)

const pageConfig: PageConfig = DisplayBanner
Expand Down Expand Up @@ -65,7 +71,7 @@ export default function routes(service: Services): Router {
href: '#',
},
{
text: `${prisonerData.lastName} ,${prisonerData.firstName}`,
text: `${convertToTitleCase(prisonerData.lastName)} ,${convertToTitleCase(prisonerData.firstName)}`,
href: `/prisoner/${req.params.prisonerNumber}`,
},
]
Expand Down
Loading