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

chore(j-s): Civil claimant spokesperson assigned notifications #16750

Merged
merged 38 commits into from
Nov 15, 2024
Merged
Show file tree
Hide file tree
Changes from 29 commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
286cfcc
feat(j-s): Handle advocate assigned to defendant notification
unakb Oct 30, 2024
75105f3
Merge branch 'main' into j-s/defender-assigned-indictment-notification
unakb Oct 31, 2024
de44e03
Update defendant.service.ts
unakb Oct 31, 2024
d1fbfdf
feat(j-s): Send civil claimant notification when assigned
unakb Oct 31, 2024
218a8b3
Update defendantNotification.service.ts
unakb Oct 31, 2024
dbb29bf
fix(j-s): Small fix on modal texts
unakb Oct 31, 2024
ace2d8b
Merge branch 'main' into j-s/defender-assigned-indictment-notification
unakb Oct 31, 2024
5acd899
fix(j-s): Stop using advocate for defender emails
unakb Nov 6, 2024
695d578
fix(j-s): remove advocate assigned from user roles rules
unakb Nov 6, 2024
69ee49c
fix(j-s): remove and change tests
unakb Nov 6, 2024
c07ec56
Merge branch 'j-s/defender-assigned-indictment-notification' into j-s…
unakb Nov 6, 2024
aa87a74
fix(j-s): Tests
unakb Nov 7, 2024
d63b8a2
test(j-s): Defendant notification tests
unakb Nov 7, 2024
4d464dd
Update update.spec.ts
unakb Nov 7, 2024
0c0102e
Update update.spec.ts
unakb Nov 7, 2024
e197f92
Merge branch 'j-s/defender-assigned-indictment-notification' into j-s…
unakb Nov 7, 2024
db2d9fc
Update sendDefenderAssignedNotifications.spec.ts
unakb Nov 7, 2024
56eeeb7
Update defendantNotification.service.ts
unakb Nov 7, 2024
9a50186
Merge branch 'j-s/defender-assigned-indictment-notification' into j-s…
unakb Nov 7, 2024
8e5b146
test(j-s): Add tests
unakb Nov 8, 2024
1ed03ba
fix(j-s): Tests
unakb Nov 8, 2024
f6bdcec
test(j-s): Added more civil claimant tests
unakb Nov 8, 2024
cb91e36
test(j-s): Added more civil claimant tests
unakb Nov 8, 2024
6575fb2
Merge branch 'main' into j-s/civil-claimant-assigned-notifications
unakb Nov 11, 2024
1a4d533
Update civilClaimantNotification.service.ts
unakb Nov 11, 2024
76f33d1
Update internalNotification.controller.ts
unakb Nov 11, 2024
8e0d4c4
Update notification.module.ts
unakb Nov 11, 2024
291a97e
Update sendAdvocateAssignedNotifications.spec.ts
unakb Nov 11, 2024
0b680dc
Merge branch 'main' into j-s/civil-claimant-assigned-notifications
unakb Nov 11, 2024
d7b1887
Update civilClaimant.service.ts
unakb Nov 11, 2024
d55030b
Merge branch 'j-s/civil-claimant-assigned-notifications' of https://g…
unakb Nov 11, 2024
2999722
Update civilClaimant.service.ts
unakb Nov 11, 2024
5c6680e
test(j-s): Civil claimant exists guard tests
unakb Nov 15, 2024
69deee8
Merge branch 'main' into j-s/civil-claimant-assigned-notifications
unakb Nov 15, 2024
25ac665
Merge branch 'main' into j-s/civil-claimant-assigned-notifications
unakb Nov 15, 2024
8c33eb9
Merge branch 'main' into j-s/civil-claimant-assigned-notifications
kodiakhq[bot] Nov 15, 2024
0af0cb7
Merge branch 'main' of github.com:island-is/island.is into j-s/civil-…
gudjong Nov 15, 2024
9a19b1e
Merge branch 'main' into j-s/civil-claimant-assigned-notifications
kodiakhq[bot] Nov 15, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 0 additions & 43 deletions apps/judicial-system/backend/src/app/formatters/formatters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -668,49 +668,6 @@ export const formatCustodyRestrictions = (
})
}

export const formatAdvocateAssignedEmailNotification = (
formatMessage: FormatMessage,
theCase: Case,
advocateType: AdvocateType,
overviewUrl?: string,
): SubjectAndBody => {
const subject =
advocateType === AdvocateType.DEFENDER
? formatMessage(
notifications.advocateAssignedEmail.subjectAccessToCaseFiles,
{
court: capitalize(theCase.court?.name ?? ''),
},
)
: formatMessage(notifications.advocateAssignedEmail.subjectAccess, {
courtCaseNumber: theCase.courtCaseNumber,
})

const body =
advocateType === AdvocateType.DEFENDER
? formatMessage(
notifications.advocateAssignedEmail.bodyAccessToCaseFiles,
{
defenderHasAccessToRVG: Boolean(overviewUrl),
courtCaseNumber: capitalize(theCase.courtCaseNumber ?? ''),
court: theCase.court?.name ?? '',
courtName: theCase.court?.name.replace('dómur', 'dómi') ?? '',
linkStart: `<a href="${overviewUrl}">`,
linkEnd: '</a>',
},
)
: formatMessage(notifications.advocateAssignedEmail.bodyAccess, {
defenderHasAccessToRVG: Boolean(overviewUrl),
court: theCase.court?.name,
advocateType,
courtCaseNumber: capitalize(theCase.courtCaseNumber ?? ''),
linkStart: `<a href="${overviewUrl}">`,
linkEnd: '</a>',
})

return { body, subject }
}

export const formatCourtOfAppealJudgeAssignedEmailNotification = (
formatMessage: FormatMessage,
caseNumber: string,
Expand Down
1 change: 0 additions & 1 deletion apps/judicial-system/backend/src/app/formatters/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ export {
formatProsecutorReceivedByCourtSmsNotification,
formatDefenderCourtDateLinkEmailNotification,
formatDefenderResubmittedToCourtEmailNotification,
formatAdvocateAssignedEmailNotification,
formatCourtIndictmentReadyForCourtEmailNotification,
formatDefenderRoute,
formatDefenderReadyForCourtEmailNotification,
Expand Down
26 changes: 0 additions & 26 deletions apps/judicial-system/backend/src/app/messages/notifications.ts
Original file line number Diff line number Diff line change
Expand Up @@ -607,32 +607,6 @@ export const notifications = {
'Notaður sem texti í tölvupósti til verjanda vegna breytingar á lengd gæslu/einangrunar/vistunar þar sem úrskurðað var í einangrun.',
},
}),
advocateAssignedEmail: defineMessages({
subjectAccessToCaseFiles: {
id: 'judicial.system.backend:notifications.defender_assigned_email.subject_access_to_case_files',
defaultMessage: '{court} - aðgangur að málsgögnum',
description:
'Fyrirsögn í pósti til verjanda þegar hann er skráður á mál.',
},
subjectAccess: {
id: 'judicial.system.backend:notifications.defender_assigned_email.subject_access',
defaultMessage: 'Skráning í máli {courtCaseNumber}',
description:
'Fyrirsögn í pósti til verjanda þegar hann er skráður á mál.',
},
bodyAccessToCaseFiles: {
id: 'judicial.system.backend:notifications.defender_assigned_email.body_access_to_case_files',
defaultMessage:
'{court} hefur skráð þig verjanda í máli {courtCaseNumber}.<br /><br />{defenderHasAccessToRVG, select, true {Gögn málsins eru aðgengileg á {linkStart}yfirlitssíðu málsins í Réttarvörslugátt{linkEnd}} other {Þú getur nálgast gögn málsins hjá {courtName} ef þau hafa ekki þegar verið afhent}}.',
description: 'Texti í pósti til verjanda þegar hann er skráður á mál.',
},
bodyAccess: {
id: 'judicial.system.backend:notifications.defender_assigned_email.body_access',
defaultMessage:
'{court} hefur skráð þig {advocateType, select, LAWYER {lögmann einkaréttarkröfuhafa} LEGAL_RIGHTS_PROTECTOR {réttargæslumann einkaréttarkröfuhafa} other {verjanda}} í máli {courtCaseNumber}.<br /><br />{defenderHasAccessToRVG, select, true {Sjá nánar á {linkStart}yfirlitssíðu málsins í Réttarvörslugátt{linkEnd}} other {Þú getur nálgast málið hjá {courtName}.}}.',
description: 'Texti í pósti til verjanda þegar hann er skráður á mál.',
},
}),
defendantsNotUpdatedAtCourt: defineMessages({
subject: {
id: 'judicial.system.backend:notifications.defendants_not_updated_at_court.subject',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,11 @@ import type { Logger } from '@island.is/logging'
import { LOGGER_PROVIDER } from '@island.is/logging'

import { normalizeAndFormatNationalId } from '@island.is/judicial-system/formatters'
import { CaseState } from '@island.is/judicial-system/types'
import { MessageService, MessageType } from '@island.is/judicial-system/message'
import {
CaseState,
CivilClaimantNotificationType,
} from '@island.is/judicial-system/types'

import { Case } from '../case/models/case.model'
import { UpdateCivilClaimantDto } from './dto/updateCivilClaimant.dto'
Expand All @@ -18,6 +22,7 @@ export class CivilClaimantService {
constructor(
@InjectModel(CivilClaimant)
private readonly civilClaimantModel: typeof CivilClaimant,
private readonly messageService: MessageService,
@Inject(LOGGER_PROVIDER) private readonly logger: Logger,
) {}

Expand All @@ -27,6 +32,24 @@ export class CivilClaimantService {
})
}

private async sendUpdateCivilClaimantMessages(
update: UpdateCivilClaimantDto,
updatedCivilClaimant: CivilClaimant,
): Promise<void> {
if (update.isSpokespersonConfirmed === true) {
await this.messageService.sendMessagesToQueue([
{
type: MessageType.CIVIL_CLAIMANT_NOTIFICATION,
caseId: updatedCivilClaimant.caseId,
body: {
type: CivilClaimantNotificationType.SPOKESPERSON_ASSIGNED,
},
elementId: updatedCivilClaimant.id,
},
])
}
}
unakb marked this conversation as resolved.
Show resolved Hide resolved

async update(
caseId: string,
civilClaimantId: string,
Expand All @@ -49,6 +72,8 @@ export class CivilClaimantService {
throw new Error(`Could not update civil claimant ${civilClaimantId}`)
}

this.sendUpdateCivilClaimantMessages(update, civilClaimants[0])
unakb marked this conversation as resolved.
Show resolved Hide resolved

return civilClaimants[0]
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { createParamDecorator } from '@nestjs/common'

import { CivilClaimant } from '../models/civilClaimant.model'

export const CurrentCivilClaimant = createParamDecorator(
(data, { args: [_1, { req }] }): CivilClaimant => req.civilClaimant,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import {
BadRequestException,
CanActivate,
ExecutionContext,
Injectable,
NotFoundException,
} from '@nestjs/common'

import { Case } from '../../case'

@Injectable()
export class CivilClaimantExistsGuard implements CanActivate {
canActivate(context: ExecutionContext): boolean {
const request = context.switchToHttp().getRequest()

const theCase: Case = request.case

if (!theCase) {
throw new BadRequestException('Missing case')
}

const civilClaimantId = request.params.civilClaimantId

if (!civilClaimantId) {
throw new BadRequestException('Missing civil id')
}

const civilClaimant = theCase.civilClaimants?.find(
(civilClaimants) => civilClaimants.id === civilClaimantId,
)

if (!civilClaimant) {
throw new NotFoundException(
`Civil claimant ${civilClaimantId} of case ${theCase.id} does not exist`,
)
}

request.civilClaimant = civilClaimant

return true
}
unakb marked this conversation as resolved.
Show resolved Hide resolved
}
unakb marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
export { Defendant } from './models/defendant.model'
export { DefendantService } from './defendant.service'
export { CivilClaimant } from './models/civilClaimant.model'
export { DefendantExistsGuard } from './guards/defendantExists.guard'
export { CurrentDefendant } from './guards/defendant.decorator'

export { CivilClaimant } from './models/civilClaimant.model'
export { CivilClaimantService } from './civilClaimant.service'
export { CivilClaimantExistsGuard } from './guards/civilClaimantExists.guard'
export { CurrentCivilClaimant } from './guards/civilClaimaint.decorator'
unakb marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import { uuid } from 'uuidv4'

import { createTestingDefendantModule } from '../createTestingDefendantModule'

import { Case } from '../../../case'
import { CivilClaimant } from '../../models/civilClaimant.model'

interface Then {
result: CivilClaimant
error: Error
}

type GivenWhenThen = (caseId?: string) => Promise<Then>

describe('CivilClaimantController - Create', () => {
const caseId = uuid()
const civilClaimantId = uuid()
const theCase = { id: caseId } as Case
const civilClaimantToCreate = {
caseId,
}
const createdCivilClaimant = { id: civilClaimantId, caseId }

let mockCivilClaimantModel: typeof CivilClaimant
let givenWhenThen: GivenWhenThen

beforeEach(async () => {
const { civilClaimantModel, civilClaimantController } =
await createTestingDefendantModule()

mockCivilClaimantModel = civilClaimantModel

const mockCreate = mockCivilClaimantModel.create as jest.Mock
mockCreate.mockResolvedValue(createdCivilClaimant)

givenWhenThen = async () => {
const then = {} as Then

await civilClaimantController
.create(theCase.id, theCase)
.then((result) => (then.result = result))
.catch((error) => (then.error = error))

return then
}
})
unakb marked this conversation as resolved.
Show resolved Hide resolved

describe('civil claimant creation', () => {
let then: Then

beforeEach(async () => {
then = await givenWhenThen(caseId)
})
it('should create a civil claimant', () => {
expect(mockCivilClaimantModel.create).toHaveBeenCalledWith(
civilClaimantToCreate,
)
})

it('should return the created civil claimant', () => {
expect(then.result).toEqual(createdCivilClaimant)
})
})

describe('civil claimant creation fails', () => {
let then: Then

beforeEach(async () => {
const mockCreate = mockCivilClaimantModel.create as jest.Mock
mockCreate.mockRejectedValue(new Error('Test error'))

then = await givenWhenThen(caseId)
})

it('should throw an error', () => {
expect(then.error).toBeInstanceOf(Error)
expect(then.error.message).toEqual('Test error')
})
})
unakb marked this conversation as resolved.
Show resolved Hide resolved
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { CanActivate } from '@nestjs/common'

import { CaseExistsGuard, CaseWriteGuard } from '../../../case'
import { CivilClaimantController } from '../../civilClaimant.controller'

describe('CivilClaimantController - Create guards', () => {
let guards: Array<new () => CanActivate>
const expectedGuards = [CaseExistsGuard, CaseWriteGuard]

beforeEach(() => {
guards = Reflect.getMetadata(
'__guards__',
CivilClaimantController.prototype.create,
)
})

it('should have the correct guards in the correct order', () => {
expect(guards).toHaveLength(expectedGuards.length)

expectedGuards.forEach((expectedGuard, index) => {
const guardInstance = new guards[index]()
expect(guardInstance).toBeInstanceOf(expectedGuard)
})
})
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import {
districtCourtAssistantRule,
districtCourtJudgeRule,
districtCourtRegistrarRule,
prosecutorRepresentativeRule,
prosecutorRule,
} from '../../../../guards'
import { CivilClaimantController } from '../../civilClaimant.controller'

describe('CivilClaimantController - Create rules', () => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
let rules: any[]

const expectedRules = [
prosecutorRule,
prosecutorRepresentativeRule,
districtCourtJudgeRule,
districtCourtRegistrarRule,
districtCourtAssistantRule,
]

beforeEach(() => {
rules = Reflect.getMetadata(
'roles-rules',
CivilClaimantController.prototype.create,
)
})

it('should give permission to roles', () => {
expect(rules).toHaveLength(expectedRules.length)
expectedRules.forEach((expectedRule) =>
expect(rules).toContain(expectedRule),
)
})
})
Loading
Loading