feat: Endpoints para imprimir templates y operaciones con variables
All checks were successful
build-and-deploy / build-and-deploy (push) Successful in 36s

- 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
This commit is contained in:
2025-11-25 11:10:57 -06:00
parent 845c89be04
commit 1d5838de6c
3 changed files with 202 additions and 0 deletions

View File

@@ -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<string, string>
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
}
}
})

View File

@@ -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<string, string>
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
}
}
})

View File

@@ -55,6 +55,21 @@ export function extractVariables(operations: Operation[]): TemplateVariable[] {
return Array.from(variablesMap.values()) return Array.from(variablesMap.values())
} }
// Resolver variables en operaciones reemplazando {{nombre}} con valores
export function resolveVariables(
operations: Operation[],
values: Record<string, string> = {}
): 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 { export interface TemplatesStore {
templates: PrintTemplate[] templates: PrintTemplate[]
} }