From 0f8ba613e344dd8d6da32b033296872d42e5fe2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=8Dvar=20Oddsson?= Date: Wed, 18 Sep 2024 13:50:06 +0000 Subject: [PATCH 01/15] Add CivilClaimants table --- .../app/modules/backend/backend.service.ts | 27 +++++ .../app/modules/case/dto/updateCase.input.ts | 5 + .../src/app/modules/case/models/case.model.ts | 7 ++ .../defendant/civilClaimant.resolver.ts | 89 ++++++++++++++ .../app/modules/defendant/defendant.module.ts | 3 +- .../dto/createCivilClaimant.input.ts | 60 ++++++++++ .../dto/deleteCivilClaimant.input.ts | 14 +++ .../dto/updateCivilClaimant.input.ts | 64 ++++++++++ .../defendant/models/civilClaimant.model.ts | 46 +++++++ .../models/deleteCivilClaimant.response.ts | 7 ++ .../20240918134825-create-civil-claimant.js | 79 ++++++++++++ .../migrations/20240918134926-update-case.js | 25 ++++ .../src/app/modules/case/case.service.ts | 2 + .../app/modules/case/dto/updateCase.dto.ts | 5 + .../src/app/modules/case/guards/rolesRules.ts | 1 + .../src/app/modules/case/models/case.model.ts | 19 ++- .../defendant/civilClaimant.controller.ts | 98 +++++++++++++++ .../defendant/civilClaimant.service.ts | 75 ++++++++++++ .../app/modules/defendant/defendant.module.ts | 13 +- .../defendant/dto/createCivilClaimant.dto.ts | 55 +++++++++ .../defendant/dto/updateCivilClaimant.dto.ts | 55 +++++++++ .../defendant/models/civilClaimant.model.ts | 113 ++++++++++++++++++ .../models/deleteCivilClaimant.response.ts | 6 + .../src/components/FormProvider/case.graphql | 15 +++ .../audit-trail/src/lib/auditTrail.service.ts | 3 + 25 files changed, 881 insertions(+), 5 deletions(-) create mode 100644 apps/judicial-system/api/src/app/modules/defendant/civilClaimant.resolver.ts create mode 100644 apps/judicial-system/api/src/app/modules/defendant/dto/createCivilClaimant.input.ts create mode 100644 apps/judicial-system/api/src/app/modules/defendant/dto/deleteCivilClaimant.input.ts create mode 100644 apps/judicial-system/api/src/app/modules/defendant/dto/updateCivilClaimant.input.ts create mode 100644 apps/judicial-system/api/src/app/modules/defendant/models/civilClaimant.model.ts create mode 100644 apps/judicial-system/api/src/app/modules/defendant/models/deleteCivilClaimant.response.ts create mode 100644 apps/judicial-system/backend/migrations/20240918134825-create-civil-claimant.js create mode 100644 apps/judicial-system/backend/migrations/20240918134926-update-case.js create mode 100644 apps/judicial-system/backend/src/app/modules/defendant/civilClaimant.controller.ts create mode 100644 apps/judicial-system/backend/src/app/modules/defendant/civilClaimant.service.ts create mode 100644 apps/judicial-system/backend/src/app/modules/defendant/dto/createCivilClaimant.dto.ts create mode 100644 apps/judicial-system/backend/src/app/modules/defendant/dto/updateCivilClaimant.dto.ts create mode 100644 apps/judicial-system/backend/src/app/modules/defendant/models/civilClaimant.model.ts create mode 100644 apps/judicial-system/backend/src/app/modules/defendant/models/deleteCivilClaimant.response.ts diff --git a/apps/judicial-system/api/src/app/modules/backend/backend.service.ts b/apps/judicial-system/api/src/app/modules/backend/backend.service.ts index 0dc40cde6cef..ba82a1cb9745 100644 --- a/apps/judicial-system/api/src/app/modules/backend/backend.service.ts +++ b/apps/judicial-system/api/src/app/modules/backend/backend.service.ts @@ -16,6 +16,8 @@ import { } from '../case' import { CaseListEntry } from '../case-list' import { Defendant, DeleteDefendantResponse } from '../defendant' +import { CivilClaimant } from '../defendant/models/civilClaimant.model' +import { DeleteCivilClaimantResponse } from '../defendant/models/deleteCivilClaimant.response' import { CreateEventLogInput } from '../event-log' import { CaseFile, @@ -329,6 +331,31 @@ export class BackendService extends DataSource<{ req: Request }> { return this.delete(`case/${caseId}/defendant/${defendantId}`) } + createCivilClaimant( + caseId: string, + createCivilClaimant: unknown, + ): Promise { + return this.post(`case/${caseId}/civilClaimant`, createCivilClaimant) + } + + updateCivilClaimant( + caseId: string, + civilClaimantId: string, + updateCivilClaimant: unknown, + ): Promise { + return this.patch( + `case/${caseId}/civilClaimant/${civilClaimantId}`, + updateCivilClaimant, + ) + } + + deleteCivilClaimant( + caseId: string, + civilClaimantId: string, + ): Promise { + return this.delete(`case/${caseId}/civilClaimant/${civilClaimantId}`) + } + createIndictmentCount( input: CreateIndictmentCountInput, ): Promise { diff --git a/apps/judicial-system/api/src/app/modules/case/dto/updateCase.input.ts b/apps/judicial-system/api/src/app/modules/case/dto/updateCase.input.ts index 0e506a67f685..936618b1c6d7 100644 --- a/apps/judicial-system/api/src/app/modules/case/dto/updateCase.input.ts +++ b/apps/judicial-system/api/src/app/modules/case/dto/updateCase.input.ts @@ -511,4 +511,9 @@ export class UpdateCaseInput { @IsOptional() @Field(() => String, { nullable: true }) readonly civilDemands?: string + + @Allow() + @IsOptional() + @Field(() => Boolean, { nullable: true }) + readonly hasCivilClaims?: boolean } diff --git a/apps/judicial-system/api/src/app/modules/case/models/case.model.ts b/apps/judicial-system/api/src/app/modules/case/models/case.model.ts index 0f09dd9b6274..80f811efa64b 100644 --- a/apps/judicial-system/api/src/app/modules/case/models/case.model.ts +++ b/apps/judicial-system/api/src/app/modules/case/models/case.model.ts @@ -27,6 +27,7 @@ import { } from '@island.is/judicial-system/types' import { Defendant } from '../../defendant' +import { CivilClaimant } from '../../defendant/models/civilClaimant.model' import { EventLog } from '../../event-log' import { CaseFile } from '../../file' import { IndictmentCount } from '../../indictment-count' @@ -454,6 +455,12 @@ export class Case { @Field(() => [Case], { nullable: true }) readonly mergedCases?: Case[] + @Field(() => [CivilClaimant], { nullable: true }) + readonly civilClaimants?: CivilClaimant[] + @Field(() => String, { nullable: true }) readonly civilDemands?: string + + @Field(() => Boolean, { nullable: true }) + readonly hasCivilClaims?: boolean } diff --git a/apps/judicial-system/api/src/app/modules/defendant/civilClaimant.resolver.ts b/apps/judicial-system/api/src/app/modules/defendant/civilClaimant.resolver.ts new file mode 100644 index 000000000000..526962292841 --- /dev/null +++ b/apps/judicial-system/api/src/app/modules/defendant/civilClaimant.resolver.ts @@ -0,0 +1,89 @@ +import { Inject, Logger, UseGuards } from '@nestjs/common' +import { Args, Context, Mutation, Resolver } from '@nestjs/graphql' + +import { LOGGER_PROVIDER } from '@island.is/logging' + +import { + AuditedAction, + AuditTrailService, +} from '@island.is/judicial-system/audit-trail' +import { + CurrentGraphQlUser, + JwtGraphQlAuthGuard, +} from '@island.is/judicial-system/auth' +import type { User } from '@island.is/judicial-system/types' + +import { BackendService } from '../backend' +import { CreateCivilClaimantInput } from './dto/createCivilClaimant.input' +import { DeleteCivilClaimantInput } from './dto/deleteCivilClaimant.input' +import { UpdateCivilClaimantInput } from './dto/updateCivilClaimant.input' +import { CivilClaimant } from './models/civilClaimant.model' +import { DeleteCivilClaimantResponse } from './models/deleteCivilClaimant.response' + +@UseGuards(JwtGraphQlAuthGuard) +@Resolver(() => CivilClaimant) +export class CivilClaimantResolver { + constructor( + private readonly auditTrailService: AuditTrailService, + @Inject(LOGGER_PROVIDER) + private readonly logger: Logger, + ) {} + + @Mutation(() => CivilClaimant) + createCivilClaimant( + @Args('input', { type: () => CreateCivilClaimantInput }) + input: CreateCivilClaimantInput, + @CurrentGraphQlUser() user: User, + @Context('dataSources') + { backendService }: { backendService: BackendService }, + ): Promise { + const { caseId, ...createCivilClaimant } = input + + return this.auditTrailService.audit( + user.id, + AuditedAction.CREATE_CIVIL_CLAIMANT, + backendService.createCivilClaimant(caseId, createCivilClaimant), + (civilClaimant) => civilClaimant.id, + ) + } + + @Mutation(() => CivilClaimant) + updateCivilClaimant( + @Args('input', { type: () => UpdateCivilClaimantInput }) + input: UpdateCivilClaimantInput, + @CurrentGraphQlUser() user: User, + @Context('dataSources') + { backendService }: { backendService: BackendService }, + ): Promise { + const { caseId, civilClaimantId, ...updateCivilClaimant } = input + + return this.auditTrailService.audit( + user.id, + AuditedAction.UPDATE_CIVIL_CLAIMANT, + backendService.updateCivilClaimant( + caseId, + civilClaimantId, + updateCivilClaimant, + ), + (civilClaimant) => civilClaimant.id, + ) + } + + @Mutation(() => DeleteCivilClaimantResponse) + async deleteCivilClaimant( + @Args('input', { type: () => DeleteCivilClaimantInput }) + input: DeleteCivilClaimantInput, + @CurrentGraphQlUser() user: User, + @Context('dataSources') + { backendService }: { backendService: BackendService }, + ): Promise { + const { caseId, civilClaimantId } = input + + return this.auditTrailService.audit( + user.id, + AuditedAction.DELETE_CIVIL_CLAIMANT, + backendService.deleteCivilClaimant(caseId, civilClaimantId), + civilClaimantId, + ) + } +} diff --git a/apps/judicial-system/api/src/app/modules/defendant/defendant.module.ts b/apps/judicial-system/api/src/app/modules/defendant/defendant.module.ts index 99de4756067f..245771d1f74e 100644 --- a/apps/judicial-system/api/src/app/modules/defendant/defendant.module.ts +++ b/apps/judicial-system/api/src/app/modules/defendant/defendant.module.ts @@ -1,8 +1,9 @@ import { Module } from '@nestjs/common' +import { CivilClaimantResolver } from './civilClaimant.resolver' import { DefendantResolver } from './defendant.resolver' @Module({ - providers: [DefendantResolver], + providers: [DefendantResolver, CivilClaimantResolver], }) export class DefendantModule {} diff --git a/apps/judicial-system/api/src/app/modules/defendant/dto/createCivilClaimant.input.ts b/apps/judicial-system/api/src/app/modules/defendant/dto/createCivilClaimant.input.ts new file mode 100644 index 000000000000..8ae8624956c6 --- /dev/null +++ b/apps/judicial-system/api/src/app/modules/defendant/dto/createCivilClaimant.input.ts @@ -0,0 +1,60 @@ +import { Allow, IsOptional } from 'class-validator' + +import { Field, ID, InputType } from '@nestjs/graphql' + +@InputType() +export class CreateCivilClaimantInput { + @Allow() + @Field(() => ID) + readonly caseId!: string + + @Allow() + @IsOptional() + @Field(() => Boolean, { nullable: true }) + readonly noNationalId?: boolean + + @Allow() + @IsOptional() + @Field(() => String, { nullable: true }) + readonly name?: string + + @Allow() + @IsOptional() + @Field(() => String, { nullable: true }) + readonly nationalId?: string + + @Allow() + @IsOptional() + @Field(() => Boolean, { nullable: true }) + readonly hasSpokesperson?: boolean + + @Allow() + @IsOptional() + @Field(() => Boolean, { nullable: true }) + readonly spokespersonIsLawyer?: boolean + + @Allow() + @IsOptional() + @Field(() => String, { nullable: true }) + readonly spokespersonNationalId?: string + + @Allow() + @IsOptional() + @Field(() => String, { nullable: true }) + readonly spokespersonName?: string + + @Allow() + @IsOptional() + @Field(() => String, { nullable: true }) + readonly spokespersonEmail?: string + + @Allow() + @IsOptional() + @Field(() => String, { nullable: true }) + readonly spokespersonPhoneNumber?: string + + @Allow() + @IsOptional() + @Field(() => Boolean, { nullable: true }) + readonly caseFilesSharedWithSpokesperson?: boolean +} diff --git a/apps/judicial-system/api/src/app/modules/defendant/dto/deleteCivilClaimant.input.ts b/apps/judicial-system/api/src/app/modules/defendant/dto/deleteCivilClaimant.input.ts new file mode 100644 index 000000000000..5aceee9f2b60 --- /dev/null +++ b/apps/judicial-system/api/src/app/modules/defendant/dto/deleteCivilClaimant.input.ts @@ -0,0 +1,14 @@ +import { Allow } from 'class-validator' + +import { Field, ID, InputType } from '@nestjs/graphql' + +@InputType() +export class DeleteCivilClaimantInput { + @Allow() + @Field(() => ID) + readonly caseId!: string + + @Allow() + @Field(() => ID) + readonly civilClaimantId!: string +} diff --git a/apps/judicial-system/api/src/app/modules/defendant/dto/updateCivilClaimant.input.ts b/apps/judicial-system/api/src/app/modules/defendant/dto/updateCivilClaimant.input.ts new file mode 100644 index 000000000000..5c00a5bfe44c --- /dev/null +++ b/apps/judicial-system/api/src/app/modules/defendant/dto/updateCivilClaimant.input.ts @@ -0,0 +1,64 @@ +import { Allow, IsOptional } from 'class-validator' + +import { Field, ID, InputType } from '@nestjs/graphql' + +@InputType() +export class UpdateCivilClaimantInput { + @Allow() + @Field(() => ID) + readonly civilClaimantId!: string + + @Allow() + @Field(() => ID) + readonly caseId!: string + + @Allow() + @IsOptional() + @Field(() => Boolean, { nullable: true }) + readonly noNationalId?: boolean + + @Allow() + @IsOptional() + @Field(() => String, { nullable: true }) + readonly name?: string + + @Allow() + @IsOptional() + @Field(() => String, { nullable: true }) + readonly nationalId?: string + + @Allow() + @IsOptional() + @Field(() => Boolean, { nullable: true }) + readonly hasSpokesperson?: boolean + + @Allow() + @IsOptional() + @Field(() => Boolean, { nullable: true }) + readonly spokespersonIsLawyer?: boolean + + @Allow() + @IsOptional() + @Field(() => String, { nullable: true }) + readonly spokespersonNationalId?: string + + @Allow() + @IsOptional() + @Field(() => String, { nullable: true }) + readonly spokespersonName?: string + + @Allow() + @IsOptional() + @Field(() => String, { nullable: true }) + readonly spokespersonEmail?: string + + @Allow() + @IsOptional() + @Field(() => String, { nullable: true }) + readonly spokespersonPhoneNumber?: string + + @Allow() + @IsOptional() + @Field(() => Boolean, { nullable: true }) + readonly caseFilesSharedWithSpokesperson?: boolean +} diff --git a/apps/judicial-system/api/src/app/modules/defendant/models/civilClaimant.model.ts b/apps/judicial-system/api/src/app/modules/defendant/models/civilClaimant.model.ts new file mode 100644 index 000000000000..ff02e939ffa8 --- /dev/null +++ b/apps/judicial-system/api/src/app/modules/defendant/models/civilClaimant.model.ts @@ -0,0 +1,46 @@ +import { Field, ID, ObjectType } from '@nestjs/graphql' + +@ObjectType() +export class CivilClaimant { + @Field(() => ID) + readonly id!: string + + @Field(() => String, { nullable: true }) + readonly created!: string + + @Field(() => String, { nullable: true }) + readonly modified?: string + + @Field(() => ID, { nullable: true }) + readonly caseId!: string + + @Field(() => Boolean, { nullable: true }) + readonly noNationalId?: boolean + + @Field(() => String, { nullable: true }) + readonly name?: string + + @Field(() => String, { nullable: true }) + readonly nationalId?: string + + @Field(() => Boolean, { nullable: true }) + readonly hasSpokesperson?: boolean + + @Field(() => Boolean, { nullable: true }) + readonly spokespersonIsLawyer?: boolean + + @Field(() => String, { nullable: true }) + readonly spokespersonNationalId?: string + + @Field(() => String, { nullable: true }) + readonly spokespersonName?: string + + @Field(() => String, { nullable: true }) + readonly spokespersonEmail?: string + + @Field(() => String, { nullable: true }) + readonly spokespersonPhoneNumber?: string + + @Field(() => Boolean, { nullable: true }) + readonly caseFilesSharedWithSpokesperson?: boolean +} diff --git a/apps/judicial-system/api/src/app/modules/defendant/models/deleteCivilClaimant.response.ts b/apps/judicial-system/api/src/app/modules/defendant/models/deleteCivilClaimant.response.ts new file mode 100644 index 000000000000..bef61e36a1da --- /dev/null +++ b/apps/judicial-system/api/src/app/modules/defendant/models/deleteCivilClaimant.response.ts @@ -0,0 +1,7 @@ +import { Field, ObjectType } from '@nestjs/graphql' + +@ObjectType() +export class DeleteCivilClaimantResponse { + @Field(() => Boolean) + deleted!: boolean +} diff --git a/apps/judicial-system/backend/migrations/20240918134825-create-civil-claimant.js b/apps/judicial-system/backend/migrations/20240918134825-create-civil-claimant.js new file mode 100644 index 000000000000..280ea158c2cf --- /dev/null +++ b/apps/judicial-system/backend/migrations/20240918134825-create-civil-claimant.js @@ -0,0 +1,79 @@ +'use strict' + +module.exports = { + up: (queryInterface, Sequelize) => { + return queryInterface.sequelize.transaction((t) => + queryInterface.createTable( + 'civil_claimant', + { + id: { + type: Sequelize.UUID, + primaryKey: true, + allowNull: false, + defaultValue: Sequelize.UUIDV4, + }, + created: { + type: 'TIMESTAMP WITH TIME ZONE', + defaultValue: Sequelize.literal('CURRENT_TIMESTAMP'), + allowNull: false, + }, + case_id: { + type: Sequelize.UUID, + references: { + model: 'case', + key: 'id', + }, + allowNull: false, + }, + name: { + type: Sequelize.STRING, + allowNull: true, + }, + national_id: { + type: Sequelize.STRING, + allowNull: true, + }, + no_national_id: { + type: Sequelize.BOOLEAN, + allowNull: true, + }, + has_spokesperson: { + type: Sequelize.BOOLEAN, + allowNull: true, + }, + spokesperson_is_lawyer: { + type: Sequelize.BOOLEAN, + allowNull: true, + }, + spokesperson_national_id: { + type: Sequelize.STRING, + allowNull: true, + }, + spokesperson_name: { + type: Sequelize.STRING, + allowNull: true, + }, + spokesperson_email: { + type: Sequelize.STRING, + allowNull: true, + }, + spokesperson_phone_number: { + type: Sequelize.STRING, + allowNull: true, + }, + case_files_shared_with_spokesperson: { + type: Sequelize.BOOLEAN, + allowNull: true, + }, + }, + { transaction: t }, + ), + ) + }, + + down: (queryInterface) => { + return queryInterface.sequelize.transaction((t) => + queryInterface.dropTable('civil_claimant', { transaction: t }), + ) + }, +} diff --git a/apps/judicial-system/backend/migrations/20240918134926-update-case.js b/apps/judicial-system/backend/migrations/20240918134926-update-case.js new file mode 100644 index 000000000000..3d39ae4e548b --- /dev/null +++ b/apps/judicial-system/backend/migrations/20240918134926-update-case.js @@ -0,0 +1,25 @@ +'use strict' + +module.exports = { + up: (queryInterface, Sequelize) => { + return queryInterface.sequelize.transaction((t) => + queryInterface.addColumn( + 'case', + 'has_civil_claims', + { + type: Sequelize.BOOLEAN, + allowNull: true, + }, + { transaction: t }, + ), + ) + }, + + down: (queryInterface) => { + return queryInterface.sequelize.transaction((t) => + queryInterface.removeColumn('case', 'has_civil_claims', { + transaction: t, + }), + ) + }, +} diff --git a/apps/judicial-system/backend/src/app/modules/case/case.service.ts b/apps/judicial-system/backend/src/app/modules/case/case.service.ts index ddd76c7772d4..c565c46de435 100644 --- a/apps/judicial-system/backend/src/app/modules/case/case.service.ts +++ b/apps/judicial-system/backend/src/app/modules/case/case.service.ts @@ -56,6 +56,7 @@ import { import { AwsS3Service } from '../aws-s3' import { CourtService } from '../court' import { Defendant, DefendantService } from '../defendant' +import { CivilClaimant } from '../defendant/models/civilClaimant.model' import { EventService } from '../event' import { EventLog, EventLogService } from '../event-log' import { CaseFile, FileService } from '../file' @@ -272,6 +273,7 @@ export const include: Includeable[] = [ }, { model: Case, as: 'childCase' }, { model: Defendant, as: 'defendants' }, + { model: CivilClaimant, as: 'civilClaimants' }, { model: IndictmentCount, as: 'indictmentCounts' }, { model: CaseFile, diff --git a/apps/judicial-system/backend/src/app/modules/case/dto/updateCase.dto.ts b/apps/judicial-system/backend/src/app/modules/case/dto/updateCase.dto.ts index 041b896821d5..4930b0b976bb 100644 --- a/apps/judicial-system/backend/src/app/modules/case/dto/updateCase.dto.ts +++ b/apps/judicial-system/backend/src/app/modules/case/dto/updateCase.dto.ts @@ -518,4 +518,9 @@ export class UpdateCaseDto { @IsString() @ApiPropertyOptional({ type: String }) readonly civilDemands?: string + + @IsOptional() + @IsBoolean() + @ApiPropertyOptional({ type: Boolean }) + readonly hasCivilClaims?: boolean } diff --git a/apps/judicial-system/backend/src/app/modules/case/guards/rolesRules.ts b/apps/judicial-system/backend/src/app/modules/case/guards/rolesRules.ts index 4fdc06391c72..dbe63f9c778a 100644 --- a/apps/judicial-system/backend/src/app/modules/case/guards/rolesRules.ts +++ b/apps/judicial-system/backend/src/app/modules/case/guards/rolesRules.ts @@ -53,6 +53,7 @@ const prosecutorFields: (keyof UpdateCaseDto)[] = [ 'indictmentDeniedExplanation', 'indictmentReviewDecision', 'civilDemands', + 'hasCivilClaims', ] const publicProsecutorFields: (keyof UpdateCaseDto)[] = ['indictmentReviewerId'] diff --git a/apps/judicial-system/backend/src/app/modules/case/models/case.model.ts b/apps/judicial-system/backend/src/app/modules/case/models/case.model.ts index bd26c92f2267..2a1058236a46 100644 --- a/apps/judicial-system/backend/src/app/modules/case/models/case.model.ts +++ b/apps/judicial-system/backend/src/app/modules/case/models/case.model.ts @@ -11,6 +11,7 @@ import { UpdatedAt, } from 'sequelize-typescript' +import { forwardRef } from '@nestjs/common' import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger' import type { @@ -38,6 +39,7 @@ import { } from '@island.is/judicial-system/types' import { Defendant } from '../../defendant' +import { CivilClaimant } from '../../defendant/models/civilClaimant.model' import { EventLog } from '../../event-log' import { CaseFile } from '../../file' import { IndictmentCount } from '../../indictment-count' @@ -181,7 +183,7 @@ export class Case extends Model { requestSharedWithDefender?: RequestSharedWithDefender /********** - * Indicates whether the secutity level of the case has been heightened - + * Indicates whether the security level of the case has been heightened - * optional **********/ @Column({ type: DataType.BOOLEAN, allowNull: true }) @@ -1067,4 +1069,19 @@ export class Case extends Model { @HasMany(() => Case, 'mergeCaseId') @ApiPropertyOptional({ type: () => Case }) mergedCases?: Case[] + + /********** + * Indicates whether a case should include any civil claims - + * optional + **********/ + @Column({ type: DataType.BOOLEAN, allowNull: true }) + @ApiPropertyOptional({ type: Boolean }) + hasCivilClaims?: boolean + + // /********** + // * The case's civil claimants + // **********/ + @HasMany(() => CivilClaimant, 'caseId') + @ApiPropertyOptional({ type: () => CivilClaimant, isArray: true }) + civilClaimants?: CivilClaimant[] } diff --git a/apps/judicial-system/backend/src/app/modules/defendant/civilClaimant.controller.ts b/apps/judicial-system/backend/src/app/modules/defendant/civilClaimant.controller.ts new file mode 100644 index 000000000000..94af7f86f3d3 --- /dev/null +++ b/apps/judicial-system/backend/src/app/modules/defendant/civilClaimant.controller.ts @@ -0,0 +1,98 @@ +import { + Body, + Controller, + Delete, + Inject, + Param, + Patch, + Post, + UseGuards, +} from '@nestjs/common' +import { ApiCreatedResponse, ApiOkResponse, ApiTags } from '@nestjs/swagger' + +import type { Logger } from '@island.is/logging' +import { LOGGER_PROVIDER } from '@island.is/logging' + +import { + JwtAuthGuard, + RolesGuard, + RolesRules, +} from '@island.is/judicial-system/auth' + +import { prosecutorRepresentativeRule, prosecutorRule } from '../../guards' +import { Case, CaseExistsGuard, CaseWriteGuard, CurrentCase } from '../case' +import { CreateCivilClaimantDto } from './dto/createCivilClaimant.dto' +import { UpdateCivilClaimantDto } from './dto/updateCivilClaimant.dto' +import { CivilClaimant } from './models/civilClaimant.model' +import { DeleteCivilClaimantResponse } from './models/deleteCivilClaimant.response' +import { CivilClaimantService } from './civilClaimant.service' + +@UseGuards(JwtAuthGuard, RolesGuard) +@Controller('api/case/:caseId/civilClaimant') +@ApiTags('civilClaimants') +export class CivilClaimantController { + constructor( + private readonly civilClaimantService: CivilClaimantService, + @Inject(LOGGER_PROVIDER) private readonly logger: Logger, + ) {} + + @UseGuards(CaseExistsGuard, CaseWriteGuard) + @RolesRules(prosecutorRule, prosecutorRepresentativeRule) + @Post() + @ApiCreatedResponse({ + type: CivilClaimant, + description: 'Civil claimant created', + }) + async create( + @Param('caseId') caseId: string, + @CurrentCase() theCase: Case, + @Body() createCivilClaimantDto: CreateCivilClaimantDto, + ): Promise { + this.logger.debug(`Creating a new civil claimant for case ${caseId}`) + + return this.civilClaimantService.create(theCase, createCivilClaimantDto) + } + + @UseGuards(CaseExistsGuard, CaseWriteGuard) + @RolesRules(prosecutorRule, prosecutorRepresentativeRule) + @Patch(':civilClaimantId') + @ApiOkResponse({ + type: CivilClaimant, + description: 'Civil claimant updated', + }) + async update( + @Param('caseId') caseId: string, + @Param('civilClaimantId') civilClaimantId: string, + @Body() updateCivilClaimantDto: UpdateCivilClaimantDto, + ): Promise { + this.logger.debug( + `Updating civil claimant ${civilClaimantId} in case ${caseId}`, + ) + return this.civilClaimantService.update( + caseId, + civilClaimantId, + updateCivilClaimantDto, + ) + } + + @UseGuards(CaseExistsGuard, CaseWriteGuard) + @RolesRules(prosecutorRule, prosecutorRepresentativeRule) + @Delete(':civilClaimantId') + @ApiOkResponse({ + type: DeleteCivilClaimantResponse, + description: 'Civil claimant deleted', + }) + async delete( + @Param('caseId') caseId: string, + @Param('civilClaimantId') civilClaimantId: string, + ): Promise { + this.logger.debug(`Deleting civil claimant ${civilClaimantId}`) + + const deleted = await this.civilClaimantService.delete( + caseId, + civilClaimantId, + ) + + return { deleted } + } +} diff --git a/apps/judicial-system/backend/src/app/modules/defendant/civilClaimant.service.ts b/apps/judicial-system/backend/src/app/modules/defendant/civilClaimant.service.ts new file mode 100644 index 000000000000..785b9b798690 --- /dev/null +++ b/apps/judicial-system/backend/src/app/modules/defendant/civilClaimant.service.ts @@ -0,0 +1,75 @@ +import { Inject, Injectable } from '@nestjs/common' +import { InjectModel } from '@nestjs/sequelize' + +import type { Logger } from '@island.is/logging' +import { LOGGER_PROVIDER } from '@island.is/logging' + +import { Case } from '../case' +import { CreateCivilClaimantDto } from './dto/createCivilClaimant.dto' +import { UpdateCivilClaimantDto } from './dto/updateCivilClaimant.dto' +import { CivilClaimant } from './models/civilClaimant.model' + +@Injectable() +export class CivilClaimantService { + constructor( + @InjectModel(CivilClaimant) + private readonly civilClaimantModel: typeof CivilClaimant, + @Inject(LOGGER_PROVIDER) private readonly logger: Logger, + ) {} + + async create( + theCase: Case, + claimantToCreate: CreateCivilClaimantDto, + ): Promise { + return this.civilClaimantModel.create({ + ...claimantToCreate, + caseId: theCase.id, + }) + } + + async update( + caseId: string, + civilClaimantId: string, + update: UpdateCivilClaimantDto, + ): Promise { + const [numberOfAffectedRows, civilClaimants] = + await this.civilClaimantModel.update(update, { + where: { + id: civilClaimantId, + caseId: caseId, + }, + returning: true, + }) + + if (numberOfAffectedRows > 1) { + this.logger.error( + `Unexpected number of rows (${numberOfAffectedRows}) affected when updating civil claimant ${civilClaimantId} of case ${caseId}`, + ) + } else if (numberOfAffectedRows < 1) { + throw new Error(`Could not update civil claimant ${civilClaimantId}`) + } + + return civilClaimants[0] + } + + async delete(caseId: string, civilClaimantId: string): Promise { + const numberOfAffectedRows = await this.civilClaimantModel.destroy({ + where: { + id: civilClaimantId, + caseId: caseId, + }, + }) + + if (numberOfAffectedRows > 1) { + // Tolerate failure, but log error + this.logger.error( + `Unexpected number of rows (${numberOfAffectedRows}) affected when deleting civil claimant ${civilClaimantId} of case ${caseId}`, + ) + if (numberOfAffectedRows < 1) { + throw new Error(`Could not delete civil claimant ${civilClaimantId}`) + } + } + + return true + } +} diff --git a/apps/judicial-system/backend/src/app/modules/defendant/defendant.module.ts b/apps/judicial-system/backend/src/app/modules/defendant/defendant.module.ts index 247148ab4b87..a7cb4fca9e0f 100644 --- a/apps/judicial-system/backend/src/app/modules/defendant/defendant.module.ts +++ b/apps/judicial-system/backend/src/app/modules/defendant/defendant.module.ts @@ -5,7 +5,10 @@ import { MessageModule } from '@island.is/judicial-system/message' import { CaseModule } from '../case/case.module' import { CourtModule } from '../court/court.module' +import { CivilClaimant } from './models/civilClaimant.model' import { Defendant } from './models/defendant.model' +import { CivilClaimantController } from './civilClaimant.controller' +import { CivilClaimantService } from './civilClaimant.service' import { DefendantController } from './defendant.controller' import { DefendantService } from './defendant.service' import { InternalDefendantController } from './internalDefendant.controller' @@ -15,10 +18,14 @@ import { InternalDefendantController } from './internalDefendant.controller' MessageModule, forwardRef(() => CourtModule), forwardRef(() => CaseModule), - SequelizeModule.forFeature([Defendant]), + SequelizeModule.forFeature([Defendant, CivilClaimant]), ], - controllers: [DefendantController, InternalDefendantController], - providers: [DefendantService], + controllers: [ + DefendantController, + InternalDefendantController, + CivilClaimantController, + ], + providers: [DefendantService, CivilClaimantService], exports: [DefendantService], }) export class DefendantModule {} diff --git a/apps/judicial-system/backend/src/app/modules/defendant/dto/createCivilClaimant.dto.ts b/apps/judicial-system/backend/src/app/modules/defendant/dto/createCivilClaimant.dto.ts new file mode 100644 index 000000000000..2d5167b8849c --- /dev/null +++ b/apps/judicial-system/backend/src/app/modules/defendant/dto/createCivilClaimant.dto.ts @@ -0,0 +1,55 @@ +import { IsBoolean, IsOptional, IsString } from 'class-validator' + +import { ApiPropertyOptional } from '@nestjs/swagger' + +export class CreateCivilClaimantDto { + @IsOptional() + @IsBoolean() + @ApiPropertyOptional({ type: Boolean }) + readonly noNationalId?: boolean + + @IsOptional() + @IsString() + @ApiPropertyOptional({ type: String }) + readonly name?: string + + @IsOptional() + @IsString() + @ApiPropertyOptional({ type: String }) + readonly nationalId?: string + + @IsOptional() + @IsBoolean() + @ApiPropertyOptional({ type: Boolean }) + readonly hasSpokesperson?: boolean + + @IsOptional() + @IsBoolean() + @ApiPropertyOptional({ type: Boolean }) + readonly spokespersonIsLawyer?: boolean + + @IsOptional() + @IsString() + @ApiPropertyOptional({ type: String }) + readonly spokespersonNationalId?: string + + @IsOptional() + @IsString() + @ApiPropertyOptional({ type: String }) + readonly spokespersonName?: string + + @IsOptional() + @IsString() + @ApiPropertyOptional({ type: String }) + readonly spokespersonEmail?: string + + @IsOptional() + @IsString() + @ApiPropertyOptional({ type: String }) + readonly spokespersonPhoneNumber?: string + + @IsOptional() + @IsBoolean() + @ApiPropertyOptional({ type: Boolean }) + readonly caseFilesSharedWithSpokesperson?: boolean +} diff --git a/apps/judicial-system/backend/src/app/modules/defendant/dto/updateCivilClaimant.dto.ts b/apps/judicial-system/backend/src/app/modules/defendant/dto/updateCivilClaimant.dto.ts new file mode 100644 index 000000000000..4ad6cb1ce29c --- /dev/null +++ b/apps/judicial-system/backend/src/app/modules/defendant/dto/updateCivilClaimant.dto.ts @@ -0,0 +1,55 @@ +import { IsBoolean, IsOptional, IsString } from 'class-validator' + +import { ApiPropertyOptional } from '@nestjs/swagger' + +export class UpdateCivilClaimantDto { + @IsOptional() + @IsBoolean() + @ApiPropertyOptional({ type: Boolean }) + readonly noNationalId?: boolean + + @IsOptional() + @IsString() + @ApiPropertyOptional({ type: String }) + readonly name?: string + + @IsOptional() + @IsString() + @ApiPropertyOptional({ type: String }) + readonly nationalId?: string + + @IsOptional() + @IsBoolean() + @ApiPropertyOptional({ type: Boolean }) + readonly hasSpokesperson?: boolean + + @IsOptional() + @IsBoolean() + @ApiPropertyOptional({ type: Boolean }) + readonly spokespersonIsLawyer?: boolean + + @IsOptional() + @IsString() + @ApiPropertyOptional({ type: String }) + readonly spokespersonNationalId?: string + + @IsOptional() + @IsString() + @ApiPropertyOptional({ type: String }) + readonly spokespersonName?: string + + @IsOptional() + @IsString() + @ApiPropertyOptional({ type: String }) + readonly spokespersonEmail?: string + + @IsOptional() + @IsString() + @ApiPropertyOptional({ type: String }) + readonly spokespersonPhoneNumber?: string + + @IsOptional() + @IsBoolean() + @ApiPropertyOptional({ type: Boolean }) + readonly caseFilesSharedWithSpokesperson?: boolean +} diff --git a/apps/judicial-system/backend/src/app/modules/defendant/models/civilClaimant.model.ts b/apps/judicial-system/backend/src/app/modules/defendant/models/civilClaimant.model.ts new file mode 100644 index 000000000000..308ba8820ce8 --- /dev/null +++ b/apps/judicial-system/backend/src/app/modules/defendant/models/civilClaimant.model.ts @@ -0,0 +1,113 @@ +import { + BelongsTo, + Column, + CreatedAt, + DataType, + ForeignKey, + Model, + Table, +} from 'sequelize-typescript' + +import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger' + +import { Case } from '../../case/models/case.model' + +@Table({ + tableName: 'civil_claimant', + timestamps: false, +}) +export class CivilClaimant extends Model { + @Column({ + type: DataType.UUID, + primaryKey: true, + allowNull: false, + defaultValue: DataType.UUIDV4, + }) + @ApiProperty({ type: String }) + id!: string + + @CreatedAt + @Column({ + type: DataType.DATE, + defaultValue: DataType.NOW, + allowNull: false, + }) + @ApiProperty({ type: Date }) + created!: Date + + @ForeignKey(() => Case) + @Column({ + type: DataType.UUID, + allowNull: false, + }) + @ApiProperty({ type: String }) + caseId!: string + + @BelongsTo(() => Case, 'caseId') + @ApiProperty({ type: Case }) + case?: Case + + @Column({ type: DataType.BOOLEAN, allowNull: true }) + @ApiPropertyOptional({ type: Boolean }) + noNationalId?: boolean + + @Column({ + type: DataType.STRING, + allowNull: true, + }) + @ApiPropertyOptional({ type: String }) + name?: string + + @Column({ + type: DataType.STRING, + allowNull: true, + }) + @ApiPropertyOptional({ type: String }) + nationalId?: string + + @Column({ type: DataType.BOOLEAN, allowNull: true }) + @ApiPropertyOptional({ type: Boolean }) + hasSpokesperson?: boolean + + @Column({ + type: DataType.BOOLEAN, + allowNull: true, + }) + @ApiPropertyOptional({ type: Boolean }) + spokespersonIsLawyer?: boolean + + @Column({ + type: DataType.STRING, + allowNull: true, + }) + @ApiPropertyOptional({ type: String }) + spokespersonNationalId?: string + + @Column({ + type: DataType.STRING, + allowNull: true, + }) + @ApiPropertyOptional({ type: String }) + spokespersonName?: string + + @Column({ + type: DataType.STRING, + allowNull: true, + }) + @ApiPropertyOptional({ type: String }) + spokespersonEmail?: string + + @Column({ + type: DataType.STRING, + allowNull: true, + }) + @ApiPropertyOptional({ type: String }) + spokespersonPhoneNumber?: string + + @Column({ + type: DataType.BOOLEAN, + allowNull: true, + }) + @ApiPropertyOptional({ type: Boolean }) + caseFilesSharedWithSpokesperson?: boolean +} diff --git a/apps/judicial-system/backend/src/app/modules/defendant/models/deleteCivilClaimant.response.ts b/apps/judicial-system/backend/src/app/modules/defendant/models/deleteCivilClaimant.response.ts new file mode 100644 index 000000000000..cfc1d8389bfd --- /dev/null +++ b/apps/judicial-system/backend/src/app/modules/defendant/models/deleteCivilClaimant.response.ts @@ -0,0 +1,6 @@ +import { ApiProperty } from '@nestjs/swagger' + +export class DeleteCivilClaimantResponse { + @ApiProperty({ type: Boolean }) + deleted!: boolean +} diff --git a/apps/judicial-system/web/src/components/FormProvider/case.graphql b/apps/judicial-system/web/src/components/FormProvider/case.graphql index 1c9635d77d2c..284342f7aa67 100644 --- a/apps/judicial-system/web/src/components/FormProvider/case.graphql +++ b/apps/judicial-system/web/src/components/FormProvider/case.graphql @@ -308,6 +308,21 @@ query Case($input: CaseQueryInput!) { policeCaseNumbers indictmentSubtypes } + civilClaimants { + id + caseId + name + nationalId + noNationalId + hasSpokesperson + spokespersonNationalId + spokespersonName + spokespersonEmail + spokespersonPhoneNumber + caseFilesSharedWithSpokesperson + isLawyer + } civilDemands + hasCivilClaims } } diff --git a/libs/judicial-system/audit-trail/src/lib/auditTrail.service.ts b/libs/judicial-system/audit-trail/src/lib/auditTrail.service.ts index 73cc3f815dd6..91f4de74ca3d 100644 --- a/libs/judicial-system/audit-trail/src/lib/auditTrail.service.ts +++ b/libs/judicial-system/audit-trail/src/lib/auditTrail.service.ts @@ -57,6 +57,9 @@ export enum AuditedAction { DELETE_INDICTMENT_COUNT = 'DELETE_INDICTMENT_COUNT', UPDATE_SUBPOENA = 'UPDATE_SUBPOENA', GET_SUBPOENA = 'GET_SUBPOENA', + CREATE_CIVIL_CLAIMANT = 'CREATE_CIVIL_CLAIMANT', + UPDATE_CIVIL_CLAIMANT = 'UPDATE_CIVIL_CLAIMANT', + DELETE_CIVIL_CLAIMANT = 'DELETE_CIVIL_CLAIMANT', } @Injectable() From 021d6a2b3e30ee37609d8e61cb4c7061824bfc0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=8Dvar=20Oddsson?= Date: Wed, 18 Sep 2024 13:55:48 +0000 Subject: [PATCH 02/15] Fix GQL --- .../web/src/components/FormProvider/case.graphql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/judicial-system/web/src/components/FormProvider/case.graphql b/apps/judicial-system/web/src/components/FormProvider/case.graphql index 284342f7aa67..70cdc86833c7 100644 --- a/apps/judicial-system/web/src/components/FormProvider/case.graphql +++ b/apps/judicial-system/web/src/components/FormProvider/case.graphql @@ -315,12 +315,12 @@ query Case($input: CaseQueryInput!) { nationalId noNationalId hasSpokesperson + spokespersonIsLawyer spokespersonNationalId spokespersonName spokespersonEmail spokespersonPhoneNumber caseFilesSharedWithSpokesperson - isLawyer } civilDemands hasCivilClaims From c8d32b4aa461e6b906a38ab3ab6a6418bcfe4bcd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=8Dvar=20Oddsson?= Date: Wed, 18 Sep 2024 13:57:21 +0000 Subject: [PATCH 03/15] Remove unused code --- .../backend/src/app/modules/case/models/case.model.ts | 1 - .../web/src/routes/Court/Indictments/Overview/Overview.tsx | 7 ++----- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/apps/judicial-system/backend/src/app/modules/case/models/case.model.ts b/apps/judicial-system/backend/src/app/modules/case/models/case.model.ts index 2a1058236a46..3a163ee3a339 100644 --- a/apps/judicial-system/backend/src/app/modules/case/models/case.model.ts +++ b/apps/judicial-system/backend/src/app/modules/case/models/case.model.ts @@ -11,7 +11,6 @@ import { UpdatedAt, } from 'sequelize-typescript' -import { forwardRef } from '@nestjs/common' import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger' import type { diff --git a/apps/judicial-system/web/src/routes/Court/Indictments/Overview/Overview.tsx b/apps/judicial-system/web/src/routes/Court/Indictments/Overview/Overview.tsx index c3982677eafc..ce7a017ecbcb 100644 --- a/apps/judicial-system/web/src/routes/Court/Indictments/Overview/Overview.tsx +++ b/apps/judicial-system/web/src/routes/Court/Indictments/Overview/Overview.tsx @@ -20,10 +20,7 @@ import { PageTitle, useIndictmentsLawsBroken, } from '@island.is/judicial-system-web/src/components' -import { - CaseState, - IndictmentDecision, -} from '@island.is/judicial-system-web/src/graphql/schema' +import { IndictmentDecision } from '@island.is/judicial-system-web/src/graphql/schema' import { useDefendants } from '@island.is/judicial-system-web/src/utils/hooks' import { SubpoenaType } from '../../components' @@ -41,7 +38,7 @@ const IndictmentOverview = () => { const [modalVisible, setModalVisible] = useState<'RETURN_INDICTMENT'>() const latestDate = workingCase.courtDate ?? workingCase.arraignmentDate - const caseHasBeenReceivedByCourt = workingCase.state === CaseState.RECEIVED + // const caseHasBeenReceivedByCourt = workingCase.state === CaseState.RECEIVED const handleNavigationTo = useCallback( async (destination: string) => { From c30625508a5bc574bd6c6faf4b95e355111b721c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=8Dvar=20Oddsson?= Date: Wed, 18 Sep 2024 14:22:05 +0000 Subject: [PATCH 04/15] Fix unreachable code error --- .../src/app/modules/defendant/civilClaimant.service.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/apps/judicial-system/backend/src/app/modules/defendant/civilClaimant.service.ts b/apps/judicial-system/backend/src/app/modules/defendant/civilClaimant.service.ts index 785b9b798690..ad43c692f933 100644 --- a/apps/judicial-system/backend/src/app/modules/defendant/civilClaimant.service.ts +++ b/apps/judicial-system/backend/src/app/modules/defendant/civilClaimant.service.ts @@ -65,9 +65,8 @@ export class CivilClaimantService { this.logger.error( `Unexpected number of rows (${numberOfAffectedRows}) affected when deleting civil claimant ${civilClaimantId} of case ${caseId}`, ) - if (numberOfAffectedRows < 1) { - throw new Error(`Could not delete civil claimant ${civilClaimantId}`) - } + } else if (numberOfAffectedRows < 1) { + throw new Error(`Could not delete civil claimant ${civilClaimantId}`) } return true From 141a170510c69e54724ac49c561552e1d704cd38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=8Dvar=20Oddsson?= Date: Wed, 18 Sep 2024 14:34:07 +0000 Subject: [PATCH 05/15] Align nullability between typescript and GQL fields. Field: created --- .../api/src/app/modules/defendant/models/civilClaimant.model.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/judicial-system/api/src/app/modules/defendant/models/civilClaimant.model.ts b/apps/judicial-system/api/src/app/modules/defendant/models/civilClaimant.model.ts index ff02e939ffa8..da90d7d1834f 100644 --- a/apps/judicial-system/api/src/app/modules/defendant/models/civilClaimant.model.ts +++ b/apps/judicial-system/api/src/app/modules/defendant/models/civilClaimant.model.ts @@ -6,7 +6,7 @@ export class CivilClaimant { readonly id!: string @Field(() => String, { nullable: true }) - readonly created!: string + readonly created?: string @Field(() => String, { nullable: true }) readonly modified?: string From 42e551a379cc1d019d047afd003d34e830c32fc4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=8Dvar=20Oddsson?= Date: Wed, 18 Sep 2024 14:36:14 +0000 Subject: [PATCH 06/15] Add modified field to create civil claimant migration --- .../migrations/20240918134825-create-civil-claimant.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/apps/judicial-system/backend/migrations/20240918134825-create-civil-claimant.js b/apps/judicial-system/backend/migrations/20240918134825-create-civil-claimant.js index 280ea158c2cf..9a5a3fd4016d 100644 --- a/apps/judicial-system/backend/migrations/20240918134825-create-civil-claimant.js +++ b/apps/judicial-system/backend/migrations/20240918134825-create-civil-claimant.js @@ -17,6 +17,11 @@ module.exports = { defaultValue: Sequelize.literal('CURRENT_TIMESTAMP'), allowNull: false, }, + modified: { + type: 'TIMESTAMP WITH TIME ZONE', + defaultValue: Sequelize.literal('CURRENT_TIMESTAMP'), + allowNull: false, + }, case_id: { type: Sequelize.UUID, references: { From e3c7d87294e1246ffc529c7ae3ff9e7abaaac815 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=8Dvar=20Oddsson?= Date: Wed, 18 Sep 2024 14:41:04 +0000 Subject: [PATCH 07/15] Better types --- .../api/src/app/modules/backend/backend.service.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/judicial-system/api/src/app/modules/backend/backend.service.ts b/apps/judicial-system/api/src/app/modules/backend/backend.service.ts index ba82a1cb9745..97d11974c577 100644 --- a/apps/judicial-system/api/src/app/modules/backend/backend.service.ts +++ b/apps/judicial-system/api/src/app/modules/backend/backend.service.ts @@ -16,6 +16,8 @@ import { } from '../case' import { CaseListEntry } from '../case-list' import { Defendant, DeleteDefendantResponse } from '../defendant' +import { CreateCivilClaimantInput } from '../defendant/dto/createCivilClaimant.input' +import { UpdateCivilClaimantInput } from '../defendant/dto/updateCivilClaimant.input' import { CivilClaimant } from '../defendant/models/civilClaimant.model' import { DeleteCivilClaimantResponse } from '../defendant/models/deleteCivilClaimant.response' import { CreateEventLogInput } from '../event-log' @@ -333,7 +335,7 @@ export class BackendService extends DataSource<{ req: Request }> { createCivilClaimant( caseId: string, - createCivilClaimant: unknown, + createCivilClaimant: CreateCivilClaimantInput, ): Promise { return this.post(`case/${caseId}/civilClaimant`, createCivilClaimant) } @@ -341,7 +343,7 @@ export class BackendService extends DataSource<{ req: Request }> { updateCivilClaimant( caseId: string, civilClaimantId: string, - updateCivilClaimant: unknown, + updateCivilClaimant: UpdateCivilClaimantInput, ): Promise { return this.patch( `case/${caseId}/civilClaimant/${civilClaimantId}`, From 2b95efccdf5564774817c3c802147e021ed332e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=8Dvar=20Oddsson?= Date: Wed, 18 Sep 2024 14:43:45 +0000 Subject: [PATCH 08/15] Revert better types --- .../api/src/app/modules/backend/backend.service.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/judicial-system/api/src/app/modules/backend/backend.service.ts b/apps/judicial-system/api/src/app/modules/backend/backend.service.ts index 97d11974c577..02697264e27f 100644 --- a/apps/judicial-system/api/src/app/modules/backend/backend.service.ts +++ b/apps/judicial-system/api/src/app/modules/backend/backend.service.ts @@ -335,7 +335,7 @@ export class BackendService extends DataSource<{ req: Request }> { createCivilClaimant( caseId: string, - createCivilClaimant: CreateCivilClaimantInput, + createCivilClaimant: unknown, ): Promise { return this.post(`case/${caseId}/civilClaimant`, createCivilClaimant) } @@ -343,7 +343,7 @@ export class BackendService extends DataSource<{ req: Request }> { updateCivilClaimant( caseId: string, civilClaimantId: string, - updateCivilClaimant: UpdateCivilClaimantInput, + updateCivilClaimant: unknown, ): Promise { return this.patch( `case/${caseId}/civilClaimant/${civilClaimantId}`, From b3f0be60a9da0bbeef03a0aff5ab59306d5081e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=8Dvar=20Oddsson?= Date: Wed, 18 Sep 2024 14:56:29 +0000 Subject: [PATCH 09/15] Remove unused imports --- .../api/src/app/modules/backend/backend.service.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/apps/judicial-system/api/src/app/modules/backend/backend.service.ts b/apps/judicial-system/api/src/app/modules/backend/backend.service.ts index 02697264e27f..ba82a1cb9745 100644 --- a/apps/judicial-system/api/src/app/modules/backend/backend.service.ts +++ b/apps/judicial-system/api/src/app/modules/backend/backend.service.ts @@ -16,8 +16,6 @@ import { } from '../case' import { CaseListEntry } from '../case-list' import { Defendant, DeleteDefendantResponse } from '../defendant' -import { CreateCivilClaimantInput } from '../defendant/dto/createCivilClaimant.input' -import { UpdateCivilClaimantInput } from '../defendant/dto/updateCivilClaimant.input' import { CivilClaimant } from '../defendant/models/civilClaimant.model' import { DeleteCivilClaimantResponse } from '../defendant/models/deleteCivilClaimant.response' import { CreateEventLogInput } from '../event-log' From 7c09f211b3a9a0b56e27c32b1307c903f7364eeb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=8Dvar=20Oddsson?= Date: Wed, 18 Sep 2024 14:58:42 +0000 Subject: [PATCH 10/15] Fix imports --- .../api/src/app/modules/backend/backend.service.ts | 9 ++++++--- .../api/src/app/modules/defendant/index.ts | 2 ++ 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/apps/judicial-system/api/src/app/modules/backend/backend.service.ts b/apps/judicial-system/api/src/app/modules/backend/backend.service.ts index ba82a1cb9745..238f4b51de76 100644 --- a/apps/judicial-system/api/src/app/modules/backend/backend.service.ts +++ b/apps/judicial-system/api/src/app/modules/backend/backend.service.ts @@ -15,9 +15,12 @@ import { SignatureConfirmationResponse, } from '../case' import { CaseListEntry } from '../case-list' -import { Defendant, DeleteDefendantResponse } from '../defendant' -import { CivilClaimant } from '../defendant/models/civilClaimant.model' -import { DeleteCivilClaimantResponse } from '../defendant/models/deleteCivilClaimant.response' +import { + CivilClaimant, + Defendant, + DeleteCivilClaimantResponse, + DeleteDefendantResponse, +} from '../defendant' import { CreateEventLogInput } from '../event-log' import { CaseFile, diff --git a/apps/judicial-system/api/src/app/modules/defendant/index.ts b/apps/judicial-system/api/src/app/modules/defendant/index.ts index b6c4df49e25e..0811956a0ca8 100644 --- a/apps/judicial-system/api/src/app/modules/defendant/index.ts +++ b/apps/judicial-system/api/src/app/modules/defendant/index.ts @@ -1,2 +1,4 @@ export { Defendant } from './models/defendant.model' export { DeleteDefendantResponse } from './models/delete.response' +export { CivilClaimant } from './models/civilClaimant.model' +export { DeleteCivilClaimantResponse } from './models/deleteCivilClaimant.response' From e1b7050759deff832ef8d47cbada88de3c1e6fab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=8Dvar=20Oddsson?= Date: Wed, 18 Sep 2024 15:01:11 +0000 Subject: [PATCH 11/15] Fix imports --- .../api/src/app/modules/case/models/case.model.ts | 3 +-- .../backend/src/app/modules/case/case.service.ts | 1 + 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/judicial-system/api/src/app/modules/case/models/case.model.ts b/apps/judicial-system/api/src/app/modules/case/models/case.model.ts index 80f811efa64b..a4e9e9778078 100644 --- a/apps/judicial-system/api/src/app/modules/case/models/case.model.ts +++ b/apps/judicial-system/api/src/app/modules/case/models/case.model.ts @@ -26,8 +26,7 @@ import { UserRole, } from '@island.is/judicial-system/types' -import { Defendant } from '../../defendant' -import { CivilClaimant } from '../../defendant/models/civilClaimant.model' +import { CivilClaimant, Defendant } from '../../defendant' import { EventLog } from '../../event-log' import { CaseFile } from '../../file' import { IndictmentCount } from '../../indictment-count' diff --git a/apps/judicial-system/backend/src/app/modules/case/case.service.ts b/apps/judicial-system/backend/src/app/modules/case/case.service.ts index c565c46de435..7f2df6274973 100644 --- a/apps/judicial-system/backend/src/app/modules/case/case.service.ts +++ b/apps/judicial-system/backend/src/app/modules/case/case.service.ts @@ -395,6 +395,7 @@ export const caseListInclude: Includeable[] = [ export const listOrder: OrderItem[] = [ [{ model: Defendant, as: 'defendants' }, 'created', 'ASC'], + [{ model: CivilClaimant, as: 'civilClaimants' }, 'created', 'ASC'], [{ model: DateLog, as: 'dateLogs' }, 'created', 'DESC'], ] From 3abd5207e82994166818afd6f822dd876ca896c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=8Dvar=20Oddsson?= Date: Wed, 18 Sep 2024 15:04:34 +0000 Subject: [PATCH 12/15] Fix imports --- .../backend/src/app/modules/case/case.service.ts | 3 +-- .../judicial-system/backend/src/app/modules/defendant/index.ts | 1 + 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/judicial-system/backend/src/app/modules/case/case.service.ts b/apps/judicial-system/backend/src/app/modules/case/case.service.ts index 7f2df6274973..d60f67175c3a 100644 --- a/apps/judicial-system/backend/src/app/modules/case/case.service.ts +++ b/apps/judicial-system/backend/src/app/modules/case/case.service.ts @@ -55,8 +55,7 @@ import { } from '../../formatters' import { AwsS3Service } from '../aws-s3' import { CourtService } from '../court' -import { Defendant, DefendantService } from '../defendant' -import { CivilClaimant } from '../defendant/models/civilClaimant.model' +import { CivilClaimant, Defendant, DefendantService } from '../defendant' import { EventService } from '../event' import { EventLog, EventLogService } from '../event-log' import { CaseFile, FileService } from '../file' diff --git a/apps/judicial-system/backend/src/app/modules/defendant/index.ts b/apps/judicial-system/backend/src/app/modules/defendant/index.ts index ee604a0d6779..3839cdb96469 100644 --- a/apps/judicial-system/backend/src/app/modules/defendant/index.ts +++ b/apps/judicial-system/backend/src/app/modules/defendant/index.ts @@ -1,2 +1,3 @@ export { Defendant } from './models/defendant.model' export { DefendantService } from './defendant.service' +export { CivilClaimant } from './models/civilClaimant.model' From 8a21663d5229626b1511debf1c6ef69ef4008d3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=8Dvar=20Oddsson?= Date: Wed, 18 Sep 2024 15:05:09 +0000 Subject: [PATCH 13/15] Fix imports --- .../backend/src/app/modules/case/models/case.model.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/apps/judicial-system/backend/src/app/modules/case/models/case.model.ts b/apps/judicial-system/backend/src/app/modules/case/models/case.model.ts index 3a163ee3a339..96f58bc55d26 100644 --- a/apps/judicial-system/backend/src/app/modules/case/models/case.model.ts +++ b/apps/judicial-system/backend/src/app/modules/case/models/case.model.ts @@ -37,8 +37,7 @@ import { UserRole, } from '@island.is/judicial-system/types' -import { Defendant } from '../../defendant' -import { CivilClaimant } from '../../defendant/models/civilClaimant.model' +import { CivilClaimant, Defendant } from '../../defendant' import { EventLog } from '../../event-log' import { CaseFile } from '../../file' import { IndictmentCount } from '../../indictment-count' From 5487ba28ca625d29bba3ed2aaa5940ada9823734 Mon Sep 17 00:00:00 2001 From: unakb Date: Wed, 18 Sep 2024 15:50:14 +0000 Subject: [PATCH 14/15] remove everything but caseid from create civil claimant --- .../dto/createCivilClaimant.input.ts | 52 +----------------- .../src/app/modules/case/case.service.ts | 1 + .../defendant/civilClaimant.controller.ts | 4 +- .../defendant/civilClaimant.service.ts | 7 +-- .../defendant/dto/createCivilClaimant.dto.ts | 55 ------------------- 5 files changed, 4 insertions(+), 115 deletions(-) delete mode 100644 apps/judicial-system/backend/src/app/modules/defendant/dto/createCivilClaimant.dto.ts diff --git a/apps/judicial-system/api/src/app/modules/defendant/dto/createCivilClaimant.input.ts b/apps/judicial-system/api/src/app/modules/defendant/dto/createCivilClaimant.input.ts index 8ae8624956c6..84d5c2ff7077 100644 --- a/apps/judicial-system/api/src/app/modules/defendant/dto/createCivilClaimant.input.ts +++ b/apps/judicial-system/api/src/app/modules/defendant/dto/createCivilClaimant.input.ts @@ -1,4 +1,4 @@ -import { Allow, IsOptional } from 'class-validator' +import { Allow } from 'class-validator' import { Field, ID, InputType } from '@nestjs/graphql' @@ -7,54 +7,4 @@ export class CreateCivilClaimantInput { @Allow() @Field(() => ID) readonly caseId!: string - - @Allow() - @IsOptional() - @Field(() => Boolean, { nullable: true }) - readonly noNationalId?: boolean - - @Allow() - @IsOptional() - @Field(() => String, { nullable: true }) - readonly name?: string - - @Allow() - @IsOptional() - @Field(() => String, { nullable: true }) - readonly nationalId?: string - - @Allow() - @IsOptional() - @Field(() => Boolean, { nullable: true }) - readonly hasSpokesperson?: boolean - - @Allow() - @IsOptional() - @Field(() => Boolean, { nullable: true }) - readonly spokespersonIsLawyer?: boolean - - @Allow() - @IsOptional() - @Field(() => String, { nullable: true }) - readonly spokespersonNationalId?: string - - @Allow() - @IsOptional() - @Field(() => String, { nullable: true }) - readonly spokespersonName?: string - - @Allow() - @IsOptional() - @Field(() => String, { nullable: true }) - readonly spokespersonEmail?: string - - @Allow() - @IsOptional() - @Field(() => String, { nullable: true }) - readonly spokespersonPhoneNumber?: string - - @Allow() - @IsOptional() - @Field(() => Boolean, { nullable: true }) - readonly caseFilesSharedWithSpokesperson?: boolean } diff --git a/apps/judicial-system/backend/src/app/modules/case/case.service.ts b/apps/judicial-system/backend/src/app/modules/case/case.service.ts index c565c46de435..878a7147d6b4 100644 --- a/apps/judicial-system/backend/src/app/modules/case/case.service.ts +++ b/apps/judicial-system/backend/src/app/modules/case/case.service.ts @@ -341,6 +341,7 @@ export const order: OrderItem[] = [ [{ model: IndictmentCount, as: 'indictmentCounts' }, 'created', 'ASC'], [{ model: DateLog, as: 'dateLogs' }, 'created', 'DESC'], [{ model: Notification, as: 'notifications' }, 'created', 'DESC'], + [{ model: CivilClaimant, as: 'civilClaimants' }, 'created', 'ASC'], ] export const caseListInclude: Includeable[] = [ diff --git a/apps/judicial-system/backend/src/app/modules/defendant/civilClaimant.controller.ts b/apps/judicial-system/backend/src/app/modules/defendant/civilClaimant.controller.ts index 94af7f86f3d3..58cff3c4941b 100644 --- a/apps/judicial-system/backend/src/app/modules/defendant/civilClaimant.controller.ts +++ b/apps/judicial-system/backend/src/app/modules/defendant/civilClaimant.controller.ts @@ -21,7 +21,6 @@ import { import { prosecutorRepresentativeRule, prosecutorRule } from '../../guards' import { Case, CaseExistsGuard, CaseWriteGuard, CurrentCase } from '../case' -import { CreateCivilClaimantDto } from './dto/createCivilClaimant.dto' import { UpdateCivilClaimantDto } from './dto/updateCivilClaimant.dto' import { CivilClaimant } from './models/civilClaimant.model' import { DeleteCivilClaimantResponse } from './models/deleteCivilClaimant.response' @@ -46,11 +45,10 @@ export class CivilClaimantController { async create( @Param('caseId') caseId: string, @CurrentCase() theCase: Case, - @Body() createCivilClaimantDto: CreateCivilClaimantDto, ): Promise { this.logger.debug(`Creating a new civil claimant for case ${caseId}`) - return this.civilClaimantService.create(theCase, createCivilClaimantDto) + return this.civilClaimantService.create(theCase) } @UseGuards(CaseExistsGuard, CaseWriteGuard) diff --git a/apps/judicial-system/backend/src/app/modules/defendant/civilClaimant.service.ts b/apps/judicial-system/backend/src/app/modules/defendant/civilClaimant.service.ts index ad43c692f933..171c3cc7ee29 100644 --- a/apps/judicial-system/backend/src/app/modules/defendant/civilClaimant.service.ts +++ b/apps/judicial-system/backend/src/app/modules/defendant/civilClaimant.service.ts @@ -5,7 +5,6 @@ import type { Logger } from '@island.is/logging' import { LOGGER_PROVIDER } from '@island.is/logging' import { Case } from '../case' -import { CreateCivilClaimantDto } from './dto/createCivilClaimant.dto' import { UpdateCivilClaimantDto } from './dto/updateCivilClaimant.dto' import { CivilClaimant } from './models/civilClaimant.model' @@ -17,12 +16,8 @@ export class CivilClaimantService { @Inject(LOGGER_PROVIDER) private readonly logger: Logger, ) {} - async create( - theCase: Case, - claimantToCreate: CreateCivilClaimantDto, - ): Promise { + async create(theCase: Case): Promise { return this.civilClaimantModel.create({ - ...claimantToCreate, caseId: theCase.id, }) } diff --git a/apps/judicial-system/backend/src/app/modules/defendant/dto/createCivilClaimant.dto.ts b/apps/judicial-system/backend/src/app/modules/defendant/dto/createCivilClaimant.dto.ts deleted file mode 100644 index 2d5167b8849c..000000000000 --- a/apps/judicial-system/backend/src/app/modules/defendant/dto/createCivilClaimant.dto.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { IsBoolean, IsOptional, IsString } from 'class-validator' - -import { ApiPropertyOptional } from '@nestjs/swagger' - -export class CreateCivilClaimantDto { - @IsOptional() - @IsBoolean() - @ApiPropertyOptional({ type: Boolean }) - readonly noNationalId?: boolean - - @IsOptional() - @IsString() - @ApiPropertyOptional({ type: String }) - readonly name?: string - - @IsOptional() - @IsString() - @ApiPropertyOptional({ type: String }) - readonly nationalId?: string - - @IsOptional() - @IsBoolean() - @ApiPropertyOptional({ type: Boolean }) - readonly hasSpokesperson?: boolean - - @IsOptional() - @IsBoolean() - @ApiPropertyOptional({ type: Boolean }) - readonly spokespersonIsLawyer?: boolean - - @IsOptional() - @IsString() - @ApiPropertyOptional({ type: String }) - readonly spokespersonNationalId?: string - - @IsOptional() - @IsString() - @ApiPropertyOptional({ type: String }) - readonly spokespersonName?: string - - @IsOptional() - @IsString() - @ApiPropertyOptional({ type: String }) - readonly spokespersonEmail?: string - - @IsOptional() - @IsString() - @ApiPropertyOptional({ type: String }) - readonly spokespersonPhoneNumber?: string - - @IsOptional() - @IsBoolean() - @ApiPropertyOptional({ type: Boolean }) - readonly caseFilesSharedWithSpokesperson?: boolean -} From 0cd975ae4449a3d5029613d0cb9e38ba33891817 Mon Sep 17 00:00:00 2001 From: unakb Date: Thu, 19 Sep 2024 10:15:55 +0000 Subject: [PATCH 15/15] fix(j-s): remove civil claim ordering from case list --- .../judicial-system/backend/src/app/modules/case/case.service.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/judicial-system/backend/src/app/modules/case/case.service.ts b/apps/judicial-system/backend/src/app/modules/case/case.service.ts index 34e9a88adc6c..7361bc67846f 100644 --- a/apps/judicial-system/backend/src/app/modules/case/case.service.ts +++ b/apps/judicial-system/backend/src/app/modules/case/case.service.ts @@ -395,7 +395,6 @@ export const caseListInclude: Includeable[] = [ export const listOrder: OrderItem[] = [ [{ model: Defendant, as: 'defendants' }, 'created', 'ASC'], - [{ model: CivilClaimant, as: 'civilClaimants' }, 'created', 'ASC'], [{ model: DateLog, as: 'dateLogs' }, 'created', 'DESC'], ]