139 lines
4.1 KiB
JavaScript
139 lines
4.1 KiB
JavaScript
// 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");
|
|
}) |