From 01127beb81a85c81b0007bcc024a62d144239807 Mon Sep 17 00:00:00 2001 From: unakb Date: Mon, 29 Apr 2024 15:31:59 +0000 Subject: [PATCH 1/3] feat(j-s): Indictment reassignment and transition to main hearing --- .../migrations/20240424112600-update-case.js | 48 +++++++++++++++++++ .../src/app/modules/case/case.controller.ts | 3 ++ .../src/app/modules/case/case.service.ts | 2 +- .../app/modules/case/filters/case.filter.ts | 2 + .../app/modules/case/filters/cases.filter.ts | 3 ++ .../src/app/modules/case/guards/rolesRules.ts | 1 + .../src/app/modules/case/state/case.state.ts | 8 ++++ .../TagCaseState/TagCaseState.spec.ts | 7 +++ .../TagCaseState/TagCaseState.strings.ts | 6 +++ .../components/TagCaseState/TagCaseState.tsx | 2 + libs/judicial-system/types/src/lib/case.ts | 2 + 11 files changed, 83 insertions(+), 1 deletion(-) create mode 100644 apps/judicial-system/backend/migrations/20240424112600-update-case.js diff --git a/apps/judicial-system/backend/migrations/20240424112600-update-case.js b/apps/judicial-system/backend/migrations/20240424112600-update-case.js new file mode 100644 index 000000000000..592e54bde70a --- /dev/null +++ b/apps/judicial-system/backend/migrations/20240424112600-update-case.js @@ -0,0 +1,48 @@ +'use strict' + +const replaceEnum = require('sequelize-replace-enum-postgres').default + +module.exports = { + up: (queryInterface) => { + return replaceEnum({ + queryInterface, + tableName: 'case', + columnName: 'state', + defaultValue: 'NEW', + newValues: [ + 'NEW', + 'DRAFT', + 'WAITING_FOR_CONFIRMATION', + 'SUBMITTED', + 'RECEIVED', + 'MAIN_HEARING', //new value + 'ACCEPTED', + 'REJECTED', + 'DELETED', + 'DISMISSED', + ], + enumName: 'enum_case_state', + }) + }, + + down: (queryInterface) => { + return replaceEnum({ + queryInterface, + tableName: 'case', + columnName: 'state', + defaultValue: 'NEW', + newValues: [ + 'NEW', + 'DRAFT', + 'WAITING_FOR_CONFIRMATION', + 'SUBMITTED', + 'RECEIVED', + 'ACCEPTED', + 'REJECTED', + 'DELETED', + 'DISMISSED', + ], + enumName: 'enum_case_state', + }) + }, +} diff --git a/apps/judicial-system/backend/src/app/modules/case/case.controller.ts b/apps/judicial-system/backend/src/app/modules/case/case.controller.ts index 0dcfd498bb03..8d0d67c15561 100644 --- a/apps/judicial-system/backend/src/app/modules/case/case.controller.ts +++ b/apps/judicial-system/backend/src/app/modules/case/case.controller.ts @@ -400,6 +400,9 @@ export class CaseController { case CaseTransition.RETURN_INDICTMENT: update.courtCaseNumber = '' break + case CaseTransition.REDISTRIBUTE: + update.judgeId = null + break } const updatedCase = await this.caseService.update( 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 2b5074d7e8d3..6a4b468ba74e 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 @@ -130,7 +130,6 @@ export interface UpdateCase | 'prosecutorAppealAnnouncement' | 'accusedPostponedAppealDate' | 'prosecutorPostponedAppealDate' - | 'judgeId' | 'registrarId' | 'caseModifiedExplanation' | 'rulingModifiedHistory' @@ -169,6 +168,7 @@ export interface UpdateCase arraignmentDate?: UpdateDateLog | null courtDate?: UpdateDateLog | null postponedIndefinitelyExplanation?: string | null + judgeId?: string | null } type DateLogKeys = keyof Pick diff --git a/apps/judicial-system/backend/src/app/modules/case/filters/case.filter.ts b/apps/judicial-system/backend/src/app/modules/case/filters/case.filter.ts index 3bce638d9e35..b1bb3f978f64 100644 --- a/apps/judicial-system/backend/src/app/modules/case/filters/case.filter.ts +++ b/apps/judicial-system/backend/src/app/modules/case/filters/case.filter.ts @@ -41,6 +41,7 @@ const canProsecutionUserAccessCase = ( CaseState.ACCEPTED, CaseState.REJECTED, CaseState.DISMISSED, + CaseState.MAIN_HEARING, ].includes(theCase.state) ) { return false @@ -101,6 +102,7 @@ const canDistrictCourtUserAccessCase = (theCase: Case, user: User): boolean => { CaseState.ACCEPTED, CaseState.REJECTED, CaseState.DISMISSED, + CaseState.MAIN_HEARING, ].includes(theCase.state) ) { return false diff --git a/apps/judicial-system/backend/src/app/modules/case/filters/cases.filter.ts b/apps/judicial-system/backend/src/app/modules/case/filters/cases.filter.ts index 9b3878d3e8d5..0af2619a065a 100644 --- a/apps/judicial-system/backend/src/app/modules/case/filters/cases.filter.ts +++ b/apps/judicial-system/backend/src/app/modules/case/filters/cases.filter.ts @@ -36,6 +36,7 @@ const getProsecutionUserCasesQueryFilter = (user: User): WhereOptions => { CaseState.ACCEPTED, CaseState.REJECTED, CaseState.DISMISSED, + CaseState.MAIN_HEARING, ], }, { @@ -88,6 +89,7 @@ const getDistrictCourtUserCasesQueryFilter = (user: User): WhereOptions => { CaseState.ACCEPTED, CaseState.REJECTED, CaseState.DISMISSED, + CaseState.MAIN_HEARING, ], }, ) @@ -119,6 +121,7 @@ const getDistrictCourtUserCasesQueryFilter = (user: User): WhereOptions => { CaseState.ACCEPTED, CaseState.REJECTED, CaseState.DISMISSED, + CaseState.MAIN_HEARING, ], }, ], 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 5311c10f4de6..2d6306394c63 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 @@ -279,6 +279,7 @@ export const districtCourtJudgeTransitionRule: RolesRule = { CaseTransition.REOPEN, CaseTransition.RECEIVE_APPEAL, CaseTransition.RETURN_INDICTMENT, + CaseTransition.REDISTRIBUTE, ], canActivate: (request) => { const theCase = request.case diff --git a/apps/judicial-system/backend/src/app/modules/case/state/case.state.ts b/apps/judicial-system/backend/src/app/modules/case/state/case.state.ts index 549e43eff8b5..aacbb34fb0ce 100644 --- a/apps/judicial-system/backend/src/app/modules/case/state/case.state.ts +++ b/apps/judicial-system/backend/src/app/modules/case/state/case.state.ts @@ -178,6 +178,14 @@ export const caseStateMachine: Map = new Map([ to: { appealState: CaseAppealState.WITHDRAWN }, }, ], + [ + CaseTransition.REDISTRIBUTE, + { + fromStates: [CaseState.RECEIVED], + fromAppealStates: [undefined], + to: { state: CaseState.MAIN_HEARING }, + }, + ], ]) export const transitionCase = function ( diff --git a/apps/judicial-system/web/src/components/TagCaseState/TagCaseState.spec.ts b/apps/judicial-system/web/src/components/TagCaseState/TagCaseState.spec.ts index 9ec3ddf40f92..79b699e103c3 100644 --- a/apps/judicial-system/web/src/components/TagCaseState/TagCaseState.spec.ts +++ b/apps/judicial-system/web/src/components/TagCaseState/TagCaseState.spec.ts @@ -111,4 +111,11 @@ describe('mapCaseStateToTagVariant', () => { text: m.unknown.defaultMessage, }) }) + + test('should return reassignment state', () => { + expect(fn(CaseState.MAIN_HEARING, false, CaseType.INDICTMENT)).toEqual({ + color: 'blue', + text: m.reassignment.defaultMessage, + }) + }) }) diff --git a/apps/judicial-system/web/src/components/TagCaseState/TagCaseState.strings.ts b/apps/judicial-system/web/src/components/TagCaseState/TagCaseState.strings.ts index accb282cb524..014eb7fa9c0e 100644 --- a/apps/judicial-system/web/src/components/TagCaseState/TagCaseState.strings.ts +++ b/apps/judicial-system/web/src/components/TagCaseState/TagCaseState.strings.ts @@ -46,4 +46,10 @@ export const tagCaseState = defineMessages({ defaultMessage: 'Óþekkt', description: 'Notað sem merki þegar mál í stöðu "Óþekkt" í málalista', }, + reassignment: { + id: 'judicial.system.core:tag_case_state.reassignment', + defaultMessage: 'Endurúthlutun', + description: + 'Notað sem merki þegar mál í stöðu "Endurúthlutun" í málalista', + }, }) diff --git a/apps/judicial-system/web/src/components/TagCaseState/TagCaseState.tsx b/apps/judicial-system/web/src/components/TagCaseState/TagCaseState.tsx index af4b70f24542..f66462fab377 100644 --- a/apps/judicial-system/web/src/components/TagCaseState/TagCaseState.tsx +++ b/apps/judicial-system/web/src/components/TagCaseState/TagCaseState.tsx @@ -60,6 +60,8 @@ export const mapCaseStateToTagVariant = ( return { color: 'dark', text: formatMessage(m.dismissed) } default: return { color: 'white', text: formatMessage(m.unknown) } + case CaseState.MAIN_HEARING: + return { color: 'blue', text: formatMessage(m.reassignment) } } } diff --git a/libs/judicial-system/types/src/lib/case.ts b/libs/judicial-system/types/src/lib/case.ts index f8ea29f716a9..168e0dee9f3f 100644 --- a/libs/judicial-system/types/src/lib/case.ts +++ b/libs/judicial-system/types/src/lib/case.ts @@ -97,6 +97,7 @@ export enum CaseState { REJECTED = 'REJECTED', DELETED = 'DELETED', DISMISSED = 'DISMISSED', + MAIN_HEARING = 'MAIN_HEARING', } export enum CaseAppealState { @@ -123,6 +124,7 @@ export enum CaseTransition { WITHDRAW_APPEAL = 'WITHDRAW_APPEAL', DENY_INDICTMENT = 'DENY_INDICTMENT', RETURN_INDICTMENT = 'RETURN_INDICTMENT', + REDISTRIBUTE = 'REDISTRIBUTE', } /* eslint-disable @typescript-eslint/naming-convention */ From ca0cb940b282650d2bc63a0ea37f4eeea0da557a Mon Sep 17 00:00:00 2001 From: unakb Date: Mon, 29 Apr 2024 15:46:51 +0000 Subject: [PATCH 2/3] test(j-s): added tests --- .../src/app/modules/case/filters/test/cases.filter.spec.ts | 4 ++++ .../app/modules/case/test/caseController/transition.spec.ts | 1 + 2 files changed, 5 insertions(+) diff --git a/apps/judicial-system/backend/src/app/modules/case/filters/test/cases.filter.spec.ts b/apps/judicial-system/backend/src/app/modules/case/filters/test/cases.filter.spec.ts index e8bca80f93b2..381b0bd79b20 100644 --- a/apps/judicial-system/backend/src/app/modules/case/filters/test/cases.filter.spec.ts +++ b/apps/judicial-system/backend/src/app/modules/case/filters/test/cases.filter.spec.ts @@ -49,6 +49,7 @@ describe('getCasesQueryFilter', () => { CaseState.ACCEPTED, CaseState.REJECTED, CaseState.DISMISSED, + CaseState.MAIN_HEARING, ], }, { @@ -104,6 +105,7 @@ describe('getCasesQueryFilter', () => { CaseState.ACCEPTED, CaseState.REJECTED, CaseState.DISMISSED, + CaseState.MAIN_HEARING, ], }, { @@ -176,6 +178,7 @@ describe('getCasesQueryFilter', () => { CaseState.ACCEPTED, CaseState.REJECTED, CaseState.DISMISSED, + CaseState.MAIN_HEARING, ], }, ], @@ -224,6 +227,7 @@ describe('getCasesQueryFilter', () => { CaseState.ACCEPTED, CaseState.REJECTED, CaseState.DISMISSED, + CaseState.MAIN_HEARING, ], }, ], diff --git a/apps/judicial-system/backend/src/app/modules/case/test/caseController/transition.spec.ts b/apps/judicial-system/backend/src/app/modules/case/test/caseController/transition.spec.ts index d31ef9f1f7fa..c5f96f322c7d 100644 --- a/apps/judicial-system/backend/src/app/modules/case/test/caseController/transition.spec.ts +++ b/apps/judicial-system/backend/src/app/modules/case/test/caseController/transition.spec.ts @@ -114,6 +114,7 @@ describe('CaseController - Transition', () => { ${CaseTransition.DELETE} | ${CaseState.RECEIVED} | ${CaseState.DELETED} ${CaseTransition.REOPEN} | ${CaseState.ACCEPTED} | ${CaseState.RECEIVED} ${CaseTransition.RETURN_INDICTMENT} | ${CaseState.RECEIVED} | ${CaseState.DRAFT} + ${CaseTransition.REDISTRIBUTE} | ${CaseState.RECEIVED} | ${CaseState.MAIN_HEARING} `.describe( '$transition $oldState case transitioning to $newState case', ({ transition, oldState, newState }) => { From 87136717fcbcd13682e7ee87dfea827556f733d7 Mon Sep 17 00:00:00 2001 From: unakb Date: Mon, 29 Apr 2024 15:57:54 +0000 Subject: [PATCH 3/3] test(j-s): Added more tests --- .../app/modules/case/state/case.state.spec.ts | 60 +++++++++++++++++++ .../src/app/modules/case/state/case.state.ts | 16 ++--- .../test/caseController/transition.spec.ts | 2 + 3 files changed, 70 insertions(+), 8 deletions(-) diff --git a/apps/judicial-system/backend/src/app/modules/case/state/case.state.spec.ts b/apps/judicial-system/backend/src/app/modules/case/state/case.state.spec.ts index fa5217861507..d886bf43c103 100644 --- a/apps/judicial-system/backend/src/app/modules/case/state/case.state.spec.ts +++ b/apps/judicial-system/backend/src/app/modules/case/state/case.state.spec.ts @@ -938,4 +938,64 @@ describe('Transition Case', () => { ) }) }) + + describe('redistribute indictment', () => { + const allowedFromStates = [CaseState.RECEIVED] + const allowedFromAppealStates = [undefined] + + describe.each(allowedFromStates)('state %s', (fromState) => { + it.each(allowedFromAppealStates)( + 'appeal state %s - should prepare indictment for redistribution', + (fromAppealState) => { + // Act + const res = transitionCase( + CaseTransition.REDISTRIBUTE, + fromState, + fromAppealState, + ) + + // Assert + expect(res).toEqual({ state: CaseState.MAIN_HEARING }) + }, + ) + + it.each(Object.values(CaseAppealState))( + 'appeal state %s - should not prepare indictment for redistribution', + (fromAppealState) => { + // Arrange + const act = () => + transitionCase( + CaseTransition.REDISTRIBUTE, + fromState, + fromAppealState, + ) + + // Act and assert + expect(act).toThrow(ForbiddenException) + }, + ) + }) + + describe.each( + Object.values(CaseState).filter( + (state) => !allowedFromStates.includes(state), + ), + )('state %s', (fromState) => { + it.each(Object.values(CaseAppealState))( + 'appeal state %s - should not prepare indictment for redistribution', + (fromAppealState) => { + // Arrange + const act = () => + transitionCase( + CaseTransition.REDISTRIBUTE, + fromState, + fromAppealState, + ) + + // Act and assert + expect(act).toThrow(ForbiddenException) + }, + ) + }) + }) }) diff --git a/apps/judicial-system/backend/src/app/modules/case/state/case.state.ts b/apps/judicial-system/backend/src/app/modules/case/state/case.state.ts index aacbb34fb0ce..6c587690e55f 100644 --- a/apps/judicial-system/backend/src/app/modules/case/state/case.state.ts +++ b/apps/judicial-system/backend/src/app/modules/case/state/case.state.ts @@ -136,6 +136,14 @@ export const caseStateMachine: Map = new Map([ to: { state: CaseState.RECEIVED }, }, ], + [ + CaseTransition.REDISTRIBUTE, + { + fromStates: [CaseState.RECEIVED], + fromAppealStates: [undefined], + to: { state: CaseState.MAIN_HEARING }, + }, + ], // APPEAL, RECEIVE_APPEAL and COMPLETE_APPEAL transitions do not affect the case state, // but they should be blocked if case is not in a state that allows for this transition to take place [ @@ -178,14 +186,6 @@ export const caseStateMachine: Map = new Map([ to: { appealState: CaseAppealState.WITHDRAWN }, }, ], - [ - CaseTransition.REDISTRIBUTE, - { - fromStates: [CaseState.RECEIVED], - fromAppealStates: [undefined], - to: { state: CaseState.MAIN_HEARING }, - }, - ], ]) export const transitionCase = function ( diff --git a/apps/judicial-system/backend/src/app/modules/case/test/caseController/transition.spec.ts b/apps/judicial-system/backend/src/app/modules/case/test/caseController/transition.spec.ts index c5f96f322c7d..e66b4747076c 100644 --- a/apps/judicial-system/backend/src/app/modules/case/test/caseController/transition.spec.ts +++ b/apps/judicial-system/backend/src/app/modules/case/test/caseController/transition.spec.ts @@ -192,6 +192,8 @@ describe('CaseController - Transition', () => { transition === CaseTransition.REOPEN ? null : undefined, courtRecordSignatureDate: transition === CaseTransition.REOPEN ? null : undefined, + judgeId: + transition === CaseTransition.REDISTRIBUTE ? null : undefined, }, { where: { id: caseId }, transaction }, )