Skip to content

Commit

Permalink
feat(j-s): Deliver subpoena revocation to police (#17291)
Browse files Browse the repository at this point in the history
* feat(j-s): Revoke subpoenas from police when indictment cancelled

* Update case.service.ts

* feat(j-s): Send subpoena revocation to police

* Create deliverSubpoenaRevokedToPoliceGuards.spec.ts

---------

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
  • Loading branch information
unakb and kodiakhq[bot] authored Jan 7, 2025
1 parent 4e1a04f commit a7ec960
Show file tree
Hide file tree
Showing 7 changed files with 238 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1069,7 +1069,7 @@ export class CaseService {
)
}

private addMessagesForRevokedIndictmentCaseToQueue(
private async addMessagesForRevokedIndictmentCaseToQueue(
theCase: Case,
user: TUser,
): Promise<void> {
Expand All @@ -1084,6 +1084,21 @@ export class CaseService {
})
}

const subpoenasToRevoke = await this.subpoenaService.findByCaseId(
theCase.id,
)

if (subpoenasToRevoke?.length > 0) {
messages.push(
...subpoenasToRevoke.map((subpoena) => ({
type: MessageType.DELIVERY_TO_POLICE_SUBPOENA_REVOCATION,
user,
caseId: theCase.id,
elementId: [subpoena.defendantId, subpoena.id],
})),
)
}

return this.messageService.sendMessagesToQueue(messages)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ import { AwsS3Service } from '../aws-s3'
import { Case } from '../case'
import { Defendant } from '../defendant/models/defendant.model'
import { EventService } from '../event'
import { SubpoenaService } from '../subpoena'
import { Subpoena, SubpoenaService } from '../subpoena'
import { UploadPoliceCaseFileDto } from './dto/uploadPoliceCaseFile.dto'
import { CreateSubpoenaResponse } from './models/createSubpoena.response'
import { PoliceCaseFile } from './models/policeCaseFile.model'
Expand Down Expand Up @@ -684,4 +684,54 @@ export class PoliceService {
throw error
}
}

async revokeSubpoena(
workingCase: Case,
subpoena: Subpoena,
user: User,
): Promise<boolean> {
const { name: actor } = user

const subpoenaId = subpoena.subpoenaId

try {
const res = await this.fetchPoliceCaseApi(
`${this.xRoadPath}/InvalidateCourtSummon?sekGuid=${subpoenaId}`,
{
method: 'POST',
headers: {
accept: '*/*',
'X-Road-Client': this.config.clientId,
'X-API-KEY': this.config.policeApiKey,
},
agent: this.agent,
} as RequestInit,
)

if (res.ok) {
return true
}

throw await res.text()
} catch (error) {
this.logger.error(
`Failed revoke subpoena with id ${subpoenaId} for case ${workingCase.id} from police`,
{
error,
},
)

this.eventService.postErrorEvent(
'Failed to revoke subpoena from police',
{
caseId: workingCase.id,
subpoenaId,
actor,
},
error,
)

return false
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -125,4 +125,38 @@ export class InternalSubpoenaController {
deliverDto.user,
)
}

@UseGuards(
CaseExistsGuard,
new CaseTypeGuard(indictmentCases),
DefendantExistsGuard,
SubpoenaExistsGuard,
)
@Post(
`case/:caseId/${
messageEndpoint[MessageType.DELIVERY_TO_POLICE_SUBPOENA_REVOCATION]
}/:defendantId/:subpoenaId`,
)
@ApiOkResponse({
type: DeliverResponse,
description: 'Delivers subpoena revocation to police',
})
deliverSubpoenaRevokedToPolice(
@Param('caseId') caseId: string,
@Param('defendantId') defendantId: string,
@Param('subpoenaId') subpoenaId: string,
@CurrentCase() theCase: Case,
@CurrentSubpoena() subpoena: Subpoena,
@Body() deliverDto: DeliverDto,
): Promise<DeliverResponse> {
this.logger.debug(
`Delivering subpoena revocation of ${subpoenaId} to police for defendant ${defendantId} of case ${caseId}`,
)

return this.subpoenaService.deliverSubpoenaRevokedToPolice(
theCase,
subpoena,
deliverDto.user,
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,13 @@ export class SubpoenaService {
return subpoena
}

async findByCaseId(caseId: string): Promise<Subpoena[]> {
return this.subpoenaModel.findAll({
include,
where: { caseId },
})
}

async getIndictmentPdf(theCase: Case): Promise<Buffer> {
if (isTrafficViolationCase(theCase)) {
return await this.pdfService.getIndictmentPdf(theCase)
Expand Down Expand Up @@ -392,7 +399,33 @@ export class SubpoenaService {
return { delivered: false }
})
}
async deliverSubpoenaRevokedToPolice(
theCase: Case,
subpoena: Subpoena,
user: TUser,
): Promise<DeliverResponse> {
if (!subpoena.subpoenaId) {
this.logger.warn(
`Attempted to revoke a subpoena with id ${subpoena.id} that had not been delivered to the police`,
)
return { delivered: true }
}

const subpoenaRevoked = await this.policeService.revokeSubpoena(
theCase,
subpoena,
user,
)

if (subpoenaRevoked) {
this.logger.info(
`Subpoena ${subpoena.subpoenaId} successfully revoked from police`,
)
return { delivered: true }
} else {
return { delivered: false }
}
}
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
@@ -0,0 +1,73 @@
import { uuid } from 'uuidv4'

import { createTestingSubpoenaModule } from '../createTestingSubpoenaModule'

import { Case } from '../../../case'
import { DeliverDto } from '../../dto/deliver.dto'
import { DeliverResponse } from '../../models/deliver.response'
import { Subpoena } from '../../models/subpoena.model'
import { SubpoenaService } from '../../subpoena.service'

interface Then {
error: Error
}

type GivenWhenThen = () => Promise<Then>

describe('InternalSubpoenaController - Deliver subpoena revocation to police', () => {
const caseId = uuid()
const subpoenaId = uuid()
const defendantId = uuid()

const subpoena = { id: subpoenaId } as Subpoena
const theCase = { id: caseId } as Case
const user = { user: { id: uuid() } } as DeliverDto
const delivered = { delivered: true } as DeliverResponse

let mockSubpoenaService: SubpoenaService
let givenWhenThen: GivenWhenThen

beforeEach(async () => {
const { subpoenaService, internalSubpoenaController } =
await createTestingSubpoenaModule()

mockSubpoenaService = subpoenaService

const deliverSubpoenaRevokedToPoliceMock = jest.fn()
mockSubpoenaService.deliverSubpoenaRevokedToPolice =
deliverSubpoenaRevokedToPoliceMock

deliverSubpoenaRevokedToPoliceMock.mockResolvedValueOnce(delivered)

givenWhenThen = async () => {
const then = {} as Then

try {
await internalSubpoenaController.deliverSubpoenaRevokedToPolice(
caseId,
defendantId,
subpoenaId,
theCase,
subpoena,
user,
)
} catch (error) {
then.error = error as Error
}

return then
}
})

describe('subpoena revoked delivered to police', () => {
beforeEach(async () => {
await givenWhenThen()
})

it('should call deliverSubpoenaRevokedToPolice', () => {
expect(
mockSubpoenaService.deliverSubpoenaRevokedToPolice,
).toHaveBeenCalledWith(theCase, subpoena, user.user)
})
})
})
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 revoked to police guards', () => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
let guards: any[]

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

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)
})
})
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 @@ -24,6 +24,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_SUBPOENA_REVOCATION = 'DELIVERY_TO_POLICE_SUBPOENA_REVOCATION',
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',
Expand Down Expand Up @@ -65,6 +66,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_SUBPOENA_REVOCATION: 'deliverSubpoenaRevocationToPolice',
DELIVERY_TO_POLICE_SIGNED_COURT_RECORD: 'deliverSignedCourtRecordToPolice',
DELIVERY_TO_POLICE_SIGNED_RULING: 'deliverSignedRulingToPolice',
DELIVERY_TO_POLICE_APPEAL: 'deliverAppealToPolice',
Expand Down

0 comments on commit a7ec960

Please sign in to comment.