Skip to content

Commit

Permalink
feat(j-s): Additional info for law and order cases and subpoenas (#16132
Browse files Browse the repository at this point in the history
)

* feat(j-s): Return acknowledged info for case in digital mailbox API

* feat(j-s): New info and cleanup for law and order

* Update subpoena.response.ts

* Update subpoena.response.ts

* Change tags and messages to enums

* Update case.response.ts

* fix(j-s): Added subtitle for subpoena response

---------

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
  • Loading branch information
2 people authored and thoreyjona committed Oct 2, 2024
1 parent 79d650d commit bf59c7f
Show file tree
Hide file tree
Showing 10 changed files with 154 additions and 29 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +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 { User, UserService } from '../user'
import { InternalCreateCaseDto } from './dto/internalCreateCase.dto'
import { archiveFilter } from './filters/case.archiveFilter'
Expand Down Expand Up @@ -1204,7 +1205,10 @@ export class InternalCaseService {
async getIndictmentCases(nationalId: string): Promise<Case[]> {
return this.caseModel.findAll({
include: [
{ model: Defendant, as: 'defendants' },
{
model: Defendant,
as: 'defendants',
},
{
model: DateLog,
as: 'dateLogs',
Expand All @@ -1228,11 +1232,25 @@ export class InternalCaseService {
async getIndictmentCase(caseId: string, nationalId: string): Promise<Case> {
const caseById = await this.caseModel.findOne({
include: [
{ model: Defendant, as: 'defendants' },
{
model: Defendant,
as: 'defendants',
include: [
{
model: Subpoena,
as: 'subpoenas',
order: [['created', 'DESC']],
},
],
},
{ model: Institution, as: 'court' },
{ model: Institution, as: 'prosecutorsOffice' },
{ model: User, as: 'judge' },
{ model: User, as: 'prosecutor' },
{
model: User,
as: 'prosecutor',
include: [{ model: Institution, as: 'institution' }],
},
{ model: DateLog, as: 'dateLogs' },
],
attributes: ['courtCaseNumber', 'id'],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ 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'
Expand All @@ -18,7 +19,7 @@ import { InternalDefendantController } from './internalDefendant.controller'
MessageModule,
forwardRef(() => CourtModule),
forwardRef(() => CaseModule),
SequelizeModule.forFeature([Defendant, CivilClaimant]),
SequelizeModule.forFeature([Defendant, CivilClaimant, Subpoena]),
],
controllers: [
DefendantController,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
CreatedAt,
DataType,
ForeignKey,
HasMany,
Model,
Table,
UpdatedAt,
Expand All @@ -20,6 +21,7 @@ import {
} from '@island.is/judicial-system/types'

import { Case } from '../../case/models/case.model'
import { Subpoena } from '../../subpoena/models/subpoena.model'

@Table({
tableName: 'defendant',
Expand Down Expand Up @@ -131,4 +133,8 @@ export class Defendant extends Model {
})
@ApiPropertyOptional({ enum: SubpoenaType })
subpoenaType?: SubpoenaType

@HasMany(() => Subpoena, { foreignKey: 'defendantId' })
@ApiPropertyOptional({ type: () => Subpoena, isArray: true })
subpoenas?: Subpoena[]
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {
XRoadMemberClass,
} from '@island.is/shared/utils/server'

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

Expand Down Expand Up @@ -520,6 +521,9 @@ export class PoliceService {
const { nationalId: defendantNationalId } = defendant
const { name: actor } = user

const normalizedNationalId =
normalizeAndFormatNationalId(defendantNationalId)[0]

const documentName = `Fyrirkall í máli ${workingCase.courtCaseNumber}`
const arraignmentInfo = dateLogs?.find(
(dateLog) => dateLog.dateType === 'ARRAIGNMENT_DATE',
Expand All @@ -541,7 +545,7 @@ export class PoliceService {
documentBase64: subpoena,
courtRegistrationDate: arraignmentInfo?.date,
prosecutorSsn: prosecutor?.nationalId,
prosecutedSsn: defendantNationalId,
prosecutedSsn: normalizedNationalId,
courtAddress: court?.address,
courtRoomNumber: arraignmentInfo?.location || '',
courtCeremony: 'Þingfesting',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class IndictmentCaseData {
caseNumber!: string

@ApiProperty({ type: Boolean })
acknowledged?: boolean
hasBeenServed?: boolean

@ApiProperty({ type: [Groups] })
groups!: Groups[]
Expand All @@ -26,21 +26,22 @@ export class CaseResponse {
data!: IndictmentCaseData

static fromInternalCaseResponse(
res: InternalCaseResponse,
internalCase: InternalCaseResponse,
lang?: string,
): CaseResponse {
const t = getTranslations(lang)
const defendant = res.defendants[0]
const subpoenaDateLog = res.dateLogs?.find(
const defendant = internalCase.defendants[0] ?? {}
const subpoenaDateLog = internalCase.dateLogs?.find(
(dateLog) => dateLog.dateType === DateType.ARRAIGNMENT_DATE,
)
const subpoenaCreatedDate = subpoenaDateLog?.created.toString() ?? ''
const subpoenaCreatedDate = subpoenaDateLog?.created?.toString() ?? '' //TODO: Change to created from subpoena db entry?
const subpoenas = defendant.subpoenas ?? []

return {
caseId: res.id,
caseId: internalCase.id,
data: {
caseNumber: `${t.caseNumber} ${res.courtCaseNumber}`,
acknowledged: false, // TODO: Connect to real data
caseNumber: `${t.caseNumber} ${internalCase.courtCaseNumber}`,
hasBeenServed: subpoenas.length > 0 ? subpoenas[0].acknowledged : false,
groups: [
{
label: t.defendant,
Expand Down Expand Up @@ -75,23 +76,23 @@ export class CaseResponse {
},
{
label: t.courtCaseNumber,
value: res.courtCaseNumber,
value: internalCase.courtCaseNumber,
},
{
label: t.court,
value: res.court.name,
value: internalCase.court.name,
},
{
label: t.judge,
value: res.judge.name,
value: internalCase.judge.name,
},
{
label: t.institution,
value: res.prosecutorsOffice.name,
value: internalCase.prosecutorsOffice.name,
},
{
label: t.prosecutor,
value: res.prosecutor.name,
value: internalCase.prosecutor.name,
},
],
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,35 @@
import { IsEnum } from 'class-validator'

import { ApiProperty } from '@nestjs/swagger'

import { isCompletedCase } from '@island.is/judicial-system/types'

import { InternalCasesResponse } from './internal/internalCases.response'
import { getTranslations } from './utils/translations.strings'

enum TagVariant {
BLUE = 'blue',
DARKER_BLUE = 'darkerBlue',
PURPLE = 'purple',
WHITE = 'white',
RED = 'red',
ROSE = 'rose',
BLUEBERRY = 'blueberry',
DARK = 'dark',
MINT = 'mint',
YELLOW = 'yellow',
DISABLED = 'disabled',
WARN = 'warn',
}

class StateTag {
@IsEnum(TagVariant)
@ApiProperty({ enum: TagVariant })
color!: TagVariant

@ApiProperty({ type: String })
label!: string
}
export class CasesResponse {
@ApiProperty({ type: String })
id!: string
Expand All @@ -15,11 +40,8 @@ export class CasesResponse {
@ApiProperty({ type: String })
type!: string

@ApiProperty({ type: Object })
state!: {
color: string
label: string
}
@ApiProperty({ type: StateTag })
state!: StateTag

static fromInternalCasesResponse(
response: InternalCasesResponse[],
Expand All @@ -31,7 +53,9 @@ export class CasesResponse {
return {
id: item.id,
state: {
color: isCompletedCase(item.state) ? 'purple' : 'blue',
color: isCompletedCase(item.state)
? TagVariant.PURPLE
: TagVariant.BLUE,
label: isCompletedCase(item.state) ? t.completed : t.active,
},
caseNumber: `${t.caseNumber} ${item.courtCaseNumber}`,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ interface Defendant {
defenderEmail?: string
defenderPhoneNumber?: string
defenderChoice?: DefenderChoice
subpoenas?: Subpoena[]
}

interface DateLog {
Expand All @@ -37,3 +38,9 @@ interface DateLog {
date: Date
location?: string
}

interface Subpoena {
id: string
subpoenaId: string
acknowledged: boolean
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,24 +12,53 @@ import { InternalCaseResponse } from './internal/internalCase.response'
import { Groups } from './shared/groups.model'
import { getTranslations } from './utils/translations.strings'

enum AlertMessageType {
ERROR = 'error',
INFO = 'info',
SUCCESS = 'success',
WARNING = 'warning',
DEFAULT = 'default',
}

class DefenderInfo {
@IsEnum(DefenderChoice)
@ApiProperty({ enum: DefenderChoice })
defenderChoice!: DefenderChoice

@ApiProperty({ type: () => String })
defenderName?: string

@ApiProperty({ type: () => Boolean })
canEdit?: boolean

@ApiProperty({ type: () => String })
courtContactInfo?: string
}

class AlertMessage {
@IsEnum(AlertMessageType)
@ApiProperty({ enum: AlertMessageType })
type?: AlertMessageType

@ApiProperty({ type: () => String })
message?: string
}

class SubpoenaData {
@ApiProperty({ type: () => String })
title!: string

@ApiProperty({ type: Boolean })
acknowledged?: boolean
@ApiProperty({ type: String })
subtitle?: string

@ApiProperty({ type: () => [Groups] })
groups!: Groups[]

@ApiProperty({ type: () => [AlertMessage] })
alerts?: AlertMessage[]

@ApiProperty({ type: Boolean })
hasBeenServed?: boolean
}

export class SubpoenaResponse {
Expand Down Expand Up @@ -59,31 +88,52 @@ export class SubpoenaResponse {

const waivedRight = defendantInfo?.defenderChoice === DefenderChoice.WAIVE
const hasDefender = defendantInfo?.defenderName !== undefined
const subpoena = defendantInfo?.subpoenas ?? []
const hasBeenServed = subpoena[0]?.acknowledged ?? false
const canChangeDefenseChoice = !waivedRight && !hasDefender

const subpoenaDateLog = internalCase.dateLogs?.find(
(dateLog) => dateLog.dateType === DateType.ARRAIGNMENT_DATE,
)
const arraignmentDate = subpoenaDateLog?.date ?? ''
const subpoenaCreatedDate = subpoenaDateLog?.created ?? '' //TODO: Change to subpoena created in RLS
const arraignmentLocation = subpoenaDateLog?.location
? `${internalCase.court.name}, Dómsalur ${subpoenaDateLog.location}`
: internalCase.court.name
const courtNameAndAddress = `${internalCase.court.name}, ${internalCase.court.address}`

return {
caseId: internalCase.id,
data: {
title: t.subpoena,
acknowledged: false, // TODO: Connect to real data
subtitle: courtNameAndAddress,
hasBeenServed: hasBeenServed,
alerts: [
...(hasBeenServed
? [
{
type: AlertMessageType.SUCCESS,
message: t.subpoenaServed,
},
]
: []),
],
groups: [
{
label: `${t.caseNumber} ${internalCase.courtCaseNumber}`,
items: [
[t.date, formatDate(subpoenaCreatedDate, 'PP')],
[t.institution, 'Lögreglustjórinn á höfuðborgarsvæðinu'],
[
t.institution,
internalCase.prosecutor?.institution?.name ?? t.notAvailable,
],
[t.prosecutor, internalCase.prosecutor?.name],
[t.accused, defendantInfo?.name],
[
t.arraignmentDate,
formatDate(arraignmentDate, "d.M.yyyy 'kl.' HH:mm"),
],
[t.location, subpoenaDateLog?.location ?? ''],
[t.location, arraignmentLocation],
[t.courtCeremony, t.parliamentaryConfirmation],
].map((item) => ({
label: item[0] ?? '',
Expand All @@ -100,6 +150,10 @@ export class SubpoenaResponse {
!waivedRight && hasDefender
? defendantInfo?.defenderName
: undefined,
canEdit: canChangeDefenseChoice,
courtContactInfo: canChangeDefenseChoice
? undefined
: t.courtContactInfo,
}
: undefined,
}
Expand Down
Loading

0 comments on commit bf59c7f

Please sign in to comment.