// Node version: 16.20.2 // Package json dependencies /* "dependencies": { "@thiagoelg/node-printer": "^0.6.2", "cors": "^2.8.5", "express": "^5.1.0", "iconv": "^3.0.1", "nodemon": "^3.1.10" } */ 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); } } app.listen(3030, () => { console.log("Servicio de impresion de tickets inicializado en el puerto 3030"); })