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 pdf #16463

Merged
merged 32 commits into from
Oct 21, 2024
Merged
Show file tree
Hide file tree
Changes from 27 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
633abbc
Make a gendered version of the subpoena pdf
oddsson Oct 15, 2024
95ca1bf
Merge branch 'main' of github.com:island-is/island.is into j-s/gender…
oddsson Oct 16, 2024
7699d78
Refactor
oddsson Oct 16, 2024
fdc374d
Add types
oddsson Oct 16, 2024
0343da0
Merge branch 'main' of github.com:island-is/island.is into j-s/gender…
oddsson Oct 16, 2024
69db6d6
Merge branch 'main' into j-s/gendered-subpoena
kodiakhq[bot] Oct 16, 2024
3c1bc6d
Checkpoint
oddsson Oct 16, 2024
1ce1ddb
Refactor
oddsson Oct 16, 2024
b9aeb50
Merge branch 'j-s/gendered-subpoena' of github.com:island-is/island.i…
oddsson Oct 16, 2024
5fbe0df
Merge branch 'main' of github.com:island-is/island.is into j-s/gender…
oddsson Oct 16, 2024
4008d20
Merge branch 'main' of github.com:island-is/island.is into j-s/servic…
oddsson Oct 16, 2024
132b189
Merge branch 'j-s/gendered-subpoena' of github.com:island-is/island.i…
oddsson Oct 16, 2024
05fbdd0
Checkpoint
oddsson Oct 16, 2024
b712a7d
Merge branch 'main' of github.com:island-is/island.is into j-s/servic…
oddsson Oct 16, 2024
289a173
Cleanup pdf doc
oddsson Oct 16, 2024
b7e597b
Cleanup
oddsson Oct 16, 2024
d10552b
Cleanup
oddsson Oct 16, 2024
344f91c
Merge branch 'main' of github.com:island-is/island.is into j-s/servic…
oddsson Oct 17, 2024
27dc3dd
Make adjustments for different service statuses
oddsson Oct 17, 2024
fedddb7
Only show service-certificate in successful service status
oddsson Oct 17, 2024
2c570e7
Merge branch 'main' of github.com:island-is/island.is into j-s/servic…
oddsson Oct 17, 2024
0dcf9b3
Merge branch 'main' of github.com:island-is/island.is into j-s/servic…
oddsson Oct 18, 2024
9ac328d
Cleanup
oddsson Oct 18, 2024
690ae65
Cleanup
oddsson Oct 18, 2024
225844d
Merge branch 'main' of github.com:island-is/island.is into j-s/servic…
oddsson Oct 21, 2024
34e6fdb
Show service certificate to defenders
oddsson Oct 21, 2024
c99f8c9
Fix typo
oddsson Oct 21, 2024
12fd1cc
Merge branch 'main' of github.com:island-is/island.is into j-s/servic…
oddsson Oct 21, 2024
f591eb8
Move guards
oddsson Oct 21, 2024
c7824ed
Remove unused code
oddsson Oct 21, 2024
f55fa57
Merge branch 'main' of github.com:island-is/island.is into j-s/servic…
oddsson Oct 21, 2024
799179f
Fix tests
oddsson Oct 21, 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
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,32 @@ export class FileController {
)
}

@Get(['subpoena/:defendantId', 'subpoena/:defendantId/:subpoenaId'])
@Get('serviceCertificate/:defendantId/:subpoenaId')
@Header('Content-Type', 'application/pdf')
getServiceCertificatePdf(
@Param('id') id: string,
@Param('defendantId') defendantId: string,
@CurrentHttpUser() user: User,
@Req() req: Request,
@Res() res: Response,
@Param('subpoenaId') subpoenaId?: string,
): Promise<Response> {
this.logger.debug(
`Getting service certificate for defendant ${defendantId} of case ${id} as a pdf document`,
)

return this.fileService.tryGetFile(
user.id,
AuditedAction.GET_SERVICE_CERTIFICATE_PDF,
id,
`defendant/${defendantId}/subpoena/${subpoenaId}/serviceCertificate`,
req,
res,
'pdf',
)
}

@Get('subpoena/:defendantId')
@Header('Content-Type', 'application/pdf')
getSubpoenaPdf(
@Param('id') id: string,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import {
Header,
Inject,
Param,
Query,
Req,
Res,
UseGuards,
Expand All @@ -20,7 +19,7 @@ import {
CurrentHttpUser,
JwtInjectBearerAuthGuard,
} from '@island.is/judicial-system/auth'
import type { SubpoenaType, User } from '@island.is/judicial-system/types'
import type { User } from '@island.is/judicial-system/types'

import { FileService } from './file.service'

Expand Down Expand Up @@ -201,6 +200,31 @@ export class LimitedAccessFileController {
)
}

@Get('serviceCertificate/:defendantId/:subpoenaId')
@Header('Content-Type', 'application/pdf')
getServiceCertificatePdf(
@Param('id') id: string,
@Param('defendantId') defendantId: string,
@CurrentHttpUser() user: User,
@Req() req: Request,
@Res() res: Response,
@Param('subpoenaId') subpoenaId?: string,
): Promise<Response> {
this.logger.debug(
`Getting service certificate for defendant ${defendantId} of case ${id} as a pdf document`,
)

return this.fileService.tryGetFile(
user.id,
AuditedAction.GET_SERVICE_CERTIFICATE_PDF,
id,
`limitedAccess/defendant/${defendantId}/subpoena/${subpoenaId}/serviceCertificate`,
req,
res,
'pdf',
)
}

@Get('allFiles')
@Header('Content-Type', 'application/zip')
async getAllFiles(
Expand Down
1 change: 1 addition & 0 deletions apps/judicial-system/backend/src/app/formatters/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,4 @@ export { createCaseFilesRecord } from './caseFilesRecordPdf'
export { createIndictment } from './indictmentPdf'
export { createConfirmedPdf } from './confirmedPdf'
export { createSubpoena } from './subpoenaPdf'
export { createServiceCertificate } from './serviceCertificatePdf'
Original file line number Diff line number Diff line change
Expand Up @@ -470,6 +470,14 @@ export const addMediumText = (
addText(doc, mediumFontSize, text, font)
}

export const addMediumCenteredText = (
doc: PDFKit.PDFDocument,
text: string,
font?: string,
) => {
addAlignedText(doc, mediumFontSize, text, 'center', font)
}

export const addNormalPlusText = (
doc: PDFKit.PDFDocument,
text: string,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
import PDFDocument from 'pdfkit'

import { FormatMessage } from '@island.is/cms-translations'

import {
capitalize,
formatDate,
formatDOB,
getWordByGender,
Word,
} from '@island.is/judicial-system/formatters'
import { ServiceStatus, SubpoenaType } from '@island.is/judicial-system/types'

import { serviceCertificate as strings } from '../messages'
import { Case } from '../modules/case'
import { Defendant } from '../modules/defendant'
import { Subpoena } from '../modules/subpoena'
import {
addEmptyLines,
addFooter,
addHugeHeading,
addMediumCenteredText,
addNormalCenteredText,
addNormalText,
setTitle,
} from './pdfHelpers'

const getSubpoenaType = (subpoenaType?: SubpoenaType): string => {
switch (subpoenaType) {
case SubpoenaType.ABSENCE:
return 'Útivistarfyrirkall'
case SubpoenaType.ARREST:
return 'Handtökufyrirkall'
default:
// Should never happen
return 'Ekki skráð'
}
}
oddsson marked this conversation as resolved.
Show resolved Hide resolved

export const createServiceCertificate = (
theCase: Case,
defendant: Defendant,
subpoena: Subpoena,
formatMessage: FormatMessage,
): Promise<Buffer> => {
const doc = new PDFDocument({
size: 'A4',
margins: {
top: 40,
bottom: 60,
left: 50,
right: 50,
},
bufferPages: true,
})

const sinc: Buffer[] = []

doc.on('data', (chunk) => sinc.push(chunk))

setTitle(doc, formatMessage(strings.title))

addHugeHeading(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)

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

addEmptyLines(doc)

addNormalText(doc, 'Birtingaraðili: ', 'Times-Bold', true)
addNormalText(
doc,
subpoena.serviceStatus === ServiceStatus.ELECTRONICALLY
? 'Rafrænt pósthólf island.is'
: subpoena.servedBy || '',
'Times-Roman',
)

if (subpoena.serviceStatus !== ServiceStatus.ELECTRONICALLY) {
addNormalText(doc, 'Athugasemd: ', 'Times-Bold', true)
addNormalText(
doc,
subpoena.serviceStatus === ServiceStatus.DEFENDER
? `Birt fyrir verjanda ${
defendant.defenderName ? `- ${defendant.defenderName}` : ''
}`
: subpoena.comment || '',
'Times-Roman',
)
}

addEmptyLines(doc, 2)

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

addEmptyLines(doc, 2)

addNormalText(doc, 'Ákærandi: ', 'Times-Bold', true)
addNormalText(
doc,
theCase.prosecutor?.institution
? theCase.prosecutor.institution.name
: 'Ekki skráður',
'Times-Roman',
)

addNormalText(doc, 'Dómari: ', 'Times-Bold', true)
addNormalText(
doc,
theCase.judge ? theCase.judge.name : 'Ekki skráður',
'Times-Roman',
)

addEmptyLines(doc)

addNormalText(doc, 'Þingfesting: ', 'Times-Bold', true)
addNormalText(
doc,
formatDate(
subpoena.arraignmentDate ? new Date(subpoena.arraignmentDate) : null,
'Pp',
) || 'Ekki skráð',
'Times-Roman',
)

addNormalText(doc, 'Staður: ', 'Times-Bold', true)
addNormalText(doc, subpoena.location || 'Ekki skráður', 'Times-Roman')

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

addFooter(doc)
doc.end()

return new Promise<Buffer>((resolve) =>
doc.on('end', () => resolve(Buffer.concat(sinc))),
)
}
1 change: 1 addition & 0 deletions apps/judicial-system/backend/src/app/messages/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ export { courtUpload } from './courtUpload'
export { caseFilesRecord } from './pdfCaseFilesRecord'
export { indictment } from './pdfIndictment'
export { subpoena } from './pdfSubpoena'
export { serviceCertificate } from './pdfServiceCertificate'
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { defineMessage } from '@formatjs/intl'

export const serviceCertificate = {
title: defineMessage({
id: 'judicial.system.backend:pdf.service_certificate.title',
defaultMessage: 'Birtingarvottorð',
description: 'Notaður sem titill á birtingarvottorði.',
}),
}
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,7 @@ export const defenderGeneratedPdfRule: RolesRule = {
const user: User = request.user
const theCase: Case = request.case

// Deny if something is missing - shuould never happen
// Deny if something is missing - should never happen
if (!user || !theCase) {
return false
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import {
Confirmation,
createCaseFilesRecord,
createIndictment,
createServiceCertificate,
createSubpoena,
getCourtRecordPdfAsBuffer,
getCustodyNoticePdfAsBuffer,
Expand Down Expand Up @@ -355,4 +356,21 @@ export class PdfService {

return generatedPdf
}

async getServiceCertificatePdf(
theCase: Case,
defendant: Defendant,
subpoena: Subpoena,
): Promise<Buffer> {
await this.refreshFormatMessage()

const generatedPdf = await createServiceCertificate(
theCase,
defendant,
subpoena,
this.formatMessage,
)

return generatedPdf
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
Get,
Header,
Inject,
InternalServerErrorException,
Param,
Res,
UseGuards,
Expand Down Expand Up @@ -82,4 +83,38 @@ export class LimitedAccessSubpoenaController {

res.end(pdf)
}

@RolesRules(defenderGeneratedPdfRule)
@Get('serviceCertificate')
@Header('Content-Type', 'application/pdf')
@ApiOkResponse({
content: { 'application/pdf': {} },
description:
'Gets the service certificate for a given defendant as a pdf document',
})
async getServiceCertificatePdf(
@Param('caseId') caseId: string,
@Param('defendantId') defendantId: string,
@Param('subpoenaId') subpoenaId: string,
@CurrentCase() theCase: Case,
@CurrentDefendant() defendant: Defendant,
@CurrentSubpoena() subpoena: Subpoena,
@Res() res: Response,
): Promise<void> {
this.logger.debug(
`Getting service certificate for defendant ${defendantId} in subpoena ${subpoenaId} of case ${caseId} as a pdf document`,
)

if (!subpoena) {
oddsson marked this conversation as resolved.
Show resolved Hide resolved
throw new InternalServerErrorException('Missing subpoena')
}

const pdf = await this.pdfService.getServiceCertificatePdf(
theCase,
defendant,
subpoena,
)

res.end(pdf)
}
}
Loading
Loading