From ff2e71f7d6dd523c1a4bac959f99cfc06e20ded9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gu=C3=B0j=C3=B3n=20Gu=C3=B0j=C3=B3nsson?= Date: Wed, 25 Sep 2024 14:41:40 +0200 Subject: [PATCH 01/18] Locks subpoena fields when arraignment date has been set --- .../routes/Court/Indictments/Subpoena/Subpoena.tsx | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/apps/judicial-system/web/src/routes/Court/Indictments/Subpoena/Subpoena.tsx b/apps/judicial-system/web/src/routes/Court/Indictments/Subpoena/Subpoena.tsx index 92455ec72667..4d13fb753f1c 100644 --- a/apps/judicial-system/web/src/routes/Court/Indictments/Subpoena/Subpoena.tsx +++ b/apps/judicial-system/web/src/routes/Court/Indictments/Subpoena/Subpoena.tsx @@ -46,11 +46,11 @@ const Subpoena: FC = () => { } = useCourtArrangements(workingCase, setWorkingCase, 'arraignmentDate') const { sendNotification } = useCase() - const isArraignmentDone = Boolean(workingCase.indictmentDecision) + const isArraignmentScheduled = Boolean(workingCase.arraignmentDate) const handleNavigationTo = useCallback( async (destination: keyof stepValidationsType) => { - if (isArraignmentDone) { + if (isArraignmentScheduled) { router.push(`${destination}/${workingCase.id}`) return } @@ -89,7 +89,7 @@ const Subpoena: FC = () => { router.push(`${destination}/${workingCase.id}`) }, [ - isArraignmentDone, + isArraignmentScheduled, sendCourtDateToServer, workingCase.defendants, workingCase.notifications, @@ -134,8 +134,8 @@ const Subpoena: FC = () => { handleCourtDateChange={handleCourtDateChange} handleCourtRoomChange={handleCourtRoomChange} courtDate={workingCase.arraignmentDate} - dateTimeDisabled={isArraignmentDone} - courtRoomDisabled={isArraignmentDone} + dateTimeDisabled={isArraignmentScheduled} + courtRoomDisabled={isArraignmentScheduled} courtRoomRequired /> @@ -169,14 +169,14 @@ const Subpoena: FC = () => { previousUrl={`${constants.INDICTMENTS_RECEPTION_AND_ASSIGNMENT_ROUTE}/${workingCase.id}`} nextIsLoading={isLoadingWorkingCase} onNextButtonClick={() => { - if (isArraignmentDone) { + if (isArraignmentScheduled) { router.push( `${constants.INDICTMENTS_DEFENDER_ROUTE}/${workingCase.id}`, ) } else setNavigateTo(constants.INDICTMENTS_DEFENDER_ROUTE) }} nextButtonText={ - isArraignmentDone + isArraignmentScheduled ? undefined : formatMessage(strings.nextButtonText) } From cf631db4b8d9115243fffc8e56b5c4d1ce9d5380 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gu=C3=B0j=C3=B3n=20Gu=C3=B0j=C3=B3nsson?= Date: Wed, 25 Sep 2024 15:49:34 +0200 Subject: [PATCH 02/18] Move arraignment date message handling to the server side --- .../src/app/modules/case/case.service.ts | 44 ++++++++++++++++--- .../notification/notification.service.ts | 9 ---- .../app/modules/subpoena/subpoena.service.ts | 1 + .../Court/Indictments/Subpoena/Subpoena.tsx | 24 +--------- 4 files changed, 39 insertions(+), 39 deletions(-) diff --git a/apps/judicial-system/backend/src/app/modules/case/case.service.ts b/apps/judicial-system/backend/src/app/modules/case/case.service.ts index 1d4043abd85d..2a21877fa13f 100644 --- a/apps/judicial-system/backend/src/app/modules/case/case.service.ts +++ b/apps/judicial-system/backend/src/app/modules/case/case.service.ts @@ -1143,15 +1143,29 @@ export class CaseService { private addMessagesForNewCourtDateToQueue( theCase: Case, user: TUser, + arraignmentDateChanged: boolean, ): Promise { - return this.messageService.sendMessagesToQueue([ + const messages: Message[] = [ { type: MessageType.NOTIFICATION, user, caseId: theCase.id, body: { type: NotificationType.COURT_DATE }, }, - ]) + ] + + if (arraignmentDateChanged) { + theCase.defendants?.forEach((defendant) => { + messages.push({ + type: MessageType.DELIVERY_TO_POLICE_SUBPOENA, + user, + caseId: theCase.id, + elementId: defendant.id, + }) + }) + } + + return this.messageService.sendMessagesToQueue(messages) } private async addMessagesForUpdatedCaseToQueue( @@ -1310,11 +1324,27 @@ export class CaseService { } // This only applies to indictments - const courtDate = DateLog.courtDate(theCase.dateLogs) - const updatedCourtDate = DateLog.courtDate(updatedCase.dateLogs) - if (updatedCourtDate && updatedCourtDate.date !== courtDate?.date) { - // New court date - await this.addMessagesForNewCourtDateToQueue(updatedCase, user) + if (isIndictment) { + const arraignmentDate = DateLog.arraignmentDate(theCase.dateLogs) + const updatedArraignmentDate = DateLog.arraignmentDate( + updatedCase.dateLogs, + ) + const arraignmentDateChanged = + updatedArraignmentDate && + updatedArraignmentDate.date !== arraignmentDate?.date + const courtDate = DateLog.courtDate(theCase.dateLogs) + const updatedCourtDate = DateLog.courtDate(updatedCase.dateLogs) + const courtDateChanged = + updatedCourtDate && updatedCourtDate.date !== courtDate?.date + + if (arraignmentDateChanged || courtDateChanged) { + // New arraignment date or new court date + await this.addMessagesForNewCourtDateToQueue( + updatedCase, + user, + Boolean(arraignmentDateChanged), + ) + } } } diff --git a/apps/judicial-system/backend/src/app/modules/notification/notification.service.ts b/apps/judicial-system/backend/src/app/modules/notification/notification.service.ts index e4ffc288777d..8103b1106f14 100644 --- a/apps/judicial-system/backend/src/app/modules/notification/notification.service.ts +++ b/apps/judicial-system/backend/src/app/modules/notification/notification.service.ts @@ -69,15 +69,6 @@ export class NotificationService { ] } else { messages = [this.getNotificationMessage(type, user, theCase)] - theCase.defendants?.forEach((defendant) => { - // TODO: move this elsewhere when we know exactly where the trigger should be - messages.push({ - type: MessageType.DELIVERY_TO_POLICE_SUBPOENA, - user, - caseId: theCase.id, - elementId: defendant.id, - }) - }) } break case NotificationType.HEADS_UP: diff --git a/apps/judicial-system/backend/src/app/modules/subpoena/subpoena.service.ts b/apps/judicial-system/backend/src/app/modules/subpoena/subpoena.service.ts index 62d0355fd57c..c28cf4ec4875 100644 --- a/apps/judicial-system/backend/src/app/modules/subpoena/subpoena.service.ts +++ b/apps/judicial-system/backend/src/app/modules/subpoena/subpoena.service.ts @@ -126,6 +126,7 @@ export class SubpoenaService { return { delivered: false } } + // TODO: Improve error handling by checking how many rows were affected and posting error event await this.subpoenaModel.update( { subpoenaId: createdSubpoena.subpoenaId }, { where: { id: subpoena.id } }, diff --git a/apps/judicial-system/web/src/routes/Court/Indictments/Subpoena/Subpoena.tsx b/apps/judicial-system/web/src/routes/Court/Indictments/Subpoena/Subpoena.tsx index 4d13fb753f1c..11c767d7008f 100644 --- a/apps/judicial-system/web/src/routes/Court/Indictments/Subpoena/Subpoena.tsx +++ b/apps/judicial-system/web/src/routes/Court/Indictments/Subpoena/Subpoena.tsx @@ -19,14 +19,9 @@ import { SectionHeading, useCourtArrangements, } from '@island.is/judicial-system-web/src/components' -import { NotificationType } from '@island.is/judicial-system-web/src/graphql/schema' import { SubpoenaType } from '@island.is/judicial-system-web/src/routes/Court/components' import type { stepValidationsType } from '@island.is/judicial-system-web/src/utils/formHelper' -import { - useCase, - useDefendants, -} from '@island.is/judicial-system-web/src/utils/hooks' -import { hasSentNotification } from '@island.is/judicial-system-web/src/utils/stepHelper' +import { useDefendants } from '@island.is/judicial-system-web/src/utils/hooks' import { isSubpoenaStepValid } from '@island.is/judicial-system-web/src/utils/validate' import { subpoena as strings } from './Subpoena.strings' @@ -39,12 +34,10 @@ const Subpoena: FC = () => { const { formatMessage } = useIntl() const { courtDate, - courtDateHasChanged, handleCourtDateChange, handleCourtRoomChange, sendCourtDateToServer, } = useCourtArrangements(workingCase, setWorkingCase, 'arraignmentDate') - const { sendNotification } = useCase() const isArraignmentScheduled = Boolean(workingCase.arraignmentDate) @@ -69,18 +62,6 @@ const Subpoena: FC = () => { }) } - if ( - !hasSentNotification( - NotificationType.COURT_DATE, - workingCase.notifications, - ).hasSent || - courtDateHasChanged - ) { - promises.push( - sendNotification(workingCase.id, NotificationType.COURT_DATE), - ) - } - const allDataSentToServer = await Promise.all(promises) if (!allDataSentToServer.every((result) => result)) { return @@ -92,11 +73,8 @@ const Subpoena: FC = () => { isArraignmentScheduled, sendCourtDateToServer, workingCase.defendants, - workingCase.notifications, workingCase.id, - courtDateHasChanged, updateDefendant, - sendNotification, ], ) From 9192246cd32f31de15dff4b58985ff6dabc2796d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gu=C3=B0j=C3=B3n=20Gu=C3=B0j=C3=B3nsson?= Date: Wed, 25 Sep 2024 16:22:36 +0200 Subject: [PATCH 03/18] Updates tests and fixes date comparison --- .../src/app/modules/case/case.service.ts | 6 ++- .../case/test/caseController/update.spec.ts | 48 ++++++++++++++++++- 2 files changed, 50 insertions(+), 4 deletions(-) diff --git a/apps/judicial-system/backend/src/app/modules/case/case.service.ts b/apps/judicial-system/backend/src/app/modules/case/case.service.ts index 2a21877fa13f..9f3973a8f152 100644 --- a/apps/judicial-system/backend/src/app/modules/case/case.service.ts +++ b/apps/judicial-system/backend/src/app/modules/case/case.service.ts @@ -1331,11 +1331,13 @@ export class CaseService { ) const arraignmentDateChanged = updatedArraignmentDate && - updatedArraignmentDate.date !== arraignmentDate?.date + updatedArraignmentDate.date.getTime() !== + arraignmentDate?.date.getTime() const courtDate = DateLog.courtDate(theCase.dateLogs) const updatedCourtDate = DateLog.courtDate(updatedCase.dateLogs) const courtDateChanged = - updatedCourtDate && updatedCourtDate.date !== courtDate?.date + updatedCourtDate && + updatedCourtDate.date.getTime() !== courtDate?.date.getTime() if (arraignmentDateChanged || courtDateChanged) { // New arraignment date or new court date diff --git a/apps/judicial-system/backend/src/app/modules/case/test/caseController/update.spec.ts b/apps/judicial-system/backend/src/app/modules/case/test/caseController/update.spec.ts index 0ffde6ad16ca..932319cac89e 100644 --- a/apps/judicial-system/backend/src/app/modules/case/test/caseController/update.spec.ts +++ b/apps/judicial-system/backend/src/app/modules/case/test/caseController/update.spec.ts @@ -872,11 +872,56 @@ describe('CaseController - Update', () => { }) }) - describe('court date updated', () => { + describe('indictment arraignment date updated', () => { + const arraignmentDate = { date: new Date(), location: uuid() } + const caseToUpdate = { arraignmentDate } + const updatedCase = { + ...theCase, + type: CaseType.INDICTMENT, + dateLogs: [{ dateType: DateType.ARRAIGNMENT_DATE, ...arraignmentDate }], + } + + beforeEach(async () => { + const mockFindOne = mockCaseModel.findOne as jest.Mock + mockFindOne.mockResolvedValueOnce(updatedCase) + + await givenWhenThen(caseId, user, theCase, caseToUpdate) + }) + + it('should update case', () => { + expect(mockDateLogModel.create).toHaveBeenCalledWith( + { dateType: DateType.ARRAIGNMENT_DATE, caseId, ...arraignmentDate }, + { transaction }, + ) + expect(mockMessageService.sendMessagesToQueue).toHaveBeenCalledWith([ + { + type: MessageType.NOTIFICATION, + user, + caseId, + body: { type: NotificationType.COURT_DATE }, + }, + { + type: MessageType.DELIVERY_TO_POLICE_SUBPOENA, + user, + caseId: theCase.id, + elementId: defendantId1, + }, + { + type: MessageType.DELIVERY_TO_POLICE_SUBPOENA, + user, + caseId: theCase.id, + elementId: defendantId2, + }, + ]) + }) + }) + + describe('indictment court date updated', () => { const courtDate = { date: new Date(), location: uuid() } const caseToUpdate = { courtDate } const updatedCase = { ...theCase, + type: CaseType.INDICTMENT, dateLogs: [{ dateType: DateType.COURT_DATE, ...courtDate }], } @@ -892,7 +937,6 @@ describe('CaseController - Update', () => { { dateType: DateType.COURT_DATE, caseId, ...courtDate }, { transaction }, ) - expect(mockMessageService.sendMessagesToQueue).toHaveBeenCalledWith([ { type: MessageType.NOTIFICATION, From 8124dbf12e26c2b6065a879cdfe6b9e2ba7f953c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gu=C3=B0j=C3=B3n=20Gu=C3=B0j=C3=B3nsson?= Date: Thu, 26 Sep 2024 13:39:51 +0200 Subject: [PATCH 04/18] Schedules new subpoenas --- .../Court/Indictments/Overview/Overview.tsx | 6 +- .../Indictments/Subpoena/Subpoena.strings.ts | 6 + .../Court/Indictments/Subpoena/Subpoena.tsx | 39 ++++-- .../components/SubpoenaType/SubpoenaType.tsx | 117 ++++++++++-------- 4 files changed, 107 insertions(+), 61 deletions(-) diff --git a/apps/judicial-system/web/src/routes/Court/Indictments/Overview/Overview.tsx b/apps/judicial-system/web/src/routes/Court/Indictments/Overview/Overview.tsx index 0df16e8b0a6d..176c08156d9e 100644 --- a/apps/judicial-system/web/src/routes/Court/Indictments/Overview/Overview.tsx +++ b/apps/judicial-system/web/src/routes/Court/Indictments/Overview/Overview.tsx @@ -38,6 +38,7 @@ const IndictmentOverview = () => { const [modalVisible, setModalVisible] = useState<'RETURN_INDICTMENT'>() const latestDate = workingCase.courtDate ?? workingCase.arraignmentDate + const isArraignmentScheduled = Boolean(workingCase.arraignmentDate) // const caseHasBeenReceivedByCourt = workingCase.state === CaseState.RECEIVED const handleNavigationTo = useCallback( @@ -122,7 +123,10 @@ const IndictmentOverview = () => { { ({ + defendant, + disabled: isArraignmentScheduled, + }))} workingCase={workingCase} setWorkingCase={setWorkingCase} updateDefendantState={updateDefendantState} diff --git a/apps/judicial-system/web/src/routes/Court/Indictments/Subpoena/Subpoena.strings.ts b/apps/judicial-system/web/src/routes/Court/Indictments/Subpoena/Subpoena.strings.ts index 8c8c4c2c47e3..baa01967b083 100644 --- a/apps/judicial-system/web/src/routes/Court/Indictments/Subpoena/Subpoena.strings.ts +++ b/apps/judicial-system/web/src/routes/Court/Indictments/Subpoena/Subpoena.strings.ts @@ -60,4 +60,10 @@ export const subpoena = defineMessages({ description: 'Notaður sem texti fyrir Handtökufyrirkall valkost á Fyrirkalls skjá í dómaraflæði í ákærum.', }, + newSubpoenaButtonText: { + id: 'judicial.system.core:subpoena.new_subpoena_button_text', + defaultMessage: 'Nýtt fyrirkall', + description: + 'Notaður sem texti á takka sem býður notanda að búa til nýtt fyrirkall.', + }, }) diff --git a/apps/judicial-system/web/src/routes/Court/Indictments/Subpoena/Subpoena.tsx b/apps/judicial-system/web/src/routes/Court/Indictments/Subpoena/Subpoena.tsx index 11c767d7008f..1a7e280c87e6 100644 --- a/apps/judicial-system/web/src/routes/Court/Indictments/Subpoena/Subpoena.tsx +++ b/apps/judicial-system/web/src/routes/Court/Indictments/Subpoena/Subpoena.tsx @@ -2,7 +2,7 @@ import { FC, useCallback, useContext, useState } from 'react' import { useIntl } from 'react-intl' import router from 'next/router' -import { Box } from '@island.is/island-ui/core' +import { Box, Button } from '@island.is/island-ui/core' import * as constants from '@island.is/judicial-system/consts' import { titles } from '@island.is/judicial-system-web/messages' import { @@ -30,6 +30,7 @@ const Subpoena: FC = () => { const { workingCase, setWorkingCase, isLoadingWorkingCase, caseNotFound } = useContext(FormContext) const [navigateTo, setNavigateTo] = useState() + const [newSubpoenas, setNewSubpoenas] = useState([]) const { updateDefendantState, updateDefendant } = useDefendants() const { formatMessage } = useIntl() const { @@ -40,10 +41,12 @@ const Subpoena: FC = () => { } = useCourtArrangements(workingCase, setWorkingCase, 'arraignmentDate') const isArraignmentScheduled = Boolean(workingCase.arraignmentDate) + const schedulingArraignmentDate = + !isArraignmentScheduled || newSubpoenas.length > 0 const handleNavigationTo = useCallback( async (destination: keyof stepValidationsType) => { - if (isArraignmentScheduled) { + if (!schedulingArraignmentDate) { router.push(`${destination}/${workingCase.id}`) return } @@ -70,7 +73,7 @@ const Subpoena: FC = () => { router.push(`${destination}/${workingCase.id}`) }, [ - isArraignmentScheduled, + schedulingArraignmentDate, sendCourtDateToServer, workingCase.defendants, workingCase.id, @@ -96,7 +99,27 @@ const Subpoena: FC = () => { { ({ + defendant, + disabled: + isArraignmentScheduled && + !newSubpoenas.includes(defendant.id), + children: isArraignmentScheduled && ( + + ), + }))} workingCase={workingCase} setWorkingCase={setWorkingCase} updateDefendantState={updateDefendantState} @@ -112,8 +135,8 @@ const Subpoena: FC = () => { handleCourtDateChange={handleCourtDateChange} handleCourtRoomChange={handleCourtRoomChange} courtDate={workingCase.arraignmentDate} - dateTimeDisabled={isArraignmentScheduled} - courtRoomDisabled={isArraignmentScheduled} + dateTimeDisabled={!schedulingArraignmentDate} + courtRoomDisabled={!schedulingArraignmentDate} courtRoomRequired /> @@ -147,14 +170,14 @@ const Subpoena: FC = () => { previousUrl={`${constants.INDICTMENTS_RECEPTION_AND_ASSIGNMENT_ROUTE}/${workingCase.id}`} nextIsLoading={isLoadingWorkingCase} onNextButtonClick={() => { - if (isArraignmentScheduled) { + if (!schedulingArraignmentDate) { router.push( `${constants.INDICTMENTS_DEFENDER_ROUTE}/${workingCase.id}`, ) } else setNavigateTo(constants.INDICTMENTS_DEFENDER_ROUTE) }} nextButtonText={ - isArraignmentScheduled + !schedulingArraignmentDate ? undefined : formatMessage(strings.nextButtonText) } diff --git a/apps/judicial-system/web/src/routes/Court/components/SubpoenaType/SubpoenaType.tsx b/apps/judicial-system/web/src/routes/Court/components/SubpoenaType/SubpoenaType.tsx index e30edd9bd129..3a89ef897e87 100644 --- a/apps/judicial-system/web/src/routes/Court/components/SubpoenaType/SubpoenaType.tsx +++ b/apps/judicial-system/web/src/routes/Court/components/SubpoenaType/SubpoenaType.tsx @@ -1,4 +1,4 @@ -import { Dispatch, FC, SetStateAction } from 'react' +import { Dispatch, FC, ReactNode, SetStateAction } from 'react' import { useIntl } from 'react-intl' import { Box, RadioButton, Text } from '@island.is/island-ui/core' @@ -17,7 +17,11 @@ import { strings } from './SubpoenaType.strings' import * as styles from '../../Indictments/Subpoena/Subpoena.css' interface SubpoenaTypeProps { - defendants: Defendant[] + subpoenaItems: { + defendant: Defendant + disabled?: boolean + children?: ReactNode + }[] workingCase: Case setWorkingCase: Dispatch> updateDefendantState: ( @@ -28,70 +32,79 @@ interface SubpoenaTypeProps { } const SubpoenaType: FC = ({ - defendants, + subpoenaItems, workingCase, setWorkingCase, updateDefendantState, required = true, }) => { const { formatMessage } = useIntl() - const isArraignmentDone = Boolean(workingCase.indictmentDecision) + return ( <> - {defendants.map((defendant, index) => ( + {subpoenaItems.map((item, index) => ( - - - {defendant.name} - - - { - updateDefendantState( - { - caseId: workingCase.id, - defendantId: defendant.id, - subpoenaType: SubpoenaTypeEnum.ABSENCE, - }, - setWorkingCase, - ) - }} - disabled={isArraignmentDone} - /> - { - updateDefendantState( - { - caseId: workingCase.id, - defendantId: defendant.id, - subpoenaType: SubpoenaTypeEnum.ARREST, - }, - setWorkingCase, - ) - }} - disabled={isArraignmentDone} - /> - - + + + + {item.defendant.name} + + + { + updateDefendantState( + { + caseId: workingCase.id, + defendantId: item.defendant.id, + subpoenaType: SubpoenaTypeEnum.ABSENCE, + }, + setWorkingCase, + ) + }} + disabled={item.disabled} + /> + { + updateDefendantState( + { + caseId: workingCase.id, + defendantId: item.defendant.id, + subpoenaType: SubpoenaTypeEnum.ARREST, + }, + setWorkingCase, + ) + }} + disabled={item.disabled} + /> + + + + {item.children} ))} From 5f3824ab33cc9356e8a09cd923764424be243be2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gu=C3=B0j=C3=B3n=20Gu=C3=B0j=C3=B3nsson?= Date: Thu, 26 Sep 2024 13:52:57 +0200 Subject: [PATCH 05/18] Enforces operation ordering --- .../routes/Court/Indictments/Subpoena/Subpoena.tsx | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/apps/judicial-system/web/src/routes/Court/Indictments/Subpoena/Subpoena.tsx b/apps/judicial-system/web/src/routes/Court/Indictments/Subpoena/Subpoena.tsx index 1a7e280c87e6..d5f779a419fe 100644 --- a/apps/judicial-system/web/src/routes/Court/Indictments/Subpoena/Subpoena.tsx +++ b/apps/judicial-system/web/src/routes/Court/Indictments/Subpoena/Subpoena.tsx @@ -51,7 +51,7 @@ const Subpoena: FC = () => { return } - const promises: Promise[] = [sendCourtDateToServer()] + const promises: Promise[] = [] if (workingCase.defendants) { workingCase.defendants.forEach((defendant) => { @@ -65,8 +65,16 @@ const Subpoena: FC = () => { }) } - const allDataSentToServer = await Promise.all(promises) - if (!allDataSentToServer.every((result) => result)) { + // Make sure defendants are updated before submitting the court date + const allDefendantsUpdated = await Promise.all(promises) + + if (!allDefendantsUpdated.every((result) => result)) { + return + } + + const courtDateUpdated = await sendCourtDateToServer() + + if (!courtDateUpdated) { return } From 33fe470985c54d5bb946e2a1a223e731075aa8d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gu=C3=B0j=C3=B3n=20Gu=C3=B0j=C3=B3nsson?= Date: Thu, 26 Sep 2024 15:08:51 +0200 Subject: [PATCH 06/18] Only sends query parameters with new subpoena requests --- .../src/app/modules/file/file.controller.ts | 12 ++++--- .../backend/src/app/formatters/subpoenaPdf.ts | 8 ++--- .../Court/Indictments/Subpoena/Subpoena.tsx | 31 ++++++++++++------- 3 files changed, 32 insertions(+), 19 deletions(-) diff --git a/apps/judicial-system/api/src/app/modules/file/file.controller.ts b/apps/judicial-system/api/src/app/modules/file/file.controller.ts index 34e61e6ad93c..e705f0e43c4e 100644 --- a/apps/judicial-system/api/src/app/modules/file/file.controller.ts +++ b/apps/judicial-system/api/src/app/modules/file/file.controller.ts @@ -182,22 +182,26 @@ export class FileController { getSubpoenaPdf( @Param('id') id: string, @Param('defendantId') defendantId: string, - @Query('arraignmentDate') arraignmentDate: string, - @Query('location') location: string, - @Query('subpoenaType') subpoenaType: SubpoenaType, @CurrentHttpUser() user: User, @Req() req: Request, @Res() res: Response, + @Query('arraignmentDate') arraignmentDate?: string, + @Query('location') location?: string, + @Query('subpoenaType') subpoenaType?: SubpoenaType, ): Promise { this.logger.debug( `Getting the subpoena for defendant ${defendantId} of case ${id} as a pdf document`, ) + const queryInjection = arraignmentDate + ? `?arraignmentDate=${arraignmentDate}&location=${location}&subpoenaType=${subpoenaType}` + : '' + return this.fileService.tryGetFile( user.id, AuditedAction.GET_SUBPOENA_PDF, id, - `defendant/${defendantId}/subpoena?arraignmentDate=${arraignmentDate}&location=${location}&subpoenaType=${subpoenaType}`, + `defendant/${defendantId}/subpoena${queryInjection}`, req, res, 'pdf', diff --git a/apps/judicial-system/backend/src/app/formatters/subpoenaPdf.ts b/apps/judicial-system/backend/src/app/formatters/subpoenaPdf.ts index 4af8001053e8..b2b3096a0eb6 100644 --- a/apps/judicial-system/backend/src/app/formatters/subpoenaPdf.ts +++ b/apps/judicial-system/backend/src/app/formatters/subpoenaPdf.ts @@ -43,9 +43,9 @@ export const createSubpoena = ( }) const sinc: Buffer[] = [] - const dateLog = theCase.dateLogs?.find( - (d) => d.dateType === DateType.ARRAIGNMENT_DATE, - ) + const dateLog = arraignmentDate + ? undefined + : theCase.dateLogs?.find((d) => d.dateType === DateType.ARRAIGNMENT_DATE) doc.on('data', (chunk) => sinc.push(chunk)) @@ -159,7 +159,7 @@ export const createSubpoena = ( actor: theCase.judge?.name || '', title: theCase.judge?.title, institution: theCase.judge?.institution?.name || '', - date: dateLog.created, + date: dateLog.modified, }) } diff --git a/apps/judicial-system/web/src/routes/Court/Indictments/Subpoena/Subpoena.tsx b/apps/judicial-system/web/src/routes/Court/Indictments/Subpoena/Subpoena.tsx index d5f779a419fe..e2cbe58c2604 100644 --- a/apps/judicial-system/web/src/routes/Court/Indictments/Subpoena/Subpoena.tsx +++ b/apps/judicial-system/web/src/routes/Court/Indictments/Subpoena/Subpoena.tsx @@ -41,12 +41,16 @@ const Subpoena: FC = () => { } = useCourtArrangements(workingCase, setWorkingCase, 'arraignmentDate') const isArraignmentScheduled = Boolean(workingCase.arraignmentDate) - const schedulingArraignmentDate = + const isSchedulingArraignmentDate = !isArraignmentScheduled || newSubpoenas.length > 0 + const isSchedulingArraignmentDateForDefendant = (defendantId: string) => + !isArraignmentScheduled || + (isArraignmentScheduled && newSubpoenas.includes(defendantId)) + const handleNavigationTo = useCallback( async (destination: keyof stepValidationsType) => { - if (!schedulingArraignmentDate) { + if (!isSchedulingArraignmentDate) { router.push(`${destination}/${workingCase.id}`) return } @@ -81,7 +85,7 @@ const Subpoena: FC = () => { router.push(`${destination}/${workingCase.id}`) }, [ - schedulingArraignmentDate, + isSchedulingArraignmentDate, sendCourtDateToServer, workingCase.defendants, workingCase.id, @@ -143,8 +147,8 @@ const Subpoena: FC = () => { handleCourtDateChange={handleCourtDateChange} handleCourtRoomChange={handleCourtRoomChange} courtDate={workingCase.arraignmentDate} - dateTimeDisabled={!schedulingArraignmentDate} - courtRoomDisabled={!schedulingArraignmentDate} + dateTimeDisabled={!isSchedulingArraignmentDate} + courtRoomDisabled={!isSchedulingArraignmentDate} courtRoomRequired /> @@ -161,12 +165,17 @@ const Subpoena: FC = () => { title={`Fyrirkall - ${defendant.name} - PDF`} pdfType="subpoena" disabled={ - !courtDate?.date || - !courtDate?.location || - !defendant.subpoenaType + isSchedulingArraignmentDateForDefendant(defendant.id) && + (!courtDate?.date || + !courtDate?.location || + !defendant.subpoenaType) } elementId={defendant.id} - queryParameters={`arraignmentDate=${courtDate?.date}&location=${courtDate?.location}&subpoenaType=${defendant.subpoenaType}`} + queryParameters={ + isSchedulingArraignmentDateForDefendant(defendant.id) + ? `arraignmentDate=${courtDate?.date}&location=${courtDate?.location}&subpoenaType=${defendant.subpoenaType}` + : undefined + } /> ))} @@ -178,14 +187,14 @@ const Subpoena: FC = () => { previousUrl={`${constants.INDICTMENTS_RECEPTION_AND_ASSIGNMENT_ROUTE}/${workingCase.id}`} nextIsLoading={isLoadingWorkingCase} onNextButtonClick={() => { - if (!schedulingArraignmentDate) { + if (!isSchedulingArraignmentDate) { router.push( `${constants.INDICTMENTS_DEFENDER_ROUTE}/${workingCase.id}`, ) } else setNavigateTo(constants.INDICTMENTS_DEFENDER_ROUTE) }} nextButtonText={ - !schedulingArraignmentDate + !isSchedulingArraignmentDate ? undefined : formatMessage(strings.nextButtonText) } From 414ec712a6a00efec0c723432c17d2f77f69becd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gu=C3=B0j=C3=B3n=20Gu=C3=B0j=C3=B3nsson?= Date: Fri, 27 Sep 2024 15:24:49 +0200 Subject: [PATCH 07/18] Supports multiple subpoenas per defendant --- .../defendant/models/defendant.model.ts | 5 + .../defendant/models/subpoena.model.ts | 31 ++++ .../src/app/modules/file/file.controller.ts | 6 +- .../20240926131706-update-subpoena.js | 61 +++++++ .../backend/src/app/formatters/subpoenaPdf.ts | 20 +-- .../src/app/modules/case/case.module.ts | 2 + .../src/app/modules/case/case.service.ts | 149 ++++++++++++------ .../app/modules/case/internalCase.service.ts | 2 +- .../modules/case/limitedAccessCase.service.ts | 19 ++- .../src/app/modules/case/pdf.service.ts | 3 + .../modules/defendant/defendant.controller.ts | 60 +------ .../app/modules/defendant/defendant.module.ts | 5 +- .../src/app/modules/defendant/index.ts | 2 + .../subpoena/guards/subpoenaExists.guard.ts | 39 ++++- .../backend/src/app/modules/subpoena/index.ts | 2 + .../subpoena/internalSubpoena.controller.ts | 21 +-- .../limitedAccessSubpoena.controller.ts} | 22 ++- .../modules/subpoena/models/subpoena.model.ts | 12 +- .../modules/subpoena/subpoena.controller.ts | 109 +++++++++++++ .../app/modules/subpoena/subpoena.module.ts | 11 +- .../app/modules/subpoena/subpoena.service.ts | 36 ++++- .../src/app/messageHandler.service.ts | 8 +- .../src/components/FormProvider/case.graphql | 4 + .../FormProvider/limitedAccessCase.graphql | 4 + .../IndictmentCaseFilesList.strings.ts | 4 +- .../IndictmentCaseFilesList.tsx | 37 +++-- .../src/components/PdfButton/PdfButton.tsx | 6 +- .../Court/Indictments/Subpoena/Subpoena.tsx | 78 ++++++--- .../message/src/lib/message.ts | 2 +- 29 files changed, 552 insertions(+), 208 deletions(-) create mode 100644 apps/judicial-system/api/src/app/modules/defendant/models/subpoena.model.ts create mode 100644 apps/judicial-system/backend/migrations/20240926131706-update-subpoena.js create mode 100644 apps/judicial-system/backend/src/app/modules/subpoena/index.ts rename apps/judicial-system/backend/src/app/modules/{defendant/limitedAccessDefendant.controller.ts => subpoena/limitedAccessSubpoena.controller.ts} (70%) create mode 100644 apps/judicial-system/backend/src/app/modules/subpoena/subpoena.controller.ts diff --git a/apps/judicial-system/api/src/app/modules/defendant/models/defendant.model.ts b/apps/judicial-system/api/src/app/modules/defendant/models/defendant.model.ts index cc761d4b363a..595b696e2c28 100644 --- a/apps/judicial-system/api/src/app/modules/defendant/models/defendant.model.ts +++ b/apps/judicial-system/api/src/app/modules/defendant/models/defendant.model.ts @@ -8,6 +8,8 @@ import { SubpoenaType, } from '@island.is/judicial-system/types' +import { Subpoena } from './subpoena.model' + registerEnumType(Gender, { name: 'Gender' }) registerEnumType(DefendantPlea, { name: 'DefendantPlea' }) registerEnumType(ServiceRequirement, { name: 'ServiceRequirement' }) @@ -75,4 +77,7 @@ export class Defendant { @Field(() => SubpoenaType, { nullable: true }) readonly subpoenaType?: SubpoenaType + + @Field(() => [Subpoena], { nullable: true }) + readonly subpoenas?: Subpoena[] } diff --git a/apps/judicial-system/api/src/app/modules/defendant/models/subpoena.model.ts b/apps/judicial-system/api/src/app/modules/defendant/models/subpoena.model.ts new file mode 100644 index 000000000000..9ba54e366b30 --- /dev/null +++ b/apps/judicial-system/api/src/app/modules/defendant/models/subpoena.model.ts @@ -0,0 +1,31 @@ +import { Field, ID, ObjectType } from '@nestjs/graphql' + +@ObjectType() +export class Subpoena { + @Field(() => ID) + readonly id!: string + + @Field(() => String, { nullable: true }) + created?: string + + @Field(() => String, { nullable: true }) + modified?: string + + @Field(() => String, { nullable: true }) + subpoenaId?: string + + @Field(() => String, { nullable: true }) + acknowledged?: string + + @Field(() => String, { nullable: true }) + registeredBy?: string + + @Field(() => String, { nullable: true }) + comment?: string + + @Field(() => String, { nullable: true }) + arraignmentDate?: string + + @Field(() => String, { nullable: true }) + location?: string +} diff --git a/apps/judicial-system/api/src/app/modules/file/file.controller.ts b/apps/judicial-system/api/src/app/modules/file/file.controller.ts index e705f0e43c4e..d278438871f3 100644 --- a/apps/judicial-system/api/src/app/modules/file/file.controller.ts +++ b/apps/judicial-system/api/src/app/modules/file/file.controller.ts @@ -177,11 +177,12 @@ export class FileController { ) } - @Get('subpoena/:defendantId') + @Get(['subpoena/:defendantId', 'subpoena/:defendantId/:subpoenaId']) @Header('Content-Type', 'application/pdf') getSubpoenaPdf( @Param('id') id: string, @Param('defendantId') defendantId: string, + @Param('subpoenaId') subpoenaId: string, @CurrentHttpUser() user: User, @Req() req: Request, @Res() res: Response, @@ -193,6 +194,7 @@ export class FileController { `Getting the subpoena for defendant ${defendantId} of case ${id} as a pdf document`, ) + const subpoenaIdInjection = subpoenaId ? `/${subpoenaId}` : '' const queryInjection = arraignmentDate ? `?arraignmentDate=${arraignmentDate}&location=${location}&subpoenaType=${subpoenaType}` : '' @@ -201,7 +203,7 @@ export class FileController { user.id, AuditedAction.GET_SUBPOENA_PDF, id, - `defendant/${defendantId}/subpoena${queryInjection}`, + `defendant/${defendantId}/subpoena${subpoenaIdInjection}${queryInjection}`, req, res, 'pdf', diff --git a/apps/judicial-system/backend/migrations/20240926131706-update-subpoena.js b/apps/judicial-system/backend/migrations/20240926131706-update-subpoena.js new file mode 100644 index 000000000000..f4e74d657c49 --- /dev/null +++ b/apps/judicial-system/backend/migrations/20240926131706-update-subpoena.js @@ -0,0 +1,61 @@ +'use strict' + +module.exports = { + up(queryInterface, Sequelize) { + return queryInterface.sequelize.transaction((transaction) => + Promise.all([ + queryInterface.addColumn( + 'subpoena', + 'arraignment_date', + { + type: Sequelize.DATE, + allowNull: false, + defaultValue: Sequelize.literal('CURRENT_TIMESTAMP'), + }, + { transaction }, + ), + queryInterface.addColumn( + 'subpoena', + 'location', + { type: Sequelize.STRING, allowNull: false, defaultValue: 'óþekkt' }, + { transaction }, + ), + queryInterface.changeColumn( + 'subpoena', + 'case_id', + { + type: Sequelize.UUID, + allowNull: false, + }, + { transaction }, + ), + ]).then(() => + queryInterface.sequelize.query( + `ALTER TABLE subpoena ALTER COLUMN arraignment_date DROP DEFAULT; + ALTER TABLE subpoena ALTER COLUMN location DROP DEFAULT;`, + { transaction }, + ), + ), + ) + }, + + down(queryInterface, Sequelize) { + return queryInterface.sequelize.transaction((transaction) => + Promise.all([ + queryInterface.removeColumn('subpoena', 'arraignment_date', { + transaction, + }), + queryInterface.removeColumn('subpoena', 'location', { transaction }), + queryInterface.changeColumn( + 'subpoena', + 'case_id', + { + type: Sequelize.UUID, + allowNull: true, + }, + { transaction }, + ), + ]), + ) + }, +} diff --git a/apps/judicial-system/backend/src/app/formatters/subpoenaPdf.ts b/apps/judicial-system/backend/src/app/formatters/subpoenaPdf.ts index b2b3096a0eb6..95567e0bd7a4 100644 --- a/apps/judicial-system/backend/src/app/formatters/subpoenaPdf.ts +++ b/apps/judicial-system/backend/src/app/formatters/subpoenaPdf.ts @@ -7,11 +7,13 @@ import { formatDOB, lowercase, } from '@island.is/judicial-system/formatters' -import { DateType, SubpoenaType } from '@island.is/judicial-system/types' +import { SubpoenaType } from '@island.is/judicial-system/types' +import { nowFactory } from '../factories/date.factory' import { subpoena as strings } from '../messages' import { Case } from '../modules/case' import { Defendant } from '../modules/defendant' +import { Subpoena } from '../modules/subpoena' import { addConfirmation, addEmptyLines, @@ -27,6 +29,7 @@ export const createSubpoena = ( theCase: Case, defendant: Defendant, formatMessage: FormatMessage, + subpoena?: Subpoena, arraignmentDate?: Date, location?: string, subpoenaType?: SubpoenaType, @@ -43,15 +46,12 @@ export const createSubpoena = ( }) const sinc: Buffer[] = [] - const dateLog = arraignmentDate - ? undefined - : theCase.dateLogs?.find((d) => d.dateType === DateType.ARRAIGNMENT_DATE) doc.on('data', (chunk) => sinc.push(chunk)) setTitle(doc, formatMessage(strings.title)) - if (dateLog) { + if (subpoena) { addEmptyLines(doc, 5) } @@ -59,12 +59,12 @@ export const createSubpoena = ( addNormalRightAlignedText( doc, - `${formatDate(new Date(dateLog?.modified ?? new Date()), 'PPP')}`, + `${formatDate(new Date(subpoena?.created ?? nowFactory()), 'PPP')}`, 'Times-Roman', ) - arraignmentDate = arraignmentDate ?? dateLog?.date - location = location ?? dateLog?.location + arraignmentDate = arraignmentDate ?? subpoena?.arraignmentDate + location = location ?? subpoena?.location subpoenaType = subpoenaType ?? defendant.subpoenaType if (theCase.court?.name) { @@ -154,12 +154,12 @@ export const createSubpoena = ( addFooter(doc) - if (dateLog) { + if (subpoena) { addConfirmation(doc, { actor: theCase.judge?.name || '', title: theCase.judge?.title, institution: theCase.judge?.institution?.name || '', - date: dateLog.modified, + date: subpoena.created, }) } diff --git a/apps/judicial-system/backend/src/app/modules/case/case.module.ts b/apps/judicial-system/backend/src/app/modules/case/case.module.ts index 10d099b3068b..139bff373cfe 100644 --- a/apps/judicial-system/backend/src/app/modules/case/case.module.ts +++ b/apps/judicial-system/backend/src/app/modules/case/case.module.ts @@ -15,6 +15,7 @@ import { FileModule, IndictmentCountModule, PoliceModule, + SubpoenaModule, UserModule, } from '../index' import { Case } from './models/case.model' @@ -35,6 +36,7 @@ import { PdfService } from './pdf.service' CmsTranslationsModule, MessageModule, forwardRef(() => DefendantModule), + forwardRef(() => SubpoenaModule), forwardRef(() => UserModule), forwardRef(() => FileModule), forwardRef(() => IndictmentCountModule), diff --git a/apps/judicial-system/backend/src/app/modules/case/case.service.ts b/apps/judicial-system/backend/src/app/modules/case/case.service.ts index 65ad33c4d2ee..eb56a53fbe28 100644 --- a/apps/judicial-system/backend/src/app/modules/case/case.service.ts +++ b/apps/judicial-system/backend/src/app/modules/case/case.service.ts @@ -62,6 +62,7 @@ import { CaseFile, FileService } from '../file' import { IndictmentCount } from '../indictment-count' import { Institution } from '../institution' import { Notification } from '../notification' +import { Subpoena, SubpoenaService } from '../subpoena' import { User } from '../user' import { CreateCaseDto } from './dto/createCase.dto' import { getCasesQueryFilter } from './filters/cases.filter' @@ -271,7 +272,22 @@ export const include: Includeable[] = [ ], }, { model: Case, as: 'childCase' }, - { model: Defendant, as: 'defendants' }, + { + model: Defendant, + as: 'defendants', + required: false, + order: [['created', 'ASC']], + include: [ + { + model: Subpoena, + as: 'subpoenas', + required: false, + order: [['created', 'DESC']], + separate: true, + }, + ], + separate: true, + }, { model: CivilClaimant, as: 'civilClaimants' }, { model: IndictmentCount, as: 'indictmentCounts' }, { @@ -340,7 +356,6 @@ export const include: Includeable[] = [ ] export const order: OrderItem[] = [ - [{ model: Defendant, as: 'defendants' }, 'created', 'ASC'], [{ model: CivilClaimant, as: 'civilClaimants' }, 'created', 'ASC'], [{ model: IndictmentCount, as: 'indictmentCounts' }, 'created', 'ASC'], [{ model: DateLog, as: 'dateLogs' }, 'created', 'DESC'], @@ -412,6 +427,7 @@ export class CaseService { @Inject(caseModuleConfig.KEY) private readonly config: ConfigType, private readonly defendantService: DefendantService, + private readonly subpoenaService: SubpoenaService, private readonly fileService: FileService, private readonly awsS3Service: AwsS3Service, private readonly courtService: CourtService, @@ -1146,29 +1162,42 @@ export class CaseService { private addMessagesForNewCourtDateToQueue( theCase: Case, user: TUser, - arraignmentDateChanged: boolean, ): Promise { - const messages: Message[] = [ + return this.messageService.sendMessagesToQueue([ { type: MessageType.NOTIFICATION, user, caseId: theCase.id, body: { type: NotificationType.COURT_DATE }, }, - ] + ]) + } - if (arraignmentDateChanged) { - theCase.defendants?.forEach((defendant) => { - messages.push({ - type: MessageType.DELIVERY_TO_POLICE_SUBPOENA, - user, - caseId: theCase.id, - elementId: defendant.id, - }) - }) + private addMessagesForNewSubpoenasToQueue( + theCase: Case, + updatedCase: Case, + user: TUser, + ) { + const messages = updatedCase.defendants + ?.filter( + (updatedDefendant) => + theCase.defendants?.find( + (defendant) => defendant.id === updatedDefendant.id, + )?.subpoenas?.[0].id !== updatedDefendant.subpoenas?.[0].id, + ) + .map((updatedDefendant) => ({ + type: MessageType.DELIVERY_TO_POLICE_SUBPOENA, + user, + caseId: theCase.id, + elementId: [ + updatedDefendant.id, + updatedDefendant.subpoenas?.[0].id ?? '', + ], + })) + + if (messages && messages.length > 0) { + return this.messageService.sendMessagesToQueue(messages) } - - return this.messageService.sendMessagesToQueue(messages) } private async addMessagesForUpdatedCaseToQueue( @@ -1344,12 +1373,10 @@ export class CaseService { if (arraignmentDateChanged || courtDateChanged) { // New arraignment date or new court date - await this.addMessagesForNewCourtDateToQueue( - updatedCase, - user, - Boolean(arraignmentDateChanged), - ) + await this.addMessagesForNewCourtDateToQueue(updatedCase, user) } + + await this.addMessagesForNewSubpoenasToQueue(theCase, updatedCase, user) } } @@ -1628,8 +1655,18 @@ export class CaseService { isIndictmentCase(theCase.type) && update.state === CaseState.DRAFT && theCase.state === CaseState.RECEIVED - const completingIndictmentCase = - isIndictmentCase(theCase.type) && update.state === CaseState.COMPLETED + const completingIndictmentCaseWithoutRuling = + isIndictmentCase(theCase.type) && + update.state === CaseState.COMPLETED && + theCase.indictmentRulingDecision && + [ + CaseIndictmentRulingDecision.FINE, + CaseIndictmentRulingDecision.CANCELLATION, + CaseIndictmentRulingDecision.MERGE, + ].includes(theCase.indictmentRulingDecision) + const updatedArraignmentDate = update.arraignmentDate + const schedulingNewArraignmentDateForIndictmentCase = + isIndictmentCase(theCase.type) && Boolean(updatedArraignmentDate) return this.sequelize .transaction(async (transaction) => { @@ -1646,24 +1683,22 @@ export class CaseService { await this.handleCommentUpdates(theCase, update, transaction) await this.handleEventLogs(theCase, update, user, transaction) - if (Object.keys(update).length === 0) { - return - } - - const [numberOfAffectedRows] = await this.caseModel.update(update, { - where: { id: theCase.id }, - transaction, - }) + if (Object.keys(update).length > 0) { + const [numberOfAffectedRows] = await this.caseModel.update(update, { + where: { id: theCase.id }, + transaction, + }) - if (numberOfAffectedRows > 1) { - // Tolerate failure, but log error - this.logger.error( - `Unexpected number of rows (${numberOfAffectedRows}) affected when updating case ${theCase.id}`, - ) - } else if (numberOfAffectedRows < 1) { - throw new InternalServerErrorException( - `Could not update case ${theCase.id}`, - ) + if (numberOfAffectedRows > 1) { + // Tolerate failure, but log error + this.logger.error( + `Unexpected number of rows (${numberOfAffectedRows}) affected when updating case ${theCase.id}`, + ) + } else if (numberOfAffectedRows < 1) { + throw new InternalServerErrorException( + `Could not update case ${theCase.id}`, + ) + } } // Update police case numbers of case files if necessary @@ -1689,22 +1724,34 @@ export class CaseService { ) } - if ( - completingIndictmentCase && - theCase.indictmentRulingDecision && - [ - CaseIndictmentRulingDecision.FINE, - CaseIndictmentRulingDecision.CANCELLATION, - ].includes(theCase.indictmentRulingDecision) - ) { + // Remove uploaded ruling files if an indictment case is completed without a ruling + if (completingIndictmentCaseWithoutRuling && theCase.caseFiles) { await Promise.all( theCase.caseFiles - ?.filter( + .filter( (caseFile) => caseFile.category === CaseFileCategory.RULING, ) - ?.map((caseFile) => + .map((caseFile) => this.fileService.deleteCaseFile(theCase, caseFile, transaction), - ) ?? [], + ), + ) + } + + // Create new subpoeans if scheduling a new arraignment date for an indictment case + if ( + schedulingNewArraignmentDateForIndictmentCase && + theCase.defendants + ) { + await Promise.all( + theCase.defendants.map((defendant) => + this.subpoenaService.createSubpoena( + defendant.id, + theCase.id, + updatedArraignmentDate?.date, + updatedArraignmentDate?.location, + transaction, + ), + ), ) } }) diff --git a/apps/judicial-system/backend/src/app/modules/case/internalCase.service.ts b/apps/judicial-system/backend/src/app/modules/case/internalCase.service.ts index 4ef8b7b5a247..26377502db54 100644 --- a/apps/judicial-system/backend/src/app/modules/case/internalCase.service.ts +++ b/apps/judicial-system/backend/src/app/modules/case/internalCase.service.ts @@ -58,7 +58,7 @@ import { CaseFile, FileService } from '../file' import { IndictmentCount, IndictmentCountService } from '../indictment-count' import { Institution } from '../institution' import { PoliceDocument, PoliceDocumentType, PoliceService } from '../police' -import { Subpoena } from '../subpoena/models/subpoena.model' +import { Subpoena } from '../subpoena' import { User, UserService } from '../user' import { InternalCreateCaseDto } from './dto/internalCreateCase.dto' import { archiveFilter } from './filters/case.archiveFilter' diff --git a/apps/judicial-system/backend/src/app/modules/case/limitedAccessCase.service.ts b/apps/judicial-system/backend/src/app/modules/case/limitedAccessCase.service.ts index fa2e9b5bbaeb..efeaf459c19a 100644 --- a/apps/judicial-system/backend/src/app/modules/case/limitedAccessCase.service.ts +++ b/apps/judicial-system/backend/src/app/modules/case/limitedAccessCase.service.ts @@ -38,6 +38,7 @@ import { } from '../file' import { IndictmentCount } from '../indictment-count' import { Institution } from '../institution' +import { Subpoena } from '../subpoena' import { User } from '../user' import { Case } from './models/case.model' import { CaseString } from './models/caseString.model' @@ -170,7 +171,22 @@ export const include: Includeable[] = [ }, { model: Case, as: 'parentCase', attributes }, { model: Case, as: 'childCase', attributes }, - { model: Defendant, as: 'defendants' }, + { + model: Defendant, + as: 'defendants', + required: false, + order: [['created', 'ASC']], + include: [ + { + model: Subpoena, + as: 'subpoenas', + required: false, + order: [['created', 'DESC']], + separate: true, + }, + ], + separate: true, + }, { model: IndictmentCount, as: 'indictmentCounts' }, { model: CivilClaimant, as: 'civilClaimants' }, { @@ -255,7 +271,6 @@ export const include: Includeable[] = [ ] export const order: OrderItem[] = [ - [{ model: Defendant, as: 'defendants' }, 'created', 'ASC'], [{ model: IndictmentCount, as: 'indictmentCounts' }, 'created', 'ASC'], [{ model: CivilClaimant, as: 'civilClaimants' }, 'created', 'ASC'], [{ model: DateLog, as: 'dateLogs' }, 'created', 'DESC'], diff --git a/apps/judicial-system/backend/src/app/modules/case/pdf.service.ts b/apps/judicial-system/backend/src/app/modules/case/pdf.service.ts index 6b956856ebb1..140501e17c59 100644 --- a/apps/judicial-system/backend/src/app/modules/case/pdf.service.ts +++ b/apps/judicial-system/backend/src/app/modules/case/pdf.service.ts @@ -33,6 +33,7 @@ import { } from '../../formatters' import { AwsS3Service } from '../aws-s3' import { Defendant } from '../defendant' +import { Subpoena } from '../subpoena' import { UserService } from '../user' import { Case } from './models/case.model' @@ -292,6 +293,7 @@ export class PdfService { async getSubpoenaPdf( theCase: Case, defendant: Defendant, + subpoena: Subpoena, arraignmentDate?: Date, location?: string, subpoenaType?: SubpoenaType, @@ -302,6 +304,7 @@ export class PdfService { theCase, defendant, this.formatMessage, + subpoena, arraignmentDate, location, subpoenaType, diff --git a/apps/judicial-system/backend/src/app/modules/defendant/defendant.controller.ts b/apps/judicial-system/backend/src/app/modules/defendant/defendant.controller.ts index cb7ab62524ed..94bfed1fc023 100644 --- a/apps/judicial-system/backend/src/app/modules/defendant/defendant.controller.ts +++ b/apps/judicial-system/backend/src/app/modules/defendant/defendant.controller.ts @@ -1,17 +1,11 @@ -import { Response } from 'express' - import { Body, Controller, Delete, - Get, - Header, Inject, Param, Patch, Post, - Query, - Res, UseGuards, } from '@nestjs/common' import { ApiCreatedResponse, ApiOkResponse, ApiTags } from '@nestjs/swagger' @@ -25,12 +19,7 @@ import { RolesGuard, RolesRules, } from '@island.is/judicial-system/auth' -import { - indictmentCases, - ServiceRequirement, - SubpoenaType, - type User, -} from '@island.is/judicial-system/types' +import { ServiceRequirement, type User } from '@island.is/judicial-system/types' import { districtCourtAssistantRule, @@ -43,8 +32,6 @@ import { import { Case, CaseExistsGuard, - CaseReadGuard, - CaseTypeGuard, CaseWriteGuard, CurrentCase, PdfService, @@ -148,49 +135,4 @@ export class DefendantController { return { deleted } } - - @UseGuards( - CaseExistsGuard, - new CaseTypeGuard(indictmentCases), - CaseReadGuard, - DefendantExistsGuard, - ) - @RolesRules( - prosecutorRule, - prosecutorRepresentativeRule, - publicProsecutorStaffRule, - districtCourtJudgeRule, - districtCourtRegistrarRule, - districtCourtAssistantRule, - ) - @Get(':defendantId/subpoena') - @Header('Content-Type', 'application/pdf') - @ApiOkResponse({ - content: { 'application/pdf': {} }, - description: 'Gets the subpoena for a given defendant as a pdf document', - }) - async getSubpoenaPdf( - @Param('caseId') caseId: string, - @Param('defendantId') defendantId: string, - @CurrentCase() theCase: Case, - @CurrentDefendant() defendant: Defendant, - @Res() res: Response, - @Query('arraignmentDate') arraignmentDate?: Date, - @Query('location') location?: string, - @Query('subpoenaType') subpoenaType?: SubpoenaType, - ): Promise { - this.logger.debug( - `Getting the subpoena for defendant ${defendantId} of case ${caseId} as a pdf document`, - ) - - const pdf = await this.pdfService.getSubpoenaPdf( - theCase, - defendant, - arraignmentDate, - location, - subpoenaType, - ) - - res.end(pdf) - } } diff --git a/apps/judicial-system/backend/src/app/modules/defendant/defendant.module.ts b/apps/judicial-system/backend/src/app/modules/defendant/defendant.module.ts index 7fc42f0f16fa..a7cb4fca9e0f 100644 --- a/apps/judicial-system/backend/src/app/modules/defendant/defendant.module.ts +++ b/apps/judicial-system/backend/src/app/modules/defendant/defendant.module.ts @@ -5,7 +5,6 @@ import { MessageModule } from '@island.is/judicial-system/message' import { CaseModule } from '../case/case.module' import { CourtModule } from '../court/court.module' -import { Subpoena } from '../subpoena/models/subpoena.model' import { CivilClaimant } from './models/civilClaimant.model' import { Defendant } from './models/defendant.model' import { CivilClaimantController } from './civilClaimant.controller' @@ -13,19 +12,17 @@ import { CivilClaimantService } from './civilClaimant.service' import { DefendantController } from './defendant.controller' import { DefendantService } from './defendant.service' import { InternalDefendantController } from './internalDefendant.controller' -import { LimitedAccessDefendantController } from './limitedAccessDefendant.controller' @Module({ imports: [ MessageModule, forwardRef(() => CourtModule), forwardRef(() => CaseModule), - SequelizeModule.forFeature([Defendant, CivilClaimant, Subpoena]), + SequelizeModule.forFeature([Defendant, CivilClaimant]), ], controllers: [ DefendantController, InternalDefendantController, - LimitedAccessDefendantController, CivilClaimantController, ], providers: [DefendantService, CivilClaimantService], diff --git a/apps/judicial-system/backend/src/app/modules/defendant/index.ts b/apps/judicial-system/backend/src/app/modules/defendant/index.ts index 3839cdb96469..ed6753c1f764 100644 --- a/apps/judicial-system/backend/src/app/modules/defendant/index.ts +++ b/apps/judicial-system/backend/src/app/modules/defendant/index.ts @@ -1,3 +1,5 @@ export { Defendant } from './models/defendant.model' export { DefendantService } from './defendant.service' export { CivilClaimant } from './models/civilClaimant.model' +export { DefendantExistsGuard } from './guards/defendantExists.guard' +export { CurrentDefendant } from './guards/defendant.decorator' diff --git a/apps/judicial-system/backend/src/app/modules/subpoena/guards/subpoenaExists.guard.ts b/apps/judicial-system/backend/src/app/modules/subpoena/guards/subpoenaExists.guard.ts index 0280c3f51f99..71a5672010c6 100644 --- a/apps/judicial-system/backend/src/app/modules/subpoena/guards/subpoenaExists.guard.ts +++ b/apps/judicial-system/backend/src/app/modules/subpoena/guards/subpoenaExists.guard.ts @@ -5,6 +5,7 @@ import { Injectable, } from '@nestjs/common' +import { Defendant } from '../../defendant' import { SubpoenaService } from '../subpoena.service' @Injectable() @@ -20,8 +21,44 @@ export class SubpoenaExistsGuard implements CanActivate { throw new BadRequestException('Missing subpoena id') } - request.subpoena = await this.subpoenaService.findBySubpoenaId(subpoenaId) + const defendant: Defendant = request.defendant + + if (!defendant) { + request.subpoena = await this.subpoenaService.findBySubpoenaId(subpoenaId) + + return true + } + + const subpoena = defendant.subpoenas?.find( + (subpoena) => subpoena.id === subpoenaId, + ) + + if (!subpoena) { + throw new BadRequestException( + `Subpoena ${subpoenaId} of defendant ${defendant.id} does not exist`, + ) + } + + request.subpoena = subpoena return true } } + +@Injectable() +export class SubpoenaExistsOptionalGuard extends SubpoenaExistsGuard { + constructor(subpoenaService: SubpoenaService) { + super(subpoenaService) + } + async canActivate(context: ExecutionContext): Promise { + const request = context.switchToHttp().getRequest() + + const subpoenaId = request.params.subpoenaId + + if (!subpoenaId) { + return true + } + + return super.canActivate(context) + } +} diff --git a/apps/judicial-system/backend/src/app/modules/subpoena/index.ts b/apps/judicial-system/backend/src/app/modules/subpoena/index.ts new file mode 100644 index 000000000000..828b617f4f30 --- /dev/null +++ b/apps/judicial-system/backend/src/app/modules/subpoena/index.ts @@ -0,0 +1,2 @@ +export { SubpoenaService } from './subpoena.service' +export { Subpoena } from './models/subpoena.model' diff --git a/apps/judicial-system/backend/src/app/modules/subpoena/internalSubpoena.controller.ts b/apps/judicial-system/backend/src/app/modules/subpoena/internalSubpoena.controller.ts index a0f909375a80..aef0e88065b6 100644 --- a/apps/judicial-system/backend/src/app/modules/subpoena/internalSubpoena.controller.ts +++ b/apps/judicial-system/backend/src/app/modules/subpoena/internalSubpoena.controller.ts @@ -1,5 +1,3 @@ -import { Base64 } from 'js-base64' - import { Body, Controller, @@ -22,12 +20,7 @@ import { } from '@island.is/judicial-system/message' import { indictmentCases } from '@island.is/judicial-system/types' -import { - CaseExistsGuard, - CaseTypeGuard, - CurrentCase, - PdfService, -} from '../case' +import { CaseExistsGuard, CaseTypeGuard, CurrentCase } from '../case' import { Case } from '../case/models/case.model' import { CurrentDefendant } from '../defendant/guards/defendant.decorator' import { DefendantExistsGuard } from '../defendant/guards/defendantExists.guard' @@ -46,7 +39,6 @@ import { SubpoenaService } from './subpoena.service' export class InternalSubpoenaController { constructor( private readonly subpoenaService: SubpoenaService, - private readonly pdfService: PdfService, @Inject(LOGGER_PROVIDER) private readonly logger: Logger, ) {} @@ -77,11 +69,12 @@ export class InternalSubpoenaController { CaseExistsGuard, new CaseTypeGuard(indictmentCases), DefendantExistsGuard, + SubpoenaExistsGuard, ) @Post( `case/:caseId/${ messageEndpoint[MessageType.DELIVERY_TO_POLICE_SUBPOENA] - }/:defendantId`, + }/:defendantId/:subpoenaId`, ) @ApiOkResponse({ type: DeliverResponse, @@ -90,20 +83,20 @@ export class InternalSubpoenaController { async deliverSubpoenaToPolice( @Param('caseId') caseId: string, @Param('defendantId') defendantId: string, + @Param('subpoenaId') subpoenaId: string, @CurrentCase() theCase: Case, @CurrentDefendant() defendant: Defendant, + @CurrentSubpoena() subpoena: Subpoena, @Body() deliverDto: DeliverDto, ): Promise { this.logger.debug( - `Delivering subpoena ${caseId} to police for defendant ${defendantId}`, + `Delivering subpoena ${subpoenaId} to police for defendant ${defendantId} og case ${caseId}`, ) - const pdf = await this.pdfService.getSubpoenaPdf(theCase, defendant) - return await this.subpoenaService.deliverSubpoenaToPolice( theCase, defendant, - Base64.btoa(pdf.toString('binary')), + subpoena, deliverDto.user, ) } diff --git a/apps/judicial-system/backend/src/app/modules/defendant/limitedAccessDefendant.controller.ts b/apps/judicial-system/backend/src/app/modules/subpoena/limitedAccessSubpoena.controller.ts similarity index 70% rename from apps/judicial-system/backend/src/app/modules/defendant/limitedAccessDefendant.controller.ts rename to apps/judicial-system/backend/src/app/modules/subpoena/limitedAccessSubpoena.controller.ts index d2e79ab2ef40..9a4c195e465e 100644 --- a/apps/judicial-system/backend/src/app/modules/defendant/limitedAccessDefendant.controller.ts +++ b/apps/judicial-system/backend/src/app/modules/subpoena/limitedAccessSubpoena.controller.ts @@ -31,11 +31,15 @@ import { CurrentCase, PdfService, } from '../case' -import { CurrentDefendant } from './guards/defendant.decorator' -import { DefendantExistsGuard } from './guards/defendantExists.guard' -import { Defendant } from './models/defendant.model' +import { CurrentDefendant, Defendant, DefendantExistsGuard } from '../defendant' +import { CurrentSubpoena } from './guards/subpoena.decorator' +import { SubpoenaExistsOptionalGuard } from './guards/subpoenaExists.guard' +import { Subpoena } from './models/subpoena.model' -@Controller('api/case/:caseId/limitedAccess/defendant/:defendantId/subpoena') +@Controller([ + 'api/case/:caseId/limitedAccess/defendant/:defendantId/subpoena', + 'api/case/:caseId/limitedAccess/defendant/:defendantId/subpoena/:subpoenaId', +]) @UseGuards( JwtAuthGuard, RolesGuard, @@ -43,9 +47,10 @@ import { Defendant } from './models/defendant.model' new CaseTypeGuard(indictmentCases), CaseReadGuard, DefendantExistsGuard, + SubpoenaExistsOptionalGuard, ) @ApiTags('limited access defendants') -export class LimitedAccessDefendantController { +export class LimitedAccessSubpoenaController { constructor( private readonly pdfService: PdfService, @Inject(LOGGER_PROVIDER) private readonly logger: Logger, @@ -61,20 +66,25 @@ export class LimitedAccessDefendantController { async getSubpoenaPdf( @Param('caseId') caseId: string, @Param('defendantId') defendantId: string, + @Param('subpoenaId') subpoenaId: string, @CurrentCase() theCase: Case, @CurrentDefendant() defendant: Defendant, + @CurrentSubpoena() subpoena: Subpoena, @Res() res: Response, @Query('arraignmentDate') arraignmentDate?: Date, @Query('location') location?: string, @Query('subpoenaType') subpoenaType?: SubpoenaType, ): Promise { this.logger.debug( - `Getting the subpoena for defendant ${defendantId} of case ${caseId} as a pdf document`, + `Getting subpoena ${ + subpoenaId ?? 'draft' + } for defendant ${defendantId} of case ${caseId} as a pdf document`, ) const pdf = await this.pdfService.getSubpoenaPdf( theCase, defendant, + subpoena, arraignmentDate, location, subpoenaType, diff --git a/apps/judicial-system/backend/src/app/modules/subpoena/models/subpoena.model.ts b/apps/judicial-system/backend/src/app/modules/subpoena/models/subpoena.model.ts index 5a540fd3af27..933b1633e1bb 100644 --- a/apps/judicial-system/backend/src/app/modules/subpoena/models/subpoena.model.ts +++ b/apps/judicial-system/backend/src/app/modules/subpoena/models/subpoena.model.ts @@ -49,9 +49,9 @@ export class Subpoena extends Model { defendant?: Defendant @ForeignKey(() => Case) - @Column({ type: DataType.UUID, allowNull: true }) + @Column({ type: DataType.UUID }) @ApiProperty({ type: String }) - caseId?: string + caseId!: string @BelongsTo(() => Case, 'caseId') @ApiPropertyOptional({ type: Case }) @@ -68,4 +68,12 @@ export class Subpoena extends Model { @Column({ type: DataType.TEXT, allowNull: true }) @ApiPropertyOptional({ type: String }) comment?: string + + @Column({ type: DataType.DATE, allowNull: false }) + @ApiProperty({ type: Date }) + arraignmentDate!: Date + + @Column({ type: DataType.STRING, allowNull: false }) + @ApiProperty({ type: String }) + location!: string } diff --git a/apps/judicial-system/backend/src/app/modules/subpoena/subpoena.controller.ts b/apps/judicial-system/backend/src/app/modules/subpoena/subpoena.controller.ts new file mode 100644 index 000000000000..e6f4ad8abc51 --- /dev/null +++ b/apps/judicial-system/backend/src/app/modules/subpoena/subpoena.controller.ts @@ -0,0 +1,109 @@ +import { Response } from 'express' + +import { + Controller, + Get, + Header, + Inject, + Param, + Query, + Res, + UseGuards, +} from '@nestjs/common' +import { ApiOkResponse, ApiTags } from '@nestjs/swagger' + +import { type Logger, LOGGER_PROVIDER } from '@island.is/logging' + +import { + JwtAuthGuard, + RolesGuard, + RolesRules, +} from '@island.is/judicial-system/auth' +import { indictmentCases, SubpoenaType } from '@island.is/judicial-system/types' + +import { + districtCourtAssistantRule, + districtCourtJudgeRule, + districtCourtRegistrarRule, + prosecutorRepresentativeRule, + prosecutorRule, + publicProsecutorStaffRule, +} from '../../guards' +import { + Case, + CaseExistsGuard, + CaseReadGuard, + CaseTypeGuard, + CurrentCase, + PdfService, +} from '../case' +import { Defendant } from '../defendant' +import { CurrentDefendant } from '../defendant/guards/defendant.decorator' +import { DefendantExistsGuard } from '../defendant/guards/defendantExists.guard' +import { CurrentSubpoena } from './guards/subpoena.decorator' +import { SubpoenaExistsOptionalGuard } from './guards/subpoenaExists.guard' +import { Subpoena } from './models/subpoena.model' + +@UseGuards(JwtAuthGuard, RolesGuard) +@Controller([ + 'api/case/:caseId/defendant/:defendantId/subpoena', + 'api/case/:caseId/defendant/:defendantId/subpoena/:subpoenaId', +]) +@ApiTags('subpoenas') +export class SubpoenaController { + constructor( + private readonly pdfService: PdfService, + @Inject(LOGGER_PROVIDER) private readonly logger: Logger, + ) {} + + @UseGuards( + CaseExistsGuard, + new CaseTypeGuard(indictmentCases), + CaseReadGuard, + DefendantExistsGuard, + SubpoenaExistsOptionalGuard, + ) + @RolesRules( + prosecutorRule, + prosecutorRepresentativeRule, + publicProsecutorStaffRule, + districtCourtJudgeRule, + districtCourtRegistrarRule, + districtCourtAssistantRule, + ) + @Get() + @Header('Content-Type', 'application/pdf') + @ApiOkResponse({ + content: { 'application/pdf': {} }, + description: 'Gets the subpoena for a given defendant as a pdf document', + }) + async getSubpoenaPdf( + @Param('caseId') caseId: string, + @Param('defendantId') defendantId: string, + @Param('subpoenaId') subpoenaId: string, + @CurrentCase() theCase: Case, + @CurrentDefendant() defendant: Defendant, + @CurrentSubpoena() subpoena: Subpoena, + @Res() res: Response, + @Query('arraignmentDate') arraignmentDate?: Date, + @Query('location') location?: string, + @Query('subpoenaType') subpoenaType?: SubpoenaType, + ): Promise { + this.logger.debug( + `Getting subpoena ${ + subpoenaId ?? 'draft' + } for defendant ${defendantId} of case ${caseId} as a pdf document`, + ) + + const pdf = await this.pdfService.getSubpoenaPdf( + theCase, + defendant, + subpoena, + arraignmentDate, + location, + subpoenaType, + ) + + res.end(pdf) + } +} diff --git a/apps/judicial-system/backend/src/app/modules/subpoena/subpoena.module.ts b/apps/judicial-system/backend/src/app/modules/subpoena/subpoena.module.ts index 1f40a7844f60..260e2154cfb5 100644 --- a/apps/judicial-system/backend/src/app/modules/subpoena/subpoena.module.ts +++ b/apps/judicial-system/backend/src/app/modules/subpoena/subpoena.module.ts @@ -2,21 +2,26 @@ import { forwardRef, Module } from '@nestjs/common' import { SequelizeModule } from '@nestjs/sequelize' import { CaseModule } from '../case/case.module' -import { DefendantModule } from '../defendant/defendant.module' import { Defendant } from '../defendant/models/defendant.model' import { PoliceModule } from '../police/police.module' import { Subpoena } from './models/subpoena.model' import { InternalSubpoenaController } from './internalSubpoena.controller' +import { LimitedAccessSubpoenaController } from './limitedAccessSubpoena.controller' +import { SubpoenaController } from './subpoena.controller' import { SubpoenaService } from './subpoena.service' @Module({ imports: [ forwardRef(() => CaseModule), - forwardRef(() => DefendantModule), forwardRef(() => PoliceModule), SequelizeModule.forFeature([Subpoena, Defendant]), ], - controllers: [InternalSubpoenaController], + controllers: [ + SubpoenaController, + InternalSubpoenaController, + LimitedAccessSubpoenaController, + ], providers: [SubpoenaService], + exports: [SubpoenaService], }) export class SubpoenaModule {} diff --git a/apps/judicial-system/backend/src/app/modules/subpoena/subpoena.service.ts b/apps/judicial-system/backend/src/app/modules/subpoena/subpoena.service.ts index c28cf4ec4875..08d0c4a83149 100644 --- a/apps/judicial-system/backend/src/app/modules/subpoena/subpoena.service.ts +++ b/apps/judicial-system/backend/src/app/modules/subpoena/subpoena.service.ts @@ -1,3 +1,4 @@ +import { Base64 } from 'js-base64' import { Includeable, Sequelize } from 'sequelize' import { Transaction } from 'sequelize/types' @@ -10,6 +11,7 @@ import { LOGGER_PROVIDER } from '@island.is/logging' import type { User } from '@island.is/judicial-system/types' import { Case } from '../case/models/case.model' +import { PdfService } from '../case/pdf.service' import { Defendant } from '../defendant/models/defendant.model' import { PoliceService } from '../police' import { UpdateSubpoenaDto } from './dto/updateSubpoena.dto' @@ -26,16 +28,28 @@ export class SubpoenaService { @InjectConnection() private readonly sequelize: Sequelize, @InjectModel(Subpoena) private readonly subpoenaModel: typeof Subpoena, @InjectModel(Defendant) private readonly defendantModel: typeof Defendant, + private readonly pdfService: PdfService, @Inject(forwardRef(() => PoliceService)) private readonly policeService: PoliceService, @Inject(LOGGER_PROVIDER) private readonly logger: Logger, ) {} - async createSubpoena(defendant: Defendant): Promise { - return await this.subpoenaModel.create({ - defendantId: defendant.id, - caseId: defendant.caseId, - }) + async createSubpoena( + defendantId: string, + caseId: string, + arraignmentDate?: Date, + location?: string, + transaction?: Transaction, + ): Promise { + return this.subpoenaModel.create( + { + defendantId, + caseId, + arraignmentDate, + location, + }, + { transaction }, + ) } async update( @@ -108,21 +122,26 @@ export class SubpoenaService { async deliverSubpoenaToPolice( theCase: Case, defendant: Defendant, - subpoenaFile: string, + subpoena: Subpoena, user: User, ): Promise { try { - const subpoena = await this.createSubpoena(defendant) + const pdf = await this.pdfService.getSubpoenaPdf( + theCase, + defendant, + subpoena, + ) const createdSubpoena = await this.policeService.createSubpoena( theCase, defendant, - subpoenaFile, + Base64.btoa(pdf.toString('binary')), user, ) if (!createdSubpoena) { this.logger.error('Failed to create subpoena file for police') + return { delivered: false } } @@ -135,6 +154,7 @@ export class SubpoenaService { return { delivered: true } } catch (error) { this.logger.error('Error delivering subpoena to police', error) + return { delivered: false } } } diff --git a/apps/judicial-system/message-handler/src/app/messageHandler.service.ts b/apps/judicial-system/message-handler/src/app/messageHandler.service.ts index 98edbe4c608d..56f7488dd2d5 100644 --- a/apps/judicial-system/message-handler/src/app/messageHandler.service.ts +++ b/apps/judicial-system/message-handler/src/app/messageHandler.service.ts @@ -33,7 +33,13 @@ export class MessageHandlerService implements OnModuleDestroy { `${this.config.backendUrl}/api/internal${ message.caseId ? `/case/${message.caseId}` : '' }/${messageEndpoint[message.type]}${ - message.elementId ? `/${message.elementId}` : '' + message.elementId + ? `/${ + Array.isArray(message.elementId) + ? message.elementId.join('/') + : message.elementId + }` + : '' }`, message.user, message.body, diff --git a/apps/judicial-system/web/src/components/FormProvider/case.graphql b/apps/judicial-system/web/src/components/FormProvider/case.graphql index f6eeefc5ba75..64acb88c88c8 100644 --- a/apps/judicial-system/web/src/components/FormProvider/case.graphql +++ b/apps/judicial-system/web/src/components/FormProvider/case.graphql @@ -26,6 +26,10 @@ query Case($input: CaseQueryInput!) { verdictViewDate verdictAppealDeadline subpoenaType + subpoenas { + id + created + } } defenderName defenderNationalId diff --git a/apps/judicial-system/web/src/components/FormProvider/limitedAccessCase.graphql b/apps/judicial-system/web/src/components/FormProvider/limitedAccessCase.graphql index 774715ba84f3..a5ba9f00d180 100644 --- a/apps/judicial-system/web/src/components/FormProvider/limitedAccessCase.graphql +++ b/apps/judicial-system/web/src/components/FormProvider/limitedAccessCase.graphql @@ -35,6 +35,10 @@ query LimitedAccessCase($input: CaseQueryInput!) { defenderPhoneNumber defenderChoice verdictViewDate + subpoenas { + id + created + } } defenderName defenderNationalId diff --git a/apps/judicial-system/web/src/components/IndictmentCaseFilesList/IndictmentCaseFilesList.strings.ts b/apps/judicial-system/web/src/components/IndictmentCaseFilesList/IndictmentCaseFilesList.strings.ts index 8372e2fbbc45..a6e7ee8bee11 100644 --- a/apps/judicial-system/web/src/components/IndictmentCaseFilesList/IndictmentCaseFilesList.strings.ts +++ b/apps/judicial-system/web/src/components/IndictmentCaseFilesList/IndictmentCaseFilesList.strings.ts @@ -40,8 +40,8 @@ export const strings = defineMessages({ description: 'Notaður sem titill á dómskjalaskjá í ákærum.', }, subpoenaButtonText: { - id: 'judicial.system.indictments:indictment_case_files_list.subpoena_button_text', - defaultMessage: 'Fyrirkall {name}.pdf', + id: 'judicial.system.indictments:indictment_case_files_list.subpoena_button_text_v2', + defaultMessage: 'Fyrirkall {name} {date}.pdf', description: 'Notaður sem texti á PDF takka til að sækja firyrkall í ákærum.', }, diff --git a/apps/judicial-system/web/src/components/IndictmentCaseFilesList/IndictmentCaseFilesList.tsx b/apps/judicial-system/web/src/components/IndictmentCaseFilesList/IndictmentCaseFilesList.tsx index 99d714df2a3e..f38145abd551 100644 --- a/apps/judicial-system/web/src/components/IndictmentCaseFilesList/IndictmentCaseFilesList.tsx +++ b/apps/judicial-system/web/src/components/IndictmentCaseFilesList/IndictmentCaseFilesList.tsx @@ -73,7 +73,9 @@ const IndictmentCaseFilesList: FC = ({ }) const showTrafficViolationCaseFiles = isTrafficViolationCase(workingCase) - const showSubpoenaPdf = workingCase.arraignmentDate + const showSubpoenaPdf = workingCase.defendants?.some( + (defendant) => defendant.subpoenas && defendant.subpoenas.length > 0, + ) const cf = workingCase.caseFiles @@ -227,28 +229,35 @@ const IndictmentCaseFilesList: FC = ({ )} - {showSubpoenaPdf && - workingCase.defendants && - workingCase.defendants.length > 0 && ( - - - {formatMessage(strings.subpoenaTitle)} - - {workingCase.defendants.map((defendant) => ( - + {showSubpoenaPdf && ( + + + {formatMessage(strings.subpoenaTitle)} + + {workingCase.defendants?.map((defendant) => + defendant.subpoenas?.map((subpoena) => ( + - ))} - - )} + )), + )} + + )} {fileNotFound && } diff --git a/apps/judicial-system/web/src/components/PdfButton/PdfButton.tsx b/apps/judicial-system/web/src/components/PdfButton/PdfButton.tsx index 8ff7a5bd0fb0..987d1fd4a624 100644 --- a/apps/judicial-system/web/src/components/PdfButton/PdfButton.tsx +++ b/apps/judicial-system/web/src/components/PdfButton/PdfButton.tsx @@ -22,7 +22,7 @@ interface Props { disabled?: boolean renderAs?: 'button' | 'row' handleClick?: () => void - elementId?: string + elementId?: string | string[] queryParameters?: string } @@ -46,7 +46,9 @@ const PdfButton: FC> = ({ const prefix = `${limitedAccess ? 'limitedAccess/' : ''}${ connectedCaseParentId ? `mergedCase/${caseId}/` : '' }` - const postfix = elementId ? `/${elementId}` : '' + const postfix = elementId + ? `/${Array.isArray(elementId) ? elementId.join('/') : elementId}` + : '' const query = queryParameters ? `?${queryParameters}` : '' const url = `${api.apiUrl}/api/case/${ connectedCaseParentId ?? caseId diff --git a/apps/judicial-system/web/src/routes/Court/Indictments/Subpoena/Subpoena.tsx b/apps/judicial-system/web/src/routes/Court/Indictments/Subpoena/Subpoena.tsx index e2cbe58c2604..77b8cca8d436 100644 --- a/apps/judicial-system/web/src/routes/Court/Indictments/Subpoena/Subpoena.tsx +++ b/apps/judicial-system/web/src/routes/Court/Indictments/Subpoena/Subpoena.tsx @@ -153,31 +153,59 @@ const Subpoena: FC = () => { /> - {workingCase.defendants?.map((defendant, index) => ( - - - + {workingCase.defendants?.map((defendant, dIndex) => ( + <> + {isSchedulingArraignmentDateForDefendant(defendant.id) && ( + + + + )} + {defendant.subpoenas?.map((subpoena, sIndex) => ( + + + + ))} + ))} diff --git a/libs/judicial-system/message/src/lib/message.ts b/libs/judicial-system/message/src/lib/message.ts index 99bfc42f74b0..1b5aaf576864 100644 --- a/libs/judicial-system/message/src/lib/message.ts +++ b/libs/judicial-system/message/src/lib/message.ts @@ -66,7 +66,7 @@ export type Message = { type: MessageType user?: User caseId?: string - elementId?: string + elementId?: string | string[] body?: { [key: string]: unknown } numberOfRetries?: number nextRetry?: number From 778daa16883eccfdb25f4211b607f20e4ea0c3c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gu=C3=B0j=C3=B3n=20Gu=C3=B0j=C3=B3nsson?= Date: Fri, 27 Sep 2024 19:09:17 +0200 Subject: [PATCH 08/18] Updates unit tests --- .../src/app/modules/case/case.service.ts | 2 +- .../case/test/caseController/update.spec.ts | 12 +- .../modules/defendant/defendant.controller.ts | 9 +- .../test/createTestingDefendantModule.ts | 20 +--- .../app/modules/subpoena/subpoena.service.ts | 2 +- .../test/createTestingSubpoenaModule.ts | 110 ++++++++++++++++++ .../getSubpoenaPdf.spec.ts | 19 +-- .../getSubpoenaPdfRolesRules.spec.ts | 6 +- ...tedAccessSubpoenaControllerGuards.spec.ts} | 12 +- .../getSubpoenaPdf.spec.ts | 20 ++-- .../getSubpoenaPdfGuards.spec.ts | 12 +- .../getSubpoenaPdfRolesRules.spec.ts | 6 +- 12 files changed, 170 insertions(+), 60 deletions(-) create mode 100644 apps/judicial-system/backend/src/app/modules/subpoena/test/createTestingSubpoenaModule.ts rename apps/judicial-system/backend/src/app/modules/{defendant/test/defendantController => subpoena/test/limitedAccessSubpoenaController}/getSubpoenaPdf.spec.ts (68%) rename apps/judicial-system/backend/src/app/modules/{defendant/test/limitedAccessDefendantController => subpoena/test/limitedAccessSubpoenaController}/getSubpoenaPdfRolesRules.spec.ts (59%) rename apps/judicial-system/backend/src/app/modules/{defendant/test/limitedAccessDefendantController/limitedAccessDefendantControllerGuards.spec.ts => subpoena/test/limitedAccessSubpoenaController/limitedAccessSubpoenaControllerGuards.spec.ts} (62%) rename apps/judicial-system/backend/src/app/modules/{defendant/test/limitedAccessDefendantController => subpoena/test/subpoenaController}/getSubpoenaPdf.spec.ts (67%) rename apps/judicial-system/backend/src/app/modules/{defendant/test/defendantController => subpoena/test/subpoenaController}/getSubpoenaPdfGuards.spec.ts (61%) rename apps/judicial-system/backend/src/app/modules/{defendant/test/defendantController => subpoena/test/subpoenaController}/getSubpoenaPdfRolesRules.spec.ts (80%) diff --git a/apps/judicial-system/backend/src/app/modules/case/case.service.ts b/apps/judicial-system/backend/src/app/modules/case/case.service.ts index eb56a53fbe28..1e5011a092ae 100644 --- a/apps/judicial-system/backend/src/app/modules/case/case.service.ts +++ b/apps/judicial-system/backend/src/app/modules/case/case.service.ts @@ -1747,9 +1747,9 @@ export class CaseService { this.subpoenaService.createSubpoena( defendant.id, theCase.id, + transaction, updatedArraignmentDate?.date, updatedArraignmentDate?.location, - transaction, ), ), ) diff --git a/apps/judicial-system/backend/src/app/modules/case/test/caseController/update.spec.ts b/apps/judicial-system/backend/src/app/modules/case/test/caseController/update.spec.ts index 932319cac89e..4939ca40beb3 100644 --- a/apps/judicial-system/backend/src/app/modules/case/test/caseController/update.spec.ts +++ b/apps/judicial-system/backend/src/app/modules/case/test/caseController/update.spec.ts @@ -875,10 +875,16 @@ describe('CaseController - Update', () => { describe('indictment arraignment date updated', () => { const arraignmentDate = { date: new Date(), location: uuid() } const caseToUpdate = { arraignmentDate } + const subpoenaId1 = uuid() + const subpoenaId2 = uuid() const updatedCase = { ...theCase, type: CaseType.INDICTMENT, dateLogs: [{ dateType: DateType.ARRAIGNMENT_DATE, ...arraignmentDate }], + defendants: [ + { id: defendantId1, subpoenas: [{ id: subpoenaId1 }] }, + { id: defendantId2, subpoenas: [{ id: subpoenaId2 }] }, + ], } beforeEach(async () => { @@ -900,17 +906,19 @@ describe('CaseController - Update', () => { caseId, body: { type: NotificationType.COURT_DATE }, }, + ]) + expect(mockMessageService.sendMessagesToQueue).toHaveBeenCalledWith([ { type: MessageType.DELIVERY_TO_POLICE_SUBPOENA, user, caseId: theCase.id, - elementId: defendantId1, + elementId: [defendantId1, subpoenaId1], }, { type: MessageType.DELIVERY_TO_POLICE_SUBPOENA, user, caseId: theCase.id, - elementId: defendantId2, + elementId: [defendantId2, subpoenaId2], }, ]) }) diff --git a/apps/judicial-system/backend/src/app/modules/defendant/defendant.controller.ts b/apps/judicial-system/backend/src/app/modules/defendant/defendant.controller.ts index 94bfed1fc023..83edd4cd8b1e 100644 --- a/apps/judicial-system/backend/src/app/modules/defendant/defendant.controller.ts +++ b/apps/judicial-system/backend/src/app/modules/defendant/defendant.controller.ts @@ -29,13 +29,7 @@ import { prosecutorRule, publicProsecutorStaffRule, } from '../../guards' -import { - Case, - CaseExistsGuard, - CaseWriteGuard, - CurrentCase, - PdfService, -} from '../case' +import { Case, CaseExistsGuard, CaseWriteGuard, CurrentCase } from '../case' import { CreateDefendantDto } from './dto/createDefendant.dto' import { UpdateDefendantDto } from './dto/updateDefendant.dto' import { CurrentDefendant } from './guards/defendant.decorator' @@ -49,7 +43,6 @@ import { DefendantService } from './defendant.service' @ApiTags('defendants') export class DefendantController { constructor( - private readonly pdfService: PdfService, private readonly defendantService: DefendantService, @Inject(LOGGER_PROVIDER) private readonly logger: Logger, ) {} diff --git a/apps/judicial-system/backend/src/app/modules/defendant/test/createTestingDefendantModule.ts b/apps/judicial-system/backend/src/app/modules/defendant/test/createTestingDefendantModule.ts index 8cb18eb62706..3b18ac9b8c8c 100644 --- a/apps/judicial-system/backend/src/app/modules/defendant/test/createTestingDefendantModule.ts +++ b/apps/judicial-system/backend/src/app/modules/defendant/test/createTestingDefendantModule.ts @@ -10,36 +10,29 @@ import { } from '@island.is/judicial-system/auth' import { MessageService } from '@island.is/judicial-system/message' -import { CaseService, PdfService } from '../../case' +import { CaseService } from '../../case' import { CourtService } from '../../court' import { UserService } from '../../user' import { DefendantController } from '../defendant.controller' import { DefendantService } from '../defendant.service' import { InternalDefendantController } from '../internalDefendant.controller' -import { LimitedAccessDefendantController } from '../limitedAccessDefendant.controller' import { Defendant } from '../models/defendant.model' jest.mock('@island.is/judicial-system/message') jest.mock('../../user/user.service') jest.mock('../../court/court.service') jest.mock('../../case/case.service') -jest.mock('../../case/pdf.service') export const createTestingDefendantModule = async () => { const defendantModule = await Test.createTestingModule({ imports: [ConfigModule.forRoot({ load: [sharedAuthModuleConfig] })], - controllers: [ - DefendantController, - InternalDefendantController, - LimitedAccessDefendantController, - ], + controllers: [DefendantController, InternalDefendantController], providers: [ SharedAuthModule, MessageService, UserService, CourtService, CaseService, - PdfService, { provide: LOGGER_PROVIDER, useValue: { @@ -69,8 +62,6 @@ export const createTestingDefendantModule = async () => { const courtService = defendantModule.get(CourtService) - const pdfService = defendantModule.get(PdfService) - const defendantModel = await defendantModule.resolve( getModelToken(Defendant), ) @@ -86,22 +77,15 @@ export const createTestingDefendantModule = async () => { InternalDefendantController, ) - const limitedAccessDefendantController = - defendantModule.get( - LimitedAccessDefendantController, - ) - defendantModule.close() return { messageService, userService, courtService, - pdfService, defendantModel, defendantService, defendantController, internalDefendantController, - limitedAccessDefendantController, } } diff --git a/apps/judicial-system/backend/src/app/modules/subpoena/subpoena.service.ts b/apps/judicial-system/backend/src/app/modules/subpoena/subpoena.service.ts index 08d0c4a83149..aa2fe114ef7f 100644 --- a/apps/judicial-system/backend/src/app/modules/subpoena/subpoena.service.ts +++ b/apps/judicial-system/backend/src/app/modules/subpoena/subpoena.service.ts @@ -37,9 +37,9 @@ export class SubpoenaService { async createSubpoena( defendantId: string, caseId: string, + transaction: Transaction, arraignmentDate?: Date, location?: string, - transaction?: Transaction, ): Promise { return this.subpoenaModel.create( { diff --git a/apps/judicial-system/backend/src/app/modules/subpoena/test/createTestingSubpoenaModule.ts b/apps/judicial-system/backend/src/app/modules/subpoena/test/createTestingSubpoenaModule.ts new file mode 100644 index 000000000000..a931f5fd7bfd --- /dev/null +++ b/apps/judicial-system/backend/src/app/modules/subpoena/test/createTestingSubpoenaModule.ts @@ -0,0 +1,110 @@ +import { Sequelize } from 'sequelize-typescript' + +import { getModelToken } from '@nestjs/sequelize' +import { Test } from '@nestjs/testing' + +import { LOGGER_PROVIDER } from '@island.is/logging' +import { ConfigModule } from '@island.is/nest/config' + +import { + SharedAuthModule, + sharedAuthModuleConfig, +} from '@island.is/judicial-system/auth' + +import { CaseService, PdfService } from '../../case' +import { Defendant } from '../../defendant' +import { PoliceService } from '../../police' +import { UserService } from '../../user' +import { InternalSubpoenaController } from '../internalSubpoena.controller' +import { LimitedAccessSubpoenaController } from '../limitedAccessSubpoena.controller' +import { Subpoena } from '../models/subpoena.model' +import { SubpoenaController } from '../subpoena.controller' +import { SubpoenaService } from '../subpoena.service' + +jest.mock('../../user/user.service') +jest.mock('../../case/case.service') +jest.mock('../../case/pdf.service') +jest.mock('../../police/police.service') + +export const createTestingSubpoenaModule = async () => { + const subpoenaModule = await Test.createTestingModule({ + imports: [ConfigModule.forRoot({ load: [sharedAuthModuleConfig] })], + controllers: [ + SubpoenaController, + InternalSubpoenaController, + LimitedAccessSubpoenaController, + ], + providers: [ + { provide: Sequelize, useValue: { transaction: jest.fn() } }, + SharedAuthModule, + UserService, + CaseService, + PdfService, + PoliceService, + { + provide: LOGGER_PROVIDER, + useValue: { + debug: jest.fn(), + info: jest.fn(), + error: jest.fn(), + }, + }, + { + provide: getModelToken(Subpoena), + useValue: { + findOne: jest.fn(), + findAll: jest.fn(), + create: jest.fn(), + update: jest.fn(), + destroy: jest.fn(), + findByPk: jest.fn(), + }, + }, + { + provide: getModelToken(Defendant), + useValue: { + findOne: jest.fn(), + findAll: jest.fn(), + create: jest.fn(), + update: jest.fn(), + destroy: jest.fn(), + findByPk: jest.fn(), + }, + }, + SubpoenaService, + ], + }).compile() + + const userService = subpoenaModule.get(UserService) + + const pdfService = subpoenaModule.get(PdfService) + + const subpoenaModel = await subpoenaModule.resolve( + getModelToken(Subpoena), + ) + + const subpoenaService = subpoenaModule.get(SubpoenaService) + + const subpoenaController = + subpoenaModule.get(SubpoenaController) + + const internalSubpoenaController = + subpoenaModule.get(InternalSubpoenaController) + + const limitedAccessSubpoenaController = + subpoenaModule.get( + LimitedAccessSubpoenaController, + ) + + subpoenaModule.close() + + return { + userService, + pdfService, + subpoenaModel, + subpoenaService, + subpoenaController, + internalSubpoenaController, + limitedAccessSubpoenaController, + } +} diff --git a/apps/judicial-system/backend/src/app/modules/defendant/test/defendantController/getSubpoenaPdf.spec.ts b/apps/judicial-system/backend/src/app/modules/subpoena/test/limitedAccessSubpoenaController/getSubpoenaPdf.spec.ts similarity index 68% rename from apps/judicial-system/backend/src/app/modules/defendant/test/defendantController/getSubpoenaPdf.spec.ts rename to apps/judicial-system/backend/src/app/modules/subpoena/test/limitedAccessSubpoenaController/getSubpoenaPdf.spec.ts index 632fc703f493..cda75ddd2fbe 100644 --- a/apps/judicial-system/backend/src/app/modules/defendant/test/defendantController/getSubpoenaPdf.spec.ts +++ b/apps/judicial-system/backend/src/app/modules/subpoena/test/limitedAccessSubpoenaController/getSubpoenaPdf.spec.ts @@ -1,10 +1,10 @@ import { Response } from 'express' import { uuid } from 'uuidv4' -import { createTestingDefendantModule } from '../createTestingDefendantModule' +import { createTestingSubpoenaModule } from '../createTestingSubpoenaModule' import { Case, PdfService } from '../../../case' -import { Defendant } from '../../models/defendant.model' +import { Subpoena } from '../../models/subpoena.model' interface Then { error: Error @@ -12,10 +12,12 @@ interface Then { type GivenWhenThen = () => Promise -describe('DefendantController - Get subpoena pdf', () => { +describe('LimitedAccessSubpoenaController - Get subpoena pdf', () => { const caseId = uuid() + const subpoenaId = uuid() + const subpoena = { id: subpoenaId } as Subpoena const defendantId = uuid() - const defendant = { id: defendantId } as Defendant + const defendant = { id: defendantId, subpoenas: [subpoena] } as Defendant const theCase = { id: caseId } as Case const res = { end: jest.fn() } as unknown as Response const pdf = Buffer.from(uuid()) @@ -23,8 +25,8 @@ describe('DefendantController - Get subpoena pdf', () => { let givenWhenThen: GivenWhenThen beforeEach(async () => { - const { pdfService, defendantController } = - await createTestingDefendantModule() + const { pdfService, limitedAccessSubpoenaController } = + await createTestingSubpoenaModule() mockPdfService = pdfService const getSubpoenaPdfMock = mockPdfService.getSubpoenaPdf as jest.Mock @@ -34,11 +36,13 @@ describe('DefendantController - Get subpoena pdf', () => { const then = {} as Then try { - await defendantController.getSubpoenaPdf( + await limitedAccessSubpoenaController.getSubpoenaPdf( caseId, defendantId, + subpoenaId, theCase, defendant, + subpoena, res, ) } catch (error) { @@ -58,6 +62,7 @@ describe('DefendantController - Get subpoena pdf', () => { expect(mockPdfService.getSubpoenaPdf).toHaveBeenCalledWith( theCase, defendant, + subpoena, undefined, undefined, undefined, diff --git a/apps/judicial-system/backend/src/app/modules/defendant/test/limitedAccessDefendantController/getSubpoenaPdfRolesRules.spec.ts b/apps/judicial-system/backend/src/app/modules/subpoena/test/limitedAccessSubpoenaController/getSubpoenaPdfRolesRules.spec.ts similarity index 59% rename from apps/judicial-system/backend/src/app/modules/defendant/test/limitedAccessDefendantController/getSubpoenaPdfRolesRules.spec.ts rename to apps/judicial-system/backend/src/app/modules/subpoena/test/limitedAccessSubpoenaController/getSubpoenaPdfRolesRules.spec.ts index 87cbfde789f8..125817664eb1 100644 --- a/apps/judicial-system/backend/src/app/modules/defendant/test/limitedAccessDefendantController/getSubpoenaPdfRolesRules.spec.ts +++ b/apps/judicial-system/backend/src/app/modules/subpoena/test/limitedAccessSubpoenaController/getSubpoenaPdfRolesRules.spec.ts @@ -1,14 +1,14 @@ import { defenderRule } from '../../../../guards' -import { LimitedAccessDefendantController } from '../../limitedAccessDefendant.controller' +import { LimitedAccessSubpoenaController } from '../../limitedAccessSubpoena.controller' -describe('LimitedAccessDefendantController - Get custody notice pdf rules', () => { +describe('LimitedAccessSubpoenaController - Get custody notice pdf rules', () => { // eslint-disable-next-line @typescript-eslint/no-explicit-any let rules: any[] beforeEach(() => { rules = Reflect.getMetadata( 'roles-rules', - LimitedAccessDefendantController.prototype.getSubpoenaPdf, + LimitedAccessSubpoenaController.prototype.getSubpoenaPdf, ) }) diff --git a/apps/judicial-system/backend/src/app/modules/defendant/test/limitedAccessDefendantController/limitedAccessDefendantControllerGuards.spec.ts b/apps/judicial-system/backend/src/app/modules/subpoena/test/limitedAccessSubpoenaController/limitedAccessSubpoenaControllerGuards.spec.ts similarity index 62% rename from apps/judicial-system/backend/src/app/modules/defendant/test/limitedAccessDefendantController/limitedAccessDefendantControllerGuards.spec.ts rename to apps/judicial-system/backend/src/app/modules/subpoena/test/limitedAccessSubpoenaController/limitedAccessSubpoenaControllerGuards.spec.ts index aee6fdebeb8c..cf4fb036e396 100644 --- a/apps/judicial-system/backend/src/app/modules/defendant/test/limitedAccessDefendantController/limitedAccessDefendantControllerGuards.spec.ts +++ b/apps/judicial-system/backend/src/app/modules/subpoena/test/limitedAccessSubpoenaController/limitedAccessSubpoenaControllerGuards.spec.ts @@ -2,19 +2,20 @@ import { JwtAuthGuard, RolesGuard } from '@island.is/judicial-system/auth' import { indictmentCases } from '@island.is/judicial-system/types' import { CaseExistsGuard, CaseReadGuard, CaseTypeGuard } from '../../../case' -import { DefendantExistsGuard } from '../../guards/defendantExists.guard' -import { LimitedAccessDefendantController } from '../../limitedAccessDefendant.controller' +import { DefendantExistsGuard } from '../../../defendant/guards/defendantExists.guard' +import { SubpoenaExistsOptionalGuard } from '../../guards/subpoenaExists.guard' +import { LimitedAccessSubpoenaController } from '../../limitedAccessSubpoena.controller' -describe('LimitedAccessDefendantController - guards', () => { +describe('LimitedAccessSubpoenaController - guards', () => { // eslint-disable-next-line @typescript-eslint/no-explicit-any let guards: any[] beforeEach(() => { - guards = Reflect.getMetadata('__guards__', LimitedAccessDefendantController) + guards = Reflect.getMetadata('__guards__', LimitedAccessSubpoenaController) }) it('should have the right guard configuration', () => { - expect(guards).toHaveLength(6) + expect(guards).toHaveLength(7) expect(new guards[0]()).toBeInstanceOf(JwtAuthGuard) expect(new guards[1]()).toBeInstanceOf(RolesGuard) expect(new guards[2]()).toBeInstanceOf(CaseExistsGuard) @@ -24,5 +25,6 @@ describe('LimitedAccessDefendantController - guards', () => { }) expect(new guards[4]()).toBeInstanceOf(CaseReadGuard) expect(new guards[5]()).toBeInstanceOf(DefendantExistsGuard) + expect(new guards[6]()).toBeInstanceOf(SubpoenaExistsOptionalGuard) }) }) diff --git a/apps/judicial-system/backend/src/app/modules/defendant/test/limitedAccessDefendantController/getSubpoenaPdf.spec.ts b/apps/judicial-system/backend/src/app/modules/subpoena/test/subpoenaController/getSubpoenaPdf.spec.ts similarity index 67% rename from apps/judicial-system/backend/src/app/modules/defendant/test/limitedAccessDefendantController/getSubpoenaPdf.spec.ts rename to apps/judicial-system/backend/src/app/modules/subpoena/test/subpoenaController/getSubpoenaPdf.spec.ts index 97ec46dde723..73d2580e33ff 100644 --- a/apps/judicial-system/backend/src/app/modules/defendant/test/limitedAccessDefendantController/getSubpoenaPdf.spec.ts +++ b/apps/judicial-system/backend/src/app/modules/subpoena/test/subpoenaController/getSubpoenaPdf.spec.ts @@ -1,10 +1,11 @@ import { Response } from 'express' import { uuid } from 'uuidv4' -import { createTestingDefendantModule } from '../createTestingDefendantModule' +import { createTestingSubpoenaModule } from '../createTestingSubpoenaModule' import { Case, PdfService } from '../../../case' -import { Defendant } from '../../models/defendant.model' +import { Defendant } from '../../../defendant/models/defendant.model' +import { Subpoena } from '../../models/subpoena.model' interface Then { error: Error @@ -12,10 +13,12 @@ interface Then { type GivenWhenThen = () => Promise -describe('LimitedAccessDefendantController - Get subpoena pdf', () => { +describe('SubpoenaController - Get subpoena pdf', () => { const caseId = uuid() + const subpoenaId = uuid() + const subpoena = { id: subpoenaId } as Subpoena const defendantId = uuid() - const defendant = { id: defendantId } as Defendant + const defendant = { id: defendantId, subpoenas: [subpoena] } as Defendant const theCase = { id: caseId } as Case const res = { end: jest.fn() } as unknown as Response const pdf = Buffer.from(uuid()) @@ -23,8 +26,8 @@ describe('LimitedAccessDefendantController - Get subpoena pdf', () => { let givenWhenThen: GivenWhenThen beforeEach(async () => { - const { pdfService, limitedAccessDefendantController } = - await createTestingDefendantModule() + const { pdfService, subpoenaController } = + await createTestingSubpoenaModule() mockPdfService = pdfService const getSubpoenaPdfMock = mockPdfService.getSubpoenaPdf as jest.Mock @@ -34,11 +37,13 @@ describe('LimitedAccessDefendantController - Get subpoena pdf', () => { const then = {} as Then try { - await limitedAccessDefendantController.getSubpoenaPdf( + await subpoenaController.getSubpoenaPdf( caseId, defendantId, + subpoenaId, theCase, defendant, + subpoena, res, ) } catch (error) { @@ -58,6 +63,7 @@ describe('LimitedAccessDefendantController - Get subpoena pdf', () => { expect(mockPdfService.getSubpoenaPdf).toHaveBeenCalledWith( theCase, defendant, + subpoena, undefined, undefined, undefined, diff --git a/apps/judicial-system/backend/src/app/modules/defendant/test/defendantController/getSubpoenaPdfGuards.spec.ts b/apps/judicial-system/backend/src/app/modules/subpoena/test/subpoenaController/getSubpoenaPdfGuards.spec.ts similarity index 61% rename from apps/judicial-system/backend/src/app/modules/defendant/test/defendantController/getSubpoenaPdfGuards.spec.ts rename to apps/judicial-system/backend/src/app/modules/subpoena/test/subpoenaController/getSubpoenaPdfGuards.spec.ts index 7fb9d19876bb..6f96a62ce278 100644 --- a/apps/judicial-system/backend/src/app/modules/defendant/test/defendantController/getSubpoenaPdfGuards.spec.ts +++ b/apps/judicial-system/backend/src/app/modules/subpoena/test/subpoenaController/getSubpoenaPdfGuards.spec.ts @@ -1,22 +1,23 @@ import { indictmentCases } from '@island.is/judicial-system/types' import { CaseExistsGuard, CaseReadGuard, CaseTypeGuard } from '../../../case' -import { DefendantController } from '../../defendant.controller' -import { DefendantExistsGuard } from '../../guards/defendantExists.guard' +import { DefendantExistsGuard } from '../../../defendant' +import { SubpoenaExistsOptionalGuard } from '../../guards/subpoenaExists.guard' +import { SubpoenaController } from '../../subpoena.controller' -describe('DefendantController - Get custody notice pdf guards', () => { +describe('SubpoenaController - Get custody notice pdf guards', () => { // eslint-disable-next-line @typescript-eslint/no-explicit-any let guards: any[] beforeEach(() => { guards = Reflect.getMetadata( '__guards__', - DefendantController.prototype.getSubpoenaPdf, + SubpoenaController.prototype.getSubpoenaPdf, ) }) it('should have the right guard configuration', () => { - expect(guards).toHaveLength(4) + expect(guards).toHaveLength(5) expect(new guards[0]()).toBeInstanceOf(CaseExistsGuard) expect(guards[1]).toBeInstanceOf(CaseTypeGuard) expect(guards[1]).toEqual({ @@ -24,5 +25,6 @@ describe('DefendantController - Get custody notice pdf guards', () => { }) expect(new guards[2]()).toBeInstanceOf(CaseReadGuard) expect(new guards[3]()).toBeInstanceOf(DefendantExistsGuard) + expect(new guards[4]()).toBeInstanceOf(SubpoenaExistsOptionalGuard) }) }) diff --git a/apps/judicial-system/backend/src/app/modules/defendant/test/defendantController/getSubpoenaPdfRolesRules.spec.ts b/apps/judicial-system/backend/src/app/modules/subpoena/test/subpoenaController/getSubpoenaPdfRolesRules.spec.ts similarity index 80% rename from apps/judicial-system/backend/src/app/modules/defendant/test/defendantController/getSubpoenaPdfRolesRules.spec.ts rename to apps/judicial-system/backend/src/app/modules/subpoena/test/subpoenaController/getSubpoenaPdfRolesRules.spec.ts index 286050136fcd..9d114d811d81 100644 --- a/apps/judicial-system/backend/src/app/modules/defendant/test/defendantController/getSubpoenaPdfRolesRules.spec.ts +++ b/apps/judicial-system/backend/src/app/modules/subpoena/test/subpoenaController/getSubpoenaPdfRolesRules.spec.ts @@ -6,16 +6,16 @@ import { prosecutorRule, publicProsecutorStaffRule, } from '../../../../guards' -import { DefendantController } from '../../defendant.controller' +import { SubpoenaController } from '../../subpoena.controller' -describe('DefendantController - Get custody notice pdf rules', () => { +describe('SubpoenaController - Get custody notice pdf rules', () => { // eslint-disable-next-line @typescript-eslint/no-explicit-any let rules: any[] beforeEach(() => { rules = Reflect.getMetadata( 'roles-rules', - DefendantController.prototype.getSubpoenaPdf, + SubpoenaController.prototype.getSubpoenaPdf, ) }) From 8331d6116a113af3d6d1a5358f6cb7226d26f5de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gu=C3=B0j=C3=B3n=20Gu=C3=B0j=C3=B3nsson?= Date: Fri, 27 Sep 2024 19:15:44 +0200 Subject: [PATCH 09/18] Updates unit test --- .../modules/subpoena/subpoena.controller.ts | 17 ++++++----- .../getSubpoenaPdfGuards.spec.ts | 30 ------------------- .../subpoenaControllerGuards.spec.ts | 30 +++++++++++++++++++ 3 files changed, 39 insertions(+), 38 deletions(-) delete mode 100644 apps/judicial-system/backend/src/app/modules/subpoena/test/subpoenaController/getSubpoenaPdfGuards.spec.ts create mode 100644 apps/judicial-system/backend/src/app/modules/subpoena/test/subpoenaController/subpoenaControllerGuards.spec.ts diff --git a/apps/judicial-system/backend/src/app/modules/subpoena/subpoena.controller.ts b/apps/judicial-system/backend/src/app/modules/subpoena/subpoena.controller.ts index e6f4ad8abc51..2dcdf3848b7e 100644 --- a/apps/judicial-system/backend/src/app/modules/subpoena/subpoena.controller.ts +++ b/apps/judicial-system/backend/src/app/modules/subpoena/subpoena.controller.ts @@ -44,7 +44,15 @@ import { CurrentSubpoena } from './guards/subpoena.decorator' import { SubpoenaExistsOptionalGuard } from './guards/subpoenaExists.guard' import { Subpoena } from './models/subpoena.model' -@UseGuards(JwtAuthGuard, RolesGuard) +@UseGuards( + JwtAuthGuard, + RolesGuard, + CaseExistsGuard, + new CaseTypeGuard(indictmentCases), + CaseReadGuard, + DefendantExistsGuard, + SubpoenaExistsOptionalGuard, +) @Controller([ 'api/case/:caseId/defendant/:defendantId/subpoena', 'api/case/:caseId/defendant/:defendantId/subpoena/:subpoenaId', @@ -56,13 +64,6 @@ export class SubpoenaController { @Inject(LOGGER_PROVIDER) private readonly logger: Logger, ) {} - @UseGuards( - CaseExistsGuard, - new CaseTypeGuard(indictmentCases), - CaseReadGuard, - DefendantExistsGuard, - SubpoenaExistsOptionalGuard, - ) @RolesRules( prosecutorRule, prosecutorRepresentativeRule, diff --git a/apps/judicial-system/backend/src/app/modules/subpoena/test/subpoenaController/getSubpoenaPdfGuards.spec.ts b/apps/judicial-system/backend/src/app/modules/subpoena/test/subpoenaController/getSubpoenaPdfGuards.spec.ts deleted file mode 100644 index 6f96a62ce278..000000000000 --- a/apps/judicial-system/backend/src/app/modules/subpoena/test/subpoenaController/getSubpoenaPdfGuards.spec.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { indictmentCases } from '@island.is/judicial-system/types' - -import { CaseExistsGuard, CaseReadGuard, CaseTypeGuard } from '../../../case' -import { DefendantExistsGuard } from '../../../defendant' -import { SubpoenaExistsOptionalGuard } from '../../guards/subpoenaExists.guard' -import { SubpoenaController } from '../../subpoena.controller' - -describe('SubpoenaController - Get custody notice pdf guards', () => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - let guards: any[] - - beforeEach(() => { - guards = Reflect.getMetadata( - '__guards__', - SubpoenaController.prototype.getSubpoenaPdf, - ) - }) - - it('should have the right guard configuration', () => { - expect(guards).toHaveLength(5) - expect(new guards[0]()).toBeInstanceOf(CaseExistsGuard) - expect(guards[1]).toBeInstanceOf(CaseTypeGuard) - expect(guards[1]).toEqual({ - allowedCaseTypes: indictmentCases, - }) - expect(new guards[2]()).toBeInstanceOf(CaseReadGuard) - expect(new guards[3]()).toBeInstanceOf(DefendantExistsGuard) - expect(new guards[4]()).toBeInstanceOf(SubpoenaExistsOptionalGuard) - }) -}) diff --git a/apps/judicial-system/backend/src/app/modules/subpoena/test/subpoenaController/subpoenaControllerGuards.spec.ts b/apps/judicial-system/backend/src/app/modules/subpoena/test/subpoenaController/subpoenaControllerGuards.spec.ts new file mode 100644 index 000000000000..966a64fecfef --- /dev/null +++ b/apps/judicial-system/backend/src/app/modules/subpoena/test/subpoenaController/subpoenaControllerGuards.spec.ts @@ -0,0 +1,30 @@ +import { JwtAuthGuard, RolesGuard } from '@island.is/judicial-system/auth' +import { indictmentCases } from '@island.is/judicial-system/types' + +import { CaseExistsGuard, CaseReadGuard, CaseTypeGuard } from '../../../case' +import { DefendantExistsGuard } from '../../../defendant/guards/defendantExists.guard' +import { SubpoenaExistsOptionalGuard } from '../../guards/subpoenaExists.guard' +import { SubpoenaController } from '../../subpoena.controller' + +describe('SubpoenaController - guards', () => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + let guards: any[] + + beforeEach(() => { + guards = Reflect.getMetadata('__guards__', SubpoenaController) + }) + + it('should have the right guard configuration', () => { + expect(guards).toHaveLength(7) + expect(new guards[0]()).toBeInstanceOf(JwtAuthGuard) + expect(new guards[1]()).toBeInstanceOf(RolesGuard) + expect(new guards[2]()).toBeInstanceOf(CaseExistsGuard) + expect(guards[3]).toBeInstanceOf(CaseTypeGuard) + expect(guards[3]).toEqual({ + allowedCaseTypes: indictmentCases, + }) + expect(new guards[4]()).toBeInstanceOf(CaseReadGuard) + expect(new guards[5]()).toBeInstanceOf(DefendantExistsGuard) + expect(new guards[6]()).toBeInstanceOf(SubpoenaExistsOptionalGuard) + }) +}) From 185d7dd93371e0490cfa57af5d0d7e78fe490db4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gu=C3=B0j=C3=B3n=20Gu=C3=B0j=C3=B3nsson?= Date: Mon, 30 Sep 2024 10:07:54 +0200 Subject: [PATCH 10/18] Fixes some typs and null reference guards --- .../api/src/app/modules/defendant/models/subpoena.model.ts | 4 ++-- .../backend/src/app/modules/case/case.service.ts | 2 +- .../backend/src/app/modules/subpoena/models/subpoena.model.ts | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/judicial-system/api/src/app/modules/defendant/models/subpoena.model.ts b/apps/judicial-system/api/src/app/modules/defendant/models/subpoena.model.ts index 9ba54e366b30..9a810b1edc10 100644 --- a/apps/judicial-system/api/src/app/modules/defendant/models/subpoena.model.ts +++ b/apps/judicial-system/api/src/app/modules/defendant/models/subpoena.model.ts @@ -14,8 +14,8 @@ export class Subpoena { @Field(() => String, { nullable: true }) subpoenaId?: string - @Field(() => String, { nullable: true }) - acknowledged?: string + @Field(() => Boolean, { nullable: true }) + acknowledged?: boolean @Field(() => String, { nullable: true }) registeredBy?: string diff --git a/apps/judicial-system/backend/src/app/modules/case/case.service.ts b/apps/judicial-system/backend/src/app/modules/case/case.service.ts index 1e5011a092ae..06c0dcee6ea1 100644 --- a/apps/judicial-system/backend/src/app/modules/case/case.service.ts +++ b/apps/judicial-system/backend/src/app/modules/case/case.service.ts @@ -1183,7 +1183,7 @@ export class CaseService { (updatedDefendant) => theCase.defendants?.find( (defendant) => defendant.id === updatedDefendant.id, - )?.subpoenas?.[0].id !== updatedDefendant.subpoenas?.[0].id, + )?.subpoenas?.[0]?.id !== updatedDefendant.subpoenas?.[0]?.id, ) .map((updatedDefendant) => ({ type: MessageType.DELIVERY_TO_POLICE_SUBPOENA, diff --git a/apps/judicial-system/backend/src/app/modules/subpoena/models/subpoena.model.ts b/apps/judicial-system/backend/src/app/modules/subpoena/models/subpoena.model.ts index 933b1633e1bb..ee7589da6301 100644 --- a/apps/judicial-system/backend/src/app/modules/subpoena/models/subpoena.model.ts +++ b/apps/judicial-system/backend/src/app/modules/subpoena/models/subpoena.model.ts @@ -59,7 +59,7 @@ export class Subpoena extends Model { @Column({ type: DataType.BOOLEAN, allowNull: true }) @ApiPropertyOptional({ type: Boolean }) - acknowledged?: string + acknowledged?: boolean @Column({ type: DataType.STRING, allowNull: true }) @ApiPropertyOptional({ type: String }) From 331ea57883d656b3ab0cd6d492fb64f049542bb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gu=C3=B0j=C3=B3n=20Gu=C3=B0j=C3=B3nsson?= Date: Mon, 30 Sep 2024 10:10:57 +0200 Subject: [PATCH 11/18] Improved type declaration --- .../backend/src/app/modules/subpoena/models/subpoena.model.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/judicial-system/backend/src/app/modules/subpoena/models/subpoena.model.ts b/apps/judicial-system/backend/src/app/modules/subpoena/models/subpoena.model.ts index ee7589da6301..4d4f05a53b67 100644 --- a/apps/judicial-system/backend/src/app/modules/subpoena/models/subpoena.model.ts +++ b/apps/judicial-system/backend/src/app/modules/subpoena/models/subpoena.model.ts @@ -49,7 +49,7 @@ export class Subpoena extends Model { defendant?: Defendant @ForeignKey(() => Case) - @Column({ type: DataType.UUID }) + @Column({ type: DataType.UUID, allowNull: false }) @ApiProperty({ type: String }) caseId!: string From 798c7f063cce058950eccb64a306ef51ab0764aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gu=C3=B0j=C3=B3n=20Gu=C3=B0j=C3=B3nsson?= Date: Mon, 30 Sep 2024 10:19:08 +0200 Subject: [PATCH 12/18] Improved date formatting --- .../IndictmentCaseFilesList.tsx | 9 ++------- .../routes/Court/Indictments/Subpoena/Subpoena.tsx | 13 ++++--------- 2 files changed, 6 insertions(+), 16 deletions(-) diff --git a/apps/judicial-system/web/src/components/IndictmentCaseFilesList/IndictmentCaseFilesList.tsx b/apps/judicial-system/web/src/components/IndictmentCaseFilesList/IndictmentCaseFilesList.tsx index f38145abd551..29f1738db99f 100644 --- a/apps/judicial-system/web/src/components/IndictmentCaseFilesList/IndictmentCaseFilesList.tsx +++ b/apps/judicial-system/web/src/components/IndictmentCaseFilesList/IndictmentCaseFilesList.tsx @@ -3,6 +3,7 @@ import { useIntl } from 'react-intl' import { AnimatePresence } from 'framer-motion' import { Box, Text } from '@island.is/island-ui/core' +import { formatDate } from '@island.is/judicial-system/formatters' import { isCompletedCase, isDefenceUser, @@ -241,13 +242,7 @@ const IndictmentCaseFilesList: FC = ({ caseId={workingCase.id} title={formatMessage(strings.subpoenaButtonText, { name: defendant.name, - date: `${subpoena.created?.slice( - 8, - 10, - )}.${subpoena.created?.slice( - 5, - 7, - )}.${subpoena.created?.slice(0, 4)}`, + date: formatDate(subpoena.created), })} pdfType="subpoena" elementId={[defendant.id, subpoena.id]} diff --git a/apps/judicial-system/web/src/routes/Court/Indictments/Subpoena/Subpoena.tsx b/apps/judicial-system/web/src/routes/Court/Indictments/Subpoena/Subpoena.tsx index 77b8cca8d436..676072ff97c2 100644 --- a/apps/judicial-system/web/src/routes/Court/Indictments/Subpoena/Subpoena.tsx +++ b/apps/judicial-system/web/src/routes/Court/Indictments/Subpoena/Subpoena.tsx @@ -4,6 +4,7 @@ import router from 'next/router' import { Box, Button } from '@island.is/island-ui/core' import * as constants from '@island.is/judicial-system/consts' +import { formatDate } from '@island.is/judicial-system/formatters' import { titles } from '@island.is/judicial-system-web/messages' import { CourtArrangements, @@ -191,15 +192,9 @@ const Subpoena: FC = () => { > From 0fd6b374cc902d054f31d864e5b79a5b1cc41609 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gu=C3=B0j=C3=B3n=20Gu=C3=B0j=C3=B3nsson?= Date: Mon, 30 Sep 2024 10:24:00 +0200 Subject: [PATCH 13/18] Improves indexing --- .../web/src/routes/Court/Indictments/Subpoena/Subpoena.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/judicial-system/web/src/routes/Court/Indictments/Subpoena/Subpoena.tsx b/apps/judicial-system/web/src/routes/Court/Indictments/Subpoena/Subpoena.tsx index 676072ff97c2..0eab4a0af95b 100644 --- a/apps/judicial-system/web/src/routes/Court/Indictments/Subpoena/Subpoena.tsx +++ b/apps/judicial-system/web/src/routes/Court/Indictments/Subpoena/Subpoena.tsx @@ -158,7 +158,7 @@ const Subpoena: FC = () => { <> {isSchedulingArraignmentDateForDefendant(defendant.id) && ( { )} {defendant.subpoenas?.map((subpoena, sIndex) => ( Date: Mon, 30 Sep 2024 10:31:02 +0200 Subject: [PATCH 14/18] Fixes spelling --- .../src/app/modules/subpoena/internalSubpoena.controller.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/judicial-system/backend/src/app/modules/subpoena/internalSubpoena.controller.ts b/apps/judicial-system/backend/src/app/modules/subpoena/internalSubpoena.controller.ts index aef0e88065b6..411c8f3e4ef3 100644 --- a/apps/judicial-system/backend/src/app/modules/subpoena/internalSubpoena.controller.ts +++ b/apps/judicial-system/backend/src/app/modules/subpoena/internalSubpoena.controller.ts @@ -90,7 +90,7 @@ export class InternalSubpoenaController { @Body() deliverDto: DeliverDto, ): Promise { this.logger.debug( - `Delivering subpoena ${subpoenaId} to police for defendant ${defendantId} og case ${caseId}`, + `Delivering subpoena ${subpoenaId} to police for defendant ${defendantId} of case ${caseId}`, ) return await this.subpoenaService.deliverSubpoenaToPolice( From 22d975f1e2f48f779fe4d77fb0101d831c30e311 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gu=C3=B0j=C3=B3n=20Gu=C3=B0j=C3=B3nsson?= Date: Mon, 30 Sep 2024 10:59:27 +0200 Subject: [PATCH 15/18] Fixes indexing --- .../src/routes/Court/components/SubpoenaType/SubpoenaType.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/judicial-system/web/src/routes/Court/components/SubpoenaType/SubpoenaType.tsx b/apps/judicial-system/web/src/routes/Court/components/SubpoenaType/SubpoenaType.tsx index 3a89ef897e87..4b36142baa59 100644 --- a/apps/judicial-system/web/src/routes/Court/components/SubpoenaType/SubpoenaType.tsx +++ b/apps/judicial-system/web/src/routes/Court/components/SubpoenaType/SubpoenaType.tsx @@ -50,7 +50,7 @@ const SubpoenaType: FC = ({ From cdaffc08632bcfb2a3454aeb6c940a5e65144bd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gu=C3=B0j=C3=B3n=20Gu=C3=B0j=C3=B3nsson?= Date: Mon, 30 Sep 2024 11:10:38 +0200 Subject: [PATCH 16/18] Fixes optional arguments --- .../judicial-system/backend/src/app/modules/case/pdf.service.ts | 2 +- .../backend/src/app/modules/subpoena/subpoena.controller.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/judicial-system/backend/src/app/modules/case/pdf.service.ts b/apps/judicial-system/backend/src/app/modules/case/pdf.service.ts index 140501e17c59..10065ea3bdb6 100644 --- a/apps/judicial-system/backend/src/app/modules/case/pdf.service.ts +++ b/apps/judicial-system/backend/src/app/modules/case/pdf.service.ts @@ -293,7 +293,7 @@ export class PdfService { async getSubpoenaPdf( theCase: Case, defendant: Defendant, - subpoena: Subpoena, + subpoena?: Subpoena, arraignmentDate?: Date, location?: string, subpoenaType?: SubpoenaType, diff --git a/apps/judicial-system/backend/src/app/modules/subpoena/subpoena.controller.ts b/apps/judicial-system/backend/src/app/modules/subpoena/subpoena.controller.ts index 2dcdf3848b7e..0a4eea819bcb 100644 --- a/apps/judicial-system/backend/src/app/modules/subpoena/subpoena.controller.ts +++ b/apps/judicial-system/backend/src/app/modules/subpoena/subpoena.controller.ts @@ -84,8 +84,8 @@ export class SubpoenaController { @Param('subpoenaId') subpoenaId: string, @CurrentCase() theCase: Case, @CurrentDefendant() defendant: Defendant, - @CurrentSubpoena() subpoena: Subpoena, @Res() res: Response, + @CurrentSubpoena() subpoena?: Subpoena, @Query('arraignmentDate') arraignmentDate?: Date, @Query('location') location?: string, @Query('subpoenaType') subpoenaType?: SubpoenaType, From 279f2f43942a7d8986e21c84bb734c4399004ea7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gu=C3=B0j=C3=B3n=20Gu=C3=B0j=C3=B3nsson?= Date: Mon, 30 Sep 2024 11:16:48 +0200 Subject: [PATCH 17/18] Removes redundant constructor --- .../src/app/modules/subpoena/guards/subpoenaExists.guard.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/apps/judicial-system/backend/src/app/modules/subpoena/guards/subpoenaExists.guard.ts b/apps/judicial-system/backend/src/app/modules/subpoena/guards/subpoenaExists.guard.ts index 71a5672010c6..624bd2d361c1 100644 --- a/apps/judicial-system/backend/src/app/modules/subpoena/guards/subpoenaExists.guard.ts +++ b/apps/judicial-system/backend/src/app/modules/subpoena/guards/subpoenaExists.guard.ts @@ -47,9 +47,6 @@ export class SubpoenaExistsGuard implements CanActivate { @Injectable() export class SubpoenaExistsOptionalGuard extends SubpoenaExistsGuard { - constructor(subpoenaService: SubpoenaService) { - super(subpoenaService) - } async canActivate(context: ExecutionContext): Promise { const request = context.switchToHttp().getRequest() From 49b739ced3c5bfa2f5a6dde363032d782522f9e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=8Dvar=20Oddsson?= Date: Mon, 30 Sep 2024 10:37:34 +0000 Subject: [PATCH 18/18] Fix tests --- .../subpoena/test/subpoenaController/getSubpoenaPdf.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/judicial-system/backend/src/app/modules/subpoena/test/subpoenaController/getSubpoenaPdf.spec.ts b/apps/judicial-system/backend/src/app/modules/subpoena/test/subpoenaController/getSubpoenaPdf.spec.ts index 73d2580e33ff..2db39b25f289 100644 --- a/apps/judicial-system/backend/src/app/modules/subpoena/test/subpoenaController/getSubpoenaPdf.spec.ts +++ b/apps/judicial-system/backend/src/app/modules/subpoena/test/subpoenaController/getSubpoenaPdf.spec.ts @@ -43,8 +43,8 @@ describe('SubpoenaController - Get subpoena pdf', () => { subpoenaId, theCase, defendant, - subpoena, res, + subpoena, ) } catch (error) { then.error = error as Error