Documentación Técnica: Módulo de Impresión
| Campo |
Valor |
| Módulo |
print |
| Ubicación |
src/modules/print/ |
| Propósito |
Impresión de documentos de SAP B1 mediante Crystal Reports y PrintNode |
| Fecha |
2026-03-24 |
| Estado |
En desarrollo |
Patrones de Diseño Utilizados
| Patrón |
Propósito |
| Strategy |
Diferentes algoritmos de impresión por entidad |
| Template Method |
Esqueleto común con pasos específicos por entidad |
| Factory |
Crear la strategy correcta según entidad |
| Observer |
Notificar eventos de impresión (logs, métricas) |
| Facade |
Ocultar complejidad de SAP + PrintNode |
Estructura de Carpetas
src/modules/print/
│
├── interfaces/
│ ├── index.ts
│ ├── crystal-param.interface.ts
│ ├── print-strategy.interface.ts
│ └── print-result.interface.ts
│
├── strategies/
│ ├── index.ts
│ ├── base-print.strategy.ts # Template Method
│ ├── order-print.strategy.ts
│ └── invoice-print.strategy.ts
│
├── observers/
│ ├── index.ts
│ ├── print-observer.interface.ts
│ └── logging-print.observer.ts
│
├── dto/
│ ├── print-request.dto.ts
│ └── print-response.dto.ts
│
├── print-strategy.registry.ts # Factory
├── print.service.ts # Facade + Observer Subject
├── print.controller.ts
└── print.module.ts
Interfaces
CrystalParam
Representa un parámetro para Crystal Reports de SAP.
| Propiedad |
Tipo |
Descripción |
name |
string |
Nombre del parámetro (ej: "Dockey@") |
type |
string |
Tipo de dato ("xsd:string" | "xsd:decimal" | "xsd:date") |
value |
string[][] |
Valor en formato SAP |
PrintStrategy
Contrato que todas las strategies de impresión deben cumplir.
Propiedades:
| Propiedad |
Tipo |
Descripción |
entity |
string |
Identificador único ("order", "invoice") |
layoutCode |
string |
Código Crystal Report ("RCRI0026") |
Métodos:
| Método |
Retorno |
Descripción |
validate(params) |
void |
Valida parámetros requeridos |
buildCrystalParams(params) |
CrystalParam[] |
Construye params para SAP |
PrintObserver
Contrato para observadores de eventos de impresión.
| Método |
Descripción |
onPrintStarted(entity, params) |
Llamado al iniciar impresión |
onPrintCompleted(entity, jobId) |
Llamado al completar exitosamente |
onPrintFailed(entity, error) |
Llamado al fallar |
PrintResult
Resultado de una operación de impresión.
| Propiedad |
Tipo |
Descripción |
success |
boolean |
Si fue exitoso |
printJobId |
number |
ID del trabajo en PrintNode |
message |
string |
Mensaje descriptivo |
Clases
BasePrintStrategy (abstract)
| Campo |
Valor |
| Patrón |
Template Method |
| Ubicación |
strategies/base-print.strategy.ts |
| Propósito |
Define el esqueleto del algoritmo de preparación para impresión |
Propiedades abstractas:
entity: string
layoutCode: string
Template Method:
prepareForPrint(params): CrystalParam[]
│
├──► commonValidation(params) [HOOK - puede sobrescribirse]
├──► validate(params) [ABSTRACT - debe implementarse]
├──► transformParams(params) [HOOK - puede sobrescribirse]
└──► buildCrystalParams(params) [ABSTRACT - debe implementarse]
Helpers protegidos:
| Método |
Retorno |
Descripción |
createStringParam(name, value) |
CrystalParam |
Crea param tipo string |
createDateParam(name, value) |
CrystalParam |
Crea param tipo date |
createDecimalParam(name, value) |
CrystalParam |
Crea param tipo decimal |
OrderPrintStrategy
| Campo |
Valor |
| Extiende |
BasePrintStrategy |
| Ubicación |
strategies/order-print.strategy.ts |
| Propósito |
Impresión de Pedidos de Venta |
Configuración:
| Propiedad |
Valor |
entity |
"order" |
layoutCode |
REPORT_LAYOUT_ORDER (.env) |
Parámetros requeridos:
| Parámetro |
Tipo |
Obligatorio |
docEntry |
number |
Sí |
docNum |
number |
Sí |
Parámetros Crystal generados:
| Crystal Param |
Origen |
Dockey@ |
params.docEntry |
FolioNum@ |
params.docNum |
InvoicePrintStrategy
| Campo |
Valor |
| Extiende |
BasePrintStrategy |
| Ubicación |
strategies/invoice-print.strategy.ts |
| Propósito |
Impresión de Facturas |
Configuración:
| Propiedad |
Valor |
entity |
"invoice" |
layoutCode |
REPORT_LAYOUT_INVOICE (.env) |
Parámetros requeridos:
| Parámetro |
Tipo |
Obligatorio |
docEntry |
number |
Sí |
docNum |
number |
Sí |
Parámetros Crystal generados:
| Crystal Param |
Origen |
Dockey@ |
params.docEntry |
FolioNum@ |
params.docNum |
PrintStrategyRegistry
| Campo |
Valor |
| Patrón |
Factory |
| Ubicación |
print-strategy.registry.ts |
| Propósito |
Mapea entity → Strategy y las instancia |
Constructor:
- Recibe todas las strategies por inyección de dependencias
- Las registra en un
Map<string, PrintStrategy> interno
Métodos:
| Método |
Retorno |
Descripción |
get(entity) |
PrintStrategy |
Retorna strategy o lanza error |
getAvailableEntities() |
string[] |
Lista entidades soportadas |
LoggingPrintObserver
| Campo |
Valor |
| Implementa |
PrintObserver |
| Ubicación |
observers/logging-print.observer.ts |
| Propósito |
Registra eventos de impresión en el log |
Comportamiento:
| Método |
Log generado |
onPrintStarted |
[START] entity: params |
onPrintCompleted |
[OK] entity: JobId=xxx |
onPrintFailed |
[FAIL] entity: error |
PrintService
| Campo |
Valor |
| Patrón |
Facade + Observer Subject |
| Ubicación |
print.service.ts |
| Propósito |
Orquesta todo el proceso de impresión |
Dependencias:
| Dependencia |
Propósito |
PrintStrategyRegistry |
Obtener strategy según entidad |
ReportsService |
Generar PDF con SAP API Gateway |
PrintNodeService |
Enviar a impresora física |
Métodos:
| Método |
Retorno |
Descripción |
print(entity, params, printerId) |
Promise<PrintResult> |
Ejecuta impresión completa |
addObserver(observer) |
void |
Registrar observer |
removeObserver(observer) |
void |
Remover observer |
getAvailableEntities() |
string[] |
Lista entidades |
Flujo de print():
1. Notificar observers: onPrintStarted()
2. registry.get(entity) → obtener strategy
3. strategy.validate(params) → validar
4. strategy.buildCrystalParams() → construir params
5. reportsService.exportToPdf() → generar PDF
6. printNodeService.print(printerId, pdf) → enviar a impresora
7. Notificar observers: onPrintCompleted() | onPrintFailed()
8. return PrintResult
PrintController
| Campo |
Valor |
| Ubicación |
print.controller.ts |
| Propósito |
Expone endpoints REST |
Endpoints:
| Método |
Ruta |
Descripción |
POST |
/api/print |
Imprimir documento |
GET |
/api/print/entities |
Listar entidades disponibles |
GET |
/api/print/printers |
Listar impresoras PrintNode |
DTOs
PrintRequestDto
Validación de entrada para POST /api/print
| Campo |
Tipo |
Requerido |
Descripción |
entity |
string |
Sí |
"order" | "invoice" | ... |
params |
object |
Sí |
{ docEntry, docNum, ... } |
printerId |
number |
Sí |
ID de impresora en PrintNode |
PrintResponseDto
Respuesta de POST /api/print
| Campo |
Tipo |
Descripción |
success |
boolean |
Si fue exitoso |
printJobId |
number |
ID del trabajo |
message |
string |
Mensaje descriptivo |
printerName |
string? |
Nombre de la impresora |
Flujo de Ejecución
┌─────────────────────────────────────────────────────────────────────┐
│ POST /api/print │
│ { entity: "order", params: { docEntry, docNum } } │
└───────────────────────────────┬─────────────────────────────────────┘
│
▼
┌───────────────────────────────────────────────────────────────────┐
│ PrintController │
│ print(@Body() dto) │
└───────────────────────────────┬───────────────────────────────────┘
│
▼
┌───────────────────────────────────────────────────────────────────┐
│ PrintService │
│ │
│ 1. Notificar observers: onPrintStarted() │
│ │ │
│ 2. registry.get("order") ─────┼──────────────────────┐ │
│ │ ▼ │
│ │ ┌─────────────────────┐ │
│ │ │ PrintStrategyRegistry│ │
│ │ │ (Factory Pattern) │ │
│ │ └──────────┬──────────┘ │
│ │ │ │
│ │ ┌──────────▼──────────┐ │
│ │ │ OrderPrintStrategy │ │
│ │ │ (Template Method) │ │
│ 3. strategy.validate() ◄──────┼─────────┤ │ │
│ │ │ - validate() │ │
│ 4. strategy.buildCrystal() ◄──┼─────────┤ - buildCrystalParams│ │
│ │ └─────────────────────┘ │
│ │ │
│ 5. reportsService.exportPdf(layoutCode, crystalParams) │
│ │ │
│ ┌────────▼────────┐ │
│ │ SAP API Gateway │ │
│ │ (Puerto 60000) │ │
│ └────────┬────────┘ │
│ │ │
│ PDF base64 │
│ │ │
│ 6. printNodeService.print(printerId, pdf) │
│ │ │
│ ┌────────▼────────┐ │
│ │ PrintNode │ │
│ └────────┬────────┘ │
│ │ │
│ printJobId │
│ │ │
│ 7. Notificar observers: onPrintCompleted() │
│ │ │
│ 8. return { success, printJobId, message } │
└───────────────────────────────┬───────────────────────────────────┘
│
▼
Response al cliente
Configuración Requerida (.env)
# Layouts de Crystal Reports
REPORT_LAYOUT_ORDER=RCRI0026
REPORT_LAYOUT_INVOICE=RCRI0029
# PrintNode
PRINTNODE_API_KEY=xxxxx
Cómo Agregar Nueva Entidad
Paso 1: Crear Strategy
Crear archivo en strategies/nueva-entidad-print.strategy.ts:
- Extender
BasePrintStrategy
- Definir
entity y layoutCode
- Implementar
validate() y buildCrystalParams()
Paso 2: Registrar en Registry
En print-strategy.registry.ts:
- Inyectar nueva strategy en constructor
- Agregar
this.strategies.set(strategy.entity, strategy)
Paso 3: Configurar layout
En .env:
REPORT_LAYOUT_NUEVA_ENTIDAD=RCRI00XX
Dependencias Externas
| Servicio |
Puerto |
Función |
| SAP Service Layer |
50000 |
Config de usuario (impresoras) |
| SAP API Gateway |
60000 |
Generar PDF con Crystal |
| PrintNode |
HTTPS |
Enviar PDF a impresora física |
Historial de Cambios
| Fecha |
Autor |
Cambio |
| 2026-03-24 |
- |
Documentación inicial |
| 2026-03-24 |
- |
Eliminado displayName, se usa entity directamente |
| 2026-03-24 |
- |
printerId es obligatorio, eliminado printerType |