Skip to content

Commit

Permalink
VB-5036 Refactor to split visit details page code (#928)
Browse files Browse the repository at this point in the history
  • Loading branch information
tpmcgowan authored Jan 31, 2025
1 parent 3617735 commit f1c214d
Show file tree
Hide file tree
Showing 8 changed files with 788 additions and 612 deletions.
2 changes: 2 additions & 0 deletions server/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import prisonerRoutes from './routes/prisoner'
import reviewRoutes from './routes/review'
import searchRoutes from './routes/search'
import timetableRoutes from './routes/timetable'
import visitRoutesNew from './routes/visit/index'
import visitRoutes from './routes/visit'
import visitsByDateRoutes from './routes/visitsByDate'
import type { Services } from './services'
Expand Down Expand Up @@ -69,6 +70,7 @@ export default function createApp(services: Services): express.Application {
app.use('/timetable', timetableRoutes(services))
app.use('/review', reviewRoutes(services))
app.use('/visit', visitRoutes(services))
app.use('/visit', visitRoutesNew(services)) // TODO rationalise/refactor visit routes
app.use('/visits', visitsByDateRoutes(services))

app.use((req, res, next) => next(createError(404, 'Not found')))
Expand Down
2 changes: 2 additions & 0 deletions server/routes/testutils/appSetup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import prisonerRoutes from '../prisoner'
import reviewRoutes from '../review'
import searchRoutes from '../search'
import timetableRoutes from '../timetable'
import visitRoutesNew from '../visit/index'
import visitRoutes from '../visit'
import visitsRoutes from '../visitsByDate'

Expand Down Expand Up @@ -106,6 +107,7 @@ function appSetup(
app.use('/search', searchRoutes(services))
app.use('/timetable', timetableRoutes(services))
app.use('/visit', visitRoutes(services))
app.use('/visit', visitRoutesNew(services))
app.use('/visits', visitsRoutes(services))

app.use((req, res, next) => next(new NotFound()))
Expand Down
528 changes: 0 additions & 528 deletions server/routes/visit.test.ts

Large diffs are not rendered by default.

86 changes: 2 additions & 84 deletions server/routes/visit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,7 @@ import { BadRequest } from 'http-errors'
import { differenceInCalendarDays } from 'date-fns'
import visitCancellationReasons from '../constants/visitCancellationReasons'
import { Prisoner } from '../data/prisonerOffenderSearchTypes'
import {
CancelVisitOrchestrationDto,
IgnoreVisitNotificationsDto,
NotificationType,
} from '../data/orchestrationApiTypes'
import { CancelVisitOrchestrationDto, IgnoreVisitNotificationsDto } from '../data/orchestrationApiTypes'
import asyncMiddleware from '../middleware/asyncMiddleware'
import { isValidVisitReference } from './validationChecks'
import { clearSession, getFlashFormValues } from './visitorUtils'
Expand All @@ -25,15 +21,9 @@ import MainContact from './visitJourney/mainContact'
import RequestMethod from './visitJourney/requestMethod'
import sessionCheckMiddleware from '../middleware/sessionCheckMiddleware'
import { type Services } from '../services'
import eventAuditTypes from '../constants/eventAuditTypes'
import { requestMethodDescriptions, requestMethodsCancellation } from '../constants/requestMethods'
import { notificationTypeWarnings, notificationTypes } from '../constants/notificationEvents'
import { requestMethodsCancellation } from '../constants/requestMethods'
import Overbooking from './visitJourney/overbooking'

const A_DAY_IN_MS = 24 * 60 * 60 * 1000
const CANCELLATION_LIMIT_DAYS = 28
const NO_UPDATE_NOTIFICATION_TYPES: NotificationType[] = ['PRISONER_RECEIVED_EVENT', 'PRISONER_RELEASED_EVENT']

export default function routes({
auditService,
prisonerProfileService,
Expand Down Expand Up @@ -67,78 +57,6 @@ export default function routes({
})
})

get('/:reference', async (req, res) => {
const reference = getVisitReference(req)
const fromPage = typeof req.query?.from === 'string' ? req.query.from : null
const fromPageQuery = typeof req.query?.query === 'string' ? req.query.query : null
const { username } = res.locals.user

const { visitHistoryDetails, visitors, notifications, additionalSupport } = await visitService.getFullVisitDetails({
reference,
username,
})
const { visit } = visitHistoryDetails
const filteredVisitHistoryDetails = visitHistoryDetails.eventsAudit.filter(event =>
Object.keys(eventAuditTypes).includes(event.type),
)

if (visit.prisonId !== req.session.selectedEstablishment.prisonId) {
const visitPrison = await supportedPrisonsService.getPrison(username, visit.prisonId)

return res.render('pages/visit/summary', {
visit: { reference: visit.reference },
visitPrisonName: visitPrison.prisonName,
})
}

const [prisoner, supportedPrisonIds] = await Promise.all([
prisonerSearchService.getPrisonerById(visit.prisonerId, username),
supportedPrisonsService.getSupportedPrisonIds(username),
])
const prisonerLocation = getPrisonerLocation(supportedPrisonIds, prisoner)

await auditService.viewedVisitDetails({
visitReference: reference,
prisonerId: visit.prisonerId,
prisonId: visit.prisonId,
username,
operationId: res.locals.appInsightsOperationId,
})

const nowTimestamp = new Date()
const visitStartTimestamp = new Date(visit.startTimestamp)
const chosenFutureInterval = new Date(visitStartTimestamp.getTime() + A_DAY_IN_MS * CANCELLATION_LIMIT_DAYS)

const showUpdate =
nowTimestamp < visitStartTimestamp &&
!notifications.some(notification => NO_UPDATE_NOTIFICATION_TYPES.includes(notification))
const showCancel = nowTimestamp < chosenFutureInterval

const filteredNotifications = notifications.filter(
notification => notification !== 'PRISON_VISITS_BLOCKED_FOR_DATE',
)
const showDoNotChange = filteredNotifications.length > 0

return res.render('pages/visit/summary', {
prisoner,
prisonerLocation,
visit,
filteredVisitHistoryDetails,
visitors,
notifications,
notificationTypeWarnings,
additionalSupport,
fromPage,
fromPageQuery,
showUpdate,
showCancel,
showDoNotChange,
requestMethodDescriptions,
eventAuditTypes,
notificationTypes,
})
})

post('/:reference', async (req, res) => {
const reference = getVisitReference(req)
const { username } = res.locals.user
Expand Down
32 changes: 32 additions & 0 deletions server/routes/visit/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { RequestHandler, Router } from 'express'
import { BadRequest } from 'http-errors'
import { Services } from '../../services'
import asyncMiddleware from '../../middleware/asyncMiddleware'
import VisitDetailsController from './visitDetailsController'
import { isValidVisitReference } from '../validationChecks'

export default function routes(services: Services): Router {
const router = Router()

const get = (path: string | string[], handler: RequestHandler) => router.get(path, asyncMiddleware(handler))

// middleware to ensure valid visit reference
router.use('/:reference', (req, res, next) => {
const { reference } = req.params
if (!isValidVisitReference(reference)) {
throw new BadRequest()
}
next()
})

const visitDetails = new VisitDetailsController(
services.auditService,
services.prisonerSearchService,
services.supportedPrisonsService,
services.visitService,
)

get('/:reference', visitDetails.view())

return router
}
Loading

0 comments on commit f1c214d

Please sign in to comment.