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): Service Certificate to Court #17904

Merged
merged 5 commits into from
Feb 14, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@ import {
capitalize,
formatDate,
formatDOB,
formatNationalId,
getWordByGender,
Word,
} from '@island.is/judicial-system/formatters'
import {
DefenderChoice,
ServiceStatus,
SubpoenaType,
UserRole,
Expand All @@ -21,8 +23,7 @@ import { Defendant } from '../modules/defendant'
import { Subpoena } from '../modules/subpoena'
import {
addEmptyLines,
addFooter,
addHugeHeading,
addLargeHeading,
addMediumCenteredText,
addNormalCenteredText,
addNormalText,
Expand Down Expand Up @@ -61,7 +62,7 @@ export const createServiceCertificate = (
const doc = new PDFDocument({
size: 'A4',
margins: {
top: 40,
top: 80,
bottom: 60,
left: 50,
right: 50,
Expand All @@ -75,25 +76,25 @@ export const createServiceCertificate = (

setTitle(doc, formatMessage(strings.title))

addHugeHeading(doc, formatMessage(strings.title).toUpperCase(), 'Times-Bold')
addLargeHeading(doc, formatMessage(strings.title).toUpperCase(), 'Times-Bold')
addMediumCenteredText(
doc,
`Mál nr. ${theCase.courtCaseNumber || ''}`,
'Times-Bold',
)
addNormalCenteredText(doc, theCase.court?.name || '', 'Times-Bold')

addEmptyLines(doc, 2)
addEmptyLines(doc, 3)

addMediumCenteredText(
doc,
`Birting tókst ${
subpoena.serviceDate ? formatDate(subpoena.serviceDate, 'PPp') : ''
subpoena.serviceDate ? formatDate(subpoena.serviceDate, 'PPPp') : ''
}`,
'Times-Bold',
)

addEmptyLines(doc)
addEmptyLines(doc, 2)

addNormalText(doc, 'Birtingaraðili: ', 'Times-Bold', true)
addNormalText(
Expand All @@ -104,6 +105,8 @@ export const createServiceCertificate = (
'Times-Roman',
)

addEmptyLines(doc)

if (subpoena.serviceStatus !== ServiceStatus.ELECTRONICALLY) {
addNormalText(doc, 'Athugasemd: ', 'Times-Bold', true)
addNormalText(
Expand All @@ -117,26 +120,34 @@ export const createServiceCertificate = (
)
}

addEmptyLines(doc, 2)
addEmptyLines(doc, 3)

addNormalText(
doc,
`${capitalize(getWordByGender(Word.AKAERDI, defendant.gender))}: `,
'Times-Bold',
true,
const defendantText = capitalize(
getWordByGender(Word.AKAERDI, defendant.gender),
)
const defendantLabel = `${defendantText}: `

addNormalText(doc, defendantLabel, 'Times-Bold', true)
addNormalText(
doc,
defendant.name && defendant.nationalId && defendant.address
defendant.name && defendant.nationalId
? `${defendant.name}, ${formatDOB(
defendant.nationalId,
defendant.noNationalId,
)}, ${defendant.address}`
)}`
: 'Ekki skráður',
'Times-Roman',
)

addEmptyLines(doc, 2)
// Consider adding indentation to helper functions
doc.text(
` ${defendant.address ?? 'Ekki skráð'}`,
50 + doc.widthOfString(defendantLabel),
doc.y + 5,
)
doc.text('', 50)

addEmptyLines(doc, 3)

addNormalText(doc, 'Ákærandi: ', 'Times-Bold', true)
addNormalText(
Expand All @@ -147,14 +158,16 @@ export const createServiceCertificate = (
'Times-Roman',
)

addEmptyLines(doc)

addNormalText(doc, `${getRole(theCase.judge?.role)}: `, 'Times-Bold', true)
addNormalText(
doc,
theCase.judge ? theCase.judge.name : 'Ekki skráður',
'Times-Roman',
)

addEmptyLines(doc)
addEmptyLines(doc, 3)

addNormalText(doc, 'Þingfesting: ', 'Times-Bold', true)
addNormalText(
Expand All @@ -166,13 +179,59 @@ export const createServiceCertificate = (
'Times-Roman',
)

addEmptyLines(doc)

addNormalText(doc, 'Staður: ', 'Times-Bold', true)
addNormalText(doc, subpoena.location || 'Ekki skráður', 'Times-Roman')
addNormalText(
doc,
`Dómsalur ${subpoena.location}` || 'ekki skráður',
'Times-Roman',
)

addEmptyLines(doc)

addNormalText(doc, 'Tegund fyrirkalls: ', 'Times-Bold', true)
addNormalText(doc, getSubpoenaType(defendant.subpoenaType), 'Times-Roman')

addFooter(doc)
addEmptyLines(doc, 3)

let defenderChoiceText = ''

switch (defendant.requestedDefenderChoice) {
case DefenderChoice.CHOOSE:
defenderChoiceText =
'Ég óska þess að valinn lögmaður verði skipaður verjandi minn.'
break
case DefenderChoice.WAIVE:
defenderChoiceText = 'Ég óska ekki eftir verjanda.'
break
case DefenderChoice.DELEGATE:
defenderChoiceText =
'Ég fel dómara málsins að tilnefna og skipa mér verjanda.'
break
case DefenderChoice.DELAY:
default:
defenderChoiceText =
'Ég óska eftir fresti fram að þingfestingu til þess að tilnefna verjanda.'
}
oddsson marked this conversation as resolved.
Show resolved Hide resolved

addNormalText(doc, 'Afstaða til verjanda: ', 'Times-Bold', true)
addNormalText(doc, defenderChoiceText, 'Times-Roman')

if (defendant.requestedDefenderChoice === DefenderChoice.CHOOSE) {
addEmptyLines(doc)

addNormalText(
doc,
defendant.requestedDefenderName && defendant.requestedDefenderNationalId
? `${defendant.requestedDefenderName}, kt. ${formatNationalId(
defendant.requestedDefenderNationalId,
)}`
: 'Ekki skráður',
'Times-Roman',
)
}

doc.end()

return new Promise<Buffer>((resolve) =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ import {
isInvestigationCase,
isRequestCase,
notificationTypes,
ServiceStatus,
StringType,
stringTypes,
UserRole,
Expand Down Expand Up @@ -1359,7 +1360,7 @@ export class CaseService {
(updatedDefendant) =>
theCase.defendants?.find(
(defendant) => defendant.id === updatedDefendant.id,
)?.subpoenas?.[0]?.id !== updatedDefendant.subpoenas?.[0]?.id,
)?.subpoenas?.[0]?.id !== updatedDefendant.subpoenas?.[0]?.id, // Only deliver new subpoenas
)
.map((updatedDefendant) => [
...(updatedCase.origin === CaseOrigin.LOKE
Expand Down Expand Up @@ -1400,6 +1401,37 @@ export class CaseService {
}
}

private addMessagesForIndictmentArraignmentCompletionToQueue(
theCase: Case,
user: TUser,
): Promise<void> {
const messages: Message[] = []

theCase.defendants?.forEach((defendant) => {
const subpoena = defendant.subpoenas?.[0]

const hasSubpoenaBeenSuccessfullyServedToDefendant =
subpoena?.serviceStatus &&
gudjong marked this conversation as resolved.
Show resolved Hide resolved
[
ServiceStatus.DEFENDER,
ServiceStatus.ELECTRONICALLY,
ServiceStatus.IN_PERSON,
].includes(subpoena.serviceStatus)

// Only send certificates for subpoenas which have been successfully served
if (hasSubpoenaBeenSuccessfullyServedToDefendant) {
messages.push({
type: MessageType.DELIVERY_TO_COURT_SERVICE_CERTIFICATE,
user,
caseId: theCase.id,
elementId: [defendant.id, subpoena.id],
})
}
})

return this.messageService.sendMessagesToQueue(messages)
}

private async addMessagesForUpdatedCaseToQueue(
theCase: Case,
updatedCase: Case,
Expand Down Expand Up @@ -1610,6 +1642,14 @@ export class CaseService {

await this.addMessagesForNewSubpoenasToQueue(theCase, updatedCase, user)
}

// This only applies to indictments and only when an arraignment has been completed
if (updatedCase.indictmentDecision && !theCase.indictmentDecision) {
await this.addMessagesForIndictmentArraignmentCompletionToQueue(
updatedCase,
user,
)
}
}

private allAppealRolesAssigned(updatedCase: Case) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,42 @@ export class InternalSubpoenaController {
)
}

@UseGuards(
CaseExistsGuard,
new CaseTypeGuard(indictmentCases),
DefendantExistsGuard,
SubpoenaExistsGuard,
)
@Post(
`case/:caseId/${
messageEndpoint[MessageType.DELIVERY_TO_COURT_SERVICE_CERTIFICATE]
}/:defendantId/:subpoenaId`,
)
@ApiOkResponse({
type: DeliverResponse,
description: 'Delivers a service certificate to the court',
})
deliverServiceCertificateToCourt(
@Param('caseId') caseId: string,
@Param('defendantId') defendantId: string,
@Param('subpoenaId') subpoenaId: string,
@CurrentCase() theCase: Case,
@CurrentDefendant() defendant: Defendant,
@CurrentSubpoena() subpoena: Subpoena,
@Body() deliverDto: DeliverDto,
): Promise<DeliverResponse> {
this.logger.debug(
`Delivering service certificate pdf to court for subpoena ${subpoenaId} of defendant ${defendantId} and case ${caseId}`,
)

return this.subpoenaService.deliverServiceCertificateToCourt(
theCase,
defendant,
subpoena,
deliverDto.user,
)
}

@UseGuards(
CaseExistsGuard,
new CaseTypeGuard(indictmentCases),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -432,6 +432,41 @@ export class SubpoenaService {
})
}

async deliverServiceCertificateToCourt(
theCase: Case,
defendant: Defendant,
subpoena: Subpoena,
user: TUser,
): Promise<DeliverResponse> {
return this.pdfService
.getServiceCertificatePdf(theCase, defendant, subpoena)
.then(async (pdf) => {
const fileName = `Birtingarvottorð - ${defendant.name}`

return this.courtService.createDocument(
user,
theCase.id,
theCase.courtId,
theCase.courtCaseNumber,
CourtDocumentFolder.SUBPOENA_DOCUMENTS,
fileName,
`${fileName}.pdf`,
'application/pdf',
pdf,
)
})
.then(() => ({ delivered: true }))
.catch((reason) => {
// Tolerate failure, but log error
this.logger.warn(
`Failed to upload service certificate pdf to court for subpoena ${subpoena.id} of defendant ${defendant.id} and case ${theCase.id}`,
{ reason },
)

return { delivered: false }
})
}

async deliverSubpoenaRevocationToPolice(
theCase: Case,
subpoena: Subpoena,
Expand Down
Loading
Loading