Skip to content

Commit

Permalink
chore(j-s): Send signed court record to police for investigation cases
Browse files Browse the repository at this point in the history
  • Loading branch information
unakb committed Dec 11, 2024
1 parent 0423040 commit d056354
Show file tree
Hide file tree
Showing 8 changed files with 284 additions and 3 deletions.
24 changes: 24 additions & 0 deletions apps/judicial-system/backend/src/app/modules/case/case.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ import {
eventTypes,
isCompletedCase,
isIndictmentCase,
isInvestigationCase,
isRequestCase,
isTrafficViolationCase,
notificationTypes,
Expand Down Expand Up @@ -846,6 +847,27 @@ export class CaseService {
)
}

private addMessagesForSignedCourtRecordToQueue(theCase: Case, user: TUser) {
const messages = []

if (
theCase.origin === CaseOrigin.LOKE &&
isInvestigationCase(theCase.type)
) {
messages.push({
type: MessageType.DELIVERY_TO_POLICE_SIGNED_COURT_RECORD,
user,
caseId: theCase.id,
})
}

if (messages && messages.length > 0) {
return this.messageService.sendMessagesToQueue(messages)
}

return
}

private addMessagesForSignedRulingToQueue(
theCase: Case,
user: TUser,
Expand Down Expand Up @@ -1899,6 +1921,8 @@ export class CaseService {
false,
)

await this.addMessagesForSignedCourtRecordToQueue(theCase, user)

return { documentSigned: true }
} catch (error) {
this.eventService.postErrorEvent(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -571,6 +571,35 @@ export class InternalCaseController {
)
}

@UseGuards(
CaseExistsGuard,
new CaseTypeGuard([...restrictionCases, ...investigationCases]),
CaseCompletedGuard,
)
@Post(
`case/:caseId/${
messageEndpoint[MessageType.DELIVERY_TO_POLICE_SIGNED_COURT_RECORD]
}`,
)
@ApiOkResponse({
type: DeliverResponse,
description: 'Delivers a signed ruling to police',
})
deliverSignedCourtRecordToPolice(
@Param('caseId') caseId: string,
@CurrentCase() theCase: Case,
@Body() deliverDto: DeliverDto,
): Promise<DeliverResponse> {
this.logger.debug(
`Delivering the signed court record for case ${caseId} to police`,
)

return this.internalCaseService.deliverSignedCourtRecordToPolice(
theCase,
deliverDto.user,
)
}

@UseGuards(
CaseExistsGuard,
new CaseTypeGuard([...restrictionCases, ...investigationCases]),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,13 @@ export class InternalCaseService {
)
}

private getSignedCourtRecordPdf(theCase: Case) {
return this.awsS3Service.getGeneratedRequestCaseObject(
theCase.type,
`${theCase.id}/courtRecord.pdf`,
)
}

private async deliverSignedRulingPdfToCourt(
theCase: Case,
user: TUser,
Expand Down Expand Up @@ -1099,6 +1106,32 @@ export class InternalCaseService {
return { delivered }
}

async deliverSignedCourtRecordToPolice(
theCase: Case,
user: TUser,
): Promise<DeliverResponse> {
const delivered = await this.getSignedCourtRecordPdf(theCase)
.then((pdf) =>
this.deliverCaseToPoliceWithFiles(theCase, user, [
{
type: PoliceDocumentType.RVTB,
courtDocument: Base64.btoa(pdf.toString('binary')),
},
]),
)
.catch((reason) => {
// Tolerate failure, but log error
this.logger.error(
`Failed to deliver signed court record for case ${theCase.id} to police`,
{ reason },
)

return false
})

return { delivered }
}

async deliverSignedRulingToPolice(
theCase: Case,
user: TUser,
Expand All @@ -1115,7 +1148,7 @@ export class InternalCaseService {
.catch((reason) => {
// Tolerate failure, but log error
this.logger.error(
`Failed to deliver sigend ruling for case ${theCase.id} to police`,
`Failed to deliver signed ruling for case ${theCase.id} to police`,
{ reason },
)

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
import { Base64 } from 'js-base64'
import { uuid } from 'uuidv4'

import {
CaseOrigin,
CaseState,
CaseType,
User,
} from '@island.is/judicial-system/types'

import { createTestingCaseModule } from '../createTestingCaseModule'

import { nowFactory } from '../../../../factories'
import { randomDate } from '../../../../test'
import { AwsS3Service } from '../../../aws-s3'
import { PoliceDocumentType, PoliceService } from '../../../police'
import { Case } from '../../models/case.model'
import { DeliverResponse } from '../../models/deliver.response'

jest.mock('../../../../factories')

interface Then {
result: DeliverResponse
error: Error
}

type GivenWhenThen = (caseId: string, theCase: Case) => Promise<Then>

describe('InternalCaseController - Deliver signed court record to police', () => {
const userId = uuid()
const user = { id: userId } as User

let mockAwsS3Service: AwsS3Service
let mockPoliceService: PoliceService
let givenWhenThen: GivenWhenThen

beforeEach(async () => {
const { awsS3Service, policeService, internalCaseController } =
await createTestingCaseModule()

mockAwsS3Service = awsS3Service
mockPoliceService = policeService

const mockGetGeneratedObject =
awsS3Service.getGeneratedRequestCaseObject as jest.Mock
mockGetGeneratedObject.mockRejectedValue(new Error('Some error'))
const mockUpdatePoliceCase = mockPoliceService.updatePoliceCase as jest.Mock
mockUpdatePoliceCase.mockRejectedValue(new Error('Some error'))

givenWhenThen = async (caseId: string, theCase: Case) => {
const then = {} as Then

await internalCaseController
.deliverSignedCourtRecordToPolice(caseId, theCase, { user })
.then((result) => (then.result = result))
.catch((error) => (then.error = error))

return then
}
})

describe('deliver case to police', () => {
const caseId = uuid()
const caseType = CaseType.PHONE_TAPPING
const caseState = CaseState.ACCEPTED
const policeCaseNumber = uuid()
const courtCaseNumber = uuid()
const defendantNationalId = '0123456789'
const validToDate = randomDate()
const caseConclusion = 'test conclusion'
const theCase = {
id: caseId,
origin: CaseOrigin.LOKE,
type: caseType,
state: caseState,
policeCaseNumbers: [policeCaseNumber],
courtCaseNumber,
defendants: [{ nationalId: defendantNationalId }],
validToDate,
conclusion: caseConclusion,
} as Case
const courtRecordPdf = 'test court record'

let then: Then

beforeEach(async () => {
const mockToday = nowFactory as jest.Mock
mockToday.mockReturnValueOnce(validToDate)

const mockGetGeneratedObject =
mockAwsS3Service.getGeneratedRequestCaseObject as jest.Mock
mockGetGeneratedObject.mockResolvedValueOnce(courtRecordPdf)
const mockUpdatePoliceCase =
mockPoliceService.updatePoliceCase as jest.Mock
mockUpdatePoliceCase.mockResolvedValueOnce(true)

then = await givenWhenThen(caseId, theCase)
})

it('should update the police case with a signed court record', async () => {
expect(
mockAwsS3Service.getGeneratedRequestCaseObject,
).toHaveBeenCalledWith(caseType, `${caseId}/courtRecord.pdf`)
expect(mockPoliceService.updatePoliceCase).toHaveBeenCalledWith(
user,
caseId,
caseType,
caseState,
policeCaseNumber,
courtCaseNumber,
defendantNationalId,
validToDate,
caseConclusion,
[
{
type: PoliceDocumentType.RVTB,
courtDocument: Base64.btoa(courtRecordPdf),
},
],
)
expect(then.result.delivered).toEqual(true)
})
})
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { CanActivate } from '@nestjs/common'

import {
investigationCases,
restrictionCases,
} from '@island.is/judicial-system/types'

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

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

beforeEach(() => {
guards = Reflect.getMetadata(
'__guards__',
InternalCaseController.prototype.deliverSignedCourtRecordToPolice,
)
})

it('should have three guards', () => {
expect(guards).toHaveLength(3)
})

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

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

it('should have CaseExistsGuard as guard 1', () => {
expect(guard).toBeInstanceOf(CaseExistsGuard)
})
})

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

beforeEach(() => {
guard = guards[1]
})

it('should have CaseTypeGuard as guard 2', () => {
expect(guard).toBeInstanceOf(CaseTypeGuard)
expect(guard).toEqual({
allowedCaseTypes: [...restrictionCases, ...investigationCases],
})
})
})

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

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

it('should have CaseCompletedGuard as guard 3', () => {
expect(guard).toBeInstanceOf(CaseCompletedGuard)
})
})
})
4 changes: 2 additions & 2 deletions apps/judicial-system/web/messages/Core/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ export const errors = defineMessages({
'Notaður sem villuskilaboð þegar ekki gengur að eyða kröfuhafa',
},
createCase: {
id: 'judicial.system.core:errors.create_case',
defaultMessage: 'Upp kom villa við stofnun máls',
id: 'judicial.system.core:errors.create_case_v1',
defaultMessage: 'Upp kom villa við stofnun máls',
description: 'Notaður sem villuskilaboð þegar ekki gengur að stofna mál',
},
updateCase: {
Expand Down
3 changes: 3 additions & 0 deletions libs/judicial-system/message/src/lib/message.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,9 @@ export class MessageService {
): Promise<void> {
const MAX_BATCH_SIZE = 10

if (messages.length === 0) {
return // No messages to send
}
if (messages.length <= MAX_BATCH_SIZE) {
const queueUrl = await this.getQueueUrl()

Expand Down
2 changes: 2 additions & 0 deletions libs/judicial-system/message/src/lib/message.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export enum MessageType {
DELIVERY_TO_POLICE_INDICTMENT = 'DELIVERY_TO_POLICE_INDICTMENT',
DELIVERY_TO_POLICE_CASE_FILES_RECORD = 'DELIVERY_TO_POLICE_CASE_FILES_RECORD',
DELIVERY_TO_POLICE_SUBPOENA = 'DELIVERY_TO_POLICE_SUBPOENA',
DELIVERY_TO_POLICE_SIGNED_COURT_RECORD = 'DELIVERY_TO_POLICE_SIGNED_COURT_RECORD',
DELIVERY_TO_POLICE_SIGNED_RULING = 'DELIVERY_TO_POLICE_SIGNED_RULING',
DELIVERY_TO_POLICE_APPEAL = 'DELIVERY_TO_POLICE_APPEAL',
NOTIFICATION = 'NOTIFICATION',
Expand Down Expand Up @@ -62,6 +63,7 @@ export const messageEndpoint: { [key in MessageType]: string } = {
DELIVERY_TO_POLICE_INDICTMENT: 'deliverIndictmentToPolice',
DELIVERY_TO_POLICE_CASE_FILES_RECORD: 'deliverCaseFilesRecordToPolice',
DELIVERY_TO_POLICE_SUBPOENA: 'deliverSubpoenaToPolice',
DELIVERY_TO_POLICE_SIGNED_COURT_RECORD: 'deliverSignedCourtRecordToPolice',
DELIVERY_TO_POLICE_SIGNED_RULING: 'deliverSignedRulingToPolice',
DELIVERY_TO_POLICE_APPEAL: 'deliverAppealToPolice',
NOTIFICATION: 'notification',
Expand Down

0 comments on commit d056354

Please sign in to comment.