Agregar resp membresias
This commit is contained in:
@@ -1,7 +1,8 @@
|
||||
const express = require('express');
|
||||
const path = require('path');
|
||||
const morgan = require('morgan');
|
||||
const mysql = require('mysql');
|
||||
//const mysql = require('mysql');
|
||||
const mysql2 = require('mysql2'); // Importa mysql2
|
||||
const cloud_file = require('express-fileupload');
|
||||
const myConecction = require('express-myconnection');
|
||||
const cors_origins = require('cors');
|
||||
@@ -23,6 +24,7 @@ const generalesRutas = require('./rutas/rt_Generales');
|
||||
const cloud_rutas = require('./rutas/rt_cloud');
|
||||
const app_restaurant = require('./rutas/rt_apps');
|
||||
const app_arduino = require('./rutas/rt_arduino');
|
||||
const proyectos = require('./rutas/rt_proyectos');
|
||||
|
||||
//configuraciones
|
||||
app.set('port',process.env.PORT||puerto);
|
||||
@@ -46,7 +48,7 @@ app.use(session({
|
||||
//middlewares
|
||||
app.use(express.static(__dirname+'/public'));//para usar la carpeta public *js*css*img
|
||||
app.use(morgan('dev'));
|
||||
app.use(myConecction(mysql,{//conexion bd
|
||||
app.use(myConecction(mysql2,{ // <-- Usa 'mysql2' aquí
|
||||
host:global.config.db.host,
|
||||
user: global.config.db.user,
|
||||
password:global.config.db.pswd,
|
||||
@@ -73,6 +75,7 @@ app.use('/', generalesRutas);
|
||||
app.use('/', cloud_rutas);
|
||||
app.use('/', app_restaurant);
|
||||
app.use('/', app_arduino);
|
||||
app.use('/', proyectos);
|
||||
|
||||
//prueba de json directa
|
||||
app.get('/pruebaJson',function(req,res){
|
||||
|
||||
@@ -40,4 +40,10 @@ controlador.upload = (req, res) => {
|
||||
res.render('video_upload')
|
||||
};
|
||||
|
||||
/** aqui iniciamo la vista de ejs **/
|
||||
controlador.config = (req, res) => {
|
||||
//res.render('speedtest');
|
||||
res.render('configuracion');
|
||||
};
|
||||
|
||||
module.exports = controlador;
|
||||
@@ -135,6 +135,100 @@ controlador.eliminarCliente = (req, res) => {
|
||||
});
|
||||
}
|
||||
|
||||
/**** Listar miembros *****/
|
||||
controlador.listarMiembros = (req, res) => {
|
||||
req.getConnection((err, conn) => {
|
||||
if (err) {
|
||||
return res.status(500).json({ error: 'Error de conexión' });
|
||||
}
|
||||
|
||||
conn.query('SELECT * FROM miembros ORDER BY nombre ASC', (err, miembros) => {
|
||||
if (err) {
|
||||
return res.status(500).json({ error: 'Error al consultar miembros' });
|
||||
}
|
||||
res.json(miembros);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/**** Obtener miembro para edición (ahora vía /api/miembros/:id) *****/
|
||||
controlador.editarMiembro = (req, res) => {
|
||||
const { id } = req.params; // *** MODIFICADO: id ahora viene de req.params ***
|
||||
req.getConnection((err, conn) => {
|
||||
if (err) {
|
||||
return res.status(500).json({ error: 'Error de conexión' });
|
||||
}
|
||||
|
||||
conn.query('SELECT * FROM miembros WHERE id = ?', [id], (err, miembro) => {
|
||||
if (err) {
|
||||
return res.status(500).json({ error: 'Error al consultar miembro' });
|
||||
}
|
||||
if (miembro.length === 0) {
|
||||
return res.status(404).json({ error: 'Miembro no encontrado' });
|
||||
}
|
||||
res.json(miembro[0]);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/**** Guardar/Crear nuevo miembro (vía POST /api/miembros) *****/
|
||||
controlador.guardarMiembro = (req, res) => {
|
||||
const miembro = req.body; // Obtener los datos del miembro desde el cuerpo de la solicitud
|
||||
req.getConnection((err, conn) => {
|
||||
if (err) {
|
||||
return res.status(500).json({ error: 'Error de conexión' });
|
||||
}
|
||||
|
||||
conn.query('INSERT INTO miembros SET ?', miembro, (err, result) => {
|
||||
if (err) {
|
||||
return res.status(500).json({ error: 'Error al guardar miembro' });
|
||||
}
|
||||
res.status(201).json({ id: result.insertId, ...miembro, message: 'Miembro creado exitosamente' }); // 201 Created
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/**** Actualizar miembro existente (vía PUT /api/miembros/:id) *****/
|
||||
controlador.actualizarMiembro = (req, res) => {
|
||||
const { id } = req.params; // *** MODIFICADO: id ahora viene de req.params ***
|
||||
const miembroActualizado = req.body; // Obtener los datos actualizados del miembro desde el cuerpo de la solicitud
|
||||
req.getConnection((err, conn) => {
|
||||
if (err) {
|
||||
return res.status(500).json({ error: 'Error de conexión' });
|
||||
}
|
||||
|
||||
conn.query('UPDATE miembros SET ? WHERE id = ?', [miembroActualizado, id], (err, result) => {
|
||||
if (err) {
|
||||
return res.status(500).json({ error: 'Error al actualizar miembro' });
|
||||
}
|
||||
if (result.affectedRows === 0) {
|
||||
return res.status(404).json({ error: 'Miembro no encontrado' });
|
||||
}
|
||||
res.json({ message: 'Miembro actualizado exitosamente' });
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/**** Eliminar miembro (vía DELETE /api/miembros/:id) *****/
|
||||
controlador.eliminarMiembro = (req, res) => {
|
||||
const { id } = req.params; // *** MODIFICADO: id ahora viene de req.params ***
|
||||
req.getConnection((err, conn) => {
|
||||
if (err) {
|
||||
return res.status(500).json({ error: 'Error de conexión' });
|
||||
}
|
||||
|
||||
conn.query('DELETE FROM miembros WHERE id = ?', [id], (err, result) => {
|
||||
if (err) {
|
||||
return res.status(500).json({ error: 'Error al eliminar miembro' });
|
||||
}
|
||||
if (result.affectedRows === 0) {
|
||||
return res.status(404).json({ error: 'Miembro no encontrado' });
|
||||
}
|
||||
res.json({ message: 'Miembro eliminado exitosamente' });
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* controlador para obtener las ciudades de la base de datos
|
||||
* @param {*} req
|
||||
|
||||
2711
src/controladores/controlador_proyecto.js
Normal file
2711
src/controladores/controlador_proyecto.js
Normal file
File diff suppressed because it is too large
Load Diff
@@ -10,4 +10,7 @@ rutas.get('/users', controlador_init.user);//devuelve usuaios con el el ROL mese
|
||||
rutas.get('/speedtest', controlador_init.speedtest);//testing velocimetro server
|
||||
rutas.get('/videos', controlador_init.videos);//videos sigma server
|
||||
rutas.get('/video_upload', controlador_init.upload);//videos sigma server
|
||||
|
||||
/*** CONFIGURACION DE UN PAGINA QUE CONFIGURE EL ARCHIVO config.js ***/
|
||||
rutas.get('/configuracion', controlador_init.config);//llama a un view de configuracion del archivo config.js
|
||||
module.exports = rutas;
|
||||
@@ -18,9 +18,22 @@ rutas.post('/actCliente/:client_id', controladorClientes.modificaCliente);//actu
|
||||
//eliminar clientes
|
||||
rutas.get('/eliminarCliente/:client_id', controladorClientes.eliminarCliente);
|
||||
//almacena cliente
|
||||
rutas.post('/addCliente', controladorClientes.guardaCliente);//almacena en bd el nuevo cliente
|
||||
rutas.post('/addCliente', controladorClientes.guardaCliente);//almacena en bd el nuevo cliente: https://app.factura-e.net/addCliente
|
||||
rutas.get('/addClienteForm', controladorClientes.verFormNclientes);//muesta form para crear cliente
|
||||
|
||||
// --- Rutas RESTful para Miembros --- https://app.factura-e.net/api/miembros
|
||||
// Listar todos los miembros (GET /api/miembros)
|
||||
rutas.get('/api/miembros', controladorClientes.listarMiembros);
|
||||
// Obtener un miembro específico por ID (GET /api/miembros/:id)
|
||||
// Usado para "editar" (obtener datos para un formulario de edición)
|
||||
rutas.get('/api/miembros/:id', controladorClientes.editarMiembro);
|
||||
// Crear un nuevo miembro (POST /api/miembros)
|
||||
rutas.post('/api/miembros', controladorClientes.guardarMiembro);
|
||||
// Actualizar un miembro existente por ID (PUT /api/miembros/:id)
|
||||
rutas.put('/api/miembros/:id', controladorClientes.actualizarMiembro);
|
||||
// Eliminar un miembro por ID (DELETE /api/miembros/:id)
|
||||
rutas.delete('/api/miembros/:id', controladorClientes.eliminarMiembro);
|
||||
|
||||
// Ruta para obtener ciudades
|
||||
rutas.get('/api/ciudades', controladorClientes.obtenerCiudades);
|
||||
|
||||
|
||||
947
src/rutas/rt_proyectos.js
Normal file
947
src/rutas/rt_proyectos.js
Normal file
@@ -0,0 +1,947 @@
|
||||
// src/rutas/rt_proyectos.js
|
||||
|
||||
// Importar el módulo express para crear el router
|
||||
const express = require('express');
|
||||
const router = express.Router();
|
||||
|
||||
// Importar el controlador de proyectos
|
||||
// Asumo que el controlador estará en 'src/controladores/controlador_proyecto.js'
|
||||
const controlador_proyecto = require('../controladores/controlador_proyecto');
|
||||
|
||||
// --- Rutas para las VISTAS EJS (Renderizan archivos EJS) ---
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /panel_proyectos:
|
||||
* get:
|
||||
* summary: Muestra el dashboard principal de gestión de proyectos.
|
||||
* tags: [Proyectos]
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Dashboard de proyectos renderizado exitosamente.
|
||||
* content:
|
||||
* text/html:
|
||||
* schema:
|
||||
* type: string
|
||||
* example: |
|
||||
* <!DOCTYPE html>... (HTML del dashboard de proyectos)
|
||||
* 500:
|
||||
* description: Error del servidor al cargar los proyectos.
|
||||
*/
|
||||
router.get('/panel_proyectos', controlador_proyecto.panel_proyectos);
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /proyecto_memoria_tecnica:
|
||||
* get:
|
||||
* summary: Muestra el formulario para crear o editar una Memoria Técnica.
|
||||
* tags: [Proyectos]
|
||||
* parameters:
|
||||
* - in: query
|
||||
* name: proyectoId
|
||||
* schema:
|
||||
* type: integer
|
||||
* description: ID del proyecto para pre-seleccionar en el formulario.
|
||||
* - in: query
|
||||
* name: memoriaId
|
||||
* schema:
|
||||
* type: integer
|
||||
* description: ID de la Memoria Técnica a editar.
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Formulario de Memoria Técnica renderizado exitosamente.
|
||||
* content:
|
||||
* text/html:
|
||||
* schema:
|
||||
* type: string
|
||||
* example: |
|
||||
* <!DOCTYPE html>... (HTML del formulario de memoria técnica)
|
||||
* 500:
|
||||
* description: Error del servidor al cargar el formulario.
|
||||
*/
|
||||
router.get('/proyecto_memoria_tecnica', controlador_proyecto.memoriaTecnica);
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /lista_memorias_tecnicas:
|
||||
* get:
|
||||
* summary: Muestra una tabla con todas las memorias técnicas.
|
||||
* tags: [Proyectos]
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Lista de memorias técnicas renderizada exitosamente.
|
||||
* content:
|
||||
* text/html:
|
||||
* schema:
|
||||
* type: string
|
||||
* example: |
|
||||
* <!DOCTYPE html>... (HTML de la lista de memorias)
|
||||
* 500:
|
||||
* description: Error del servidor al cargar la lista.
|
||||
*/
|
||||
router.get('/lista_memorias_tecnicas', controlador_proyecto.listarMemoriasTecnicas);
|
||||
|
||||
|
||||
// --- Rutas de la API RESTful (Para operaciones CRUD de datos) ---
|
||||
|
||||
// --- Rutas para la Memoria Técnica Principal ---
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/proyectos/memorias-tecnicas:
|
||||
* post:
|
||||
* summary: Crea una nueva Memoria Técnica.
|
||||
* tags: [Memoria Técnica API]
|
||||
* requestBody:
|
||||
* required: true
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: object
|
||||
* required:
|
||||
* - id_proyecto
|
||||
* - id_empresa_autora
|
||||
* - objetivo_memoria_especifico
|
||||
* properties:
|
||||
* id_proyecto:
|
||||
* type: integer
|
||||
* description: ID del proyecto asociado.
|
||||
* id_empresa_autora:
|
||||
* type: integer
|
||||
* description: ID de la empresa autora de la memoria.
|
||||
* objetivo_memoria_especifico:
|
||||
* type: string
|
||||
* description: Objetivo específico de esta memoria técnica.
|
||||
* descripcion_introduccion:
|
||||
* type: string
|
||||
* description: Descripción introductoria de la memoria.
|
||||
* funcionamiento_operacion:
|
||||
* type: string
|
||||
* description: Detalles de funcionamiento y operación.
|
||||
* conectividad_red:
|
||||
* type: string
|
||||
* description: Información sobre conectividad de red.
|
||||
* acceso_remoto_aplicaciones:
|
||||
* type: string
|
||||
* description: Detalles de acceso remoto y aplicaciones.
|
||||
* seguridad_fisica_logica:
|
||||
* type: string
|
||||
* responses:
|
||||
* 201:
|
||||
* description: Memoria Técnica creada exitosamente.
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: object
|
||||
* properties:
|
||||
* message:
|
||||
* type: string
|
||||
* example: Memoria técnica creada exitosamente
|
||||
* id:
|
||||
* type: integer
|
||||
* example: 1
|
||||
* 400:
|
||||
* description: Datos de entrada inválidos.
|
||||
* 500:
|
||||
* description: Error del servidor.
|
||||
*/
|
||||
router.post('/api/proyectos/memorias-tecnicas', controlador_proyecto.createMemoriaTecnica);
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/proyectos/memorias-tecnicas/{id}:
|
||||
* get:
|
||||
* summary: Obtiene una Memoria Técnica por su ID.
|
||||
* tags: [Memoria Técnica API]
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: id
|
||||
* required: true
|
||||
* schema:
|
||||
* type: integer
|
||||
* description: ID de la Memoria Técnica a obtener.
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Detalles de la Memoria Técnica.
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: object
|
||||
* properties:
|
||||
* id: { type: integer, example: 1 }
|
||||
* id_proyecto: { type: integer, example: 101 }
|
||||
* objetivo_memoria_especifico: { type: string, example: "Documentar instalación de sistema CCTV" }
|
||||
* descripcion_introduccion: { type: string, example: "Esta memoria detalla la configuración inicial del sistema." }
|
||||
* 404:
|
||||
* description: Memoria Técnica no encontrada.
|
||||
* 500:
|
||||
* description: Error del servidor.
|
||||
*/
|
||||
router.get('/api/proyectos/memorias-tecnicas/:id', controlador_proyecto.getMemoriaTecnicaById);
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/proyectos/memorias-tecnicas/{id}:
|
||||
* put:
|
||||
* summary: Actualiza una Memoria Técnica existente.
|
||||
* tags: [Memoria Técnica API]
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: id
|
||||
* required: true
|
||||
* schema:
|
||||
* type: integer
|
||||
* description: ID de la Memoria Técnica a actualizar.
|
||||
* requestBody:
|
||||
* required: true
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: object
|
||||
* properties:
|
||||
* id_proyecto:
|
||||
* type: integer
|
||||
* id_empresa_autora:
|
||||
* type: integer
|
||||
* objetivo_memoria_especifico:
|
||||
* type: string
|
||||
* descripcion_introduccion:
|
||||
* type: string
|
||||
* funcionamiento_operacion:
|
||||
* type: string
|
||||
* conectividad_red:
|
||||
* type: string
|
||||
* acceso_remoto_aplicaciones:
|
||||
* type: string
|
||||
* seguridad_fisica_logica:
|
||||
* type: string
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Memoria Técnica actualizada exitosamente.
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: object
|
||||
* properties:
|
||||
* message:
|
||||
* type: string
|
||||
* example: Memoria técnica actualizada exitosamente
|
||||
* 400:
|
||||
* description: Datos de entrada inválidos.
|
||||
* 404:
|
||||
* description: Memoria Técnica no encontrada.
|
||||
* 500:
|
||||
* description: Error del servidor.
|
||||
*/
|
||||
router.put('/api/proyectos/memorias-tecnicas/:id', controlador_proyecto.updateMemoriaTecnica);
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/proyectos/memorias-tecnicas/{id}:
|
||||
* delete:
|
||||
* summary: Elimina una Memoria Técnica.
|
||||
* tags: [Memoria Técnica API]
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: id
|
||||
* required: true
|
||||
* schema:
|
||||
* type: integer
|
||||
* description: ID de la Memoria Técnica a eliminar.
|
||||
* responses:
|
||||
* 204:
|
||||
* description: Memoria Técnica eliminada exitosamente.
|
||||
* 404:
|
||||
* description: Memoria Técnica no encontrada.
|
||||
* 500:
|
||||
* description: Error del servidor.
|
||||
*/
|
||||
router.delete('/api/proyectos/memorias-tecnicas/:id', controlador_proyecto.deleteMemoriaTecnica);
|
||||
|
||||
// --- Rutas para Componentes de la Memoria Técnica ---
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/proyectos/memorias-tecnicas/{memoriaId}/componentes:
|
||||
* get:
|
||||
* summary: Obtiene todos los componentes asociados a una Memoria Técnica.
|
||||
* tags: [Memoria Técnica API]
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: memoriaId
|
||||
* required: true
|
||||
* schema:
|
||||
* type: integer
|
||||
* description: ID de la Memoria Técnica.
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Lista de componentes.
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: array
|
||||
* items:
|
||||
* type: object
|
||||
* properties:
|
||||
* id: { type: integer, example: 1 }
|
||||
* id_memoria: { type: integer, example: 10 }
|
||||
* nombre_componente: { type: string, example: "Cámara IP Hikvision" }
|
||||
* tipo: { type: string, example: "Cámara" }
|
||||
* modelo_marca: { type: string, example: "DS-2CD2143G0-I" }
|
||||
* numero_serie: { type: string, example: "SN123456789" }
|
||||
* ubicacion: { type: string, example: "Entrada principal" }
|
||||
* descripcion_breve: { type: string, example: "Cámara domo de 4MP con IR" }
|
||||
* 500:
|
||||
* description: Error del servidor.
|
||||
* post:
|
||||
* summary: Agrega un nuevo componente a una Memoria Técnica.
|
||||
* tags: [Memoria Técnica API]
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: memoriaId
|
||||
* required: true
|
||||
* schema:
|
||||
* type: integer
|
||||
* description: ID de la Memoria Técnica.
|
||||
* requestBody:
|
||||
* required: true
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: object
|
||||
* required:
|
||||
* - nombre_componente
|
||||
* properties:
|
||||
* nombre_componente:
|
||||
* type: string
|
||||
* tipo:
|
||||
* type: string
|
||||
* modelo_marca:
|
||||
* type: string
|
||||
* numero_serie:
|
||||
* type: string
|
||||
* ubicacion:
|
||||
* type: string
|
||||
* descripcion_breve:
|
||||
* type: string
|
||||
* responses:
|
||||
* 201:
|
||||
* description: Componente añadido exitosamente.
|
||||
* 400:
|
||||
* description: Datos de entrada inválidos.
|
||||
* 500:
|
||||
* description: Error del servidor.
|
||||
*/
|
||||
router.get('/api/proyectos/memorias-tecnicas/:memoriaId/componentes', controlador_proyecto.getComponentesByMemoriaId);
|
||||
router.post('/api/proyectos/memorias-tecnicas/:memoriaId/componentes', controlador_proyecto.addComponente);
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/proyectos/componentes/{id}:
|
||||
* put:
|
||||
* summary: Actualiza un componente de la Memoria Técnica.
|
||||
* tags: [Memoria Técnica API]
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: id
|
||||
* required: true
|
||||
* schema:
|
||||
* type: integer
|
||||
* description: ID del componente a actualizar.
|
||||
* requestBody:
|
||||
* required: true
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: object
|
||||
* properties:
|
||||
* nombre_componente:
|
||||
* type: string
|
||||
* tipo:
|
||||
* type: string
|
||||
* modelo_marca:
|
||||
* type: string
|
||||
* numero_serie:
|
||||
* type: string
|
||||
* ubicacion:
|
||||
* type: string
|
||||
* descripcion_breve:
|
||||
* type: string
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Componente actualizado exitosamente.
|
||||
* 404:
|
||||
* description: Componente no encontrado.
|
||||
* 500:
|
||||
* description: Error del servidor.
|
||||
* delete:
|
||||
* summary: Elimina un componente de la Memoria Técnica.
|
||||
* tags: [Memoria Técnica API]
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: id
|
||||
* required: true
|
||||
* schema:
|
||||
* type: integer
|
||||
* description: ID del componente a eliminar.
|
||||
* responses:
|
||||
* 204:
|
||||
* description: Componente eliminado exitosamente.
|
||||
* 404:
|
||||
* description: Componente no encontrado.
|
||||
* 500:
|
||||
* description: Error del servidor.
|
||||
*/
|
||||
router.put('/api/proyectos/componentes/:id', controlador_proyecto.updateComponente);
|
||||
router.delete('/api/proyectos/componentes/:id', controlador_proyecto.deleteComponente);
|
||||
|
||||
// --- Rutas para Plan de Mantenimiento ---
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/proyectos/memorias-tecnicas/{memoriaId}/mantenimiento:
|
||||
* get:
|
||||
* summary: Obtiene todos los planes de mantenimiento asociados a una Memoria Técnica.
|
||||
* tags: [Memoria Técnica API]
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: memoriaId
|
||||
* required: true
|
||||
* schema:
|
||||
* type: integer
|
||||
* description: ID de la Memoria Técnica.
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Lista de planes de mantenimiento.
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: array
|
||||
* items:
|
||||
* type: object
|
||||
* properties:
|
||||
* id: { type: integer, example: 1 }
|
||||
* id_memoria: { type: integer, example: 10 }
|
||||
* tipo_mantenimiento: { type: string, example: "Preventivo" }
|
||||
* frecuencia: { type: string, example: "Mensual" }
|
||||
* tareas_procedimientos: { type: string, example: "Limpieza de filtros y revisión de conexiones." }
|
||||
* responsable: { type: string, example: "Equipo de Mantenimiento A" }
|
||||
* 500:
|
||||
* description: Error del servidor.
|
||||
* post:
|
||||
* summary: Agrega un nuevo plan de mantenimiento a una Memoria Técnica.
|
||||
* tags: [Memoria Técnica API]
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: memoriaId
|
||||
* required: true
|
||||
* schema:
|
||||
* type: integer
|
||||
* description: ID de la Memoria Técnica.
|
||||
* requestBody:
|
||||
* required: true
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: object
|
||||
* required:
|
||||
* - tareas_procedimientos
|
||||
* properties:
|
||||
* tipo_mantenimiento:
|
||||
* type: string
|
||||
* frecuencia:
|
||||
* type: string
|
||||
* tareas_procedimientos:
|
||||
* type: string
|
||||
* responsable:
|
||||
* type: string
|
||||
* responses:
|
||||
* 201:
|
||||
* description: Plan de mantenimiento añadido exitosamente.
|
||||
* 400:
|
||||
* description: Datos de entrada inválidos.
|
||||
* 500:
|
||||
* description: Error del servidor.
|
||||
*/
|
||||
router.get('/api/proyectos/memorias-tecnicas/:memoriaId/mantenimiento', controlador_proyecto.getMantenimientoByMemoriaId);
|
||||
router.post('/api/proyectos/memorias-tecnicas/:memoriaId/mantenimiento', controlador_proyecto.addMantenimiento);
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/proyectos/mantenimiento/{id}:
|
||||
* put:
|
||||
* summary: Actualiza un plan de mantenimiento.
|
||||
* tags: [Memoria Técnica API]
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: id
|
||||
* required: true
|
||||
* schema:
|
||||
* type: integer
|
||||
* description: ID del plan de mantenimiento a actualizar.
|
||||
* requestBody:
|
||||
* required: true
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: object
|
||||
* properties:
|
||||
* tipo_mantenimiento:
|
||||
* type: string
|
||||
* frecuencia:
|
||||
* type: string
|
||||
* tareas_procedimientos:
|
||||
* type: string
|
||||
* responsable:
|
||||
* type: string
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Plan de mantenimiento actualizado exitosamente.
|
||||
* 404:
|
||||
* description: Plan de mantenimiento no encontrado.
|
||||
* 500:
|
||||
* description: Error del servidor.
|
||||
* delete:
|
||||
* summary: Elimina un plan de mantenimiento.
|
||||
* tags: [Memoria Técnica API]
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: id
|
||||
* required: true
|
||||
* schema:
|
||||
* type: integer
|
||||
* description: ID del plan de mantenimiento a eliminar.
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Plan de mantenimiento eliminado exitosamente.
|
||||
* 404:
|
||||
* description: Plan de mantenimiento no encontrado.
|
||||
* 500:
|
||||
* description: Error del servidor.
|
||||
*/
|
||||
router.put('/api/proyectos/mantenimiento/:id', controlador_proyecto.updateMantenimiento);
|
||||
router.delete('/api/proyectos/mantenimiento/:id', controlador_proyecto.deleteMantenimiento);
|
||||
|
||||
// --- Rutas para Credenciales de Dispositivos ---
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/proyectos/memorias-tecnicas/{memoriaId}/credenciales:
|
||||
* get:
|
||||
* summary: Obtiene todas las credenciales asociadas a una Memoria Técnica.
|
||||
* tags: [Memoria Técnica API]
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: memoriaId
|
||||
* required: true
|
||||
* schema:
|
||||
* type: integer
|
||||
* description: ID de la Memoria Técnica.
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Lista de credenciales.
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: array
|
||||
* items:
|
||||
* type: object
|
||||
* properties:
|
||||
* id: { type: integer, example: 1 }
|
||||
* id_memoria: { type: integer, example: 10 }
|
||||
* tipo_credencial: { type: string, example: "Usuario" }
|
||||
* valor_credencial: { type: string, example: "admin" }
|
||||
* descripcion: { type: string, example: "Credencial de acceso al NVR" }
|
||||
* 500:
|
||||
* description: Error del servidor.
|
||||
* post:
|
||||
* summary: Agrega una nueva credencial a una Memoria Técnica.
|
||||
* tags: [Memoria Técnica API]
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: memoriaId
|
||||
* required: true
|
||||
* schema:
|
||||
* type: integer
|
||||
* description: ID de la Memoria Técnica.
|
||||
* requestBody:
|
||||
* required: true
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: object
|
||||
* required:
|
||||
* - tipo_credencial
|
||||
* - valor_credencial
|
||||
* properties:
|
||||
* tipo_credencial:
|
||||
* type: string
|
||||
* valor_credencial:
|
||||
* type: string
|
||||
* descripcion:
|
||||
* type: string
|
||||
* responses:
|
||||
* 201:
|
||||
* description: Credencial agregada exitosamente.
|
||||
* 400:
|
||||
* description: Datos de entrada inválidos.
|
||||
* 500:
|
||||
* description: Error del servidor.
|
||||
*/
|
||||
router.get('/api/proyectos/memorias-tecnicas/:memoriaId/credenciales', controlador_proyecto.getCredencialesByMemoriaId);
|
||||
router.post('/api/proyectos/memorias-tecnicas/:memoriaId/credenciales', controlador_proyecto.addCredencial);
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/proyectos/credenciales/{id}:
|
||||
* put:
|
||||
* summary: Actualiza una credencial de dispositivo.
|
||||
* tags: [Memoria Técnica API]
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: id
|
||||
* required: true
|
||||
* schema:
|
||||
* type: integer
|
||||
* description: ID de la credencial a actualizar.
|
||||
* requestBody:
|
||||
* required: true
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: object
|
||||
* properties:
|
||||
* tipo_credencial:
|
||||
* type: string
|
||||
* valor_credencial:
|
||||
* type: string
|
||||
* descripcion:
|
||||
* type: string
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Credencial actualizada exitosamente.
|
||||
* 404:
|
||||
* description: Credencial no encontrada.
|
||||
* 500:
|
||||
* description: Error del servidor.
|
||||
* delete:
|
||||
* summary: Elimina una credencial de dispositivo.
|
||||
* tags: [Memoria Técnica API]
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: id
|
||||
* required: true
|
||||
* schema:
|
||||
* type: integer
|
||||
* description: ID de la credencial a eliminar.
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Credencial eliminada exitosamente.
|
||||
* 404:
|
||||
* description: Credencial no encontrada.
|
||||
* 500:
|
||||
* description: Error del servidor.
|
||||
*/
|
||||
router.put('/api/proyectos/credenciales/:id', controlador_proyecto.updateCredencial);
|
||||
router.delete('/api/proyectos/credenciales/:id', controlador_proyecto.deleteCredencial);
|
||||
|
||||
// --- Rutas para Documentos Genéricos (relacionados con Memoria Técnica) ---
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/documentos:
|
||||
* post:
|
||||
* summary: Sube un nuevo documento.
|
||||
* tags: [Documentos y Archivos API]
|
||||
* requestBody:
|
||||
* required: true
|
||||
* content:
|
||||
* multipart/form-data:
|
||||
* schema:
|
||||
* type: object
|
||||
* required:
|
||||
* - documento
|
||||
* - id_entidad_asociada
|
||||
* - tipo_entidad_asociada
|
||||
* properties:
|
||||
* documento:
|
||||
* type: string
|
||||
* format: binary
|
||||
* memoriaId:
|
||||
* type: integer
|
||||
* description: ID de la Memoria Técnica a la que se asocia el documento (opcional).
|
||||
* descripcion:
|
||||
* type: string
|
||||
* description: Descripción del documento.
|
||||
* responses:
|
||||
* 201:
|
||||
* description: Documento subido exitosamente.
|
||||
* 400:
|
||||
* description: Datos de entrada inválidos o archivo no proporcionado.
|
||||
* 500:
|
||||
* description: Error del servidor.
|
||||
*/
|
||||
router.post('/api/documentos', controlador_proyecto.uploadDocumento);
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/documentos/{id}:
|
||||
* get:
|
||||
* summary: Obtiene un documento por su ID.
|
||||
* tags: [Documentos y Archivos API]
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: id
|
||||
* required: true
|
||||
* schema:
|
||||
* type: integer
|
||||
* description: ID del documento a obtener.
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Documento encontrado (puede devolver el archivo o metadatos).
|
||||
* 404:
|
||||
* description: Documento no encontrado.
|
||||
* 500:
|
||||
* description: Error del servidor.
|
||||
* delete:
|
||||
* summary: Elimina un documento por su ID.
|
||||
* tags: [Documentos y Archivos API]
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: id
|
||||
* required: true
|
||||
* schema:
|
||||
* type: integer
|
||||
* description: ID del documento a eliminar.
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Documento eliminado exitosamente.
|
||||
* 404:
|
||||
* description: Documento no encontrado.
|
||||
* 500:
|
||||
* description: Error del servidor.
|
||||
*/
|
||||
router.get('/api/documentos/:id', controlador_proyecto.getDocumentoById);
|
||||
router.delete('/api/documentos/:id', controlador_proyecto.deleteDocumento);
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/proyectos/memorias-tecnicas/{memoriaId}/documentos:
|
||||
* get:
|
||||
* summary: Obtiene todos los documentos asociados a una Memoria Técnica.
|
||||
* tags: [Documentos y Archivos API]
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: memoriaId
|
||||
* required: true
|
||||
* schema:
|
||||
* type: integer
|
||||
* description: ID de la Memoria Técnica.
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Lista de documentos.
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: array
|
||||
* items:
|
||||
* type: object
|
||||
* properties:
|
||||
* id: { type: integer, example: 1 }
|
||||
* nombre_documento: { type: string, example: "Manual_CCTV.pdf" }
|
||||
* ruta_archivo: { type: string, example: "uploads/documentos/manual_cctv.pdf" }
|
||||
* tipo_entidad_asociada: { type: string, example: "MEMORIA_TECNICA" }
|
||||
* 500:
|
||||
* description: Error del servidor.
|
||||
*/
|
||||
router.get('/api/proyectos/memorias-tecnicas/:memoriaId/documentos', controlador_proyecto.getDocumentosByMemoriaId);
|
||||
router.get('/api/documentos/:id/download', controlador_proyecto.downloadDocumento); // Nueva ruta para descargar
|
||||
|
||||
// --- Rutas para Imágenes Genéricas (relacionadas con Memoria Técnica) ---
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/imagenes:
|
||||
* post:
|
||||
* summary: Sube una nueva imagen.
|
||||
* tags: [Documentos y Archivos API]
|
||||
* requestBody:
|
||||
* required: true
|
||||
* content:
|
||||
* multipart/form-data:
|
||||
* schema:
|
||||
* type: object
|
||||
* required:
|
||||
* - imagen
|
||||
* - id_entidad_asociada
|
||||
* - tipo_entidad_asociada
|
||||
* properties:
|
||||
* imagen:
|
||||
* type: string
|
||||
* format: binary
|
||||
* memoriaId:
|
||||
* type: integer
|
||||
* description: ID de la Memoria Técnica a la que se asocia la imagen (opcional).
|
||||
* descripcion:
|
||||
* type: string
|
||||
* description: Descripción de la imagen.
|
||||
* responses:
|
||||
* 201:
|
||||
* description: Imagen subida exitosamente.
|
||||
* 400:
|
||||
* description: Datos de entrada inválidos o archivo no proporcionado.
|
||||
* 500:
|
||||
* description: Error del servidor.
|
||||
*/
|
||||
router.post('/api/imagenes', controlador_proyecto.uploadImagen);
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/imagenes/{id}:
|
||||
* get:
|
||||
* summary: Obtiene una imagen por su ID.
|
||||
* tags: [Documentos y Archivos API]
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: id
|
||||
* required: true
|
||||
* schema:
|
||||
* type: integer
|
||||
* description: ID de la imagen a obtener.
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Imagen encontrada (puede devolver el archivo o metadatos).
|
||||
* 404:
|
||||
* description: Imagen no encontrada.
|
||||
* 500:
|
||||
* description: Error del servidor.
|
||||
* delete:
|
||||
* summary: Elimina una imagen por su ID.
|
||||
* tags: [Documentos y Archivos API]
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: id
|
||||
* required: true
|
||||
* schema:
|
||||
* type: integer
|
||||
* description: ID de la imagen a eliminar.
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Imagen eliminada exitosamente.
|
||||
* 404:
|
||||
* description: Imagen no encontrada.
|
||||
* 500:
|
||||
* description: Error del servidor.
|
||||
*/
|
||||
router.get('/api/imagenes/:id', controlador_proyecto.getImagenById);
|
||||
router.delete('/api/imagenes/:id', controlador_proyecto.deleteImagen);
|
||||
router.get('/api/imagenes/:id/view', controlador_proyecto.viewImagen); // Nueva ruta para visualizar
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/entidades/{tipoEntidad}/{entidadId}/documentos:
|
||||
* get:
|
||||
* summary: Obtiene todos los documentos asociados a una entidad específica.
|
||||
* tags: [Documentos y Archivos API]
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: tipoEntidad
|
||||
* required: true
|
||||
* schema:
|
||||
* type: string
|
||||
* description: Tipo de la entidad (ej. 'PROYECTO', 'CLIENTE', 'MEMORIA_TECNICA').
|
||||
* - in: path
|
||||
* name: entidadId
|
||||
* required: true
|
||||
* schema:
|
||||
* type: integer
|
||||
* description: ID de la entidad.
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Lista de documentos.
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: array
|
||||
* items:
|
||||
* type: object
|
||||
* properties:
|
||||
* id: { type: integer, example: 1 }
|
||||
* nombre_documento: { type: string, example: "Contrato_Cliente.pdf" }
|
||||
* tipo_entidad_asociada: { type: string, example: "CLIENTE" }
|
||||
* id_entidad_asociada: { type: integer, example: 5 }
|
||||
* 500:
|
||||
* description: Error del servidor.
|
||||
*/
|
||||
router.get('/api/entidades/:tipoEntidad/:entidadId/documentos', controlador_proyecto.getDocumentosByEntidad);
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/entidades/{tipoEntidad}/{entidadId}/imagenes:
|
||||
* get:
|
||||
* summary: Obtiene todas las imágenes asociadas a una entidad específica.
|
||||
* tags: [Documentos y Archivos API]
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: tipoEntidad
|
||||
* required: true
|
||||
* schema:
|
||||
* type: string
|
||||
* description: Tipo de la entidad (ej. 'PROYECTO', 'CLIENTE', 'MEMORIA_TECNICA').
|
||||
* - in: path
|
||||
* name: entidadId
|
||||
* required: true
|
||||
* schema:
|
||||
* type: integer
|
||||
* description: ID de la entidad.
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Lista de imágenes.
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: array
|
||||
* items:
|
||||
* type: object
|
||||
* properties:
|
||||
* id: { type: integer, example: 1 }
|
||||
* nombre_imagen: { type: string, example: "Fachada_Edificio.jpg" }
|
||||
* tipo_entidad_asociada: { type: string, example: "PROYECTO" }
|
||||
* id_entidad_asociada: { type: integer, example: 3 }
|
||||
* 500:
|
||||
* description: Error del servidor.
|
||||
*/
|
||||
router.get('/api/entidades/:tipoEntidad/:entidadId/imagenes', controlador_proyecto.getImagenesByEntidad);
|
||||
|
||||
// Nueva ruta para generar PDF
|
||||
/**
|
||||
* @swagger
|
||||
* /api/proyectos/memorias-tecnicas/{id}/generar-pdf:
|
||||
* get:
|
||||
* summary: Genera un PDF de una memoria técnica específica.
|
||||
* tags: [Memoria Técnica API]
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: id
|
||||
* required: true
|
||||
* schema:
|
||||
* type: integer
|
||||
* description: ID de la Memoria Técnica para generar el PDF.
|
||||
* responses:
|
||||
* 200:
|
||||
* description: PDF generado y enviado exitosamente.
|
||||
* content:
|
||||
* application/pdf:
|
||||
* schema:
|
||||
* type: string
|
||||
* format: binary
|
||||
* 404:
|
||||
* description: Memoria Técnica no encontrada.
|
||||
* 500:
|
||||
* description: Error del servidor al generar el PDF.
|
||||
*/
|
||||
router.get('/api/proyectos/memorias-tecnicas/:id/generar-pdf', controlador_proyecto.generarPdfMemoriaTecnica);
|
||||
|
||||
|
||||
// Exportar el router
|
||||
module.exports = router;
|
||||
@@ -41,7 +41,8 @@ const swaggerOptions = {
|
||||
'./rutas/rt_Generales.js',
|
||||
'./rutas/rt_cloud.js',
|
||||
'./rutas/rt_apps.js',
|
||||
'./rutas/rt_arduino.js'
|
||||
'./rutas/rt_arduino.js',
|
||||
'./rutas/rt_proyectos.js',
|
||||
]
|
||||
};
|
||||
|
||||
|
||||
BIN
src/uploads/documentos/doc_1748852222471_mkdl5f19o.xlsx
Normal file
BIN
src/uploads/documentos/doc_1748852222471_mkdl5f19o.xlsx
Normal file
Binary file not shown.
BIN
src/uploads/imagenes/img_1748852241294_vk7eefxl3.jpg
Normal file
BIN
src/uploads/imagenes/img_1748852241294_vk7eefxl3.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 44 KiB |
0
src/views/configuracion.ejs
Normal file
0
src/views/configuracion.ejs
Normal file
158
src/views/lista_memorias_tecnicas.ejs
Normal file
158
src/views/lista_memorias_tecnicas.ejs
Normal file
@@ -0,0 +1,158 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="es">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Lista de Memorias Técnicas - SIGMA</title>
|
||||
<link rel="stylesheet" href="/css/estilos_generales.css">
|
||||
<style>
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
margin: 20px;
|
||||
background-color: #f4f4f4;
|
||||
color: #333;
|
||||
}
|
||||
.container {
|
||||
background-color: #fff;
|
||||
padding: 20px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
|
||||
max-width: 1200px;
|
||||
margin: auto;
|
||||
}
|
||||
h1 {
|
||||
color: #007bff;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.action-buttons {
|
||||
margin-bottom: 20px;
|
||||
text-align: right;
|
||||
}
|
||||
.action-buttons button {
|
||||
padding: 10px 15px;
|
||||
background-color: #28a745;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
font-size: 16px;
|
||||
}
|
||||
.action-buttons button:hover {
|
||||
background-color: #218838;
|
||||
}
|
||||
table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin-top: 10px;
|
||||
}
|
||||
th, td {
|
||||
border: 1px solid #ddd;
|
||||
padding: 8px;
|
||||
text-align: left;
|
||||
}
|
||||
th {
|
||||
background-color: #f2f2f2;
|
||||
color: #555;
|
||||
}
|
||||
tr:nth-child(even) {
|
||||
background-color: #f9f9f9;
|
||||
}
|
||||
.table-actions button {
|
||||
padding: 5px 10px;
|
||||
margin-right: 5px;
|
||||
border: none;
|
||||
border-radius: 3px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.table-actions .btn-cargar {
|
||||
background-color: #007bff;
|
||||
color: white;
|
||||
}
|
||||
.table-actions .btn-cargar:hover {
|
||||
background-color: #0056b3;
|
||||
}
|
||||
.table-actions .btn-eliminar {
|
||||
background-color: #dc3545;
|
||||
color: white;
|
||||
}
|
||||
.table-actions .btn-eliminar:hover {
|
||||
background-color: #c82333;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1>Lista de Memorias Técnicas</h1>
|
||||
|
||||
<div class="action-buttons">
|
||||
<button onclick="location.href='/proyecto_memoria_tecnica'">Crear Nueva Memoria Técnica</button>
|
||||
</div>
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>Objetivo de la Memoria</th>
|
||||
<th>Proyecto</th>
|
||||
<th>Cliente</th>
|
||||
<th>Empresa Autora</th>
|
||||
<th>Fecha Elaboración</th>
|
||||
<th>Última Modificación</th>
|
||||
<th>Acciones</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<% if (memorias && memorias.length > 0) { %>
|
||||
<% memorias.forEach(function(memoria) { %>
|
||||
<tr>
|
||||
<td><%= memoria.id %></td>
|
||||
<td><%= memoria.objetivo_memoria_especifico %></td>
|
||||
<td><%= memoria.nombre_proyecto || 'N/A' %></td>
|
||||
<td><%= memoria.nombre_cliente || 'N/A' %></td>
|
||||
<td><%= memoria.nombre_empresa_autora || 'N/A' %></td>
|
||||
<td><%= new Date(memoria.fecha_elaboracion).toLocaleDateString() %></td>
|
||||
<td><%= new Date(memoria.ultima_modificacion).toLocaleDateString() %></td>
|
||||
<td class="table-actions">
|
||||
<button class="btn-cargar" onclick="cargarMemoria(<%= memoria.id %>)">Cargar</button>
|
||||
<button class="btn-eliminar" onclick="eliminarMemoria(<%= memoria.id %>)">Eliminar</button>
|
||||
</td>
|
||||
</tr>
|
||||
<% }); %>
|
||||
<% } else { %>
|
||||
<tr>
|
||||
<td colspan="8">No hay memorias técnicas disponibles.</td>
|
||||
</tr>
|
||||
<% } %>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function cargarMemoria(memoriaId) {
|
||||
// Redirige al formulario de memoria técnica, pasando el ID como parámetro
|
||||
window.location.href = `/proyecto_memoria_tecnica?memoriaId=${memoriaId}`;
|
||||
}
|
||||
|
||||
async function eliminarMemoria(memoriaId) {
|
||||
if (confirm(`¿Está seguro de eliminar la memoria técnica con ID ${memoriaId}? Esto eliminará todos los datos asociados (componentes, mantenimiento, etc.).`)) {
|
||||
try {
|
||||
const response = await fetch(`/api/proyectos/memorias-tecnicas/${memoriaId}`, {
|
||||
method: 'DELETE'
|
||||
});
|
||||
|
||||
if (response.status === 204) { // 204 No Content es para eliminaciones exitosas
|
||||
alert('Memoria técnica eliminada exitosamente.');
|
||||
location.reload(); // Recargar la página para actualizar la tabla
|
||||
} else {
|
||||
const errorData = await response.json();
|
||||
alert('Error al eliminar memoria técnica: ' + (errorData.error || response.statusText));
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error de red al eliminar memoria:', error);
|
||||
alert('Error de conexión al eliminar la memoria técnica.');
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
130
src/views/panel_proyectos.ejs
Normal file
130
src/views/panel_proyectos.ejs
Normal file
@@ -0,0 +1,130 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="es">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Panel de Proyectos - SIGMA</title>
|
||||
<link rel="stylesheet" href="/css/estilos_generales.css">
|
||||
<style>
|
||||
/* Estilos básicos en línea para una visualización rápida.
|
||||
Idealmente, estos estilos deberían ir en un archivo CSS externo en /public/css/ */
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
margin: 20px;
|
||||
background-color: #f4f4f4;
|
||||
color: #333;
|
||||
}
|
||||
.container {
|
||||
background-color: #fff;
|
||||
padding: 20px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
|
||||
max-width: 1000px;
|
||||
margin: auto;
|
||||
}
|
||||
h1 {
|
||||
color: #007bff;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.action-buttons {
|
||||
margin-bottom: 20px;
|
||||
text-align: right;
|
||||
}
|
||||
.action-buttons button {
|
||||
padding: 10px 15px;
|
||||
background-color: #28a745;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
font-size: 16px;
|
||||
}
|
||||
.action-buttons button:hover {
|
||||
background-color: #218838;
|
||||
}
|
||||
table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin-top: 10px;
|
||||
}
|
||||
th, td {
|
||||
border: 1px solid #ddd;
|
||||
padding: 8px;
|
||||
text-align: left;
|
||||
}
|
||||
th {
|
||||
background-color: #f2f2f2;
|
||||
color: #555;
|
||||
}
|
||||
tr:nth-child(even) {
|
||||
background-color: #f9f9f9;
|
||||
}
|
||||
.table-actions button {
|
||||
padding: 5px 10px;
|
||||
margin-right: 5px;
|
||||
border: none;
|
||||
border-radius: 3px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.table-actions .btn-ver {
|
||||
background-color: #007bff;
|
||||
color: white;
|
||||
}
|
||||
.table-actions .btn-ver:hover {
|
||||
background-color: #0056b3;
|
||||
}
|
||||
.table-actions .btn-memoria {
|
||||
background-color: #ffc107;
|
||||
color: #333;
|
||||
}
|
||||
.table-actions .btn-memoria:hover {
|
||||
background-color: #e0a800;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1>Panel de Gestión de Proyectos</h1>
|
||||
|
||||
<div class="action-buttons">
|
||||
<button onclick="location.href='/proyecto_memoria_tecnica'">Crear Nueva Memoria Técnica</button>
|
||||
</div>
|
||||
|
||||
<h2>Lista de Proyectos</h2>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>ID Proyecto</th>
|
||||
<th>Nombre del Proyecto</th>
|
||||
<th>Cliente</th>
|
||||
<th>Objetivo</th>
|
||||
<th>Estado</th>
|
||||
<th>Acciones</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<% if (proyectos && proyectos.length > 0) { %>
|
||||
<% proyectos.forEach(function(proyecto) { %>
|
||||
<tr>
|
||||
<td><%= proyecto.id %></td>
|
||||
<td><%= proyecto.nombre_proyecto %></td>
|
||||
<td><%= proyecto.nombre_cliente || 'N/A' %></td>
|
||||
<td><%= proyecto.objetivo %></td>
|
||||
<td><%= proyecto.estado %></td>
|
||||
<td class="table-actions">
|
||||
<button class="btn-ver" onclick="location.href='/proyectos/<%= proyecto.id %>'">Ver Detalles</button>
|
||||
<button class="btn-memoria" onclick="location.href='/proyecto_memoria_tecnica?proyectoId=<%= proyecto.id %>'">Memoria Técnica</button>
|
||||
</td>
|
||||
</tr>
|
||||
<% }); %>
|
||||
<% } else { %>
|
||||
<tr>
|
||||
<td colspan="6">No hay proyectos disponibles.</td>
|
||||
</tr>
|
||||
<% } %>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
284
src/views/pdf_memoria_tecnica.ejs
Normal file
284
src/views/pdf_memoria_tecnica.ejs
Normal file
@@ -0,0 +1,284 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="es">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Memoria Técnica - <%= memoria.id %></title>
|
||||
<style>
|
||||
/* Estilos CSS para el PDF */
|
||||
body {
|
||||
font-family: 'Arial', sans-serif;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-size: 10pt;
|
||||
line-height: 1.5;
|
||||
color: #333;
|
||||
}
|
||||
.header, .footer {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
position: fixed;
|
||||
font-size: 8pt;
|
||||
color: #555;
|
||||
}
|
||||
.header {
|
||||
top: 0;
|
||||
border-bottom: 1px solid #eee;
|
||||
padding-bottom: 5px;
|
||||
}
|
||||
.footer {
|
||||
bottom: 0;
|
||||
border-top: 1px solid #eee;
|
||||
padding-top: 5px;
|
||||
}
|
||||
.content {
|
||||
margin: 20mm; /* Márgenes definidos en page.pdf */
|
||||
}
|
||||
h1 {
|
||||
text-align: center;
|
||||
color: #007bff;
|
||||
font-size: 18pt;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
h2 {
|
||||
color: #0056b3;
|
||||
font-size: 14pt;
|
||||
border-bottom: 1px solid #007bff;
|
||||
padding-bottom: 5px;
|
||||
margin-top: 30px;
|
||||
}
|
||||
h3 {
|
||||
color: #333;
|
||||
font-size: 12pt;
|
||||
margin-top: 20px;
|
||||
}
|
||||
.section-block {
|
||||
margin-bottom: 20px;
|
||||
padding: 10px;
|
||||
border: 1px solid #eee;
|
||||
border-radius: 5px;
|
||||
background-color: #f9f9f9;
|
||||
}
|
||||
.data-item {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
.data-item strong {
|
||||
color: #007bff;
|
||||
display: inline-block;
|
||||
width: 150px; /* Ajusta según necesidad */
|
||||
}
|
||||
table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin-top: 10px;
|
||||
font-size: 9pt;
|
||||
}
|
||||
th, td {
|
||||
border: 1px solid #ddd;
|
||||
padding: 6px;
|
||||
text-align: left;
|
||||
}
|
||||
th {
|
||||
background-color: #e9ecef;
|
||||
color: #495057;
|
||||
}
|
||||
.text-area-content {
|
||||
white-space: pre-wrap; /* Mantiene saltos de línea y espacios */
|
||||
background-color: #fff;
|
||||
border: 1px solid #ddd;
|
||||
padding: 10px;
|
||||
border-radius: 4px;
|
||||
margin-top: 5px;
|
||||
}
|
||||
.image-gallery {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 10px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
.image-gallery img {
|
||||
max-width: 100%; /* Asegura que la imagen no se desborde */
|
||||
height: auto;
|
||||
border: 1px solid #ddd;
|
||||
padding: 5px;
|
||||
background-color: #fff;
|
||||
}
|
||||
.page-break {
|
||||
page-break-before: always;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="header">
|
||||
Memoria Técnica SIGMA - ID: <%= memoria.id %>
|
||||
</div>
|
||||
|
||||
<div class="footer">
|
||||
Página <span class="pageNumber"></span> de <span class="totalPages"></span>
|
||||
</div>
|
||||
|
||||
<div class="content">
|
||||
<h1>MEMORIA TÉCNICA DEL PROYECTO</h1>
|
||||
|
||||
<div class="section-block">
|
||||
<h2>Datos Generales de la Memoria</h2>
|
||||
<div class="data-item"><strong>ID Memoria:</strong> <%= memoria.id %></div>
|
||||
<div class="data-item"><strong>Proyecto:</strong> <%= proyecto ? proyecto.nombre_proyecto : 'N/A' %></div>
|
||||
<div class="data-item"><strong>Cliente:</strong> <%= proyecto ? proyecto.nombre_cliente : 'N/A' %></div>
|
||||
<div class="data-item"><strong>Empresa Autora:</strong> <%= empresaAutora ? (empresaAutora.RazonSocial || empresaAutora.Nombre) : 'N/A' %></div>
|
||||
<div class="data-item"><strong>Fecha Elaboración:</strong> <%= new Date(memoria.fecha_elaboracion).toLocaleDateString('es-ES', { year: 'numeric', month: 'long', day: 'numeric' }) %></div>
|
||||
<div class="data-item"><strong>Última Modificación:</strong> <%= new Date(memoria.ultima_modificacion).toLocaleDateString('es-ES', { year: 'numeric', month: 'long', day: 'numeric' }) %></div>
|
||||
<div class="data-item"><strong>Objetivo de la Memoria:</strong></div>
|
||||
<div class="text-area-content"><%= memoria.objetivo_memoria_especifico || 'No especificado.' %></div>
|
||||
<div class="data-item"><strong>Descripción/Introducción:</strong></div>
|
||||
<div class="text-area-content"><%= memoria.descripcion_introduccion || 'No especificado.' %></div>
|
||||
</div>
|
||||
|
||||
<% if (memoria.funcionamiento_operacion || memoria.conectividad_red || memoria.seguridad_fisica_logica || credenciales.length > 0) { %>
|
||||
<div class="page-break"></div>
|
||||
<div class="section-block">
|
||||
<h2>Información de Conectividad y Seguridad</h2>
|
||||
<% if (memoria.funcionamiento_operacion) { %>
|
||||
<h3>Funcionamiento y Operación:</h3>
|
||||
<div class="text-area-content"><%= memoria.funcionamiento_operacion %></div>
|
||||
<% } %>
|
||||
<% if (memoria.conectividad_red) { %>
|
||||
<h3>Conectividad de Red:</h3>
|
||||
<div class="text-area-content"><%= memoria.conectividad_red %></div>
|
||||
<% } %>
|
||||
<% if (memoria.acceso_remoto_aplicaciones) { %>
|
||||
<h3>Acceso Remoto y Aplicaciones:</h3>
|
||||
<div class="text-area-content"><%= memoria.acceso_remoto_aplicaciones %></div>
|
||||
<% } %>
|
||||
<% if (memoria.seguridad_fisica_logica) { %>
|
||||
<h3>Seguridad Física y Lógica:</h3>
|
||||
<div class="text-area-content"><%= memoria.seguridad_fisica_logica %></div>
|
||||
<% } %>
|
||||
|
||||
<% if (credenciales.length > 0) { %>
|
||||
<h3>Credenciales de Dispositivos:</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Tipo</th>
|
||||
<th>Valor</th>
|
||||
<th>Descripción</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<% credenciales.forEach(function(cred) { %>
|
||||
<tr>
|
||||
<td><%= cred.tipo_credencial %></td>
|
||||
<td><%= cred.valor_credencial %></td>
|
||||
<td><%= cred.descripcion || 'N/A' %></td>
|
||||
</tr>
|
||||
<% }); %>
|
||||
</tbody>
|
||||
</table>
|
||||
<% } %>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<% if (componentes.length > 0) { %>
|
||||
<div class="page-break"></div>
|
||||
<div class="section-block">
|
||||
<h2>Componentes del Proyecto</h2>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Nombre</th>
|
||||
<th>Tipo</th>
|
||||
<th>Modelo/Marca</th>
|
||||
<th>Nº Serie</th>
|
||||
<th>Ubicación</th>
|
||||
<th>Descripción</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<% componentes.forEach(function(comp) { %>
|
||||
<tr>
|
||||
<td><%= comp.nombre_componente %></td>
|
||||
<td><%= comp.tipo || 'N/A' %></td>
|
||||
<td><%= comp.modelo_marca || 'N/A' %></td>
|
||||
<td><%= comp.numero_serie || 'N/A' %></td>
|
||||
<td><%= comp.ubicacion || 'N/A' %></td>
|
||||
<td><%= comp.descripcion_breve || 'N/A' %></td>
|
||||
</tr>
|
||||
<% }); %>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<% if (mantenimiento.length > 0) { %>
|
||||
<div class="page-break"></div>
|
||||
<div class="section-block">
|
||||
<h2>Plan de Mantenimiento</h2>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Tipo Mantenimiento</th>
|
||||
<th>Frecuencia</th>
|
||||
<th>Tareas/Procedimientos</th>
|
||||
<th>Responsable</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<% mantenimiento.forEach(function(mtto) { %>
|
||||
<tr>
|
||||
<td><%= mtto.tipo_mantenimiento || 'N/A' %></td>
|
||||
<td><%= mtto.frecuencia || 'N/A' %></td>
|
||||
<td><%= mtto.tareas_procedimientos %></td>
|
||||
<td><%= mtto.responsable || 'N/A' %></td>
|
||||
</tr>
|
||||
<% }); %>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<% if (documentos.length > 0 || imagenes.length > 0) { %>
|
||||
<div class="page-break"></div>
|
||||
<div class="section-block">
|
||||
<h2>Documentos y Archivos Adjuntos</h2>
|
||||
<% if (documentos.length > 0) { %>
|
||||
<h3>Documentos:</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Nombre</th>
|
||||
<th>Descripción</th>
|
||||
<th>Tipo</th>
|
||||
<th>Tamaño</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<% documentos.forEach(function(doc) { %>
|
||||
<tr>
|
||||
<td><%= doc.nombre_documento %></td>
|
||||
<td><%= doc.descripcion || 'N/A' %></td>
|
||||
<td><%= doc.tipo_contenido || 'N/A' %></td>
|
||||
<td><%= (doc.tamano_bytes / 1024).toFixed(2) %> KB</td>
|
||||
</tr>
|
||||
<% }); %>
|
||||
</tbody>
|
||||
</table>
|
||||
<% } %>
|
||||
|
||||
<% if (imagenes.length > 0) { %>
|
||||
<h3 style="margin-top: 20px;">Imágenes / Planos:</h3>
|
||||
<div class="image-gallery">
|
||||
<% imagenes.forEach(function(img) { %>
|
||||
<div>
|
||||
<img src="<%= getFileUrl(img.ruta_imagen) %>" alt="<%= img.nombre_imagen %>" style="max-width: 300px; height: auto;">
|
||||
<p style="text-align: center; font-size: 8pt;"><%= img.nombre_imagen %></p>
|
||||
<p style="text-align: center; font-size: 7pt; color: #666;"><%= img.descripcion || '' %></p>
|
||||
</div>
|
||||
<% }); %>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
1124
src/views/proyecto_memoria_tecnica.ejs
Normal file
1124
src/views/proyecto_memoria_tecnica.ejs
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user