From 1d5838de6cdfa828d703978227c0b6320712a822 Mon Sep 17 00:00:00 2001 From: josedario87 Date: Tue, 25 Nov 2025 11:10:57 -0600 Subject: [PATCH] feat: Endpoints para imprimir templates y operaciones con variables MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - POST /api/print/template: Imprime un template guardado por ID con variables - POST /api/print/raw: Imprime operaciones arbitrarias con soporte de variables inline - Agregada función resolveVariables() en server/utils/templates.ts --- server/api/print/raw.post.ts | 87 ++++++++++++++++++++++++++ server/api/print/template.post.ts | 100 ++++++++++++++++++++++++++++++ server/utils/templates.ts | 15 +++++ 3 files changed, 202 insertions(+) create mode 100644 server/api/print/raw.post.ts create mode 100644 server/api/print/template.post.ts diff --git a/server/api/print/raw.post.ts b/server/api/print/raw.post.ts new file mode 100644 index 0000000..68c0185 --- /dev/null +++ b/server/api/print/raw.post.ts @@ -0,0 +1,87 @@ +// Endpoint para imprimir operaciones arbitrarias con variables inline +import { buildFromOperations } from '../../utils/eposBuilder' +import { buildSoapEnvelope, sendToPrinter, parsePrinterResponse } from '../../utils/printer' +import { getSelectedPrinter, getPrinterById } from '../../utils/printers' +import { resolveVariables, Operation } from '../../utils/templates' + +export default defineEventHandler(async (event) => { + try { + const body = await readBody(event) + + const { + operations, + variables = {}, + dryRun = false, + printerId + } = body as { + operations: Operation[] + variables?: Record + dryRun?: boolean + printerId?: string + } + + // Validar operations + if (!operations || !Array.isArray(operations) || operations.length === 0) { + return { + ok: false, + error: 'operations es requerido y debe ser un array no vacío' + } + } + + // Resolver variables en las operaciones + const resolvedOperations = resolveVariables(operations, variables) + + // Construir el XML + const inner = buildFromOperations(resolvedOperations) + const soap = buildSoapEnvelope(inner) + + // Si es dryRun, devolver sin enviar a la impresora + if (dryRun) { + return { + ok: true, + dryRun: true, + soap, + resolvedOperations + } + } + + // Obtener la impresora + let printer = printerId + ? await getPrinterById(printerId) + : await getSelectedPrinter() + + if (!printer) { + return { + ok: false, + error: 'No hay impresora configurada. Por favor, agrega una impresora primero.' + } + } + + // Enviar a la impresora + const result = await sendToPrinter( + soap, + printer.host, + printer.deviceId, + printer.timeout + ) + + // Parsear la respuesta + const { success, code } = parsePrinterResponse(result.data) + + return { + ok: success, + httpStatus: result.status, + code, + raw: result.data, + printerUsed: { + id: printer.id, + name: printer.name + } + } + } catch (err: any) { + return { + ok: false, + error: err.message + } + } +}) diff --git a/server/api/print/template.post.ts b/server/api/print/template.post.ts new file mode 100644 index 0000000..bfe1529 --- /dev/null +++ b/server/api/print/template.post.ts @@ -0,0 +1,100 @@ +// Endpoint para imprimir un template guardado con variables resueltas +import { buildFromOperations } from '../../utils/eposBuilder' +import { buildSoapEnvelope, sendToPrinter, parsePrinterResponse } from '../../utils/printer' +import { getSelectedPrinter, getPrinterById } from '../../utils/printers' +import { getTemplateById, resolveVariables } from '../../utils/templates' + +export default defineEventHandler(async (event) => { + try { + const body = await readBody(event) + + const { + templateId, + variables = {}, + dryRun = false, + printerId + } = body as { + templateId: string + variables?: Record + dryRun?: boolean + printerId?: string + } + + // Validar templateId + if (!templateId) { + return { + ok: false, + error: 'templateId es requerido' + } + } + + // Obtener el template + const template = await getTemplateById(templateId) + if (!template) { + return { + ok: false, + error: `Template no encontrado: ${templateId}` + } + } + + // Resolver variables en las operaciones + const resolvedOperations = resolveVariables(template.operations, variables) + + // Construir el XML + const inner = buildFromOperations(resolvedOperations) + const soap = buildSoapEnvelope(inner) + + // Si es dryRun, devolver sin enviar a la impresora + if (dryRun) { + return { + ok: true, + dryRun: true, + templateId: template.id, + templateName: template.name, + soap, + resolvedOperations + } + } + + // Obtener la impresora + let printer = printerId + ? await getPrinterById(printerId) + : await getSelectedPrinter() + + if (!printer) { + return { + ok: false, + error: 'No hay impresora configurada. Por favor, agrega una impresora primero.' + } + } + + // Enviar a la impresora + const result = await sendToPrinter( + soap, + printer.host, + printer.deviceId, + printer.timeout + ) + + // Parsear la respuesta + const { success, code } = parsePrinterResponse(result.data) + + return { + ok: success, + templateId: template.id, + templateName: template.name, + httpStatus: result.status, + code, + raw: result.data, + printerUsed: { + id: printer.id, + name: printer.name + } + } + } catch (err: any) { + return { + ok: false, + error: err.message + } + } +}) diff --git a/server/utils/templates.ts b/server/utils/templates.ts index 9e059b6..e38423f 100644 --- a/server/utils/templates.ts +++ b/server/utils/templates.ts @@ -55,6 +55,21 @@ export function extractVariables(operations: Operation[]): TemplateVariable[] { return Array.from(variablesMap.values()) } +// Resolver variables en operaciones reemplazando {{nombre}} con valores +export function resolveVariables( + operations: Operation[], + values: Record = {} +): Operation[] { + return JSON.parse(JSON.stringify(operations)).map((op: Operation) => { + for (const [key, val] of Object.entries(op)) { + if (typeof val === 'string') { + op[key] = val.replace(VARIABLE_REGEX, (_, name) => values[name] ?? '') + } + } + return op + }) +} + export interface TemplatesStore { templates: PrintTemplate[] }