Skip to content

Commit

Permalink
Merge branch 'main' into j-s/fix-defender-confirmed-uploaded-indictment
Browse files Browse the repository at this point in the history
  • Loading branch information
oddsson authored Jun 4, 2024
2 parents 6df8e20 + 1566034 commit cae6c80
Show file tree
Hide file tree
Showing 123 changed files with 3,137 additions and 710 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { BypassDelegation } from './guards/bypass-delegation.decorator'
import {
ApplicationAdminPaginatedResponse,
ApplicationListAdminResponseDto,
ApplicationStatistics,
} from './dto/applicationAdmin.response.dto'
import { ApplicationAdminSerializer } from './tools/applicationAdmin.serializer'

Expand All @@ -42,6 +43,40 @@ export class AdminController {
@Inject(LOGGER_PROVIDER) private logger: Logger,
) {}

@Scopes(AdminPortalScope.applicationSystemAdmin)
@BypassDelegation()
@Get('admin/applications-statistics')
@Documentation({
description: 'Get applications statistics',
response: {
status: 200,
type: [ApplicationStatistics],
},
request: {
query: {
startDate: {
type: 'string',
required: true,
description: 'Start date for the statistics',
},
endDate: {
type: 'string',
required: true,
description: 'End date for the statistics',
},
},
},
})
async getCountByTypeIdAndStatus(
@Query('startDate') startDate: string,
@Query('endDate') endDate: string,
) {
return this.applicationService.getApplicationCountByTypeIdAndStatus(
startDate,
endDate,
)
}

@Scopes(AdminPortalScope.applicationSystemAdmin)
@BypassDelegation()
@Get('admin/:nationalId/applications')
Expand Down Expand Up @@ -94,6 +129,7 @@ export class AdminController {
true, // Show pruned applications
)
}

@Scopes(AdminPortalScope.applicationSystemInstitution)
@BypassDelegation()
@Get('admin/institution/:nationalId/applications/:page/:count')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,40 @@ export class ApplicationAdminPaginatedResponse {
@IsNumber()
count!: number
}

export class ApplicationStatistics {
@ApiProperty()
@Expose()
@IsString()
typeid!: string

@ApiProperty()
@Expose()
@IsNumber()
count!: number

@ApiProperty()
@Expose()
@IsNumber()
draft!: number

@ApiProperty()
@Expose()
@IsNumber()
inprogress!: number

@ApiProperty()
@Expose()
@IsNumber()
completed!: number

@ApiProperty()
@Expose()
@IsNumber()
rejected!: number

@ApiProperty()
@Expose()
@IsNumber()
approved!: number
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { Field, ID, InputType } from '@nestjs/graphql'

import {
DefendantPlea,
DefenderChoice,
Gender,
ServiceRequirement,
} from '@island.is/judicial-system/types'
Expand Down Expand Up @@ -68,11 +69,6 @@ export class UpdateDefendantInput {
@Field(() => String, { nullable: true })
readonly defenderPhoneNumber?: string

@Allow()
@IsOptional()
@Field(() => Boolean, { nullable: true })
readonly defendantWaivesRightToCounsel?: boolean

@Allow()
@IsOptional()
@Field(() => DefendantPlea, { nullable: true })
Expand All @@ -87,4 +83,9 @@ export class UpdateDefendantInput {
@IsOptional()
@Field(() => String, { nullable: true })
readonly verdictViewDate?: string

@Allow()
@IsOptional()
@Field(() => DefenderChoice, { nullable: true })
readonly defenderChoice?: DefenderChoice
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@ import { Field, ID, ObjectType, registerEnumType } from '@nestjs/graphql'

import {
DefendantPlea,
DefenderChoice,
Gender,
ServiceRequirement,
} from '@island.is/judicial-system/types'

registerEnumType(Gender, { name: 'Gender' })
registerEnumType(DefendantPlea, { name: 'DefendantPlea' })
registerEnumType(ServiceRequirement, { name: 'ServiceRequirement' })
registerEnumType(DefenderChoice, { name: 'DefenderChoice' })

@ObjectType()
export class Defendant {
Expand Down Expand Up @@ -54,9 +56,6 @@ export class Defendant {
@Field(() => String, { nullable: true })
readonly defenderPhoneNumber?: string

@Field(() => Boolean, { nullable: true })
readonly defendantWaivesRightToCounsel?: boolean

@Field(() => DefendantPlea, { nullable: true })
readonly defendantPlea?: DefendantPlea

Expand All @@ -68,4 +67,7 @@ export class Defendant {

@Field(() => String, { nullable: true })
readonly verdictAppealDeadline?: string

@Field(() => DefenderChoice, { nullable: true })
readonly defenderChoice?: DefenderChoice
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
module.exports = {
up: (queryInterface, Sequelize) => {
return queryInterface.sequelize.transaction((t) =>
queryInterface
.addColumn(
'defendant',
'defender_choice',
{
type: Sequelize.STRING,
allowNull: true,
},
{ transaction: t },
)
.then(() =>
queryInterface.sequelize.query(
`UPDATE "defendant" SET defender_choice = 'WAIVE' WHERE defendant_waives_right_to_counsel = true;`,
{ transaction: t },
),
)
.then(() =>
queryInterface.removeColumn(
'defendant',
'defendant_waives_right_to_counsel',
{ transaction: t },
),
),
)
},

down: (queryInterface, Sequelize) => {
return queryInterface.sequelize.transaction((t) =>
queryInterface
.addColumn(
'defendant',
'defendant_waives_right_to_counsel',
{
type: Sequelize.BOOLEAN,
defaultValue: false,
allowNull: false,
},
{ transaction: t },
)
.then(() =>
queryInterface.sequelize.query(
`UPDATE "defendant" SET defendant_waives_right_to_counsel = true WHERE defender_choice = 'WAIVE';`,
{ transaction: t },
),
)
.then(() =>
queryInterface.removeColumn('defendant', 'defender_choice', {
transaction: t,
}),
),
)
},
}
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,10 @@ export class InternalCaseController {
@Body() internalCasesDto: InternalCasesDto,
): Promise<Case[]> {
this.logger.debug('Getting all indictment cases')
const nationalId = formatNationalId(internalCasesDto.nationalId)

return this.internalCaseService.getIndictmentCases(nationalId)
return this.internalCaseService.getIndictmentCases(
internalCasesDto.nationalId,
)
}

@Post('cases/indictment/:caseId')
Expand All @@ -95,9 +96,11 @@ export class InternalCaseController {
@Body() internalCasesDto: InternalCasesDto,
): Promise<Case | null> {
this.logger.debug(`Getting indictment case ${caseId}`)
const nationalId = formatNationalId(internalCasesDto.nationalId)

return this.internalCaseService.getIndictmentCase(caseId, nationalId)
return this.internalCaseService.getIndictmentCase(
caseId,
internalCasesDto.nationalId,
)
}

@UseGuards(CaseExistsGuard)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@ import { FormatMessage, IntlService } from '@island.is/cms-translations'
import { type Logger, LOGGER_PROVIDER } from '@island.is/logging'
import type { ConfigType } from '@island.is/nest/config'

import { formatCaseType } from '@island.is/judicial-system/formatters'
import {
formatCaseType,
formatNationalId,
} from '@island.is/judicial-system/formatters'
import {
CaseFileCategory,
CaseOrigin,
Expand Down Expand Up @@ -1048,6 +1051,8 @@ export class InternalCaseService {
}

async getIndictmentCases(nationalId: string): Promise<Case[]> {
const formattedNationalId = formatNationalId(nationalId)

return this.caseModel.findAll({
include: [
{ model: Defendant, as: 'defendants' },
Expand All @@ -1057,7 +1062,10 @@ export class InternalCaseService {
attributes: ['id', 'courtCaseNumber', 'type', 'state'],
where: {
type: CaseType.INDICTMENT,
'$defendants.national_id$': nationalId,
[Op.or]: [
{ '$defendants.national_id$': nationalId },
{ '$defendants.national_id$': formattedNationalId },
],
},
})
}
Expand All @@ -1066,6 +1074,10 @@ export class InternalCaseService {
caseId: string,
nationalId: string,
): Promise<Case | null> {
// The national id could be without a hyphen or with a hyphen so we need to
// search for both
const formattedNationalId = formatNationalId(nationalId)

const caseById = await this.caseModel.findOne({
include: [
{ model: Defendant, as: 'defendants' },
Expand All @@ -1078,7 +1090,10 @@ export class InternalCaseService {
where: {
type: CaseType.INDICTMENT,
id: caseId,
'$defendants.national_id$': nationalId,
[Op.or]: [
{ '$defendants.national_id$': nationalId },
{ '$defendants.national_id$': formattedNationalId },
],
},
})

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ export const attributes: (keyof Case)[] = [
'appealRulingModifiedHistory',
'requestAppealRulingNotToBePublished',
'prosecutorsOfficeId',
'indictmentRulingDecision',
'indictmentHash',
]

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@ import {
Inject,
Injectable,
InternalServerErrorException,
NotFoundException,

Check warning on line 8 in apps/judicial-system/backend/src/app/modules/defendant/defendant.service.ts

View workflow job for this annotation

GitHub Actions / linting (judicial-system-backend)

'NotFoundException' is defined but never used. Allowed unused vars must match /^_[a-zA-Z0-9]*$/u
} from '@nestjs/common'
import { InjectModel } from '@nestjs/sequelize'

import type { Logger } from '@island.is/logging'
import { LOGGER_PROVIDER } from '@island.is/logging'

import { formatNationalId } from '@island.is/judicial-system/formatters'
import {
CaseMessage,
MessageService,
Expand Down Expand Up @@ -195,6 +197,37 @@ export class DefendantService {
return updatedDefendant
}

async updateByNationalId(
caseId: string,
defendantNationalId: string,
update: UpdateDefendantDto,
): Promise<Defendant> {
const formattedNationalId = formatNationalId(defendantNationalId)

const [numberOfAffectedRows, defendants] = await this.defendantModel.update(
update,
{
where: {
caseId,
[Op.or]: [
{ national_id: formattedNationalId },
{ national_id: defendantNationalId },
],
},
returning: true,
},
)

const updatedDefendant = this.getUpdatedDefendant(
numberOfAffectedRows,
defendants,
defendants[0].id,
caseId,
)

return updatedDefendant
}

async delete(
theCase: Case,
defendantId: string,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { IsBoolean, IsEnum, IsOptional, IsString } from 'class-validator'

import { ApiPropertyOptional } from '@nestjs/swagger'

import { Gender } from '@island.is/judicial-system/types'
import { DefenderChoice, Gender } from '@island.is/judicial-system/types'

export class CreateDefendantDto {
@IsOptional()
Expand Down Expand Up @@ -56,7 +56,7 @@ export class CreateDefendantDto {
readonly defenderPhoneNumber?: string

@IsOptional()
@IsBoolean()
@ApiPropertyOptional({ type: Boolean })
readonly defendantWaivesRightToCounsel?: boolean
@IsEnum(DefenderChoice)
@ApiPropertyOptional({ enum: DefenderChoice })
readonly defenderChoice?: DefenderChoice
}
Loading

0 comments on commit cae6c80

Please sign in to comment.