Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/BladimirGS/judicial-backend/llms.txt

Use this file to discover all available pages before exploring further.

The Judicial Backend generates court-ready PDF documents using pdfmake. All PDF infrastructure lives in src/shared/pdf/ and is consumed by module-level report classes that extend PdfBuilder<T>. The shared layer handles font loading, page layout, institutional headers and footers, and the full pdfmake document definition — module reports only implement construirContenido() to describe the document body specific to their data.

PdfPrinter

src/shared/pdf/pdf.printer.ts — class that loads the Roboto font family from public/fonts/ at module load time and exposes a single imprimir() method.

PdfBuilder

src/shared/pdf/pdf.builder.ts — abstract class that assembles the full TDocumentDefinitions object: page size, margins, institutional header, footer with pagination, and merged styles.

pdf.helpers

src/shared/pdf/pdf.helpers.ts — utility functions for formatting values and constructing typed TableCell objects used throughout report tables.

pdf.styles

src/shared/pdf/pdf.styles.ts — global pdfmake StyleDictionary and the COLORES palette consumed by helpers and builder styles.

Font Loading — PdfPrinter

PdfPrinter resolves font files relative to process.cwd() and registers them with pdfmake before any report is built.
// src/shared/pdf/pdf.printer.ts
import path from 'path';
import pdfmake from 'pdfmake';
import type { TDocumentDefinitions } from 'pdfmake/interfaces';

const fontsPath = path.join(process.cwd(), 'public', 'fonts');

const fuentes = {
  Roboto: {
    normal:      path.join(fontsPath, 'Roboto-Regular.ttf'),
    bold:        path.join(fontsPath, 'Roboto-Medium.ttf'),
    italics:     path.join(fontsPath, 'Roboto-Italic.ttf'),
    bolditalics: path.join(fontsPath, 'Roboto-MediumItalic.ttf'),
  },
};

pdfmake.addFonts(fuentes);

export class PdfPrinter {
  async imprimir(definicion: TDocumentDefinitions): Promise<Buffer>
}
imprimir() calls pdfmake.createPdf(definicion).getBuffer() and returns the result as a Promise<Buffer>. No temporary files are written to disk.

Bundled font files

The following Roboto variants are present in public/fonts/:
Filepdfmake key
Roboto-Regular.ttfnormal
Roboto-Medium.ttfbold
Roboto-Italic.ttfitalics
Roboto-MediumItalic.ttfbolditalics
Roboto-Black.ttf— (available, not mapped)
Roboto-BlackItalic.ttf
Roboto-Bold.ttf
Roboto-BoldItalic.ttf
Roboto-Light.ttf
Roboto-LightItalic.ttf
Roboto-Thin.ttf
Roboto-ThinItalic.ttf
pdfmake requires exactly the four keys normal, bold, italics, and bolditalics. The extra Roboto variants are available on disk and can be added to the fuentes map if a future report needs Black or Light weights.

Styles — pdf.styles.ts

Styles are shared across every report through estilosBase (a pdfmake StyleDictionary) and the COLORES palette.
// src/shared/pdf/pdf.styles.ts
export const COLORES = {
  grisHeader:    '#d9d9d9',
  grisSubheader: '#f2f2f2',
  grisPar:       '#f9f9f9',
  azulHeader:    '#9BC2E6',
  azulDato:      '#DDEBF7',
} as const;

export const estilosBase: StyleDictionary = {
  tituloPrincipal: { bold: true, alignment: 'center' },
  tituloSeccion:   { bold: true, alignment: 'center' },
  etiquetaSeccion: { bold: true },
  encabezadoCol:   { bold: true, alignment: 'center' },
  textoCelda:      { alignment: 'center' },
  encabezadoSub:   { bold: true, alignment: 'center' },
};
PdfBuilder.generarDefinicion() merges estilosBase with any caller-supplied estilos via OpcionesDocumento.estilos, so module reports can extend or override styles without touching the shared file.

Helpers — pdf.helpers.ts

pdf.helpers.ts exports typed TableCell factories and layout constants used everywhere a report builds a table.
// Format any value to a readable string
export const fmt = (val: unknown): string

// Typed empty cell — required to fill colSpan gaps
export const celdaVacia = (): TableCell

// Table layouts
export const layoutAnidado: {
  hLineWidth: () => number;  // 0.5
  vLineWidth: () => number;  // 0.5
  hLineColor: () => string;  // '#aaaaaa'
  vLineColor: () => string;  // '#aaaaaa'
}

// Pre-styled TableCell factories
export const celdaEncabezado    = (texto: string): TableCell
export const celdaSubEncabezado = (texto: string): TableCell
export const celdaDato          = (val: unknown, negrita?: boolean): TableCell

// Zebra-striped layout for main report tables
export const layoutTablaReporte: {
  ...layoutAnidado,
  fillColor:     (rowIndex: number) => string | null;  // grisPar on even rows > 0
  paddingLeft:   () => number;   // 0
  paddingRight:  () => number;   // 0
  paddingTop:    () => number;   // 3
  paddingBottom: () => number;   // 3
}

// Header layout — pdfmake built-in 'noBorders'
export const layoutSinBordes: 'noBorders'
fmt() handles the following cases:
Input typeOutput
null / undefined''
DatetoLocaleDateString('es-MX')
boolean'SÍ' or 'NO'
anything elseString(val)

PdfBuilder — Abstract Class

PdfBuilder<TDato> is the abstract base for all PDF reports. It builds the complete TDocumentDefinitions object and delegates only the body content to subclasses.

Constructor

export interface OpcionesDocumento {
  titulo: string;
  subtitulo?: string;
  estilos?: StyleDictionary;
}

constructor(protected readonly opciones: OpcionesDocumento)

Public method

generarDefinicion(datos: TDato[]): TDocumentDefinitions
Returns a complete pdfmake document definition with:
  • defaultStyle: { fontSize: 6 }
  • pageSize: 'LETTER'
  • pageMargins: [40, 80, 40, 40]
  • A shared institutional header on every page
  • A footer on every page with expedition date, total records, and page number
  • content produced by construirContenido(datos)
  • Merged styles from estilosBase + opciones.estilos

Abstract method (implement in subclasses)

protected abstract construirContenido(datos: TDato[]): Content[]

Protected utility (available to subclasses)

protected etiquetaSeccion(texto: string): Content
// Returns a bold section label with margin [0, 8, 0, 4]

Institutional Header

The header is a full-width table with three columns (25% | 50% | 25%):
  • Left cell: public/assets/logo-1.png at 60 px width (falls back to [LOGO] text if the file is absent)
  • Centre cell: Stack of three lines — “PODER JUDICIAL DEL ESTADO DE OAXACA”, “OFICIALÍA DE PARTES COMÚN DE 2DA INSTANCIA”, and opciones.titulo
  • Right cell: public/assets/logo-2.png at 60 px width (falls back to [CJO])
The header table uses layoutSinBordes so no grid lines appear. The footer is a two-column row rendered at [40, 10, 40, 0] margins:
  • Left: Expedition date (toLocaleString('es-MX')) and total record count
  • Right: Página N de M

Module-Level Reports

ApelacionPdfReport (búsqueda completa)

Located at src/modules/busqueda/reports/pdf/apelacion-pdf.report.ts.
export class ApelacionPdfReport extends PdfBuilder<ApelacionDTO> {
  constructor() {
    super({ titulo: 'REPORTE DE APELACIONES' });
  }

  protected construirContenido(apelaciones: ApelacionDTO[]): Content[]
}
The report groups apelaciones by sala. Each sala produces a section label (etiquetaSeccion) followed by a table built with construirTablaSala(). The second and subsequent salas are preceded by pageBreak: 'before'. The main table uses 13 columns (ANCHOS_COLS = [45, 35, 35, 45, 40, 35, 45, 45, 40, 28, 60, 35, 40]) and renders three row types:
Row typeMethodContents
Header rowfilaEncabezado()13 celdaEncabezado() cells
Data rowfilaDatos(apelacion)13 celdaDato() cells
Nested rowfilaAnidada(apelacion)Cols 1–4 blank, col 5 spans 9 and contains sub-tables
The nested row embeds up to two inner tables using layoutAnidado:
  • Partes table (widths [60, 118, 70, 41, 41]): Parte, Nombre, Dirección, Menor de Edad, Sexo
  • Anexos table (widths [60, 118, 70, 90]): Cantidad, Anexo, Es Valor, Monto
Both sub-tables use celdaSubEncabezado() for their header rows.

Export Endpoints

All export routes are protected by the JWT protect middleware.
MethodPathReport classDescription
GET/api/busquedas/exportar-pdfApelacionPdfReportFull apelaciones, grouped by sala
GET/api/busquedas/plano/exportar-pdfApelacionPlanoPdfReportFlat apelaciones
GET/api/busquedas/historico/exportar-pdfApelacionHistoricoPdfReportHistorical apelaciones

HTTP Response Headers

Content-Type: application/pdf
Content-Disposition: attachment; filename="reporte.pdf"

Example — download with curl

curl -o reporte.pdf \
  'http://localhost:4000/api/busquedas/exportar-pdf?idSala=1' \
  -H 'Authorization: Bearer <token>'
# Flat (plano) variant
curl -o reporte.pdf \
  'http://localhost:4000/api/busquedas/plano/exportar-pdf?idSala=1' \
  -H 'Authorization: Bearer <token>'

Data Flow

The sequence from HTTP request to downloaded PDF:
GET /api/busquedas/exportar-pdf?idSala=1


protect middleware  (JWT RS256 verify)


BusquedaApelacionController.exportarPdf(filtros)


BusquedaApelacionService.exportarPdf(filtros)
  ├─► BusquedaApelacionRepository.buscar(filtros)  → ApelacionDTO[]
  ├─► new ApelacionPdfReport().generarDefinicion(apelaciones)  → TDocumentDefinitions
  └─► new PdfPrinter().imprimir(definicion)  → Promise<Buffer>


res.setHeader('Content-Type', 'application/pdf')
res.setHeader('Content-Disposition', 'attachment; filename="reporte.pdf"')
res.send(buffer)
PdfBuilder and PdfPrinter are intentionally separate. PdfBuilder knows what the document looks like; PdfPrinter only knows how to render it. This lets you unit-test generarDefinicion() by inspecting the returned object without triggering font loading or PDF serialization.
If a logo file is missing from public/assets/, the header gracefully falls back to a plain text placeholder ([LOGO] or [CJO]). This means the server will start and generate valid PDFs even in environments where the asset files have not been deployed yet.

Build docs developers (and LLMs) love