Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(j-s): Deliver Subpoena to Court #17239

Merged
merged 4 commits into from
Dec 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 25 additions & 11 deletions apps/judicial-system/backend/src/app/modules/case/case.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1312,18 +1312,29 @@ export class CaseService {
(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 ?? '',
],
}))
.map((updatedDefendant) => [
{
type: MessageType.DELIVERY_TO_POLICE_SUBPOENA,
user,
caseId: theCase.id,
elementId: [
updatedDefendant.id,
updatedDefendant.subpoenas?.[0].id ?? '',
],
},
{
type: MessageType.DELIVERY_TO_COURT_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.flat())
}
}

Expand Down Expand Up @@ -1426,7 +1437,10 @@ export class CaseService {
await this.addMessagesForCourtCaseConnectionToQueue(updatedCase, user)
}
} else {
if (updatedCase.prosecutorId !== theCase.prosecutorId) {
if (
!isIndictment &&
unakb marked this conversation as resolved.
Show resolved Hide resolved
updatedCase.prosecutorId !== theCase.prosecutorId
) {
// New prosecutor
await this.addMessagesForProsecutorChangeToQueue(updatedCase, user)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,10 @@ export class InternalCaseController {
)
}

@UseGuards(CaseExistsGuard)
@UseGuards(
CaseExistsGuard,
new CaseTypeGuard([...restrictionCases, ...investigationCases]),
)
unakb marked this conversation as resolved.
Show resolved Hide resolved
gudjong marked this conversation as resolved.
Show resolved Hide resolved
@Post(
`case/:caseId/${messageEndpoint[MessageType.DELIVERY_TO_COURT_PROSECUTOR]}`,
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -897,12 +897,24 @@ describe('CaseController - Update', () => {
caseId: theCase.id,
elementId: [defendantId1, subpoenaId1],
},
{
type: MessageType.DELIVERY_TO_COURT_SUBPOENA,
user,
caseId: theCase.id,
elementId: [defendantId1, subpoenaId1],
},
{
type: MessageType.DELIVERY_TO_POLICE_SUBPOENA,
user,
caseId: theCase.id,
elementId: [defendantId2, subpoenaId2],
},
{
type: MessageType.DELIVERY_TO_COURT_SUBPOENA,
user,
caseId: theCase.id,
elementId: [defendantId2, subpoenaId2],
},
])
})
})
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import { CanActivate } from '@nestjs/common'
import {
investigationCases,
restrictionCases,
} from '@island.is/judicial-system/types'

import { CaseExistsGuard } from '../../guards/caseExists.guard'
import { CaseTypeGuard } from '../../guards/caseType.guard'
import { InternalCaseController } from '../../internalCase.controller'

describe('InternalCaseController - Deliver prosecutor to court guards', () => {
Expand All @@ -14,19 +18,12 @@ describe('InternalCaseController - Deliver prosecutor to court guards', () => {
)
})

it('should have one guards', () => {
expect(guards).toHaveLength(1)
})

describe('CaseExistsGuard', () => {
let guard: CanActivate

beforeEach(() => {
guard = new guards[0]()
})

it('should have CaseExistsGuard as guard 1', () => {
expect(guard).toBeInstanceOf(CaseExistsGuard)
it('should have the right guard configuration', () => {
expect(guards).toHaveLength(2)
expect(new guards[0]()).toBeInstanceOf(CaseExistsGuard)
expect(guards[1]).toBeInstanceOf(CaseTypeGuard)
expect(guards[1]).toEqual({
allowedCaseTypes: [...restrictionCases, ...investigationCases],
})
gudjong marked this conversation as resolved.
Show resolved Hide resolved
})
})
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ export enum CourtDocumentFolder {
CASE_DOCUMENTS = 'Gögn málsins',
COURT_DOCUMENTS = 'Dómar, úrskurðir og Þingbók',
APPEAL_DOCUMENTS = 'Kæra til Landsréttar',
SUBPOENA_DOCUMENTS = 'Boðanir',
}

export type Subtype = Exclude<CaseType, CaseType.INDICTMENT> | IndictmentSubtype
Expand Down Expand Up @@ -342,6 +343,7 @@ export class CourtService {

return await this.courtClientService.createCase(courtId, {
caseType: isIndictment ? 'S - Ákærumál' : 'R - Rannsóknarmál',
// TODO: send a list of subtypes when CourtService supports it
subtype: courtSubtype as string,
status: 'Skráð',
receivalDate: formatISO(receivalDate, { representation: 'date' }),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ export class InternalSubpoenaController {
)
@ApiOkResponse({
type: DeliverResponse,
description: 'Delivers a subpoena to police',
description: 'Delivers a subpoena to the police',
})
deliverSubpoenaToPolice(
@Param('caseId') caseId: string,
Expand All @@ -79,7 +79,7 @@ export class InternalSubpoenaController {
@Body() deliverDto: DeliverDto,
): Promise<DeliverResponse> {
this.logger.debug(
`Delivering subpoena ${subpoenaId} to police for defendant ${defendantId} of case ${caseId}`,
`Delivering subpoena ${subpoenaId} pdf to police for defendant ${defendantId} of case ${caseId}`,
)

return this.subpoenaService.deliverSubpoenaToPolice(
Expand All @@ -89,4 +89,40 @@ export class InternalSubpoenaController {
deliverDto.user,
)
}

@UseGuards(
CaseExistsGuard,
new CaseTypeGuard(indictmentCases),
DefendantExistsGuard,
SubpoenaExistsGuard,
)
@Post(
`case/:caseId/${
messageEndpoint[MessageType.DELIVERY_TO_COURT_SUBPOENA]
}/:defendantId/:subpoenaId`,
)
@ApiOkResponse({
type: DeliverResponse,
description: 'Delivers a subpoena to the court',
})
deliverSubpoenaToCourt(
@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<DeliverResponse> {
this.logger.debug(
`Delivering subpoena ${subpoenaId} pdf to court for defendant ${defendantId} of case ${caseId}`,
)

return this.subpoenaService.deliverSubpoenaToCourt(
theCase,
defendant,
subpoena,
deliverDto.user,
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { SequelizeModule } from '@nestjs/sequelize'
import { MessageModule } from '@island.is/judicial-system/message'

import { CaseModule } from '../case/case.module'
import { CourtModule } from '../court/court.module'
import { DefendantModule } from '../defendant/defendant.module'
import { Defendant } from '../defendant/models/defendant.model'
import { EventModule } from '../event/event.module'
Expand All @@ -23,6 +24,7 @@ import { SubpoenaService } from './subpoena.service'
forwardRef(() => MessageModule),
forwardRef(() => EventModule),
forwardRef(() => DefendantModule),
CourtModule,
SequelizeModule.forFeature([Subpoena, Defendant]),
],
controllers: [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import {

import { Case } from '../case/models/case.model'
import { PdfService } from '../case/pdf.service'
import { CourtDocumentFolder, CourtService } from '../court'
import { DefendantService } from '../defendant/defendant.service'
import { Defendant } from '../defendant/models/defendant.model'
import { EventService } from '../event'
Expand Down Expand Up @@ -93,6 +94,7 @@ export class SubpoenaService {
private readonly fileService: FileService,
private readonly eventService: EventService,
private readonly defendantService: DefendantService,
private readonly courtService: CourtService,
@Inject(LOGGER_PROVIDER) private readonly logger: Logger,
) {}

Expand Down Expand Up @@ -356,6 +358,41 @@ export class SubpoenaService {
}
}

async deliverSubpoenaToCourt(
theCase: Case,
defendant: Defendant,
subpoena: Subpoena,
user: TUser,
): Promise<DeliverResponse> {
return this.pdfService
.getSubpoenaPdf(theCase, defendant, subpoena)
.then(async (pdf) => {
const fileName = `Fyrirkall - ${defendant.name}`

return this.courtService.createDocument(
user,
theCase.id,
theCase.courtId,
theCase.courtCaseNumber,
CourtDocumentFolder.SUBPOENA_DOCUMENTS,
fileName,
`${fileName}.pdf`,
'application/pdf',
pdf,
)
})
.then(() => ({ delivered: true }))
.catch((reason) => {
// Tolerate failure, but log error
this.logger.warn(
`Failed to upload subpoena ${subpoena.id} pdf to court for defendant ${defendant.id} of case ${theCase.id}`,
{ reason },
)

return { delivered: false }
})
}
gudjong marked this conversation as resolved.
Show resolved Hide resolved

async getSubpoena(subpoena: Subpoena, user?: TUser): Promise<Subpoena> {
if (!subpoena.subpoenaId) {
// The subpoena has not been delivered to the police
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
import { MessageService } from '@island.is/judicial-system/message'

import { CaseService, PdfService } from '../../case'
import { CourtService } from '../../court'
import { Defendant, DefendantService } from '../../defendant'
import { EventService } from '../../event'
import { FileService } from '../../file'
Expand All @@ -24,14 +25,15 @@ import { Subpoena } from '../models/subpoena.model'
import { SubpoenaController } from '../subpoena.controller'
import { SubpoenaService } from '../subpoena.service'

jest.mock('@island.is/judicial-system/message')
jest.mock('../../user/user.service')
jest.mock('../../case/case.service')
jest.mock('../../case/pdf.service')
jest.mock('../../police/police.service')
jest.mock('../../file/file.service')
jest.mock('../../event/event.service')
jest.mock('../../defendant/defendant.service')
jest.mock('@island.is/judicial-system/message')
jest.mock('../../court/court.service')

export const createTestingSubpoenaModule = async () => {
const subpoenaModule = await Test.createTestingModule({
Expand All @@ -51,6 +53,7 @@ export const createTestingSubpoenaModule = async () => {
FileService,
EventService,
DefendantService,
CourtService,
{
provide: LOGGER_PROVIDER,
useValue: {
Expand Down Expand Up @@ -94,6 +97,8 @@ export const createTestingSubpoenaModule = async () => {

const fileService = subpoenaModule.get<FileService>(FileService)

const courtService = subpoenaModule.get<CourtService>(CourtService)

const subpoenaModel = await subpoenaModule.resolve<typeof Subpoena>(
getModelToken(Subpoena),
)
Expand All @@ -118,6 +123,7 @@ export const createTestingSubpoenaModule = async () => {
pdfService,
policeService,
fileService,
courtService,
subpoenaModel,
subpoenaService,
subpoenaController,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { indictmentCases } from '@island.is/judicial-system/types'

import { CaseExistsGuard, CaseTypeGuard } from '../../../case'
import { DefendantExistsGuard } from '../../../defendant'
import { SubpoenaExistsGuard } from '../../guards/subpoenaExists.guard'
import { InternalSubpoenaController } from '../../internalSubpoena.controller'

describe('InternalSubpoenaController - Deliver subpoena to court guards', () => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
let guards: any[]

beforeEach(() => {
guards = Reflect.getMetadata(
'__guards__',
InternalSubpoenaController.prototype.deliverSubpoenaToCourt,
)
})

it('should have the right guard configuration', () => {
expect(guards).toHaveLength(4)
expect(new guards[0]()).toBeInstanceOf(CaseExistsGuard)
expect(guards[1]).toBeInstanceOf(CaseTypeGuard)
expect(guards[1]).toEqual({
allowedCaseTypes: indictmentCases,
})
expect(new guards[2]()).toBeInstanceOf(DefendantExistsGuard)
expect(new guards[3]()).toBeInstanceOf(SubpoenaExistsGuard)
})
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { indictmentCases } from '@island.is/judicial-system/types'

import { CaseExistsGuard, CaseTypeGuard } from '../../../case'
import { DefendantExistsGuard } from '../../../defendant'
import { SubpoenaExistsGuard } from '../../guards/subpoenaExists.guard'
import { InternalSubpoenaController } from '../../internalSubpoena.controller'

describe('InternalSubpoenaController - Deliver subpoena to police guards', () => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
let guards: any[]

beforeEach(() => {
guards = Reflect.getMetadata(
'__guards__',
InternalSubpoenaController.prototype.deliverSubpoenaToPolice,
)
})

it('should have the right guard configuration', () => {
expect(guards).toHaveLength(4)
expect(new guards[0]()).toBeInstanceOf(CaseExistsGuard)
expect(guards[1]).toBeInstanceOf(CaseTypeGuard)
expect(guards[1]).toEqual({
allowedCaseTypes: indictmentCases,
})
expect(new guards[2]()).toBeInstanceOf(DefendantExistsGuard)
expect(new guards[3]()).toBeInstanceOf(SubpoenaExistsGuard)
})
})
Loading
Loading