import express from 'express' import cors from 'cors' import printer from '@thiagoelg/node-printer' import iconv from "iconv-lite"; const ESC = "\x1B" const GS = "\x1D" const defaultPrinter = printer.getDefaultPrinterName() function init() { return ESC + "@"; } function cut() { return GS + "V" + "\x41" + "\x00"; } function line(n = 1) { return "\n".repeat(n); } function boldOn() { return ESC + "E" + "\x01"; } function boldOff() { return ESC + "E" + "\x00"; } function center() { return ESC + "a" + "\x01"; } function left() { return ESC + "a" + "\x00"; } function right() { return ESC + "a" + "\x02"; } function printTicketDataRaw(data) { printer.printDirect({ data, printer: defaultPrinter, type: "RAW", success: jobID => console.log("Trabajo enviado:", jobID), error: err => console.error("Error:", err) }) } const app = express() app.use(cors()) app.use(express.json()) const max = 30; app.get('/printers', (req, res) => { res.send(200) }) app.post('/digitalpowerstock/ticket/venta', (req, res) => { const { nombre, direccion, cp, localidad, provincia, pais, telefono, mensaje, comprobante, cliente, fecha, vendedor, productos, total } = req.body; ticketDPSTock(nombre, direccion, cp, localidad, provincia, pais, telefono, mensaje, comprobante, cliente, fecha, vendedor, productos, total) res.send(200) }) export function removeAccents(str) { return String(str) .normalize('NFD') // descompone letras + diacríticos .replace(/[\u0300-\u036f]/g, ''); // elimina marcas diacríticas } async function ticketDPSTock( nombre, direccion, cp, localidad, provincia, pais, telefono, mensaje, comprobante, cliente, fecha, vendedor, productos, total ) { try { const products = JSON.parse(productos); //const products = productos; let ticket = ""; // Encabezado ticket += init(); ticket += center(); ticket += boldOn() + nombre + boldOff() + line(); ticket += direccion + line(); ticket += `(${cp}) ${localidad}` + line(); ticket += `${provincia} ${pais}` + line(); ticket += telefono + line(); ticket += mensaje + line(3); // Datos comprobante ticket += left(); ticket += `Nro comprobante: #${comprobante}` + line(); ticket += `Cliente: ${cliente}` + line(); ticket += `Fecha: ${fecha}` + line(); ticket += `Vendedor: ${vendedor}` + line(2); // Productos const max = 20; // ancho máximo de nombre antes de cortar for (const producto of products) { const nombre = removeAccents(producto.nombre); if (producto.nombre.length > max) { ticket += left() + `${producto.cantidad} x ${nombre}` + line(); ticket += right() + `$${producto.precio}` + line(); } else { ticket += left() + `${producto.cantidad} x ${nombre} - $${producto.precio}` + line(); } if (producto.observacion) { ticket += left() + `Observacion: ${producto.observacion}` + line(); } ticket += line(); } // Total ticket += line(2); ticket += left() + `Total: $${total}` + line(3); // Corte ticket += cut(); // Convertir a CP850 (acentos correctos) const data = iconv.encode(ticket, "CP850"); // Enviar a la impresora printer.printDirect({ data, printer: printer.getDefaultPrinterName(), type: "RAW", success: jobID => console.log("Trabajo enviado:", jobID), error: err => console.error("Error:", err) }); } catch (error) { console.error("Error al imprimir:", error); } } async function test() { /* const ticket = init() + boldOn() + "Ticket de prueba" + boldOff() + line(2) + "Cliente: Juan Perez" + line() + "Ticket de prueba" + line(30) + cut(); printTicketDataRaw(Buffer.from(ticket, 'ascii')) */ return; const ids = findPrinterIds() if (!ids) { console.error('No se pudo detectar la impresora USB de manera automatica'); process.exit(1) } const { vendor, product } = ids; console.log(`Usando vendor=0x${vendor?.toString(16)} product=0x${product?.toString(16)}`); const device = new escpos.USB(vendor, product); const printer = new escpos.Printer(device); await new Promise((resolve, reject) => { device.open((err) => { if (err) return reject(err) printer.encode('UTF-8') .text(' o ') .text(' /|\\ ') .text(' / \\ ') .feed(3) .cut() .close() resolve() }) }) } app.listen(3030, () => { console.log("Servicio de impresion de tickets inicializado en el puerto 3030"); test(); })