From 93ac1db5f1ff1fc2ac82c433fd663de89dc6120e Mon Sep 17 00:00:00 2001 From: msaldain Date: Mon, 1 Sep 2025 20:32:39 +0000 Subject: [PATCH] =?UTF-8?q?Creaci=C3=B3n=20de=20la=20secci=C3=B3n=20"Repor?= =?UTF-8?q?tes"=20y=20"Compras"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- compose.tools.yaml | 10 +- services/manso/src/index.js | 107 +++- services/manso/src/views/compras.ejs | 361 ++++++++++++ services/manso/src/views/partials/_navbar.ejs | 2 + services/manso/src/views/reportes.ejs | 548 ++++++++++++++++++ services/manso/src/views/reportes.ejs.bak | 402 +++++++++++++ 6 files changed, 1424 insertions(+), 6 deletions(-) create mode 100644 services/manso/src/views/compras.ejs create mode 100644 services/manso/src/views/reportes.ejs create mode 100644 services/manso/src/views/reportes.ejs.bak diff --git a/compose.tools.yaml b/compose.tools.yaml index 49fd8d2..bb692ea 100644 --- a/compose.tools.yaml +++ b/compose.tools.yaml @@ -1,4 +1,4 @@ -# compose.tools.yaml +# $ compose.tools.yaml name: suitecoffee_tools services: @@ -14,7 +14,7 @@ services: - dbeaver_logs:/opt/cloudbeaver/logs - dbeaver_workspace:/opt/cloudbeaver/workspace networks: - suitecoffee_prod_net: {} + # suitecoffee_prod_net: {} suitecoffee_dev_net: {} healthcheck: test: ["CMD-SHELL", "curl -fsS http://localhost:8978 || exit 1"] @@ -37,7 +37,7 @@ services: - npm_data:/data - npm_letsencrypt:/etc/letsencrypt networks: - suitecoffee_prod_net: {} + # suitecoffee_prod_net: {} suitecoffee_dev_net: {} healthcheck: test: ["CMD-SHELL", "curl -fsS http://localhost:81 || exit 1"] @@ -50,8 +50,8 @@ services: networks: suitecoffee_dev_net: external: true - suitecoffee_prod_net: - external: true + # suitecoffee_prod_net: + # external: true volumes: npm_data: diff --git a/services/manso/src/index.js b/services/manso/src/index.js index cb8e9bc..f9d5f48 100644 --- a/services/manso/src/index.js +++ b/services/manso/src/index.js @@ -84,7 +84,7 @@ const ALLOWED_TABLES = [ 'mate_primas','deta_comp_materias', 'prov_producto','prov_mate_prima', 'receta_producto', 'asistencia_resumen_diario', - 'asistencia_intervalo' + 'asistencia_intervalo', 'vw_compras' ]; const VALID_IDENT = /^[a-zA-Z_][a-zA-Z0-9_]*$/; @@ -243,6 +243,18 @@ app.get('/usuarios', (req, res) => { res.render('usuarios'); }); +app.get('/reportes', (req, res) => { + res.locals.pageTitle = 'Reportes'; + res.locals.pageId = 'reportes'; + res.render('reportes'); +}); + +app.get('/compras', (req, res) => { + res.locals.pageTitle = 'Compras'; + res.locals.pageId = 'compras'; + res.render('compras'); +}); + // ---------------------------------------------------------- // API // ---------------------------------------------------------- @@ -649,6 +661,99 @@ app.post('/api/rpc/asistencia_delete_raw', async (req, res) => { } }); +app.post('/api/rpc/report_asistencia', async (req,res)=>{ + const {desde, hasta} = req.body||{}; + const sql = 'SELECT * FROM public.report_asistencia($1::date,$2::date)'; + const {rows} = await pool.query(sql,[desde, hasta]); + res.json(rows); +}); + +app.post('/api/rpc/report_tickets', async (req, res) => { + try { + const { year } = req.body || {}; + const sql = 'SELECT public.report_tickets_year($1::int) AS data'; + const { rows } = await pool.query(sql, [year]); + res.json(rows[0]?.data || {}); + } catch (e) { + console.error(e); + res.status(500).json({ error: 'report_tickets failed' }); + } +}); + + +// Guardar (insert/update) +app.post('/api/rpc/save_compra', async (req, res) => { + try { + const { id_compra, id_proveedor, fec_compra, detalles } = req.body || {}; + const sql = 'SELECT * FROM public.save_compra($1::int,$2::int,$3::timestamptz,$4::jsonb)'; + const args = [id_compra ?? null, id_proveedor, fec_compra ? new Date(fec_compra) : null, JSON.stringify(detalles)]; + const { rows } = await pool.query(sql, args); + res.json(rows[0]); // { id_compra, total } + } catch (e) { + console.error('save_compra error:', e); + res.status(500).json({ error: 'save_compra failed', message: e.message, detail: e.detail, where: e.where, code: e.code }); + } +}); + + +// Obtener para editar +app.post('/api/rpc/get_compra', async (req, res) => { + try { + const { id_compra } = req.body || {}; + const sql = `SELECT public.get_compra($1::int) AS data`; + const { rows } = await pool.query(sql, [id_compra]); + res.json(rows[0]?.data || {}); + } catch (e) { + console.error(e); res.status(500).json({ error: 'get_compra failed' }); + } +}); + +// Eliminar +app.post('/api/rpc/delete_compra', async (req, res) => { + try { + const { id_compra } = req.body || {}; + await pool.query(`SELECT public.delete_compra($1::int)`, [id_compra]); + res.json({ ok: true }); + } catch (e) { + console.error(e); res.status(500).json({ error: 'delete_compra failed' }); + } +}); + + +// POST /api/rpc/report_gastos { year: 2025 } +app.post('/api/rpc/report_gastos', async (req, res) => { + try { + const year = parseInt(req.body?.year ?? new Date().getFullYear(), 10); + const { rows } = await pool.query( + 'SELECT public.report_gastos($1::int) AS j', [year] + ); + res.json(rows[0].j); + } catch (e) { + console.error('report_gastos error:', e); + res.status(500).json({ + error: 'report_gastos failed', + message: e.message, detail: e.detail, code: e.code + }); + } +}); + +// (Opcional) GET para probar rápido desde el navegador: +// /api/rpc/report_gastos?year=2025 +app.get('/api/rpc/report_gastos', async (req, res) => { + try { + const year = parseInt(req.query.year ?? new Date().getFullYear(), 10); + const { rows } = await pool.query( + 'SELECT public.report_gastos($1::int) AS j', [year] + ); + res.json(rows[0].j); + } catch (e) { + console.error('report_gastos error:', e); + res.status(500).json({ + error: 'report_gastos failed', + message: e.message, detail: e.detail, code: e.code + }); + } +}); // ---------------------------------------------------------- diff --git a/services/manso/src/views/compras.ejs b/services/manso/src/views/compras.ejs new file mode 100644 index 0000000..6111cdd --- /dev/null +++ b/services/manso/src/views/compras.ejs @@ -0,0 +1,361 @@ +<% /* Compras / Gastos */ %> +
+
+

Compras / Gastos

+
+ + +
+
+ + +
+
Nueva compra
+
+
+ +
+ + +
+
+ + +
+
+ + +
+ +
+
+
Renglones
+
+ +
+
+ +
+ + + + + + + + + + + + + + + + +
TipoÍtemCantidadPrecioSubtotal
Sin renglones
+
+
+ +
+ + +
+
+
+
+ + +
+
+ Compras recientes + +
+
+
+ + + + + + + + + + + + + +
#ProveedorFechaTotal
Sin datos
+
+
+
+
+ + + + diff --git a/services/manso/src/views/partials/_navbar.ejs b/services/manso/src/views/partials/_navbar.ejs index 6d16359..486666a 100644 --- a/services/manso/src/views/partials/_navbar.ejs +++ b/services/manso/src/views/partials/_navbar.ejs @@ -14,6 +14,8 @@ + + diff --git a/services/manso/src/views/reportes.ejs b/services/manso/src/views/reportes.ejs new file mode 100644 index 0000000..0716a16 --- /dev/null +++ b/services/manso/src/views/reportes.ejs @@ -0,0 +1,548 @@ +<% /* Reportes - Asistencias, Tickets y Gastos */ %> +
+ +
+

Reportes

+ +
+ + +
+
+
+
+ +
+
+
+
+ + + +
+
+
+ +
+ +
+
+
+ + + +
+
+
+
+ +
+ Los Excel se generan como CSV. Los PDF se generan con “Imprimir área” del navegador. +
+
+
+ + + + + + + + + + + + + + + +
+ + + + \ No newline at end of file diff --git a/services/manso/src/views/reportes.ejs.bak b/services/manso/src/views/reportes.ejs.bak new file mode 100644 index 0000000..7f5ce28 --- /dev/null +++ b/services/manso/src/views/reportes.ejs.bak @@ -0,0 +1,402 @@ +<% /* Reportes - Asistencias y Tickets (Comandas) */ %> +
+ +
+

Reportes

+ +
+ + +
+
+
+
+ +
+
+ +
+
+ +
+
+ + + +
+
+
+ +
+ +
+
+ +
+
+ + + +
+
+
+
+ +
+ Los archivos Excel se generan como CSV (compatibles). Los PDF se generan con “Imprimir área” del navegador. +
+
+
+ + + + + + + +
+ + + +