Add API routes for articulos, catalogo, config, and print

Create four route modules:
- articulos.js: global article search across conceptos/facturas
- catalogo.js: catalog CRUD with Excel import via multer
- config.js: key-value configuration get/put
- print.js: ZPL label generation and Zebra printer dispatch

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
consultoria-as
2026-02-17 06:33:59 +00:00
parent c341726dda
commit bec6599c5f
4 changed files with 140 additions and 0 deletions

27
src/routes/articulos.js Normal file
View File

@@ -0,0 +1,27 @@
const { Router } = require('express');
function articulosRouter(db) {
const router = Router();
router.get('/', (req, res) => {
const { q } = req.query;
if (!q || q.length < 2) return res.json([]);
const articulos = db.prepare(`
SELECT c.*, f.nombre_emisor, f.fecha, f.uuid as factura_uuid
FROM conceptos c
JOIN facturas f ON f.id = c.factura_id
WHERE c.descripcion LIKE ?
OR c.no_identificacion LIKE ?
OR c.intercambio LIKE ?
ORDER BY f.fecha DESC
LIMIT 200
`).all(`%${q}%`, `%${q}%`, `%${q}%`);
res.json(articulos);
});
return router;
}
module.exports = { articulosRouter };

47
src/routes/catalogo.js Normal file
View File

@@ -0,0 +1,47 @@
const { Router } = require('express');
const multer = require('multer');
const path = require('path');
const { importCatalog, searchCatalog, updateIntercambio } = require('../services/catalog-service');
const upload = multer({ dest: path.join(__dirname, '../../data/uploads/') });
function catalogoRouter(db) {
const router = Router();
router.get('/', (req, res) => {
const { q } = req.query;
if (!q) {
const all = db.prepare('SELECT * FROM catalogo_intercambios ORDER BY no_parte_proveedor LIMIT 500').all();
return res.json(all);
}
res.json(searchCatalog(db, q));
});
router.post('/import', upload.single('file'), (req, res) => {
if (!req.file) return res.status(400).json({ error: 'No file uploaded' });
try {
const result = importCatalog(db, req.file.path);
res.json({ success: true, imported: result.imported });
} catch (err) {
res.status(500).json({ error: err.message });
}
});
router.put('/:noParteProveedor', (req, res) => {
const { noParteIntercambio } = req.body;
updateIntercambio(db, req.params.noParteProveedor, noParteIntercambio);
res.json({ success: true });
});
router.post('/', (req, res) => {
const { no_parte_proveedor, no_parte_intercambio } = req.body;
db.prepare(
'INSERT OR REPLACE INTO catalogo_intercambios (no_parte_proveedor, no_parte_intercambio) VALUES (?, ?)'
).run(no_parte_proveedor, no_parte_intercambio);
res.json({ success: true });
});
return router;
}
module.exports = { catalogoRouter };

29
src/routes/config.js Normal file
View File

@@ -0,0 +1,29 @@
const { Router } = require('express');
function configRouter(db) {
const router = Router();
router.get('/', (req, res) => {
const rows = db.prepare('SELECT * FROM configuracion').all();
const config = {};
for (const row of rows) {
config[row.clave] = row.valor;
}
res.json(config);
});
router.put('/', (req, res) => {
const update = db.prepare('INSERT OR REPLACE INTO configuracion (clave, valor) VALUES (?, ?)');
const transaction = db.transaction(() => {
for (const [clave, valor] of Object.entries(req.body)) {
update.run(clave, valor);
}
});
transaction();
res.json({ success: true });
});
return router;
}
module.exports = { configRouter };

37
src/routes/print.js Normal file
View File

@@ -0,0 +1,37 @@
const { Router } = require('express');
const { generateLabel } = require('../services/zpl-generator');
const { printZpl } = require('../services/print-service');
function printRouter(db) {
const router = Router();
router.post('/', async (req, res) => {
const { articles } = req.body;
if (!articles || !articles.length) {
return res.status(400).json({ error: 'No articles provided' });
}
const config = {};
const rows = db.prepare('SELECT * FROM configuracion').all();
for (const row of rows) config[row.clave] = row.valor;
const zebraIp = config.zebra_ip;
const zebraPort = parseInt(config.zebra_port || '9100', 10);
let allZpl = '';
for (const article of articles) {
allZpl += generateLabel(article, article.quantity || 1) + '\n';
}
try {
await printZpl(allZpl, zebraIp, zebraPort);
res.json({ success: true, labels: articles.length });
} catch (err) {
res.status(500).json({ error: err.message });
}
});
return router;
}
module.exports = { printRouter };