diff --git a/.circleci/config.yml b/.circleci/config.yml index ded25735e..948a82a8f 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -128,7 +128,7 @@ jobs: ENABLE_TEST_UTILS: true NOMIS_API_URL: http://localhost:8080/prisonApi NOMIS_AUTH_URL: http://hmpps-auth:9090/auth - DELIUS_API_URL: http://localhost:8080/communityapi + DELIUS_API_URL: http://localhost:8080/delius PROBATION_TEAMS_API_URL: http://localhost:8080/probationteams TOKENVERIFICATION_API_ENABLED: false GOTENBERG_API_URL: http://localhost:3001 diff --git a/Notes.md b/Notes.md index 800385592..5af0cbfb7 100644 --- a/Notes.md +++ b/Notes.md @@ -177,7 +177,7 @@ For, ``` CA and DM: prisonApi, /offender-sentences/home-detention-curfew-candidates -> OffenderSentenceCalc - RO: deliusApi, /staff/staffCode/${deliusStaffCode}/managedOffenders -> OffenderSummary + RO: deliusApi, /staff/${deliusStaffCode}/managedPrisonerIds -> OffenderSummary ``` Every row links to a taskList: hdc/taskList/:bookingId diff --git a/README.md b/README.md index f358da39b..52d066e64 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ To run locally you need: - redis - auth server - nomis -- community api +- delius api - probation teams - gotenberg - nomis-user-roles-api diff --git a/docker-compose-full.yml b/docker-compose-full.yml index 0fc427ba5..e0bd6bc3c 100644 --- a/docker-compose-full.yml +++ b/docker-compose-full.yml @@ -29,7 +29,7 @@ services: NOMIS_AUTH_EXTERNAL_URL: "http://localhost:9090/auth" TOKENVERIFICATION_API_URL: "http://token-verification-api:8080" NOMIS_API_URL: "http://stubs:3000/prisonApi" - DELIUS_API_URL: "http://stubs:3000/communityapi" + DELIUS_API_URL: "http://stubs:3000/delius" PROBATION_TEAMS_API_URL: "http://stubs:3000/probationteams" HDC_URL: "http://licences:3000" GOTENBERG_API_URL: "http://gotenberg:3000" diff --git a/feature.env b/feature.env index 9cb04f2e2..fd9b032ff 100644 --- a/feature.env +++ b/feature.env @@ -25,11 +25,10 @@ ADMIN_API_CLIENT_ID=licencesadmin ADMIN_API_CLIENT_SECRET=clientsecret # DELIUS API -DELIUS_API_URL=http://localhost:8080/communityapi +DELIUS_API_URL=http://localhost:8080/delius DELIUS_AUTH_URL=http://localhost:9090/auth DELIUS_API_CLIENT_ID=licencesadmin DELIUS_API_CLIENT_SECRET=clientsecret -DELIUS_API_PREFIX=/api DELIUS_RO_ROLE_ID=LHDCBT002 DELIUS_RO_VARY_ROLE_ID=LHDCBT003 diff --git a/helm_deploy/licences/templates/_envs.tpl b/helm_deploy/licences/templates/_envs.tpl index 54822f915..054d3a70e 100644 --- a/helm_deploy/licences/templates/_envs.tpl +++ b/helm_deploy/licences/templates/_envs.tpl @@ -106,9 +106,6 @@ env: - name: DELIUS_API_URL value: {{ .Values.env.DELIUS_API_URL | quote }} - - name: DELIUS_API_PREFIX - value: {{ .Values.env.DELIUS_API_PREFIX | quote }} - - name: PROBATION_TEAMS_API_URL value: {{ .Values.env.PROBATION_TEAMS_API_URL | quote }} diff --git a/helm_deploy/values-dev.yaml b/helm_deploy/values-dev.yaml index 373982a00..edb461ff5 100644 --- a/helm_deploy/values-dev.yaml +++ b/helm_deploy/values-dev.yaml @@ -37,8 +37,7 @@ env: SCHEDULED_JOBS_OVERLAP: "5000" NOTIFY_ACTIVE_TEMPLATES: "CA_RETURN,CA_DECISION,RO_NEW,RO_TWO_DAYS,RO_DUE,RO_OVERDUE,DM_NEW,DM_TO_CA_RETURN" RO_SERVICE_TYPE: "DELIUS" - DELIUS_API_URL: "https://community-api-secure.test.delius.probation.hmpps.dsd.io" - DELIUS_API_PREFIX: "/secure" + DELIUS_API_URL: "https://hdc-licences-and-delius-dev.hmpps.service.justice.gov.uk" PROBATION_TEAMS_API_URL: "https://probation-teams-dev.prison.service.justice.gov.uk" PRISONER_SEARCH_API_URL: "https://prisoner-search-dev.prison.service.justice.gov.uk" EXIT_LOCATION_URL: "https://digital-dev.prison.service.justice.gov.uk/" diff --git a/helm_deploy/values-preprod.yaml b/helm_deploy/values-preprod.yaml index 5330edece..47ad03380 100644 --- a/helm_deploy/values-preprod.yaml +++ b/helm_deploy/values-preprod.yaml @@ -34,8 +34,7 @@ env: SCHEDULED_JOBS_AUTOSTART: "yes" SCHEDULED_JOBS_OVERLAP: "5000" NOTIFY_ACTIVE_TEMPLATES: "CA_RETURN,CA_DECISION,RO_NEW,DM_NEW,DM_TO_CA_RETURN" - DELIUS_API_URL: "https://community-api-secure.pre-prod.delius.probation.hmpps.dsd.io" - DELIUS_API_PREFIX: "/secure" + DELIUS_API_URL: "https://hdc-licences-and-delius-preprod.hmpps.service.justice.gov.uk" PROBATION_TEAMS_API_URL: "https://probation-teams-preprod.prison.service.justice.gov.uk" PRISONER_SEARCH_API_URL: "https://prisoner-search-preprod.prison.service.justice.gov.uk" EXIT_LOCATION_URL: "https://digital-preprod.prison.service.justice.gov.uk/" diff --git a/helm_deploy/values-prod.yaml b/helm_deploy/values-prod.yaml index 024430d2d..7c2c39a60 100644 --- a/helm_deploy/values-prod.yaml +++ b/helm_deploy/values-prod.yaml @@ -34,8 +34,7 @@ env: SCHEDULED_JOBS_AUTOSTART: "yes" SCHEDULED_JOBS_OVERLAP: "5000" NOTIFY_ACTIVE_TEMPLATES: "CA_RETURN,CA_DECISION,RO_NEW,DM_NEW,DM_TO_CA_RETURN" - DELIUS_API_URL: "https://community-api-secure.probation.service.justice.gov.uk" - DELIUS_API_PREFIX: "/secure" + DELIUS_API_URL: "https://hdc-licences-and-delius.hmpps.service.justice.gov.uk" PROBATION_TEAMS_API_URL: "https://probation-teams.prison.service.justice.gov.uk" PRISONER_SEARCH_API_URL: "https://prisoner-search.prison.service.justice.gov.uk" EXIT_LOCATION_URL: "https://digital.prison.service.justice.gov.uk/" diff --git a/mock-server/app.js b/mock-server/app.js index 1e4fcdecb..8227a21bf 100644 --- a/mock-server/app.js +++ b/mock-server/app.js @@ -42,7 +42,7 @@ app.use('/prisonApi/api/agencies', agenciesRouter) app.use('/prisonApi/api/movements', movementsRouter) app.use('/prisonApi/api/prisoners', prisonersRouter) -app.use('/communityapi/api', deliusRouter) +app.use('/delius', deliusRouter) app.use('/probationteams', probationteamsRouter) app.get('/prisonApi/health/ping', (req, res) => { @@ -53,7 +53,7 @@ app.get('/probationteams/health/ping', (req, res) => { res.send({ status: 'UP' }) }) -app.get('/communityapi/health/ping', (req, res) => { +app.get('/delius/health/ping', (req, res) => { res.send('pong') }) diff --git a/mock-server/routes/delius.js b/mock-server/routes/delius.js index be3e782a2..256ff5bea 100644 --- a/mock-server/routes/delius.js +++ b/mock-server/routes/delius.js @@ -5,19 +5,17 @@ const teamC01T04 = { code: 'C01T04', description: 'OMU A', telephone: '01234567890', - localDeliveryUnit: { code: 'ABC124', description: 'ABC124 delivery unit' }, - district: { code: 'D', description: 'E' }, - borough: { code: 'F', description: 'G' }, + localAdminUnit: { code: 'ABC124', description: 'ABC124 delivery unit' }, } const deliusTeams = [teamC01T04] const AUTH_RO_USER_TEST = { username: 'AUTH_RO_USER_TEST', - staffCode: 'DELIUS_ID_TEST', - staffIdentifier: 1, + code: 'DELIUS_ID_TEST', + staffId: 1, email: 'hdc_test+RO_USER_TEST@digital.justice.gov.uk', - staff: { + name: { forenames: 'FIRSTA', surname: 'LASTA', }, @@ -26,10 +24,10 @@ const AUTH_RO_USER_TEST = { const RO_USER_TEST = { username: 'RO_USER_TEST', - staffCode: 'AUTH_DELIUS_ID_TEST', - staffIdentifier: 2, + code: 'AUTH_DELIUS_ID_TEST', + staffId: 2, email: 'hdc_test+RO_USER_TEST@digital.justice.gov.uk', - staff: { + name: { forenames: 'FIRSTA', surname: 'LASTA', }, @@ -38,10 +36,10 @@ const RO_USER_TEST = { const RO_USER = { username: 'RO_USER', - staffCode: 'DELIUS_ID', - staffIdentifier: 3, + code: 'DELIUS_ID', + staffId: 3, email: 'hdc_test+RO_USER@digital.justice.gov.uk', - staff: { + name: { forenames: 'JESSY', surname: 'SMITH', }, @@ -69,14 +67,22 @@ const staffDetailsByStaffIdentifier = { const router = express.Router() -router.get('/staff/username/:username', (req, res) => { - const { username } = req.params - const staffDetails = staffDetailsByUsername[username] - if (staffDetails) { - res.send(staffDetails) - } else { - res.sendStatus(404) +router.get('/staff', (req, res) => { + const { username, id } = req.query + if (username) { + const staffDetails = staffDetailsByUsername[username] + if (staffDetails) { + res.send(staffDetails) + return + } + } else if (id) { + const staffDetails = staffDetailsByStaffIdentifier[id] + if (staffDetails) { + res.send(staffDetails) + return + } } + res.sendStatus(404) }) /* @@ -112,55 +118,23 @@ router.get('/staff/staffCode/:staffCode/managedOffenders', (req, res) => { }) */ -router.get('/staff/staffIdentifier/:staffIdentifier', (req, res) => { - const { staffIdentifier } = req.params - const staffDetails = staffDetailsByStaffIdentifier[staffIdentifier] - if (staffDetails) { - res.send(staffDetails) - } else { - res.sendStatus(404) - } -}) - -router.get('/staff/staffIdentifier/:staffIdentifier/managedOffenders', (req, res) => { - const { staffIdentifier } = req.params - - const offenders = [ - { - staffIdentifier, - offenderId: 1234567, - nomsNumber: 'A5001DY', - crnNumber: 1234567, - offenderSurname: 'Andrews', - isCurrentRo: true, - isCurrentOm: true, - isCurrentPom: true, - omStartDate: '01/01/2001', - omEndDate: '01/01/2001', - }, - ] - - res.send(offenders) +router.get('/managedPrisonerIds', (req, res) => { + res.send(['A5001DY']) }) -router.get('/offenders/nomsNumber/:nomsNumber/allOffenderManagers', (req, res) => { - const ros = [ - { - isPrisonOffenderManager: false, - isUnallocated: false, - isResponsibleOfficer: true, - staff: { forenames: 'Ryan', surname: 'Orton' }, - staffCode: 'DELIUS_ID', - staffId: 2, - team: teamC01T04, - probationArea: { code: 'ABC', description: 'ABC probation area' }, - }, - ] - - res.send(ros) +router.get('/case/:nomsNumber/communityManager', (req, res) => { + res.send({ + code: 'DELIUS_ID', + staffId: 2, + name: { forenames: 'Ryan', surname: 'Orton' }, + team: teamC01T04, + provider: { code: 'ABC', description: 'ABC probation area' }, + localAdminUnit: { code: 'ABC124', description: 'ABC124 delivery unit' }, + isUnallocated: false, + }) }) -router.get('/probationAreas', (req, res) => { +router.get('/providers', (req, res) => { // return all probation areas const allProbationAreas = probationAreas.map((probArea) => ({ code: probArea.code, @@ -170,11 +144,15 @@ router.get('/probationAreas', (req, res) => { res.send(response) }) -router.get('/probationAreas/code/:code/localDeliveryUnits', (req, res) => { +router.get('/providers/:code', (req, res) => { // return the LDUs for a specific probation area const { code: probationAreaCode } = req.params const probationArea = probationAreas.filter((probArea) => probArea.code === probationAreaCode) - const response = { content: probationArea[0].ldus } + const response = { + code: probationArea[0].code, + description: probationArea[0].description, + localAdminUnits: probationArea[0].ldus, + } res.send(response) }) diff --git a/server/config.js b/server/config.js index e2a54d9be..087e59175 100644 --- a/server/config.js +++ b/server/config.js @@ -58,7 +58,7 @@ module.exports = { }, delius: { - apiUrl: get('DELIUS_API_URL', 'http://localhost:8080/communityapi'), + apiUrl: get('DELIUS_API_URL', 'http://localhost:8080/delius'), authUrl: get('DELIUS_AUTH_URL', get('NOMIS_AUTH_URL', 'http://localhost:9090/auth')), admin: { apiClientId: get('DELIUS_API_CLIENT_ID', get('ADMIN_API_CLIENT_ID', 'licencesadmin')), @@ -73,7 +73,6 @@ module.exports = { maxFreeSockets: 10, freeSocketTimeout: 30000, }, - apiPrefix: get('DELIUS_API_PREFIX', '/api'), // this refers to the 'HDC Digital Update' RBAC which is mapped to LICENCE_RO and GLOBAL_SEARCH in the auth server responsibleOfficerRoleId: get('DELIUS_RO_ROLE_ID', 'LHDCBT002'), // this refers to the 'HDC Digital Update' RBAC which is mapped to LICENCE_RO, GLOBAL_SEARCH and LICENCE_VARY in the auth server diff --git a/server/data/deliusClient.ts b/server/data/deliusClient.ts index 603e38389..7b7c14ab7 100644 --- a/server/data/deliusClient.ts +++ b/server/data/deliusClient.ts @@ -1,153 +1,106 @@ import config from '../config' -export interface KeyValue { - code: string - description: string -} - -export interface Human { - forenames: string - surname: string -} - -export interface Team { - code: string - description: string - telephone: string - localDeliveryUnit: KeyValue - district: KeyValue - borough: KeyValue -} - -export interface StaffDetails { - username?: string - email?: string - staffCode: string - staffIdentifier: number - staff: Human - teams: Team[] +export interface DeliusUser { + username: string + enabled: boolean + roles: string[] } -interface Institution { - institutionId: number - isEstablishment: boolean - code: string +export interface LocalAdminUnit { description: string - institutionName: string - establishmentType: KeyValue - isPrivate: boolean + teams: KeyValue[] } -interface AllTeam { - providerTeamId: number - teamId: number +export interface ProviderWithLaus { code: string description: string - name: string - isPrivate: boolean - externalProvider: KeyValue - scProvider: KeyValue - localDeliveryUnit: KeyValue - district: KeyValue - borough: KeyValue + localAdminUnits: KeyValue[] } -export interface ProbationArea { - probationAreaId: number +export interface CommunityManager { code: string - description: string - nps: boolean - organisation: KeyValue - institution: Institution - teams: AllTeam[] -} - -export interface CommunityOrPrisonOffenderManager { - staffCode: string + /** @deprecated use code instead */ staffId: number - isResponsibleOfficer: boolean - isPrisonOffenderManager: boolean + name: Name + team: KeyValue + provider: KeyValue + localAdminUnit: KeyValue isUnallocated: boolean - staff: Human - team: Team - probationArea: ProbationArea - fromDate: Date } -export interface ProbationAreaSummary { +export interface KeyValue { code: string description: string } -export interface Ldu { - code: string - description: string +export interface Name { + forenames: string + surname: string } -export interface ProbationTeam { +export interface Team { code: string description: string + telephone: string + probationDeliveryUnit: KeyValue + localAdminUnit: KeyValue } -export interface ManagedOffender { - staffCode: string - staffIdentifier: number - offenderId: number - nomsNumber: string - crnNumber: string - offenderSurname: string - isCurrentRo: boolean - isCurrentOm: boolean - isCurrentPom: boolean - omStartDate: Date - omEndDate: Date -} - -export interface Page { - content?: T[] +export interface StaffDetails { + code: string + /** @deprecated use code instead */ + staffId: number + name: Name + teams: Team[] + username?: string + email?: string } export class DeliusClient { constructor(readonly restClient) {} - getStaffDetailsByStaffCode(staffCode): Promise { - return this.restClient.getResource(`/staff/staffCode/${staffCode}`) + getStaffDetailsByStaffCode(staffCode: string): Promise { + return this.restClient.getResource(`/staff/${staffCode}`) } + /** @deprecated use getStaffDetailsByStaffCode instead */ getStaffDetailsByStaffIdentifier(staffIdentifier: number): Promise { - return this.restClient.getResource(`/staff/staffIdentifier/${staffIdentifier}`) + return this.restClient.getResource(`/staff?id=${staffIdentifier}`) } getStaffDetailsByUsername(username: string): Promise { - return this.restClient.getResource(`/staff/username/${username}`) + return this.restClient.getResource(`/staff?username=${username}`) + } + + getManagedPrisonerIdsByStaffCode(staffCode: string): Promise { + return this.restClient.getResource(`/staff/${staffCode}/managedPrisonerIds`) } - getROPrisonersByStaffIdentifier(staffIdentifier: number): Promise> { - return this.restClient.getResource(`/staff/staffIdentifier/${staffIdentifier}/managedOffenders`) + /** @deprecated use getStaffDetailsByStaffCode instead */ + getManagedPrisonerIdsByStaffId(staffIdentifier: number): Promise { + return this.restClient.getResource(`/managedPrisonerIds?staffId=${staffIdentifier}`) } - getAllOffenderManagers(offenderNo: string): Promise> { - return this.restClient.getResource(`/offenders/nomsNumber/${offenderNo}/allOffenderManagers`) + getCommunityManager(offenderNo: string): Promise { + return this.restClient.getResource(`/case/${offenderNo}/communityManager`) } - getAllProbationAreas(): Promise> { - return this.restClient.getResource(`/probationAreas?excludeEstablishments=true&active=true`) + getAllProbationAreas(): Promise { + return this.restClient.getResource(`/providers`) } - async getAllLdusForProbationArea(probationAreaCode: string): Promise> { - const ldus = await this.restClient.getResource(`/probationAreas/code/${probationAreaCode}/localDeliveryUnits`) - return ldus?.content ? ldus : { content: [] } + async getProbationArea(probationAreaCode: string): Promise { + return (await this.restClient.getResource(`/providers/${probationAreaCode}`)) ?? { localAdminUnits: [] } } - async getAllTeamsForLdu(probationAreaCode: string, lduCode: string): Promise> { - const teams = await this.restClient.getResource( - `/probationAreas/code/${probationAreaCode}/localDeliveryUnits/code/${lduCode}/teams` + async getLduWithTeams(probationAreaCode: string, lauCode: string): Promise { + return ( + (await this.restClient.getResource(`/providers/${probationAreaCode}/localAdminUnits/${lauCode}`)) ?? { teams: [] } ) - return teams?.content ? teams : { content: [] } } - async addResponsibleOfficerRole(username: string): Promise { - await this.addRole(username, config.delius.responsibleOfficerRoleId) + addResponsibleOfficerRole(username: string): Promise { + return this.addRole(username, config.delius.responsibleOfficerRoleId) } async addRole(username: string, code: string): Promise { @@ -158,7 +111,7 @@ export class DeliusClient { } } - async getUser(username: string): Promise { + getUser(username: string): Promise { return this.restClient.getResource(`/users/${username}/details`) } } diff --git a/server/index.js b/server/index.js index 7aafa24a6..1f023a68e 100644 --- a/server/index.js +++ b/server/index.js @@ -62,8 +62,8 @@ const conditionsServiceFactory = new ConditionServiceFactory() const deliusClient = new DeliusClient( buildRestClient( clientCredentialsTokenSource(signInService, 'delius'), - `${config.delius.apiUrl}${config.delius.apiPrefix}`, - 'Delius community API', + config.delius.apiUrl, + 'Delius Integration API', { timeout: config.delius.timeout, agent: config.delius.agent } ) ) diff --git a/server/services/caseListService.ts b/server/services/caseListService.ts index 2aa51dd81..082edf85a 100644 --- a/server/services/caseListService.ts +++ b/server/services/caseListService.ts @@ -54,10 +54,10 @@ export = function createCaseListService( const getIdsFromDelius = async (username: string): Promise> => { const staffDetailsResult = await getStaffDetailsFromDelius(username) - return staffDetailsResult.flatMap(({ staffIdentifier }) => - isEmpty(staffIdentifier) + return staffDetailsResult.flatMap(({ staffId }) => + isEmpty(staffId) ? Fail(`Delius did not supply a staff identifier for username ${username}`) - : Success({ staffIdentifier }) + : Success({ staffIdentifier: staffId }) ) } diff --git a/server/services/functionalMailboxService.ts b/server/services/functionalMailboxService.ts index f2616d4ba..cbeae2bd7 100644 --- a/server/services/functionalMailboxService.ts +++ b/server/services/functionalMailboxService.ts @@ -1,12 +1,12 @@ import * as R from 'ramda' import { - LocalDeliveryUnitDto, - ProbationTeamsClient, LduIdentifier, + LocalDeliveryUnitDto, ProbationTeamIdentifier, + ProbationTeamsClient, } from '../data/probationTeamsClient' -import { DeliusClient, Ldu, ProbationArea, ProbationTeam } from '../data/deliusClient' +import { DeliusClient, KeyValue } from '../data/deliusClient' export interface LduMap { [code: string]: { @@ -33,7 +33,7 @@ export interface ProbationTeamMap { } export const mergeLduData = ( - ldus: Ldu[], + ldus: KeyValue[], lduDtos: { [localDeliveryUnitCode: string]: LocalDeliveryUnitDto } ): LduMap => { const lduMap = ldus.reduce((map, { code, description }) => ({ ...map, [code]: { description } }), {}) @@ -44,7 +44,7 @@ export const mergeLduData = ( return R.mergeDeepRight(lduMap, filteredDtos) } -export const mergeProbationTeams = (probationTeams: ProbationTeam[], localDeliveryUnitDto: LocalDeliveryUnitDto) => { +export const mergeProbationTeams = (probationTeams: KeyValue[], localDeliveryUnitDto: LocalDeliveryUnitDto) => { const probationTeamMap = probationTeams.reduce( (map, { code, description }) => ({ ...map, [code]: { description } }), {} @@ -53,7 +53,7 @@ export const mergeProbationTeams = (probationTeams: ProbationTeam[], localDelive return R.mergeDeepRight(probationTeamMap, probationTeamDtoMap) } -export function mergeProbationAreaData(probationAreas: ProbationArea[], probationAreaCodes: string[]) { +export function mergeProbationAreaData(probationAreas: KeyValue[], probationAreaCodes: string[]) { const probationCodeMap = probationAreaCodes.reduce((map, code) => ({ ...map, [code]: {} }), {}) const probationAreaMap = probationAreas.reduce( (map, { code, description }) => ({ ...map, [code]: { description } }), @@ -78,7 +78,7 @@ export class FunctionalMailboxService { ) {} getAllProbationAreas = async () => { - const [{ content: probationAreas } = { content: [] }, probationAreaCodes = []] = await Promise.all([ + const [probationAreas = [], probationAreaCodes = []] = await Promise.all([ this.deliusClient.getAllProbationAreas(), this.probationTeamsClient.getProbationAreaCodes(), ]) @@ -86,8 +86,8 @@ export class FunctionalMailboxService { } getLdusForProbationArea = async (probationAreaCode): Promise => { - const [{ content: ldus }, { localDeliveryUnits = {} } = {}] = await Promise.all([ - this.deliusClient.getAllLdusForProbationArea(probationAreaCode), + const [{ localAdminUnits: ldus }, { localDeliveryUnits = {} } = {}] = await Promise.all([ + this.deliusClient.getProbationArea(probationAreaCode), this.probationTeamsClient.getProbationArea(probationAreaCode), ]) @@ -95,16 +95,15 @@ export class FunctionalMailboxService { } getLduWithProbationTeams = async ({ probationAreaCode, lduCode }): Promise => { - const [{ content: ldus }, { content: probationTeams }, localDeliveryUnitDto] = await Promise.all([ - this.deliusClient.getAllLdusForProbationArea(probationAreaCode), - this.deliusClient.getAllTeamsForLdu(probationAreaCode, lduCode), + const [ldu, localDeliveryUnitDto] = await Promise.all([ + this.deliusClient.getLduWithTeams(probationAreaCode, lduCode), this.probationTeamsClient.getLduWithProbationTeams({ probationAreaCode, lduCode }), ]) return { - description: getDescription(ldus, lduCode), + description: ldu.description ?? '', functionalMailbox: R.propOr('', 'functionalMailbox', localDeliveryUnitDto), - probationTeams: mergeProbationTeams(probationTeams, localDeliveryUnitDto), + probationTeams: mergeProbationTeams(ldu.teams, localDeliveryUnitDto), } } diff --git a/server/services/lduService.js b/server/services/lduService.js index 9c76481ac..77c078733 100644 --- a/server/services/lduService.js +++ b/server/services/lduService.js @@ -15,19 +15,16 @@ const logger = require('../../log') module.exports = function createLduService(deliusClient, activeLduClient) { return { async getAllProbationAreas() { - const { content: probationAreas } = await deliusClient.getAllProbationAreas() + const probationAreas = await deliusClient.getAllProbationAreas() probationAreas.sort((a, b) => a.description.localeCompare(b.description, 'en', { ignorePunctuation: true })) return probationAreas }, async getProbationArea(probationAreaCode) { - const { content: probationAreas } = await deliusClient.getAllProbationAreas() - const probationAreaDescription = probationAreas.find((area) => probationAreaCode === area.code).description - const activeLdus = await activeLduClient.allActiveLdusInArea(probationAreaCode) const activeLdusCodes = activeLdus.map((ldu) => ldu.code) - const { content: ldus } = await deliusClient.getAllLdusForProbationArea(probationAreaCode) + const { description, localAdminUnits: ldus } = await deliusClient.getProbationArea(probationAreaCode) const allLdus = ldus.map((ldu) => ({ code: ldu.code, @@ -41,7 +38,7 @@ module.exports = function createLduService(deliusClient, activeLduClient) { return { code: probationAreaCode, - description: probationAreaDescription, + description, ldus: uniqueLdus, } }, diff --git a/server/services/migrationService.ts b/server/services/migrationService.ts index 8dee44ea2..8ffbc2f6b 100644 --- a/server/services/migrationService.ts +++ b/server/services/migrationService.ts @@ -1,4 +1,4 @@ -import { DeliusClient } from '../data/deliusClient' +import { DeliusClient, DeliusUser, StaffDetails } from '../data/deliusClient' import UserAdminService from './userAdminService' import logger from '../../log' import config from '../config' @@ -66,7 +66,7 @@ export default class MigrationService { return { licenceUser, deliusUser: deliusStaffDetails, authUser, flags } } - private async getDeliusStaffDetails(licenceUser) { + private async getDeliusStaffDetails(licenceUser): Promise { const { staffIdentifier, deliusId } = licenceUser if (staffIdentifier) try { @@ -86,9 +86,9 @@ export default class MigrationService { return null } - private getFlags(deliusUser, authUser, licenceUser, deliusStaffDetails, failedToLoadAuth: boolean) { + private getFlags(deliusUser: DeliusUser, authUser, licenceUser, deliusStaffDetails, failedToLoadAuth: boolean) { const deliusRoles = deliusUser ? deliusUser.roles : [] - const hasRoRole = deliusRoles.map((r) => r.name).includes(config.delius.responsibleOfficerRoleId) + const hasRoRole = deliusRoles.includes(config.delius.responsibleOfficerRoleId) const hasVaryRole = authUser?.roles.includes('LICENCE_VARY') @@ -121,15 +121,12 @@ export default class MigrationService { await this.deliusClient.addRole(deliusUsername, role) } - public async getDeliusRoles(deliusUsername): Promise { + public async getDeliusRoles(deliusUsername: string): Promise { const user = await this.getUserFromDelius(deliusUsername) if (!user) { return null } - const deliusRoles = user.roles || [] - return deliusRoles - .map((r) => r.name) - .filter((r) => [config.delius.responsibleOfficerRoleId, config.delius.responsibleOfficerVaryRoleId].includes(r)) + return user.roles || [] } public async disableAuthAccount(token, nomisUsername) { @@ -151,10 +148,9 @@ export default class MigrationService { } } - private async getUserFromDelius(username) { + private async getUserFromDelius(username: string): Promise { try { - const result = await this.deliusClient.getUser(username) - return result + return await this.deliusClient.getUser(username) } catch (error) { logger.warn(`Problem retrieving user from delius for username: ${username}`, error.stack) return null diff --git a/server/services/roService.ts b/server/services/roService.ts index 3821a2f40..7d05d8be3 100644 --- a/server/services/roService.ts +++ b/server/services/roService.ts @@ -1,4 +1,4 @@ -import { CommunityOrPrisonOffenderManager, DeliusClient, StaffDetails } from '../data/deliusClient' +import { CommunityManager, DeliusClient, StaffDetails } from '../data/deliusClient' import { ResponsibleOfficer, ResponsibleOfficerResult, Result } from '../../types/licences' const setCase = require('case') @@ -12,9 +12,9 @@ export class RoService { readonly nomisClientBuilder ) {} - private async getROPrisonersFromDeliusForStaffIdentifier(staffIdentifier: number): Promise> { + private async getROPrisonersFromDeliusForStaffIdentifier(staffIdentifier: number): Promise { try { - return await this.deliusClient.getROPrisonersByStaffIdentifier(staffIdentifier) + return await this.deliusClient.getManagedPrisonerIdsByStaffId(staffIdentifier) } catch (error) { logger.error(`Problem retrieving RO prisoners for: ${staffIdentifier}`, error.stack) throw error @@ -42,14 +42,10 @@ export class RoService { async getROPrisonersForStaffIdentifier(staffIdentifier: number, token: string) { const nomisClient = this.nomisClientBuilder(token) - const requiredPrisoners = await this.getROPrisonersFromDeliusForStaffIdentifier(staffIdentifier) - if (!requiredPrisoners) { + const requiredIDs = await this.getROPrisonersFromDeliusForStaffIdentifier(staffIdentifier) + if (!requiredIDs) { return null } - - const requiredIDs = requiredPrisoners - .filter((prisoner) => prisoner.nomsNumber) - .map((prisoner) => prisoner.nomsNumber) return nomisClient.getOffenderSentencesByNomisId(requiredIDs) } @@ -63,12 +59,12 @@ export class RoService { logger.info(`findResponsibleOfficerWithOffenderNo: ${offenderNo}`) try { - const offenderManagers = await this.deliusClient.getAllOffenderManagers(offenderNo) - if (!offenderManagers) { + const communityManager = await this.deliusClient.getCommunityManager(offenderNo) + if (!communityManager) { logger.error(`Offender not present in delius: ${offenderNo}`) return { code: NO_OFFENDER_NUMBER, message: 'Offender number not entered in delius' } } - return extractCommunityOffenderManager(offenderNo, offenderManagers) + return toResponsibleOfficer(offenderNo, communityManager) } catch (error) { logger.error(`findResponsibleOfficer for: ${offenderNo}`, error.stack) throw error @@ -76,37 +72,25 @@ export class RoService { } } -function extractCommunityOffenderManager( - offenderNumber: string, - offenderManagers: CommunityOrPrisonOffenderManager[] -): ResponsibleOfficerResult { - const responsibleOfficer = offenderManagers.find((manager) => !manager.isPrisonOffenderManager) - return !responsibleOfficer - ? { code: NO_COM_ASSIGNED, message: `Offender has not been assigned a COM: ${offenderNumber}` } - : toResponsibleOfficer(offenderNumber, responsibleOfficer) -} - -function toResponsibleOfficer( - offenderNumber: string, - offenderManager: CommunityOrPrisonOffenderManager -): ResponsibleOfficer { +function toResponsibleOfficer(offenderNumber: string, offenderManager: CommunityManager): ResponsibleOfficer { const { - staff: { forenames, surname }, - staffCode, + name: { forenames, surname }, + code, staffId, isUnallocated, - team: { localDeliveryUnit, code, description }, - probationArea, + team, + localAdminUnit: localDeliveryUnit, + provider: probationArea, } = offenderManager const name = setCase.capital([forenames, surname].join(' ').trim().toLowerCase()) return { name, isAllocated: !isUnallocated, - deliusId: staffCode, + deliusId: code, staffIdentifier: staffId, nomsNumber: offenderNumber, - teamCode: code, - teamDescription: description, + teamCode: team.code, + teamDescription: team.description, lduCode: localDeliveryUnit.code, lduDescription: localDeliveryUnit.description, probationAreaCode: probationArea.code, diff --git a/server/views/admin/users/migrate.pug b/server/views/admin/users/migrate.pug index 390c51e79..6ce7dee69 100644 --- a/server/views/admin/users/migrate.pug +++ b/server/views/admin/users/migrate.pug @@ -41,13 +41,13 @@ block content h3.heading-medium Delius record if deliusUser div.pure-u-1-3 Name - div.pure-u-2-3.bold #{deliusUser.staff.forenames} #{deliusUser.staff.surname} + div.pure-u-2-3.bold #{deliusUser.name.forenames} #{deliusUser.name.surname} div.pure-u-1-3 Delius staff code - div.pure-u-2-3.bold #{deliusUser.staffCode} + div.pure-u-2-3.bold #{deliusUser.code} div.pure-u-1-3 Delius staff identifier - div.pure-u-2-3.bold #{deliusUser.staffIdentifier} + div.pure-u-2-3.bold #{deliusUser.staffId} if !flags.includes('UNLINKED_ACCOUNT') div.pure-u-1-3 Delius username diff --git a/test/data/deliusClient.test.js b/test/data/deliusClient.test.js index 176134136..df586bc84 100644 --- a/test/data/deliusClient.test.js +++ b/test/data/deliusClient.test.js @@ -13,13 +13,13 @@ describe('deliusClient', () => { let signInService beforeEach(() => { - fakeDelius = nock(`${config.delius.apiUrl}${config.delius.apiPrefix}`) + fakeDelius = nock(config.delius.apiUrl) signInService = new SignInService(null) signInService.getAnonymousClientCredentialsTokens = jest.fn().mockResolvedValue('token') const restClient = buildRestClient( clientCredentialsTokenSource(signInService, 'delius'), - `${config.delius.apiUrl}${config.delius.apiPrefix}`, - 'Delius community API', + config.delius.apiUrl, + 'Delius Integration API', { timeout: config.delius.timeout, agent: config.delius.agent } ) deliusClient = new DeliusClient(restClient) @@ -32,19 +32,19 @@ describe('deliusClient', () => { describe('deliusClient', () => { test('should throw error on GET when no token', () => { signInService.getAnonymousClientCredentialsTokens.mockReturnValue(null) - return expect(deliusClient.getROPrisonersByStaffIdentifier(1)).rejects.toThrow('Error obtaining OAuth token') + return expect(deliusClient.getManagedPrisonerIdsByStaffId(1)).rejects.toThrow('Error obtaining OAuth token') }) }) describe('getStaffBystaffIdentifier', () => { test('should return data from api', () => { - fakeDelius.get(`/staff/staffIdentifier/1`).reply(200, { key: 'value' }) + fakeDelius.get(`/staff?id=1`).reply(200, { key: 'value' }) return expect(deliusClient.getStaffDetailsByStaffIdentifier(1)).resolves.toStrictEqual({ key: 'value' }) }) test('should reject if api fails', () => { - fakeDelius.get(`/staff/staffIdentifier/1`).thrice().reply(500, '1') + fakeDelius.get(`/staff?id=1`).thrice().reply(500, '1') return expect(deliusClient.getStaffDetailsByStaffIdentifier(1)).rejects.toStrictEqual( Error('Internal Server Error') @@ -54,13 +54,13 @@ describe('deliusClient', () => { describe('getStaffByUsername', () => { test('should return data from api', () => { - fakeDelius.get(`/staff/username/1`).reply(200, { key: 'value' }) + fakeDelius.get(`/staff?username=1`).reply(200, { key: 'value' }) return expect(deliusClient.getStaffDetailsByUsername('1')).resolves.toStrictEqual({ key: 'value' }) }) test('should reject if api fails', () => { - fakeDelius.get(`/staff/username/1`).thrice().reply(500) + fakeDelius.get(`/staff?username=1`).thrice().reply(500) return expect(deliusClient.getStaffDetailsByUsername('1')).rejects.toStrictEqual(Error('Internal Server Error')) }) @@ -68,15 +68,15 @@ describe('deliusClient', () => { describe('getROPrisoners', () => { test('should return data from api', () => { - fakeDelius.get(`/staff/staffIdentifier/1/managedOffenders`).reply(200, { key: 'value' }) + fakeDelius.get(`/managedPrisonerIds?staffId=1`).reply(200, { key: 'value' }) - return expect(deliusClient.getROPrisonersByStaffIdentifier(1)).resolves.toStrictEqual({ key: 'value' }) + return expect(deliusClient.getManagedPrisonerIdsByStaffId(1)).resolves.toStrictEqual({ key: 'value' }) }) test('should reject if api fails', () => { - fakeDelius.get(`/staff/staffIdentifier/1/managedOffenders`).thrice().reply(500) + fakeDelius.get(`/managedPrisonerIds?staffId=1`).thrice().reply(500) - return expect(deliusClient.getROPrisonersByStaffIdentifier(1)).rejects.toStrictEqual( + return expect(deliusClient.getManagedPrisonerIdsByStaffId(1)).rejects.toStrictEqual( Error('Internal Server Error') ) }) @@ -84,29 +84,27 @@ describe('deliusClient', () => { describe('getAllOffenderManagers', () => { test('should return data from api', () => { - fakeDelius.get(`/offenders/nomsNumber/1/allOffenderManagers`).reply(200, [{ key: 'value' }]) + fakeDelius.get(`/case/1/communityManager`).reply(200, [{ key: 'value' }]) - return expect(deliusClient.getAllOffenderManagers('1')).resolves.toStrictEqual([{ key: 'value' }]) + return expect(deliusClient.getCommunityManager('1')).resolves.toStrictEqual([{ key: 'value' }]) }) test('should return undefined when not found', () => { - fakeDelius.get(`/offenders/nomsNumber/1/allOffenderManagers`).reply(404) + fakeDelius.get(`/case/1/communityManager`).reply(404) - return expect(deliusClient.getAllOffenderManagers('1')).resolves.toBeUndefined() + return expect(deliusClient.getCommunityManager('1')).resolves.toBeUndefined() }) test('should reject if api fails', () => { - fakeDelius.get(`/offenders/nomsNumber/1/allOffenderManagers`).thrice().reply(500) + fakeDelius.get(`/case/1/communityManager`).thrice().reply(500) - return expect(deliusClient.getAllOffenderManagers('1')).rejects.toStrictEqual(Error('Internal Server Error')) + return expect(deliusClient.getCommunityManager('1')).rejects.toStrictEqual(Error('Internal Server Error')) }) }) describe('getAllProbationAreas', () => { test('should return list of all probation areas', () => { - fakeDelius - .get(`/probationAreas?excludeEstablishments=true&active=true`) - .reply(200, [{ code: 'some code', description: 'some description' }]) + fakeDelius.get(`/providers`).reply(200, [{ code: 'some code', description: 'some description' }]) return expect(deliusClient.getAllProbationAreas()).resolves.toStrictEqual([ { code: 'some code', description: 'some description' }, @@ -116,58 +114,35 @@ describe('deliusClient', () => { describe('getAllLdusForProbationArea', () => { test('should return list of all probation codes', () => { - fakeDelius - .get(`/probationAreas/code/N02/localDeliveryUnits`) - .reply(200, { content: [{ code: 'some code', description: 'some description' }] }) + fakeDelius.get(`/providers/N02`).reply(200, { content: [{ code: 'some code', description: 'some description' }] }) - return expect(deliusClient.getAllLdusForProbationArea('N02')).resolves.toStrictEqual({ + return expect(deliusClient.getProbationArea('N02')).resolves.toStrictEqual({ content: [{ code: 'some code', description: 'some description' }], }) }) test('Probation code not known to Delius', () => { - fakeDelius.get(`/probationAreas/code/N02/localDeliveryUnits`).reply(404) + fakeDelius.get(`/providers/N02`).reply(404) - return expect(deliusClient.getAllLdusForProbationArea('N02')).resolves.toStrictEqual({ content: [] }) + return expect(deliusClient.getProbationArea('N02')).resolves.toStrictEqual({ localAdminUnits: [] }) }) }) describe('getAllTeamsForLdu', () => { test('should return list of all probation codes', () => { fakeDelius - .get('/probationAreas/code/N02/localDeliveryUnits/code/LDU/teams') - .reply(200, { content: [{ code: 'some code', description: 'some description' }] }) + .get('/providers/N02/localAdminUnits/LDU') + .reply(200, { localAdminUnits: [{ code: 'some code', description: 'some description' }] }) - return expect(deliusClient.getAllTeamsForLdu('N02', 'LDU')).resolves.toStrictEqual({ - content: [{ code: 'some code', description: 'some description' }], + return expect(deliusClient.getLduWithTeams('N02', 'LDU')).resolves.toStrictEqual({ + localAdminUnits: [{ code: 'some code', description: 'some description' }], }) }) - test('LDU not known to Delius: 200, but no "content" field', () => { - fakeDelius.get('/probationAreas/code/N02/localDeliveryUnits/code/LDU/teams').reply(200, { - pageable: 'INSTANCE', - totalElements: 0, - last: true, - totalPages: 1, - sort: { - sorted: false, - unsorted: true, - empty: true, - }, - first: true, - number: 0, - size: 0, - numberOfElements: 0, - empty: true, - }) - - return expect(deliusClient.getAllTeamsForLdu('N02', 'LDU')).resolves.toStrictEqual({ content: [] }) - }) - test('LDU not known to Delius: 404', () => { - fakeDelius.get('/probationAreas/code/N02/localDeliveryUnits/code/LDU/teams').reply(404) + fakeDelius.get('/providers/N02/localAdminUnits/LDU').reply(404) - return expect(deliusClient.getAllTeamsForLdu('N02', 'LDU')).resolves.toStrictEqual({ content: [] }) + return expect(deliusClient.getLduWithTeams('N02', 'LDU')).resolves.toStrictEqual({ teams: [] }) }) }) diff --git a/test/routes/contact.test.ts b/test/routes/contact.test.ts index b46949f70..930531c61 100644 --- a/test/routes/contact.test.ts +++ b/test/routes/contact.test.ts @@ -34,17 +34,16 @@ describe('/contact', () => { roService.getStaffByStaffIdentifier.mockResolvedValue({ username: 'username', email: '123456@somewhere.com', - staffCode: 'DELIUS_ID', - staffIdentifier: 999, - staff: { forenames: 'RO', surname: 'Name' }, + code: 'DELIUS_ID', + staffId: 999, + name: { forenames: 'RO', surname: 'Name' }, teams: [ { code: 'TEAM_CODE', description: 'The Team', telephone: '01234567890', - localDeliveryUnit: { code: 'ABC123', description: 'LDU Description' }, - district: { code: 'D', description: 'District' }, - borough: { code: 'B', description: 'Borough' }, + probationDeliveryUnit: { code: 'ABC123', description: 'PDU Description' }, + localAdminUnit: { code: 'ABC123', description: 'LDU Description' }, }, ], }) diff --git a/test/services/caseListService.test.ts b/test/services/caseListService.test.ts index 190f80f26..0227c8938 100644 --- a/test/services/caseListService.test.ts +++ b/test/services/caseListService.test.ts @@ -80,14 +80,14 @@ describe('caseListService', () => { const staffDetailsNoStaffIdentifier = { username: 'username', email: 'email', - staffCode: 'ABC123', - staff: { forenames: 'user', surname: 'name' }, + code: 'ABC123', + name: { forenames: 'user', surname: 'name' }, teams: [], } as StaffDetails const staffDetails: StaffDetails = { ...staffDetailsNoStaffIdentifier, - staffIdentifier: 2, + staffId: 2, } const deliusId1: DeliusIds = { staffIdentifier: 1, deliusUsername: 'deliusUser' } diff --git a/test/services/functionalMailboxService.test.ts b/test/services/functionalMailboxService.test.ts index 51222e4cc..9950b3cec 100644 --- a/test/services/functionalMailboxService.test.ts +++ b/test/services/functionalMailboxService.test.ts @@ -7,28 +7,15 @@ import { import { AuditMock, mockAudit } from '../mockClients' import { ProbationTeamsClient } from '../../server/data/probationTeamsClient' -import { DeliusClient } from '../../server/data/deliusClient' -import type { ProbationArea } from '../../server/data/deliusClient' +import { DeliusClient, LocalAdminUnit, ProviderWithLaus } from '../../server/data/deliusClient' jest.mock('../../server/data/deliusClient') jest.mock('../../server/data/probationTeamsClient') -const BASE_PROBATION_AREA: ProbationArea = Object.freeze({ +const BASE_PROBATION_AREA: ProviderWithLaus = Object.freeze({ code: '', description: '', - probationAreaId: 1, - nps: false, - institution: Object.freeze({ - institutionId: 1, - isEstablishment: false, - code: 'I1', - description: 'I1', - institutionName: 'I1', - establishmentType: { code: 'I1', description: 'I1' }, - isPrivate: false, - }), - organisation: { code: 'org', description: 'org' }, - teams: [], + localAdminUnits: [], }) describe('FunctionalMailboxService', () => { @@ -96,13 +83,11 @@ describe('FunctionalMailboxService', () => { ...BASE_PROBATION_AREA, code: 'A', description: 'PA A', - probationAreaId: 1, }, { ...BASE_PROBATION_AREA, code: 'B', description: 'PA B', - probationAreaId: 2, }, ], ['B', 'C'] @@ -142,12 +127,10 @@ describe('FunctionalMailboxService', () => { beforeEach(initMocks) it('Happy path', async () => { - deliusClient.getAllProbationAreas.mockResolvedValue({ - content: [ - { ...BASE_PROBATION_AREA, code: 'A', description: 'PA A' }, - { ...BASE_PROBATION_AREA, code: 'B', description: 'PA B' }, - ], - }) + deliusClient.getAllProbationAreas.mockResolvedValue([ + { ...BASE_PROBATION_AREA, code: 'A', description: 'PA A' }, + { ...BASE_PROBATION_AREA, code: 'B', description: 'PA B' }, + ]) probationTeamsClient.getProbationAreaCodes.mockResolvedValue(['B', 'C']) expect(await functionalMailboxService.getAllProbationAreas()).toEqual({ @@ -173,8 +156,10 @@ describe('FunctionalMailboxService', () => { beforeEach(initMocks) it('Happy path', async () => { - deliusClient.getAllLdusForProbationArea.mockResolvedValue({ - content: [{ code: 'B', description: 'LDU B' }], + deliusClient.getProbationArea.mockResolvedValue({ + code: 'PA', + description: 'PA 1', + localAdminUnits: [{ code: 'B', description: 'LDU B' }], }) probationTeamsClient.getProbationArea.mockResolvedValue({ probationAreaCode: 'PA', @@ -197,7 +182,7 @@ describe('FunctionalMailboxService', () => { }) it('Handles missing data', async () => { - deliusClient.getAllLdusForProbationArea.mockResolvedValue({ content: [] }) + deliusClient.getProbationArea.mockResolvedValue({ localAdminUnits: [] } as ProviderWithLaus) probationTeamsClient.getProbationArea.mockResolvedValue(undefined) expect(await functionalMailboxService.getLdusForProbationArea('PA')).toEqual({}) @@ -208,20 +193,14 @@ describe('FunctionalMailboxService', () => { beforeEach(initMocks) it('Happy path', async () => { - deliusClient.getAllLdusForProbationArea.mockResolvedValue({ - content: [ - { code: 'A', description: 'LDU A' }, - { code: 'B', description: 'LDU B' }, - { code: 'C', description: 'LDU C' }, - ], - }) - - deliusClient.getAllTeamsForLdu.mockResolvedValue({ - content: [ + deliusClient.getLduWithTeams.mockResolvedValue({ + code: 'B', + description: 'LDU B', + teams: [ { code: 'TA', description: 'Team A' }, { code: 'TB', description: 'Team B' }, ], - }) + } as LocalAdminUnit) probationTeamsClient.getLduWithProbationTeams.mockResolvedValue({ probationAreaCode: 'PA', @@ -257,8 +236,8 @@ describe('FunctionalMailboxService', () => { }) it('No data', async () => { - deliusClient.getAllLdusForProbationArea.mockResolvedValue({ content: [] }) - deliusClient.getAllTeamsForLdu.mockResolvedValue({ content: [] }) + deliusClient.getProbationArea.mockResolvedValue({ localAdminUnits: [] } as ProviderWithLaus) + deliusClient.getLduWithTeams.mockResolvedValue({ teams: [] } as LocalAdminUnit) probationTeamsClient.getLduWithProbationTeams.mockResolvedValue(undefined) expect( @@ -274,8 +253,8 @@ describe('FunctionalMailboxService', () => { }) it('Not found', async () => { - deliusClient.getAllLdusForProbationArea.mockResolvedValue({ content: [] }) - deliusClient.getAllTeamsForLdu.mockResolvedValue({ content: [] }) + deliusClient.getProbationArea.mockResolvedValue({ localAdminUnits: [] } as ProviderWithLaus) + deliusClient.getLduWithTeams.mockResolvedValue({ teams: [] } as LocalAdminUnit) probationTeamsClient.getLduWithProbationTeams.mockResolvedValue(undefined) expect( diff --git a/test/services/lduService.test.js b/test/services/lduService.test.js index faf9a5371..89417131d 100644 --- a/test/services/lduService.test.js +++ b/test/services/lduService.test.js @@ -1,7 +1,7 @@ const createLduService = require('../../server/services/lduService') /** @type {any} */ const deliusClient = { - getAllLdusForProbationArea: jest.fn(), + getProbationArea: jest.fn(), getAllProbationAreas: jest.fn(), } const activeLduClient = { @@ -17,12 +17,10 @@ let lduService describe('lduService', () => { beforeEach(async () => { lduService = await createLduService(deliusClient, activeLduClient) - deliusClient.getAllProbationAreas.mockResolvedValue({ - content: [ - { code: 'ABC123', description: 'desc-1' }, - { code: 'DEF345', description: 'desc-2' }, - ], - }) + deliusClient.getAllProbationAreas.mockResolvedValue([ + { code: 'ABC123', description: 'desc-1' }, + { code: 'DEF345', description: 'desc-2' }, + ]) }) afterEach(() => { @@ -49,10 +47,12 @@ describe('lduService', () => { }) describe('getProbationArea', () => { - it(`Should return all the LDUs from Delius for London and cross match with those in active_local_delivery_units table in DB. + it(`Should return all the LDUs from Delius for London and cross match with those in active_local_delivery_units table in DB. Those that cross-matchs will have a 'active = true' status`, async () => { - deliusClient.getAllLdusForProbationArea.mockResolvedValue({ - content: [ + deliusClient.getProbationArea.mockResolvedValue({ + code: 'Lon', + description: 'London', + localAdminUnits: [ { code: 'ham', description: 'Hampstead' }, { code: 'wtl', description: 'Waterloo' }, { code: 'pic', description: 'Picadilly' }, @@ -76,8 +76,10 @@ describe('lduService', () => { }) it('Should remove duplicate ldus and only show the first description', async () => { - deliusClient.getAllLdusForProbationArea.mockResolvedValue({ - content: [ + deliusClient.getProbationArea.mockResolvedValue({ + code: 'Lon', + description: 'London', + localAdminUnits: [ { code: 'ham', description: 'Hampstead' }, { code: 'pic', description: 'Picadilly' }, { code: 'ham', description: 'Hampstead2' }, diff --git a/test/services/migrationService.test.ts b/test/services/migrationService.test.ts index e42062d68..b49728c12 100644 --- a/test/services/migrationService.test.ts +++ b/test/services/migrationService.test.ts @@ -1,6 +1,6 @@ import MigrationService, { Flag } from '../../server/services/migrationService' import { delius } from '../../server/config' -import { DeliusClient, StaffDetails } from '../../server/data/deliusClient' +import { DeliusClient, DeliusUser, StaffDetails } from '../../server/data/deliusClient' jest.mock('../../server/data/deliusClient') @@ -65,19 +65,6 @@ describe('MigrationService', () => { }) describe('getDeliusRoles', () => { - test('get roles filters out non HDC roles', async () => { - deliusClient.getUser.mockResolvedValue({ - roles: [ - { name: delius.responsibleOfficerRoleId }, - { name: delius.responsibleOfficerVaryRoleId }, - { name: 'other-role' }, - ], - }) - - const result = await migrationService.getDeliusRoles('user-1') - - expect(result).toStrictEqual([delius.responsibleOfficerRoleId, delius.responsibleOfficerVaryRoleId]) - }) test('get roles when missing user', async () => { deliusClient.getUser.mockResolvedValue(null) @@ -98,9 +85,9 @@ describe('MigrationService', () => { email: 'user@gov.uk', } as StaffDetails) deliusClient.getUser.mockResolvedValue({ - roles: [{ name: delius.responsibleOfficerRoleId }], + roles: [delius.responsibleOfficerRoleId], enabled: true, - }) + } as DeliusUser) const result = await migrationService.getStaffDetails('token', 'user-1') @@ -133,9 +120,9 @@ describe('MigrationService', () => { email: 'user@gov.uk', } as StaffDetails) deliusClient.getUser.mockResolvedValue({ - roles: [{ name: delius.responsibleOfficerRoleId }], + roles: [delius.responsibleOfficerRoleId], enabled: true, - }) + } as DeliusUser) const result = await migrationService.getStaffDetails('token', 'user-1') @@ -168,7 +155,7 @@ describe('MigrationService', () => { nomisClient.getAuthUser.mockResolvedValue({ username: 'user-1', enabled: true }) - deliusClient.getStaffDetailsByStaffIdentifier.mockResolvedValue({ staffIdentifier: 1 } as StaffDetails) + deliusClient.getStaffDetailsByStaffIdentifier.mockResolvedValue({ staffId: 1 } as StaffDetails) const result = await migrationService.getStaffDetails('token', 'user-1') @@ -179,7 +166,7 @@ describe('MigrationService', () => { username: 'user-1', }, deliusUser: { - staffIdentifier: 1, + staffId: 1, }, flags: [Flag.UNLINKED_ACCOUNT], licenceUser: { @@ -203,10 +190,11 @@ describe('MigrationService', () => { deliusClient.getStaffDetailsByStaffIdentifier.mockResolvedValue({ username: 'delius-user', - staffIdentifier: 1, + staffId: 1, email: 'delius-user@gov.uk', } as StaffDetails) deliusClient.getUser.mockResolvedValue({ + username: 'delius-user', roles: [], enabled: true, }) @@ -221,7 +209,7 @@ describe('MigrationService', () => { }, deliusUser: { email: 'delius-user@gov.uk', - staffIdentifier: 1, + staffId: 1, username: 'delius-user', }, flags: [Flag.REQUIRES_RO_ROLE, Flag.EMAIL_MISMATCH, Flag.USERNAME_MISMATCH], @@ -247,12 +235,12 @@ describe('MigrationService', () => { deliusClient.getStaffDetailsByStaffIdentifier.mockResolvedValue({ username: 'delius-user', - staffIdentifier: 1, + staffId: 1, } as StaffDetails) deliusClient.getUser.mockResolvedValue({ roles: [], enabled: true, - }) + } as DeliusUser) const result = await migrationService.getStaffDetails('token', 'user-1') @@ -263,7 +251,7 @@ describe('MigrationService', () => { username: 'user-1', }, deliusUser: { - staffIdentifier: 1, + staffId: 1, username: 'delius-user', }, flags: [Flag.REQUIRES_RO_ROLE, Flag.EMAIL_MISMATCH, Flag.USERNAME_MISMATCH], @@ -316,7 +304,8 @@ describe('MigrationService', () => { email: 'user@gov.uk', } as StaffDetails) deliusClient.getUser.mockResolvedValue({ - roles: [{ name: delius.responsibleOfficerRoleId }], + username: 'user-1', + roles: [delius.responsibleOfficerRoleId], enabled: true, }) @@ -356,7 +345,8 @@ describe('MigrationService', () => { email: 'user@gov.uk', } as StaffDetails) deliusClient.getUser.mockResolvedValue({ - roles: [{ name: delius.responsibleOfficerRoleId }], + username: 'user-1', + roles: [delius.responsibleOfficerRoleId], enabled: true, }) diff --git a/test/services/roService.test.ts b/test/services/roService.test.ts index bcfdc4e08..2fdff020a 100644 --- a/test/services/roService.test.ts +++ b/test/services/roService.test.ts @@ -1,11 +1,5 @@ import { RoService } from '../../server/services/roService' -import { - CommunityOrPrisonOffenderManager, - DeliusClient, - ManagedOffender, - ProbationArea, - Team, -} from '../../server/data/deliusClient' +import { DeliusClient, StaffDetails } from '../../server/data/deliusClient' jest.mock('../../server/data/deliusClient') @@ -28,12 +22,13 @@ describe('roService', () => { omEndDate: undefined, } - const roPrisoners = [ - { ...prototypeRoPrisoner, nomsNumber: 'A' }, - { ...prototypeRoPrisoner, nomsNumber: 'B' }, - { ...prototypeRoPrisoner, nomsNumber: 'C' }, - ] - const staffDetails = { staffCode: 'N02A008', staffIdentifier: 1, staff: { forenames: 'x', surname: 'x' }, teams: [] } + const roPrisoners = ['A', 'B', 'C'] + const staffDetails: StaffDetails = { + code: 'N02A008', + staffId: 1, + name: { forenames: 'x', surname: 'x' }, + teams: [], + } beforeEach(() => { nomisClient = { @@ -44,7 +39,7 @@ describe('roService', () => { const nomisClientBuilder = jest.fn().mockReturnValue(nomisClient) deliusClient = new DeliusClient(undefined) as jest.Mocked - deliusClient.getROPrisonersByStaffIdentifier.mockResolvedValue(roPrisoners) + deliusClient.getManagedPrisonerIdsByStaffId.mockResolvedValue(roPrisoners) deliusClient.getStaffDetailsByStaffIdentifier.mockResolvedValue(staffDetails) deliusClient.getStaffDetailsByUsername.mockResolvedValue(staffDetails) @@ -81,35 +76,28 @@ describe('roService', () => { describe('getROPrisoners', () => { test('should call getROPrisoners from deliusClient && getOffenderSentencesByNomisId from nomisClient', async () => { - deliusClient.getROPrisonersByStaffIdentifier.mockResolvedValue(roPrisoners) + deliusClient.getManagedPrisonerIdsByStaffId.mockResolvedValue(roPrisoners) await service.getROPrisonersForStaffIdentifier(123, 'token') - expect(deliusClient.getROPrisonersByStaffIdentifier).toHaveBeenCalled() + expect(deliusClient.getManagedPrisonerIdsByStaffId).toHaveBeenCalled() expect(nomisClient.getOffenderSentencesByNomisId).toHaveBeenCalled() expect(nomisClient.getOffenderSentencesByNomisId).toHaveBeenCalledWith(['A', 'B', 'C']) }) test('should not call getOffenderSentencesByNomisId when no results from getROPrisoners', async () => { - deliusClient.getROPrisonersByStaffIdentifier.mockResolvedValue([]) + deliusClient.getManagedPrisonerIdsByStaffId.mockResolvedValue([]) await service.getROPrisonersForStaffIdentifier(123, 'token') - expect(deliusClient.getROPrisonersByStaffIdentifier).toHaveBeenCalled() + expect(deliusClient.getManagedPrisonerIdsByStaffId).toHaveBeenCalled() expect(nomisClient.getOffenderSentencesByNomisId).toHaveBeenCalled() }) - test('should not call getOffenderSentencesByNomisId when no offender numbers are returned from getROPrisoners', async () => { - deliusClient.getROPrisonersByStaffIdentifier.mockResolvedValue([{}, {}, {}] as ManagedOffender[]) - await service.getROPrisonersForStaffIdentifier(123, 'token') - expect(deliusClient.getROPrisonersByStaffIdentifier).toHaveBeenCalled() - expect(nomisClient.getOffenderSentencesByNomisId).toHaveBeenCalledWith([]) - }) - test('should return empty array and explanation message if no eligible releases found', async () => { - deliusClient.getROPrisonersByStaffIdentifier.mockResolvedValue([]) + deliusClient.getManagedPrisonerIdsByStaffId.mockResolvedValue([]) const result = await service.getROPrisonersForStaffIdentifier(123, 'token') expect(result).toEqual([]) }) test('should return empty array when staff member not found in delius', async () => { - deliusClient.getROPrisonersByStaffIdentifier.mockResolvedValue(undefined) + deliusClient.getManagedPrisonerIdsByStaffId.mockResolvedValue(undefined) const result = await service.getROPrisonersForStaffIdentifier(123, 'token') expect(result).toEqual(null) }) @@ -117,33 +105,27 @@ describe('roService', () => { describe('findResponsibleOfficer', () => { test('should call the api with the offenderNo', async () => { - deliusClient.getAllOffenderManagers.mockResolvedValue([]) + deliusClient.getCommunityManager.mockResolvedValue(null) await service.findResponsibleOfficer('123', 'token') expect(nomisClient.getBooking).toHaveBeenCalled() expect(nomisClient.getBooking).toHaveBeenCalledWith('123') - expect(deliusClient.getAllOffenderManagers).toHaveBeenCalled() - expect(deliusClient.getAllOffenderManagers).toHaveBeenCalledWith(1) + expect(deliusClient.getCommunityManager).toHaveBeenCalled() + expect(deliusClient.getCommunityManager).toHaveBeenCalledWith(1) }) test('should return the found COM', () => { - deliusClient.getAllOffenderManagers.mockResolvedValue([ - { - isResponsibleOfficer: true, - staff: { forenames: 'Jo', surname: 'Smith' }, - staffCode: 'CODE-1', - staffId: 1, - isUnallocated: false, - team: { - localDeliveryUnit: { code: 'LDU-1', description: 'LDU-1 Description' }, - code: 'TEAM_1', - description: 'The Team', - } as Team, - probationArea: { code: 'PROB-1', description: 'PROB-1 Description' } as ProbationArea, - } as CommunityOrPrisonOffenderManager, - ]) + deliusClient.getCommunityManager.mockResolvedValue({ + code: 'CODE-1', + staffId: 1, + name: { forenames: 'Jo', surname: 'Smith' }, + team: { code: 'TEAM_1', description: 'The Team' }, + provider: { code: 'PROB-1', description: 'PROB-1 Description' }, + localAdminUnit: { code: 'LDU-1', description: 'LDU-1 Description' }, + isUnallocated: false, + }) const expectedComData = { deliusId: 'CODE-1', @@ -162,26 +144,13 @@ describe('roService', () => { return expect(service.findResponsibleOfficer('123', 'token')).resolves.toEqual(expectedComData) }) - test('offender has not been assigned a COM', () => { - deliusClient.getAllOffenderManagers.mockResolvedValue([ - { isPrisonOffenderManager: true } as CommunityOrPrisonOffenderManager, - ]) - - const expectedComData = { - code: 'NO_COM_ASSIGNED', - message: 'Offender has not been assigned a COM: 1', - } - - return expect(service.findResponsibleOfficer('123', 'token')).resolves.toEqual(expectedComData) - }) - test('should throw if error in api when getting ro', () => { - deliusClient.getAllOffenderManagers.mockRejectedValue(new Error('dead')) + deliusClient.getCommunityManager.mockRejectedValue(new Error('dead')) return expect(service.findResponsibleOfficer('123', 'token')).rejects.toEqual(Error('dead')) }) test('should return message when 404 in api when getting RO relationship', () => { - deliusClient.getAllOffenderManagers.mockResolvedValue(undefined) + deliusClient.getCommunityManager.mockResolvedValue(undefined) return expect(service.findResponsibleOfficer('123', 'token')).resolves.toEqual({ code: 'NO_OFFENDER_NUMBER', message: 'Offender number not entered in delius', diff --git a/types/licences.d.ts b/types/licences.d.ts index 55e9e00d7..2c74f2b5a 100644 --- a/types/licences.d.ts +++ b/types/licences.d.ts @@ -1,4 +1,4 @@ -import { ProbationAreaSummary } from '../server/data/deliusClient' +import { KeyValue } from '../server/data/deliusClient' export interface ResponsibleOfficer { deliusId: string @@ -133,7 +133,7 @@ export interface LduStatus { } export interface LduService { - getAllProbationAreas: () => Promise> + getAllProbationAreas: () => Promise> getProbationArea: (probationAreaCode: string) => Promise updateActiveLdus: (probationAreaCode: string, activeLdus: string[]) => Promise }