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): Additional info for law and order cases and subpoenas #16132

Merged
merged 9 commits into from
Sep 24, 2024
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
Expand Up @@ -5,6 +5,14 @@ import { isCompletedCase } from '@island.is/judicial-system/types'
import { InternalCasesResponse } from './internal/internalCases.response'
import { getTranslations } from './utils/translations.strings'

class StateTag {
@ApiProperty({ type: String })
color!: string

@ApiProperty({ type: String })
label!: string
}

export class CasesResponse {
@ApiProperty({ type: String })
id!: string
Expand All @@ -15,11 +23,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 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 @@ -19,17 +19,34 @@ class DefenderInfo {

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

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

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

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

@ApiProperty({ type: () => String })
message!: string
}
unakb marked this conversation as resolved.
Show resolved Hide resolved

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

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

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

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

export class SubpoenaResponse {
Expand Down Expand Up @@ -59,31 +76,50 @@ 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

return {
caseId: internalCase.id,
data: {
title: t.subpoena,
acknowledged: false, // TODO: Connect to real data
hasBeenServed: hasBeenServed,
alerts: [
...(hasBeenServed
? [
{
type: '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 +136,10 @@ export class SubpoenaResponse {
!waivedRight && hasDefender
? defendantInfo?.defenderName
: undefined,
canEdit: canChangeDefenseChoice,
courtContactInfo: canChangeDefenseChoice
? undefined
: t.courtContactInfo,
}
: undefined,
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ type Translations = {
court: string
courtCaseNumber: string
courtCeremony: string
courtContactInfo: string
date: string
defendant: string
defender: string
Expand All @@ -29,6 +30,7 @@ type Translations = {
prosecutorsOffice: string
subpoena: string
subpoenaSent: string
subpoenaServed: string
type: string
waiveRightToCounsel: string
}
Expand All @@ -45,6 +47,8 @@ const translations: Translations = {
court: 'Court',
courtCaseNumber: 'Case number',
courtCeremony: 'Court ceremony',
courtContactInfo:
'Please contact the court if you wish to change your choice of defender',
date: 'Date',
defendant: 'Defendant',
defender: 'Defender',
Expand All @@ -63,6 +67,8 @@ const translations: Translations = {
prosecutorsOffice: 'Institution',
subpoena: 'Subpoena',
subpoenaSent: 'Subpoena sent',
subpoenaServed:
'Confirmation of subpoena service has been sent to the court',
type: 'Type',
waiveRightToCounsel: 'Right to counsel waived',
},
Expand All @@ -76,6 +82,8 @@ const translations: Translations = {
court: 'Dómstóll',
courtCaseNumber: 'Málsnúmer héraðsdóms',
courtCeremony: 'Dómsathöfn',
courtContactInfo:
'Vinsamlegast hafið samband við dómstól til að breyta verjanda vali',
date: 'Dagsetning',
defendant: 'Varnaraðili',
defender: 'Verjandi',
Expand All @@ -94,6 +102,7 @@ const translations: Translations = {
prosecutorsOffice: 'Embætti',
subpoena: 'Fyrirkall',
subpoenaSent: 'Fyrirkall sent',
subpoenaServed: 'Staðfesting á móttöku hefur verið send á dómstóla',
type: 'Tegund',
waiveRightToCounsel: 'Ekki er óskað eftir verjanda',
},
Expand Down
Loading