Cambios de unificacion en ingresos de visitas.
This commit is contained in:
@@ -1,69 +1,70 @@
|
||||
// src/controladores/controlador_Clientes_MiembrosVisitas.js
|
||||
|
||||
// NO NECESITARÁS 'moment-timezone' NI CÁLCULOS MANUALES COMPLEJOS
|
||||
// const moment = require('moment-timezone');
|
||||
|
||||
// ¡IMPORTANTE: Cambia el nombre de esta constante para que coincida con la importación en rt_clientes.js!
|
||||
const controlador_Clientes_MiembrosVisitas = {
|
||||
|
||||
/**
|
||||
* @function registrarVisita
|
||||
* @description Registra una nueva visita de miembro en la tabla clientes_miembros_visitas.
|
||||
* @param {Object} req - Objeto de solicitud de Express.
|
||||
* @function crearVisita
|
||||
* @description Registra una nueva visita en la tabla `clientes_miembros_visitas`.
|
||||
* Maneja tanto visitas de miembros como de clientes ocasionales.
|
||||
* @param {Object} req - Objeto de solicitud de Express (req.body).
|
||||
* @param {Object} res - Objeto de respuesta de Express.
|
||||
*/
|
||||
registrarVisita: (req, res) => {
|
||||
crearVisita: (req, res) => {
|
||||
req.getConnection((err, connection) => {
|
||||
if (err) {
|
||||
console.error('Error al obtener conexión para registrar visita:', err);
|
||||
console.error('Error al obtener conexión para crear visita:', err);
|
||||
return res.status(500).json({ mensaje: 'Error interno del servidor al obtener conexión', error: err.message });
|
||||
}
|
||||
|
||||
const {
|
||||
id_miembro,
|
||||
matricula_registrada,
|
||||
client_id, // Obligatorio, siempre debe estar
|
||||
es_miembro, // Booleano: true (1) o false (0)
|
||||
id_miembro, // Opcional, solo si es_miembro es true
|
||||
nombre_area_acceso,
|
||||
estado_acceso, // 'CONCEDIDO' o 'DENEGADO'
|
||||
estado_acceso,
|
||||
motivo_denegacion,
|
||||
registrado_por,
|
||||
observaciones
|
||||
} = req.body;
|
||||
|
||||
// Validación básica de los campos requeridos
|
||||
if (!id_miembro || !matricula_registrada || !nombre_area_acceso || !estado_acceso) {
|
||||
return res.status(400).json({ mensaje: 'Faltan campos obligatorios para registrar la visita (id_miembro, matricula_registrada, nombre_area_acceso, estado_acceso).' });
|
||||
// Validaciones básicas de campos obligatorios
|
||||
if (client_id === undefined || client_id === null || !nombre_area_acceso || !estado_acceso || es_miembro === undefined || es_miembro === null) {
|
||||
return res.status(400).json({ mensaje: 'Faltan campos obligatorios (client_id, nombre_area_acceso, estado_acceso, es_miembro).' });
|
||||
}
|
||||
|
||||
// Asegúrate de que estado_acceso sea uno de los valores ENUM permitidos
|
||||
if (!['CONCEDIDO', 'DENEGADO'].includes(estado_acceso.toUpperCase())) {
|
||||
return res.status(400).json({ mensaje: 'El estado de acceso debe ser "CONCEDIDO" o "DENEGADO".' });
|
||||
}
|
||||
|
||||
// --- SIMPLIFICACIÓN: Usar la fecha nativa de JavaScript ---
|
||||
const now = new Date(); // Esto obtendrá la fecha y hora local del servidor (Quito)
|
||||
// Validación de coherencia entre `es_miembro` y `id_miembro` (gestionada por código)
|
||||
if (es_miembro && (id_miembro === undefined || id_miembro === null)) {
|
||||
return res.status(400).json({ mensaje: 'Si es_miembro es TRUE, id_miembro es obligatorio.' });
|
||||
}
|
||||
if (!es_miembro && (id_miembro !== undefined && id_miembro !== null)) {
|
||||
return res.status(400).json({ mensaje: 'Si es_miembro es FALSE, id_miembro no debe ser proporcionado.' });
|
||||
}
|
||||
|
||||
// Formatear la fecha y hora a 'YYYY-MM-DD HH:mm:ss' para MySQL
|
||||
// Usar la fecha nativa de JavaScript, asumiendo que el servidor está en UTC-5 (Quito)
|
||||
const now = new Date();
|
||||
const year = now.getFullYear();
|
||||
const month = String(now.getMonth() + 1).padStart(2, '0'); // getMonth() es 0-indexado
|
||||
const month = String(now.getMonth() + 1).padStart(2, '0');
|
||||
const day = String(now.getDate()).padStart(2, '0');
|
||||
const hours = String(now.getHours()).padStart(2, '0');
|
||||
const minutes = String(now.getMinutes()).padStart(2, '0');
|
||||
const seconds = String(now.getSeconds()).padStart(2, '0');
|
||||
|
||||
const fecha_hora_visita = `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
|
||||
// ---------------------------------------------------
|
||||
|
||||
const query = `
|
||||
INSERT INTO clientes_miembros_visitas
|
||||
(id_miembro, matricula_registrada, fecha_hora_visita, nombre_area_acceso, estado_acceso, motivo_denegacion, registrado_por, observaciones)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
||||
(client_id, es_miembro, id_miembro, fecha_hora_visita, nombre_area_acceso, estado_acceso, motivo_denegacion, registrado_por, observaciones)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
`;
|
||||
const values = [
|
||||
id_miembro,
|
||||
matricula_registrada,
|
||||
fecha_hora_visita, // Usa la fecha formateada
|
||||
client_id,
|
||||
es_miembro, // Se insertará como 1 (TRUE) o 0 (FALSE) en MySQL
|
||||
es_miembro ? id_miembro : null, // Inserta id_miembro si es miembro, de lo contrario NULL
|
||||
fecha_hora_visita,
|
||||
nombre_area_acceso,
|
||||
estado_acceso.toUpperCase(), // Asegura que se guarde en mayúsculas
|
||||
estado_acceso.toUpperCase(),
|
||||
motivo_denegacion || null,
|
||||
registrado_por || null,
|
||||
observaciones || null
|
||||
@@ -71,11 +72,14 @@ const controlador_Clientes_MiembrosVisitas = {
|
||||
|
||||
connection.query(query, values, (err, result) => {
|
||||
if (err) {
|
||||
console.error('Error al registrar visita:', err);
|
||||
console.error('Error al crear visita:', err);
|
||||
if (err.code === 'ER_NO_REFERENCED_ROW_2' || err.code === 'ER_NO_REFERENCED_ROW') {
|
||||
return res.status(400).json({ mensaje: 'El ID de miembro especificado no existe. Asegúrate de que el miembro esté registrado en el sistema.', error: err.message });
|
||||
let msg = 'El ID de cliente o ID de miembro especificado no existe.';
|
||||
if (es_miembro) msg += ' Asegúrese de que el miembro y su cliente asociado existan.';
|
||||
else msg += ' Asegúrese de que el cliente exista.';
|
||||
return res.status(400).json({ mensaje: msg, error: err.message });
|
||||
}
|
||||
return res.status(500).json({ mensaje: 'Error interno del servidor al registrar la visita', error: err.message });
|
||||
return res.status(500).json({ mensaje: 'Error interno del servidor al crear la visita', error: err.message });
|
||||
}
|
||||
|
||||
if (result.affectedRows === 1) {
|
||||
@@ -83,15 +87,16 @@ const controlador_Clientes_MiembrosVisitas = {
|
||||
mensaje: 'Visita registrada exitosamente.',
|
||||
id_visita: result.insertId,
|
||||
datos_visita: {
|
||||
id_miembro,
|
||||
matricula_registrada,
|
||||
client_id,
|
||||
es_miembro,
|
||||
id_miembro: es_miembro ? id_miembro : null,
|
||||
nombre_area_acceso,
|
||||
estado_acceso,
|
||||
fecha_hora_visita // Devuelve la fecha formateada
|
||||
fecha_hora_visita
|
||||
}
|
||||
});
|
||||
} else {
|
||||
res.status(500).json({ mensaje: 'Error al registrar la visita: no se afectó ninguna fila.' });
|
||||
res.status(500).json({ mensaje: 'Error al crear la visita: no se afectó ninguna fila.' });
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -99,8 +104,9 @@ const controlador_Clientes_MiembrosVisitas = {
|
||||
|
||||
/**
|
||||
* @function listarVisitas
|
||||
* @description Lista todos los registros de visitas.
|
||||
* @param {Object} req - Objeto de solicitud de Express.
|
||||
* @description Lista todas las visitas, con información detallada de cliente y miembro si aplica.
|
||||
* Soporta filtros opcionales por client_id, id_miembro, estado_acceso, nombre_area_acceso, y rango de fechas.
|
||||
* @param {Object} req - Objeto de solicitud de Express (req.query para filtros).
|
||||
* @param {Object} res - Objeto de respuesta de Express.
|
||||
*/
|
||||
listarVisitas: (req, res) => {
|
||||
@@ -110,30 +116,81 @@ const controlador_Clientes_MiembrosVisitas = {
|
||||
return res.status(500).json({ mensaje: 'Error interno del servidor al obtener conexión', error: err.message });
|
||||
}
|
||||
|
||||
const query = `
|
||||
let query = `
|
||||
SELECT
|
||||
cv.id_visita,
|
||||
cv.id_miembro,
|
||||
cmv.id_visita,
|
||||
cmv.fecha_hora_visita,
|
||||
cmv.nombre_area_acceso,
|
||||
cmv.estado_acceso,
|
||||
cmv.motivo_denegacion,
|
||||
cmv.registrado_por,
|
||||
cmv.observaciones,
|
||||
cmv.client_id,
|
||||
cli.client_nombre,
|
||||
cli.client_rucCed,
|
||||
cmv.es_miembro,
|
||||
cmv.id_miembro,
|
||||
cm.matricula AS matricula_miembro,
|
||||
cli.client_nombre AS nombre_cliente,
|
||||
cv.matricula_registrada,
|
||||
cv.fecha_hora_visita,
|
||||
cv.nombre_area_acceso,
|
||||
cv.estado_acceso,
|
||||
cv.motivo_denegacion,
|
||||
cv.registrado_por,
|
||||
cv.observaciones,
|
||||
cv.fecha_creacion
|
||||
ctm.nombre_tipo AS nombre_tipo_membresia,
|
||||
cmv.fecha_creacion,
|
||||
cmv.fecha_actualizacion
|
||||
FROM
|
||||
clientes_miembros_visitas cv
|
||||
clientes_miembros_visitas cmv
|
||||
JOIN
|
||||
clientes_miembros cm ON cv.id_miembro = cm.id_miembro
|
||||
JOIN
|
||||
clientes cli ON cm.client_id = cli.client_id
|
||||
ORDER BY cv.fecha_hora_visita DESC
|
||||
clientes cli ON cmv.client_id = cli.client_id
|
||||
LEFT JOIN
|
||||
clientes_miembros cm ON cmv.id_miembro = cm.id_miembro
|
||||
LEFT JOIN
|
||||
clientes_membresias ctm ON cm.id_tipo_membresia = ctm.id_tipo_membresia
|
||||
WHERE 1=1
|
||||
`;
|
||||
const queryParams = [];
|
||||
|
||||
connection.query(query, (err, rows) => {
|
||||
// Aplicar filtros desde req.query
|
||||
if (req.query.client_id) {
|
||||
query += ` AND cmv.client_id = ?`;
|
||||
queryParams.push(req.query.client_id);
|
||||
}
|
||||
if (req.query.id_miembro) {
|
||||
query += ` AND cmv.id_miembro = ?`;
|
||||
queryParams.push(req.query.id_miembro);
|
||||
}
|
||||
if (req.query.estado_acceso) {
|
||||
const estado = req.query.estado_acceso.toUpperCase();
|
||||
if (['CONCEDIDO', 'DENEGADO'].includes(estado)) {
|
||||
query += ` AND cmv.estado_acceso = ?`;
|
||||
queryParams.push(estado);
|
||||
} else {
|
||||
return res.status(400).json({ mensaje: 'Estado de acceso inválido para el filtro.' });
|
||||
}
|
||||
}
|
||||
if (req.query.nombre_area) {
|
||||
query += ` AND cmv.nombre_area_acceso LIKE ?`;
|
||||
queryParams.push(`%${req.query.nombre_area}%`);
|
||||
}
|
||||
if (req.query.fecha_desde) {
|
||||
query += ` AND cmv.fecha_hora_visita >= ?`;
|
||||
queryParams.push(req.query.fecha_desde + ' 00:00:00'); // Desde el inicio del día
|
||||
}
|
||||
if (req.query.fecha_hasta) {
|
||||
query += ` AND cmv.fecha_hora_visita <= ?`;
|
||||
queryParams.push(req.query.fecha_hasta + ' 23:59:59'); // Hasta el final del día
|
||||
}
|
||||
// Filtro para `es_miembro` (true/false)
|
||||
if (req.query.es_miembro !== undefined && req.query.es_miembro !== null) {
|
||||
const esMiembroBool = req.query.es_miembro === 'true' || req.query.es_miembro === '1';
|
||||
query += ` AND cmv.es_miembro = ?`;
|
||||
queryParams.push(esMiembroBool);
|
||||
}
|
||||
|
||||
query += ` ORDER BY cmv.fecha_hora_visita DESC`;
|
||||
// Implementar paginación si se necesita
|
||||
// if (req.query.limit && req.query.offset) {
|
||||
// query += ` LIMIT ? OFFSET ?`;
|
||||
// queryParams.push(parseInt(req.query.limit), parseInt(req.query.offset));
|
||||
// }
|
||||
|
||||
connection.query(query, queryParams, (err, rows) => {
|
||||
if (err) {
|
||||
console.error('Error al listar visitas:', err);
|
||||
return res.status(500).json({ mensaje: 'Error interno del servidor al listar visitas', error: err.message });
|
||||
@@ -159,25 +216,31 @@ const controlador_Clientes_MiembrosVisitas = {
|
||||
|
||||
const query = `
|
||||
SELECT
|
||||
cv.id_visita,
|
||||
cv.id_miembro,
|
||||
cmv.id_visita,
|
||||
cmv.fecha_hora_visita,
|
||||
cmv.nombre_area_acceso,
|
||||
cmv.estado_acceso,
|
||||
cmv.motivo_denegacion,
|
||||
cmv.registrado_por,
|
||||
cmv.observaciones,
|
||||
cmv.client_id,
|
||||
cli.client_nombre,
|
||||
cli.client_rucCed,
|
||||
cmv.es_miembro,
|
||||
cmv.id_miembro,
|
||||
cm.matricula AS matricula_miembro,
|
||||
cli.client_nombre AS nombre_cliente,
|
||||
cv.matricula_registrada,
|
||||
cv.fecha_hora_visita,
|
||||
cv.nombre_area_acceso,
|
||||
cv.estado_acceso,
|
||||
cv.motivo_denegacion,
|
||||
cv.registrado_por,
|
||||
cv.observaciones,
|
||||
cv.fecha_creacion
|
||||
ctm.nombre_tipo AS nombre_tipo_membresia,
|
||||
cmv.fecha_creacion,
|
||||
cmv.fecha_actualizacion
|
||||
FROM
|
||||
clientes_miembros_visitas cv
|
||||
clientes_miembros_visitas cmv
|
||||
JOIN
|
||||
clientes_miembros cm ON cv.id_miembro = cm.id_miembro
|
||||
JOIN
|
||||
clientes cli ON cm.client_id = cli.client_id
|
||||
WHERE cv.id_visita = ?
|
||||
clientes cli ON cmv.client_id = cli.client_id
|
||||
LEFT JOIN
|
||||
clientes_miembros cm ON cmv.id_miembro = cm.id_miembro
|
||||
LEFT JOIN
|
||||
clientes_membresias ctm ON cm.id_tipo_membresia = ctm.id_tipo_membresia
|
||||
WHERE cmv.id_visita = ?
|
||||
`;
|
||||
|
||||
connection.query(query, [id_visita], (err, rows) => {
|
||||
@@ -193,9 +256,164 @@ const controlador_Clientes_MiembrosVisitas = {
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* @function actualizarVisita
|
||||
* @description Actualiza un registro de visita existente por su ID en `clientes_miembros_visitas`.
|
||||
* Solo permite actualizar campos como área, estado, motivo, registrado_por, observaciones.
|
||||
* NO se permite actualizar `client_id`, `es_miembro`, `id_miembro` o `fecha_hora_visita`.
|
||||
* @param {Object} req - Objeto de solicitud de Express (req.params.id_visita, req.body).
|
||||
* @param {Object} res - Objeto de respuesta de Express.
|
||||
*/
|
||||
actualizarVisita: (req, res) => {
|
||||
const { id_visita } = req.params;
|
||||
const {
|
||||
nombre_area_acceso,
|
||||
estado_acceso,
|
||||
motivo_denegacion,
|
||||
registrado_por,
|
||||
observaciones
|
||||
} = req.body;
|
||||
|
||||
if (!nombre_area_acceso || !estado_acceso) {
|
||||
return res.status(400).json({ mensaje: 'Faltan campos obligatorios para actualizar la visita (nombre_area_acceso, estado_acceso).' });
|
||||
}
|
||||
if (!['CONCEDIDO', 'DENEGADO'].includes(estado_acceso.toUpperCase())) {
|
||||
return res.status(400).json({ mensaje: 'El estado de acceso debe ser "CONCEDIDO" o "DENEGADO".' });
|
||||
}
|
||||
|
||||
req.getConnection((err, connection) => {
|
||||
if (err) {
|
||||
console.error('Error al obtener conexión para actualizar visita:', err);
|
||||
return res.status(500).json({ mensaje: 'Error interno del servidor al obtener conexión', error: err.message });
|
||||
}
|
||||
|
||||
const query = `
|
||||
UPDATE clientes_miembros_visitas SET
|
||||
nombre_area_acceso = ?,
|
||||
estado_acceso = ?,
|
||||
motivo_denegacion = ?,
|
||||
registrado_por = ?,
|
||||
observaciones = ?,
|
||||
fecha_actualizacion = CURRENT_TIMESTAMP()
|
||||
WHERE id_visita = ?
|
||||
`;
|
||||
const values = [
|
||||
nombre_area_acceso,
|
||||
estado_acceso.toUpperCase(),
|
||||
motivo_denegacion || null,
|
||||
registrado_por || null,
|
||||
observaciones || null,
|
||||
id_visita
|
||||
];
|
||||
|
||||
connection.query(query, values, (err, result) => {
|
||||
if (err) {
|
||||
console.error('Error al actualizar visita:', err);
|
||||
return res.status(500).json({ mensaje: 'Error interno del servidor al actualizar visita', error: err.message });
|
||||
}
|
||||
|
||||
if (result.affectedRows === 0) {
|
||||
return res.status(404).json({ mensaje: 'Visita no encontrada para actualizar' });
|
||||
}
|
||||
res.json({ mensaje: 'Visita actualizada exitosamente' });
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* @function eliminarVisita
|
||||
* @description Elimina físicamente una visita de la tabla `clientes_miembros_visitas`.
|
||||
* NOTA: Para propósitos de auditoría, a menudo se prefiere una "eliminación lógica"
|
||||
* (por ejemplo, actualizando un campo `estado_visita` a 'ANULADA').
|
||||
* @param {Object} req - Objeto de solicitud de Express (req.params.id_visita).
|
||||
* @param {Object} res - Objeto de respuesta de Express.
|
||||
*/
|
||||
eliminarVisita: (req, res) => {
|
||||
const { id_visita } = req.params;
|
||||
req.getConnection((err, connection) => {
|
||||
if (err) {
|
||||
console.error('Error al obtener conexión para eliminar visita:', err);
|
||||
return res.status(500).json({ mensaje: 'Error interno del servidor al obtener conexión', error: err.message });
|
||||
}
|
||||
|
||||
const query = `DELETE FROM clientes_miembros_visitas WHERE id_visita = ?`;
|
||||
|
||||
connection.query(query, [id_visita], (err, result) => {
|
||||
if (err) {
|
||||
console.error('Error al eliminar visita:', err);
|
||||
return res.status(500).json({ mensaje: 'Error interno del servidor al eliminar visita', error: err.message });
|
||||
}
|
||||
|
||||
if (result.affectedRows === 0) {
|
||||
return res.status(404).json({ mensaje: 'Visita no encontrada para eliminar' });
|
||||
}
|
||||
res.json({ mensaje: 'Visita eliminada exitosamente.' });
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* @function listarVisitasPorCliente
|
||||
* @description Lista visitas filtradas por un `client_id` específico.
|
||||
* Incluye tanto visitas de miembros como de clientes ocasionales asociados a ese cliente.
|
||||
* @param {Object} req - Objeto de solicitud de Express (req.params.client_id).
|
||||
* @param {Object} res - Objeto de respuesta de Express.
|
||||
*/
|
||||
listarVisitasPorCliente: (req, res) => {
|
||||
const { client_id } = req.params;
|
||||
req.getConnection((err, connection) => {
|
||||
if (err) {
|
||||
console.error('Error al obtener conexión para listar visitas por cliente:', err);
|
||||
return res.status(500).json({ mensaje: 'Error interno del servidor al obtener conexión', error: err.message });
|
||||
}
|
||||
|
||||
const query = `
|
||||
SELECT
|
||||
cmv.id_visita,
|
||||
cmv.fecha_hora_visita,
|
||||
cmv.nombre_area_acceso,
|
||||
cmv.estado_acceso,
|
||||
cmv.motivo_denegacion,
|
||||
cmv.registrado_por,
|
||||
cmv.observaciones,
|
||||
cmv.client_id,
|
||||
cli.client_nombre,
|
||||
cli.client_rucCed,
|
||||
cmv.es_miembro,
|
||||
cmv.id_miembro,
|
||||
cm.matricula AS matricula_miembro,
|
||||
ctm.nombre_tipo AS nombre_tipo_membresia,
|
||||
cmv.fecha_creacion,
|
||||
cmv.fecha_actualizacion
|
||||
FROM
|
||||
clientes_miembros_visitas cmv
|
||||
JOIN
|
||||
clientes cli ON cmv.client_id = cli.client_id
|
||||
LEFT JOIN
|
||||
clientes_miembros cm ON cmv.id_miembro = cm.id_miembro
|
||||
LEFT JOIN
|
||||
clientes_membresias ctm ON cm.id_tipo_membresia = ctm.id_tipo_membresia
|
||||
WHERE cmv.client_id = ?
|
||||
ORDER BY cmv.fecha_hora_visita DESC
|
||||
`;
|
||||
|
||||
connection.query(query, [client_id], (err, rows) => {
|
||||
if (err) {
|
||||
console.error('Error al listar visitas por cliente:', err);
|
||||
return res.status(500).json({ mensaje: 'Error interno del servidor al listar visitas por cliente', error: err.message });
|
||||
}
|
||||
if (rows.length === 0) {
|
||||
return res.status(404).json({ mensaje: 'No se encontraron visitas para el cliente proporcionado.' });
|
||||
}
|
||||
res.json(rows);
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* @function listarVisitasPorMiembro
|
||||
* @description Lista el historial de visitas para un miembro específico por su id_miembro.
|
||||
* @description Lista visitas filtradas por un `id_miembro` específico.
|
||||
* Solo devolverá visitas donde `es_miembro` sea TRUE.
|
||||
* @param {Object} req - Objeto de solicitud de Express (req.params.id_miembro).
|
||||
* @param {Object} res - Objeto de respuesta de Express.
|
||||
*/
|
||||
@@ -209,18 +427,32 @@ const controlador_Clientes_MiembrosVisitas = {
|
||||
|
||||
const query = `
|
||||
SELECT
|
||||
cv.id_visita,
|
||||
cv.matricula_registrada,
|
||||
cv.fecha_hora_visita,
|
||||
cv.nombre_area_acceso,
|
||||
cv.estado_acceso,
|
||||
cv.motivo_denegacion,
|
||||
cv.registrado_por,
|
||||
cv.observaciones
|
||||
cmv.id_visita,
|
||||
cmv.fecha_hora_visita,
|
||||
cmv.nombre_area_acceso,
|
||||
cmv.estado_acceso,
|
||||
cmv.motivo_denegacion,
|
||||
cmv.registrado_por,
|
||||
cmv.observaciones,
|
||||
cmv.client_id,
|
||||
cli.client_nombre,
|
||||
cli.client_rucCed,
|
||||
cmv.es_miembro,
|
||||
cmv.id_miembro,
|
||||
cm.matricula AS matricula_miembro,
|
||||
ctm.nombre_tipo AS nombre_tipo_membresia,
|
||||
cmv.fecha_creacion,
|
||||
cmv.fecha_actualizacion
|
||||
FROM
|
||||
clientes_miembros_visitas cv
|
||||
WHERE cv.id_miembro = ?
|
||||
ORDER BY cv.fecha_hora_visita DESC
|
||||
clientes_miembros_visitas cmv
|
||||
JOIN
|
||||
clientes cli ON cmv.client_id = cli.client_id
|
||||
JOIN
|
||||
clientes_miembros cm ON cmv.id_miembro = cm.id_miembro AND cmv.es_miembro = TRUE
|
||||
LEFT JOIN
|
||||
clientes_membresias ctm ON cm.id_tipo_membresia = ctm.id_tipo_membresia
|
||||
WHERE cmv.id_miembro = ?
|
||||
ORDER BY cmv.fecha_hora_visita DESC
|
||||
`;
|
||||
|
||||
connection.query(query, [id_miembro], (err, rows) => {
|
||||
@@ -229,7 +461,7 @@ const controlador_Clientes_MiembrosVisitas = {
|
||||
return res.status(500).json({ mensaje: 'Error interno del servidor al listar visitas por miembro', error: err.message });
|
||||
}
|
||||
if (rows.length === 0) {
|
||||
return res.status(404).json({ mensaje: 'No se encontraron visitas para el miembro con el ID proporcionado.' });
|
||||
return res.status(404).json({ mensaje: 'No se encontraron visitas para el miembro proporcionado.' });
|
||||
}
|
||||
res.json(rows);
|
||||
});
|
||||
@@ -238,13 +470,12 @@ const controlador_Clientes_MiembrosVisitas = {
|
||||
|
||||
/**
|
||||
* @function listarVisitasPorEstadoAcceso
|
||||
* @description Lista las visitas filtradas por un estado de acceso específico (CONCEDIDO/DENEGADO).
|
||||
* @description Lista visitas filtradas por un estado de acceso específico (CONCEDIDO/DENEGADO).
|
||||
* @param {Object} req - Objeto de solicitud de Express (req.params.estado_acceso).
|
||||
* @param {Object} res - Objeto de respuesta de Express.
|
||||
*/
|
||||
listarVisitasPorEstadoAcceso: (req, res) => {
|
||||
const { estado_acceso } = req.params;
|
||||
// Validar que el estado sea uno de los permitidos por el ENUM
|
||||
const estadosPermitidos = ['CONCEDIDO', 'DENEGADO'];
|
||||
if (!estadosPermitidos.includes(estado_acceso.toUpperCase())) {
|
||||
return res.status(400).json({ mensaje: `El estado de acceso proporcionado '${estado_acceso}' no es válido. Los estados permitidos son: ${estadosPermitidos.join(', ')}.` });
|
||||
@@ -258,23 +489,30 @@ const controlador_Clientes_MiembrosVisitas = {
|
||||
|
||||
const query = `
|
||||
SELECT
|
||||
cv.id_visita,
|
||||
cv.id_miembro,
|
||||
cmv.id_visita,
|
||||
cmv.fecha_hora_visita,
|
||||
cmv.nombre_area_acceso,
|
||||
cmv.estado_acceso,
|
||||
cmv.motivo_denegacion,
|
||||
cmv.registrado_por,
|
||||
cmv.observaciones,
|
||||
cmv.client_id,
|
||||
cli.client_nombre,
|
||||
cli.client_rucCed,
|
||||
cmv.es_miembro,
|
||||
cmv.id_miembro,
|
||||
cm.matricula AS matricula_miembro,
|
||||
cli.client_nombre AS nombre_cliente,
|
||||
cv.matricula_registrada,
|
||||
cv.fecha_hora_visita,
|
||||
cv.nombre_area_acceso,
|
||||
cv.estado_acceso,
|
||||
cv.motivo_denegacion
|
||||
ctm.nombre_tipo AS nombre_tipo_membresia
|
||||
FROM
|
||||
clientes_miembros_visitas cv
|
||||
clientes_miembros_visitas cmv
|
||||
JOIN
|
||||
clientes_miembros cm ON cv.id_miembro = cm.id_miembro
|
||||
JOIN
|
||||
clientes cli ON cm.client_id = cli.client_id
|
||||
WHERE cv.estado_acceso = ?
|
||||
ORDER BY cv.fecha_hora_visita DESC
|
||||
clientes cli ON cmv.client_id = cli.client_id
|
||||
LEFT JOIN
|
||||
clientes_miembros cm ON cmv.id_miembro = cm.id_miembro
|
||||
LEFT JOIN
|
||||
clientes_membresias ctm ON cm.id_tipo_membresia = ctm.id_tipo_membresia
|
||||
WHERE cmv.estado_acceso = ?
|
||||
ORDER BY cmv.fecha_hora_visita DESC
|
||||
`;
|
||||
|
||||
connection.query(query, [estado_acceso.toUpperCase()], (err, rows) => {
|
||||
@@ -289,13 +527,12 @@ const controlador_Clientes_MiembrosVisitas = {
|
||||
|
||||
/**
|
||||
* @function listarVisitasPorArea
|
||||
* @description Lista las visitas filtradas por el nombre del área de acceso.
|
||||
* @description Lista visitas filtradas por el nombre del área de acceso.
|
||||
* @param {Object} req - Objeto de solicitud de Express (req.params.nombre_area).
|
||||
* @param {Object} res - Objeto de respuesta de Express.
|
||||
*/
|
||||
listarVisitasPorArea: (req, res) => {
|
||||
const { nombre_area } = req.params;
|
||||
|
||||
if (!nombre_area) {
|
||||
return res.status(400).json({ mensaje: 'El nombre del área es obligatorio.' });
|
||||
}
|
||||
@@ -308,26 +545,33 @@ const controlador_Clientes_MiembrosVisitas = {
|
||||
|
||||
const query = `
|
||||
SELECT
|
||||
cv.id_visita,
|
||||
cv.id_miembro,
|
||||
cmv.id_visita,
|
||||
cmv.fecha_hora_visita,
|
||||
cmv.nombre_area_acceso,
|
||||
cmv.estado_acceso,
|
||||
cmv.motivo_denegacion,
|
||||
cmv.registrado_por,
|
||||
cmv.observaciones,
|
||||
cmv.client_id,
|
||||
cli.client_nombre,
|
||||
cli.client_rucCed,
|
||||
cmv.es_miembro,
|
||||
cmv.id_miembro,
|
||||
cm.matricula AS matricula_miembro,
|
||||
cli.client_nombre AS nombre_cliente,
|
||||
cv.matricula_registrada,
|
||||
cv.fecha_hora_visita,
|
||||
cv.nombre_area_acceso,
|
||||
cv.estado_acceso,
|
||||
cv.motivo_denegacion
|
||||
ctm.nombre_tipo AS nombre_tipo_membresia
|
||||
FROM
|
||||
clientes_miembros_visitas cv
|
||||
clientes_miembros_visitas cmv
|
||||
JOIN
|
||||
clientes_miembros cm ON cv.id_miembro = cm.id_miembro
|
||||
JOIN
|
||||
clientes cli ON cm.client_id = cli.client_id
|
||||
WHERE cv.nombre_area_acceso LIKE ?
|
||||
ORDER BY cv.fecha_hora_visita DESC
|
||||
clientes cli ON cmv.client_id = cli.client_id
|
||||
LEFT JOIN
|
||||
clientes_miembros cm ON cmv.id_miembro = cm.id_miembro
|
||||
LEFT JOIN
|
||||
clientes_membresias ctm ON cm.id_tipo_membresia = ctm.id_tipo_membresia
|
||||
WHERE cmv.nombre_area_acceso LIKE ?
|
||||
ORDER BY cmv.fecha_hora_visita DESC
|
||||
`;
|
||||
|
||||
connection.query(query, [`%${nombre_area}%`], (err, rows) => { // Uso de LIKE para búsqueda parcial
|
||||
connection.query(query, [`%${nombre_area}%`], (err, rows) => {
|
||||
if (err) {
|
||||
console.error('Error al listar visitas por área:', err);
|
||||
return res.status(500).json({ mensaje: 'Error interno del servidor al listar visitas por área', error: err.message });
|
||||
@@ -336,7 +580,6 @@ const controlador_Clientes_MiembrosVisitas = {
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
module.exports = controlador_Clientes_MiembrosVisitas;
|
||||
@@ -5,7 +5,7 @@ const controladorClientes = require('../controladores/controlador_Clientes');
|
||||
const controladorMembresias = require('../controladores/controlador_Clientes_Membresias');
|
||||
const controladorMiembros = require('../controladores/controlador_Clientes_Miembros');
|
||||
const controladorAreas = require('../controladores/controlador_Areas'); // Controlador para áreas de configuración
|
||||
const controladorVisitasMiembros = require('../controladores/controlador_Clientes_MiembrosVisitas'); // Controlador para visitas de miembros
|
||||
const controladorVisitas = require('../controladores/controlador_Clientes_MiembrosVisitas'); // Controlador para visitas de miembros
|
||||
|
||||
//indice inical
|
||||
rutas.get('/clientes', controladorClientes.ver);//ver lista de clientes
|
||||
@@ -44,57 +44,45 @@ rutas.delete('/api/tipos-membresia/:id', controladorMembresias.eliminarTipoMembr
|
||||
// --- Rutas RESTful para MIEMBROS (tabla 'clientes_miembros') ---
|
||||
// Estas rutas apuntarán al nuevo controlador_Miembros
|
||||
// Obtener todos los miembros
|
||||
// GET /api/miembros
|
||||
rutas.get('/api/miembros', controladorMiembros.listarMiembros);
|
||||
// Obtener un miembro por su ID
|
||||
// GET /api/miembros/:id_miembro
|
||||
rutas.get('/api/miembros/:id_miembro', controladorMiembros.obtenerMiembroPorId);
|
||||
// Crear un nuevo miembro
|
||||
// POST /api/miembros
|
||||
// Datos esperados en el cuerpo de la solicitud: matricula, client_id, id_tipo_membresia, fecha_inicio, fecha_fin, etc.
|
||||
rutas.post('/api/miembros', controladorMiembros.crearMiembro);
|
||||
// Actualizar un miembro existente por su ID
|
||||
// PUT /api/miembros/:id_miembro
|
||||
// Datos esperados en el cuerpo de la solicitud para actualizar: estado, fechas, etc.
|
||||
rutas.put('/api/miembros/:id_miembro', controladorMiembros.actualizarMiembro);
|
||||
// Eliminar (lógicamente/cambiar estado a CANCELADO/SUSPENDIDO) un miembro por su ID
|
||||
// DELETE /api/miembros/:id_miembro
|
||||
// NOTA: Dada la importancia del historial, es más común cambiar el estado a 'CANCELADO' o 'SUSPENDIDO'
|
||||
// en lugar de una eliminación física. El controlador debería manejar esto.
|
||||
rutas.delete('/api/miembros/:id_miembro', controladorMiembros.eliminarMiembro);
|
||||
|
||||
// --- Rutas Adicionales Comunes para Miembros (Opcional) ---
|
||||
// Obtener miembros por client_id (útil para ver todas las membresías de un cliente)
|
||||
// GET /api/clientes/:client_id/miembros
|
||||
rutas.get('/api/clientes/:client_id/miembros', controladorMiembros.listarMiembrosPorCliente);
|
||||
// Obtener miembros por estado (ej. 'ACTIVO', 'VENCIDO')
|
||||
// GET /api/miembros/estado/:estado
|
||||
rutas.get('/api/miembros/estado/:estado', controladorMiembros.listarMiembrosPorEstado);
|
||||
// Obtener miembros por tipo de membresía
|
||||
// GET /api/tipos-membresia/:id_tipo_membresia/miembros
|
||||
rutas.get('/api/tipos-membresia/:id_tipo_membresia/miembros', controladorMiembros.listarMiembrosPorTipoMembresia);
|
||||
|
||||
// --- Rutas RESTful para VISITAS de Miembros (tabla 'clientes_miembros_visitas') ---
|
||||
// Estas rutas apuntarán al nuevo controlador_VisitasMiembros
|
||||
// Registrar una nueva visita de miembro
|
||||
// POST /api/visitas-miembros
|
||||
// Datos esperados en el cuerpo: id_miembro, matricula_registrada, nombre_area_acceso, estado_acceso, motivo_denegacion (opcional), registrado_por (opcional), observaciones (opcional)
|
||||
rutas.post('/api/visitas-miembros', controladorVisitasMiembros.registrarVisita);
|
||||
// Obtener todas las visitas (puede ser útil para reportes o auditorías, pero cuidado con el volumen)
|
||||
// GET /api/visitas-miembros
|
||||
rutas.get('/api/visitas-miembros', controladorVisitasMiembros.listarVisitas);
|
||||
// Obtener visitas por ID de miembro (para ver el historial de un miembro específico)
|
||||
// GET /api/miembros/:id_miembro/visitas
|
||||
rutas.get('/api/miembros/:id_miembro/visitas', controladorVisitasMiembros.listarVisitasPorMiembro);
|
||||
/// --- Rutas RESTful para VISITAS UNIFICADAS (tabla 'clientes_visitas') ---
|
||||
// Estas rutas apuntarán al nuevo controlador_ClientesVisitas
|
||||
// Registrar una nueva visita (para miembro o ocasional)
|
||||
rutas.post('/api/visitas', controladorVisitas.crearVisita); // Renombrado a 'crearVisita'
|
||||
// Obtener todas las visitas (con posibilidad de filtros, cuidado con volumen)
|
||||
rutas.get('/api/visitas', controladorVisitas.listarVisitas);
|
||||
// Obtener una visita específica por su ID
|
||||
// GET /api/visitas-miembros/:id_visita
|
||||
rutas.get('/api/visitas-miembros/:id_visita', controladorVisitasMiembros.obtenerVisitaPorId);
|
||||
// (Opcional) Obtener visitas por estado de acceso (CONCEDIDO/DENEGADO)
|
||||
// GET /api/visitas-miembros/estado/:estado_acceso
|
||||
rutas.get('/api/visitas-miembros/estado/:estado_acceso', controladorVisitasMiembros.listarVisitasPorEstadoAcceso);
|
||||
// (Opcional) Obtener visitas por área de acceso
|
||||
// GET /api/visitas-miembros/area/:nombre_area
|
||||
rutas.get('/api/visitas-miembros/area/:nombre_area', controladorVisitasMiembros.listarVisitasPorArea);
|
||||
rutas.get('/api/visitas/:id_visita', controladorVisitas.obtenerVisitaPorId);
|
||||
// Actualizar una visita existente (ej. corregir observaciones, cambiar estado si se permite)
|
||||
rutas.put('/api/visitas/:id_visita', controladorVisitas.actualizarVisita);
|
||||
// Eliminar lógicamente una visita (ej. marcar como 'ANULADA' si tuvieras ese estado)
|
||||
rutas.delete('/api/visitas/:id_visita', controladorVisitas.eliminarVisita); // Implementación para una eliminación lógica
|
||||
// Rutas de consulta específicas para visitas
|
||||
rutas.get('/api/visitas/por-cliente/:client_id', controladorVisitas.listarVisitasPorCliente);
|
||||
rutas.get('/api/visitas/por-miembro/:id_miembro', controladorVisitas.listarVisitasPorMiembro);
|
||||
rutas.get('/api/visitas/estado/:estado_acceso', controladorVisitas.listarVisitasPorEstadoAcceso);
|
||||
rutas.get('/api/visitas/area/:nombre_area', controladorVisitas.listarVisitasPorArea);
|
||||
|
||||
// Rutas para la administración de Áreas de Acceso
|
||||
rutas.get('/api/areas', controladorAreas.listarAreas);
|
||||
|
||||
Reference in New Issue
Block a user