Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(j-s): Case Files Added Notification #16452

Merged
merged 12 commits into from
Oct 23, 2024
Merged
13 changes: 13 additions & 0 deletions apps/judicial-system/backend/src/app/messages/notifications.ts
Original file line number Diff line number Diff line change
Expand Up @@ -859,4 +859,17 @@ export const notifications = {
description: 'Texti í pósti til dómstóls þegar ákæra er afturkölluð',
},
}),
caseFilesUpdated: defineMessages({
subject: {
id: 'judicial.system.backend:notifications.case_files_updated.subject',
defaultMessage: 'Ný gögn í máli {courtCaseNumber}',
description: 'Fyrirsögn í pósti til aðila máls þegar ný gögn eru send',
},
body: {
id: 'judicial.system.backend:notifications.case_files_updated.body',
defaultMessage:
'Ný gögn hafa borist vegna máls {courtCaseNumber}. {userHasAccessToRVG, select, true {Hægt er að nálgast gögn málsins á {linkStart}yfirlitssíðu málsins í Réttarvörslugátt{linkEnd}} other {Hægt er að nálgast gögn málsins hjá {court} ef þau hafa ekki þegar verið afhent}}',
description: 'Texti í pósti til aðila máls þegar ný gögn eru send',
},
}),
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export const prosecutorNotificationRule: RolesRule = {
NotificationType.HEADS_UP,
NotificationType.READY_FOR_COURT,
NotificationType.APPEAL_CASE_FILES_UPDATED,
NotificationType.CASE_FILES_UPDATED,
],
} as RolesRule

Expand All @@ -18,7 +19,10 @@ export const defenderNotificationRule: RolesRule = {
role: UserRole.DEFENDER,
type: RulesType.FIELD_VALUES,
dtoField: 'type',
dtoFieldValues: [NotificationType.APPEAL_CASE_FILES_UPDATED],
dtoFieldValues: [
NotificationType.APPEAL_CASE_FILES_UPDATED,
NotificationType.CASE_FILES_UPDATED,
],
} as RolesRule

// Allows district court judges to send notifiications
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ import {
RequestSharedWithDefender,
SessionArrangements,
type User,
UserRole,
} from '@island.is/judicial-system/types'

import {
Expand Down Expand Up @@ -75,7 +74,11 @@ import {
import { notifications } from '../../messages'
import { type Case, DateLog } from '../case'
import { CourtService } from '../court'
import { type Defendant, DefendantService } from '../defendant'
import {
type CivilClaimant,
type Defendant,
DefendantService,
} from '../defendant'
import { EventService } from '../event'
import { DeliverResponse } from './models/deliver.response'
import { Notification, Recipient } from './models/notification.model'
Expand Down Expand Up @@ -1545,7 +1548,9 @@ export class InternalNotificationService extends BaseNotificationService {
SessionArrangements.ALL_PRESENT_SPOKESPERSON,
].includes(theCase.sessionArrangements)

if (!isDefenderIncludedInSessionArrangements) return false
if (!isDefenderIncludedInSessionArrangements) {
return false
}
} else {
const hasDefenderBeenNotified = this.hasReceivedNotification(
[
Expand Down Expand Up @@ -1633,10 +1638,11 @@ export class InternalNotificationService extends BaseNotificationService {
} = civilClaimant

const shouldSend =
hasSpokesperson &&
this.shouldSendAdvocateAssignedNotification(
theCase,
spokespersonEmail,
) && hasSpokesperson
)

if (shouldSend === true) {
promises.push(
Expand Down Expand Up @@ -1781,6 +1787,110 @@ export class InternalNotificationService extends BaseNotificationService {
}
//#endregion

//#region CASE_FILES_UPDATED notifications
private sendCaseFilesUpdatedNotification(
courtCaseNumber?: string,
link?: string,
name?: string,
email?: string,
) {
const subject = this.formatMessage(notifications.caseFilesUpdated.subject, {
courtCaseNumber,
})
const html = this.formatMessage(notifications.caseFilesUpdated.body, {
courtCaseNumber,
userHasAccessToRVG: Boolean(link),
linkStart: `<a href="${link}">`,
linkEnd: '</a>',
})

return this.sendEmail(subject, html, name, email, undefined, !link)
}

private async sendCaseFilesUpdatedNotifications(
theCase: Case,
user: User,
): Promise<DeliverResponse> {
const promises = [
this.sendCaseFilesUpdatedNotification(
theCase.courtCaseNumber,
`${this.config.clientUrl}${INDICTMENTS_COURT_OVERVIEW_ROUTE}/${theCase.id}`,
theCase.judge?.name,
theCase.judge?.email,
),
]

const uniqueSpokespersons = _uniqBy(
theCase.civilClaimants?.filter((c) => c.hasSpokesperson) ?? [],
(c: CivilClaimant) => c.spokespersonEmail,
)
uniqueSpokespersons.forEach((civilClaimant) => {
if (civilClaimant.spokespersonEmail) {
promises.push(
this.sendCaseFilesUpdatedNotification(
theCase.courtCaseNumber,
civilClaimant.spokespersonNationalId &&
formatDefenderRoute(
this.config.clientUrl,
theCase.type,
theCase.id,
),
civilClaimant.spokespersonName,
civilClaimant.spokespersonEmail,
),
)
}
})

if (isProsecutionUser(user)) {
const uniqueDefendants = _uniqBy(
theCase.defendants ?? [],
(d: Defendant) => d.defenderEmail,
)
uniqueDefendants.forEach((defendant) => {
if (defendant.defenderEmail) {
promises.push(
this.sendCaseFilesUpdatedNotification(
theCase.courtCaseNumber,
defendant.defenderNationalId &&
formatDefenderRoute(
this.config.clientUrl,
theCase.type,
theCase.id,
),
defendant.defenderName,
defendant.defenderEmail,
),
)
}
})
}

if (isDefenceUser(user)) {
promises.push(
this.sendCaseFilesUpdatedNotification(
theCase.courtCaseNumber,
`${this.config.clientUrl}${INDICTMENTS_OVERVIEW_ROUTE}/${theCase.id}`,
theCase.prosecutor?.name,
theCase.prosecutor?.email,
),
)
}
gudjong marked this conversation as resolved.
Show resolved Hide resolved

const recipients = await Promise.all(promises)

if (recipients.length > 0) {
return this.recordNotification(
theCase.id,
NotificationType.APPEAL_JUDGES_ASSIGNED,
recipients,
)
}

return { delivered: true }
}
//#endregion
gudjong marked this conversation as resolved.
Show resolved Hide resolved

//#region Appeal notifications
//#region COURT_OF_APPEAL_JUDGE_ASSIGNED notifications
private async sendCourtOfAppealJudgeAssignedNotification(
Expand Down Expand Up @@ -1875,7 +1985,7 @@ export class InternalNotificationService extends BaseNotificationService {
)
}

if (user.role === UserRole.DEFENDER) {
if (isDefenceUser(user)) {
promises.push(
this.sendEmail(
subject,
Expand All @@ -1887,7 +1997,7 @@ export class InternalNotificationService extends BaseNotificationService {
promises.push(this.sendSms(smsText, theCase.prosecutor?.mobileNumber))
}

if (user.role === UserRole.PROSECUTOR && theCase.defenderEmail) {
if (isProsecutionUser(user) && theCase.defenderEmail) {
const url =
theCase.defenderNationalId &&
formatDefenderRoute(this.config.clientUrl, theCase.type, theCase.id)
Expand Down Expand Up @@ -2105,7 +2215,7 @@ export class InternalNotificationService extends BaseNotificationService {
}
}

if (user.role === UserRole.DEFENDER) {
if (isDefenceUser(user)) {
const prosecutorHtml = this.formatMessage(
notifications.caseAppealStatement.body,
{
Expand All @@ -2127,7 +2237,7 @@ export class InternalNotificationService extends BaseNotificationService {
)
}

if (user.role === UserRole.PROSECUTOR && theCase.defenderEmail) {
if (isProsecutionUser(user)) {
const url =
theCase.defenderNationalId &&
formatDefenderRoute(this.config.clientUrl, theCase.type, theCase.id)
Expand Down Expand Up @@ -2210,7 +2320,7 @@ export class InternalNotificationService extends BaseNotificationService {
}
})

if (user.role === UserRole.DEFENDER) {
if (isDefenceUser(user)) {
const prosecutorHtml = this.formatMessage(
notifications.caseAppealCaseFilesUpdated.body,
{
Expand Down Expand Up @@ -2587,6 +2697,8 @@ export class InternalNotificationService extends BaseNotificationService {
return this.sendIndictmentDeniedNotifications(theCase)
case NotificationType.INDICTMENT_RETURNED:
return this.sendIndictmentReturnedNotifications(theCase)
case NotificationType.CASE_FILES_UPDATED:
return this.sendCaseFilesUpdatedNotifications(theCase, user)
default:
throw new InternalServerErrorException(
`Invalid notification type ${type}`,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ export class NotificationService {
case NotificationType.ADVOCATE_ASSIGNED:
case NotificationType.APPEAL_JUDGES_ASSIGNED:
case NotificationType.APPEAL_CASE_FILES_UPDATED:
case NotificationType.CASE_FILES_UPDATED:
messages = [this.getNotificationMessage(type, user, theCase)]
break
default:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { uuid } from 'uuidv4'
import { EmailService } from '@island.is/email-service'

import {
InstitutionType,
NotificationType,
User,
UserRole,
Expand All @@ -19,13 +20,12 @@ interface Then {
}

type GivenWhenThen = (
role: UserRole,
user: User,
defenderNationalId?: string,
appealsCourtNumber?: string,
) => Promise<Then>

describe('InternalNotificationController - Send appeal statement notifications', () => {
const userId = uuid()
const caseId = uuid()
const prosecutorName = uuid()
const prosecutorEmail = uuid()
Expand Down Expand Up @@ -54,7 +54,7 @@ describe('InternalNotificationController - Send appeal statement notifications',
mockEmailService = emailService

givenWhenThen = async (
role: UserRole,
user: User,
defenderNationalId?: string,
appealCaseNumber?: string,
) => {
Expand All @@ -77,7 +77,7 @@ describe('InternalNotificationController - Send appeal statement notifications',
appealJudge1: { name: judgeName1, email: judgeEmail1 },
} as Case,
{
user: { id: userId, role } as User,
user,
type: NotificationType.APPEAL_STATEMENT,
},
)
Expand All @@ -99,7 +99,14 @@ describe('InternalNotificationController - Send appeal statement notifications',
let then: Then

beforeEach(async () => {
then = await givenWhenThen(UserRole.PROSECUTOR, uuid(), appealCaseNumber)
then = await givenWhenThen(
{
role: UserRole.PROSECUTOR,
institution: { type: InstitutionType.PROSECUTORS_OFFICE },
} as User,
uuid(),
appealCaseNumber,
)
})

it('should send notification to appeals court and defender', () => {
Expand All @@ -123,7 +130,10 @@ describe('InternalNotificationController - Send appeal statement notifications',

beforeEach(async () => {
then = await givenWhenThen(
UserRole.PROSECUTOR,
{
role: UserRole.PROSECUTOR,
institution: { type: InstitutionType.PROSECUTORS_OFFICE },
} as User,
undefined,
appealCaseNumber,
)
Expand All @@ -149,7 +159,11 @@ describe('InternalNotificationController - Send appeal statement notifications',
let then: Then

beforeEach(async () => {
then = await givenWhenThen(UserRole.DEFENDER, uuid(), appealCaseNumber)
then = await givenWhenThen(
{ role: UserRole.DEFENDER } as User,
uuid(),
appealCaseNumber,
)
})

it('should send notification to appeals court and prosecutor', () => {
Expand All @@ -172,7 +186,13 @@ describe('InternalNotificationController - Send appeal statement notifications',
let then: Then

beforeEach(async () => {
then = await givenWhenThen(UserRole.PROSECUTOR, uuid())
then = await givenWhenThen(
{
role: UserRole.PROSECUTOR,
institution: { type: InstitutionType.PROSECUTORS_OFFICE },
} as User,
uuid(),
)
})

it('should send notification to defender', () => {
Expand All @@ -191,7 +211,10 @@ describe('InternalNotificationController - Send appeal statement notifications',
let then: Then

beforeEach(async () => {
then = await givenWhenThen(UserRole.PROSECUTOR)
then = await givenWhenThen({
role: UserRole.PROSECUTOR,
institution: { type: InstitutionType.PROSECUTORS_OFFICE },
} as User)
})

it('should send notification to defender', () => {
Expand All @@ -210,7 +233,7 @@ describe('InternalNotificationController - Send appeal statement notifications',
let then: Then

beforeEach(async () => {
then = await givenWhenThen(UserRole.DEFENDER, uuid())
then = await givenWhenThen({ role: UserRole.DEFENDER } as User, uuid())
})

it('should send notification to prosecutor', () => {
Expand Down
Loading