first commit
This commit is contained in:
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
node_modules/
|
||||
170
index.js
Normal file
170
index.js
Normal 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
2440
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
19
package.json
Normal file
19
package.json
Normal 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"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user