first commit

This commit is contained in:
martin
2025-10-08 22:29:05 -03:00
commit b3ebaed097
4 changed files with 2630 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
node_modules/

170
index.js Normal file
View File

@@ -0,0 +1,170 @@
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();
})

2440
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

19
package.json Normal file
View File

@@ -0,0 +1,19 @@
{
"name": "controlador_impresoras_ticket",
"version": "1.0.0",
"description": "",
"main": "index.js",
"type": "module",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"@thiagoelg/node-printer": "^0.6.2",
"cors": "^2.8.5",
"express": "^5.1.0",
"iconv": "^3.0.1",
"nodemon": "^3.1.10"
}
}