ProyectoGestionDocumentos/database/gestion_documentos.sql

362 lines
18 KiB
SQL

-- ============================================================
-- SISTEMA DE CONTROL DE GESTIÓN DE DOCUMENTACIÓN
-- Oficios Jurídicos Institucionales
-- Versión: 1.0 | Fecha: 2026-04-22
-- ============================================================
SET FOREIGN_KEY_CHECKS = 0;
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
SET time_zone = "+00:00";
CREATE DATABASE IF NOT EXISTS `gestion_documentos`
CHARACTER SET utf8mb4
COLLATE utf8mb4_unicode_ci;
USE `gestion_documentos`;
-- -----------------------------------------------------------
-- TABLA: roles
-- -----------------------------------------------------------
CREATE TABLE `roles` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`nombre` VARCHAR(50) NOT NULL,
`descripcion` VARCHAR(255) DEFAULT NULL,
`permisos` JSON DEFAULT NULL COMMENT 'Permisos en formato JSON para RBAC',
`created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_rol_nombre` (`nombre`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
INSERT INTO `roles` (`nombre`, `descripcion`, `permisos`) VALUES
('administrador', 'Acceso total al sistema', '{"oficios":"CRUD","usuarios":"CRUD","reportes":true,"respaldo":true,"papelera_fisica":true,"config_alertas":true}'),
('supervisor', 'Supervisa usuarios y recibe escalaciones', '{"oficios":"CRUD","usuarios":"read","reportes":true,"respaldo":false,"papelera_fisica":false,"config_alertas":false}'),
('estandar', 'Gestión de oficios propios', '{"oficios":"CRUD_own","usuarios":"none","reportes":"own","respaldo":false,"papelera_fisica":false,"config_alertas":false}');
-- -----------------------------------------------------------
-- TABLA: usuarios
-- -----------------------------------------------------------
CREATE TABLE `usuarios` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`rol_id` INT UNSIGNED NOT NULL DEFAULT 3,
`nombre` VARCHAR(100) NOT NULL,
`apellido` VARCHAR(100) NOT NULL,
`email` VARCHAR(150) NOT NULL,
`username` VARCHAR(60) NOT NULL,
`password_hash` VARCHAR(255) NOT NULL,
`cargo` VARCHAR(100) DEFAULT NULL,
`area` VARCHAR(100) DEFAULT NULL,
`supervisor_id` INT UNSIGNED DEFAULT NULL COMMENT 'Usuario supervisor para escalaciones',
`token_recuperacion` VARCHAR(100) DEFAULT NULL,
`token_expira` DATETIME DEFAULT NULL,
`ultimo_login` DATETIME DEFAULT NULL,
`activo` TINYINT(1) NOT NULL DEFAULT 1,
`deleted_at` DATETIME DEFAULT NULL,
`created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_email` (`email`),
UNIQUE KEY `uk_username` (`username`),
KEY `fk_usuario_rol` (`rol_id`),
KEY `fk_usuario_supervisor` (`supervisor_id`),
CONSTRAINT `fk_usuario_rol` FOREIGN KEY (`rol_id`) REFERENCES `roles` (`id`) ON UPDATE CASCADE,
CONSTRAINT `fk_usuario_supervisor` FOREIGN KEY (`supervisor_id`) REFERENCES `usuarios` (`id`) ON DELETE SET NULL ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- Usuario administrador por defecto: admin / Admin@2026
INSERT INTO `usuarios` (`rol_id`, `nombre`, `apellido`, `email`, `username`, `password_hash`, `cargo`, `area`, `activo`) VALUES
(1, 'Administrador', 'Sistema', 'admin@sistema.local', 'admin', '$2y$12$hF3W4J5K9L2M7N8P1Q6R4OQKvVbFa.Np/GzDzFH8fRv1sXkLmEpWu', 'Administrador TI', 'Sistemas', 1);
-- -----------------------------------------------------------
-- TABLA: etiquetas
-- -----------------------------------------------------------
CREATE TABLE `etiquetas` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`nombre` VARCHAR(80) NOT NULL,
`color` VARCHAR(7) NOT NULL DEFAULT '#6c757d' COMMENT 'Hex color',
`icono` VARCHAR(50) DEFAULT 'fa-tag',
`creado_por` INT UNSIGNED DEFAULT NULL,
`created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_etiqueta_nombre` (`nombre`),
KEY `fk_etiqueta_usuario` (`creado_por`),
CONSTRAINT `fk_etiqueta_usuario` FOREIGN KEY (`creado_por`) REFERENCES `usuarios` (`id`) ON DELETE SET NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
INSERT INTO `etiquetas` (`nombre`, `color`, `icono`) VALUES
('Contrato', '#0d6efd', 'fa-file-contract'),
('Demanda', '#dc3545', 'fa-gavel'),
('Recurso', '#fd7e14', 'fa-folder-open'),
('Solicitud', '#198754', 'fa-envelope-open'),
('Circular', '#6f42c1', 'fa-circle-info'),
('Convenio', '#20c997', 'fa-handshake'),
('Resolución', '#0dcaf0', 'fa-stamp'),
('Decreto', '#e91e63', 'fa-scroll');
-- -----------------------------------------------------------
-- TABLA: plantillas_respuesta
-- -----------------------------------------------------------
CREATE TABLE `plantillas_respuesta` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`titulo` VARCHAR(150) NOT NULL,
`contenido` TEXT NOT NULL,
`tipo` ENUM('recibido','enviado','general') NOT NULL DEFAULT 'general',
`creado_por` INT UNSIGNED DEFAULT NULL,
`activo` TINYINT(1) NOT NULL DEFAULT 1,
`created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `fk_plantilla_usuario` (`creado_por`),
CONSTRAINT `fk_plantilla_usuario` FOREIGN KEY (`creado_por`) REFERENCES `usuarios` (`id`) ON DELETE SET NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
INSERT INTO `plantillas_respuesta` (`titulo`, `contenido`, `tipo`) VALUES
('Acuse de recibo', 'En respuesta a su oficio N° {numero_oficio} de fecha {fecha_recepcion}, le informamos que hemos recibido correctamente su comunicación y procederemos a darle el trámite correspondiente.', 'recibido'),
('Solicitud de información adicional', 'En atención a su oficio N° {numero_oficio}, nos permitimos solicitarle amablemente información complementaria sobre el asunto referido, a fin de darle una respuesta adecuada y oportuna.', 'recibido'),
('Respuesta favorable', 'En atención a lo solicitado en el oficio N° {numero_oficio}, nos complace comunicarle que su petición ha sido evaluada favorablemente por esta instancia.', 'enviado'),
('Respuesta negativa', 'Lamentamos comunicarle que, tras la revisión del oficio N° {numero_oficio}, esta instancia no puede dar respuesta favorable a lo solicitado por las razones que se detallan a continuación.', 'enviado');
-- -----------------------------------------------------------
-- TABLA: oficios
-- -----------------------------------------------------------
CREATE TABLE `oficios` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`numero_oficio` VARCHAR(50) NOT NULL,
`tipo` ENUM('recibido','enviado') NOT NULL DEFAULT 'recibido',
`remitente` VARCHAR(200) NOT NULL,
`destinatario` VARCHAR(200) NOT NULL,
`asunto` TEXT NOT NULL,
`descripcion` TEXT DEFAULT NULL,
`fecha_recepcion` DATE NOT NULL,
`fecha_vencimiento` DATE DEFAULT NULL,
`prioridad` ENUM('alta','media','baja') NOT NULL DEFAULT 'media',
`estado` ENUM('recibido','en_proceso','respondido','vencido','archivado') NOT NULL DEFAULT 'recibido',
`responsable_id` INT UNSIGNED DEFAULT NULL,
`creado_por` INT UNSIGNED DEFAULT NULL,
`derivado_de_id` INT UNSIGNED DEFAULT NULL COMMENT 'Oficio del que fue derivado',
`derivado_a_id` INT UNSIGNED DEFAULT NULL COMMENT 'Usuario al que se derivó',
`comentario_derivacion` TEXT DEFAULT NULL,
`es_confidencial` TINYINT(1) NOT NULL DEFAULT 0,
`deleted_at` DATETIME DEFAULT NULL,
`created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_numero_oficio` (`numero_oficio`),
KEY `idx_tipo` (`tipo`),
KEY `idx_estado` (`estado`),
KEY `idx_prioridad` (`prioridad`),
KEY `idx_fecha_vencimiento` (`fecha_vencimiento`),
KEY `idx_deleted_at` (`deleted_at`),
KEY `fk_oficio_responsable` (`responsable_id`),
KEY `fk_oficio_creador` (`creado_por`),
KEY `fk_oficio_derivado_a` (`derivado_a_id`),
FULLTEXT KEY `ft_busqueda` (`numero_oficio`, `remitente`, `destinatario`, `asunto`),
CONSTRAINT `fk_oficio_responsable` FOREIGN KEY (`responsable_id`) REFERENCES `usuarios` (`id`) ON DELETE SET NULL ON UPDATE CASCADE,
CONSTRAINT `fk_oficio_creador` FOREIGN KEY (`creado_por`) REFERENCES `usuarios` (`id`) ON DELETE SET NULL ON UPDATE CASCADE,
CONSTRAINT `fk_oficio_derivado_a` FOREIGN KEY (`derivado_a_id`) REFERENCES `usuarios` (`id`) ON DELETE SET NULL ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- -----------------------------------------------------------
-- TABLA: oficio_etiquetas (N:M)
-- -----------------------------------------------------------
CREATE TABLE `oficio_etiquetas` (
`oficio_id` INT UNSIGNED NOT NULL,
`etiqueta_id` INT UNSIGNED NOT NULL,
PRIMARY KEY (`oficio_id`, `etiqueta_id`),
KEY `fk_oe_etiqueta` (`etiqueta_id`),
CONSTRAINT `fk_oe_oficio` FOREIGN KEY (`oficio_id`) REFERENCES `oficios` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `fk_oe_etiqueta` FOREIGN KEY (`etiqueta_id`) REFERENCES `etiquetas` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- -----------------------------------------------------------
-- TABLA: documentos_adjuntos
-- -----------------------------------------------------------
CREATE TABLE `documentos_adjuntos` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`oficio_id` INT UNSIGNED NOT NULL,
`nombre_original` VARCHAR(255) NOT NULL,
`nombre_archivo` VARCHAR(255) NOT NULL COMMENT 'Nombre hasheado en servidor',
`ruta` VARCHAR(500) NOT NULL,
`tipo_mime` VARCHAR(100) NOT NULL,
`tamanio` INT UNSIGNED NOT NULL COMMENT 'Tamaño en bytes',
`subido_por` INT UNSIGNED DEFAULT NULL,
`created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `fk_doc_oficio` (`oficio_id`),
KEY `fk_doc_usuario` (`subido_por`),
CONSTRAINT `fk_doc_oficio` FOREIGN KEY (`oficio_id`) REFERENCES `oficios` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `fk_doc_usuario` FOREIGN KEY (`subido_por`) REFERENCES `usuarios` (`id`) ON DELETE SET NULL ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- -----------------------------------------------------------
-- TABLA: tareas
-- -----------------------------------------------------------
CREATE TABLE `tareas` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`oficio_id` INT UNSIGNED NOT NULL,
`asignado_a` INT UNSIGNED DEFAULT NULL,
`creado_por` INT UNSIGNED DEFAULT NULL,
`titulo` VARCHAR(200) NOT NULL,
`descripcion` TEXT DEFAULT NULL,
`fecha_limite` DATE DEFAULT NULL,
`estado` ENUM('pendiente','en_proceso','completada','cancelada') NOT NULL DEFAULT 'pendiente',
`prioridad` ENUM('alta','media','baja') NOT NULL DEFAULT 'media',
`created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `fk_tarea_oficio` (`oficio_id`),
KEY `fk_tarea_asignado` (`asignado_a`),
CONSTRAINT `fk_tarea_oficio` FOREIGN KEY (`oficio_id`) REFERENCES `oficios` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `fk_tarea_asignado` FOREIGN KEY (`asignado_a`) REFERENCES `usuarios` (`id`) ON DELETE SET NULL ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- -----------------------------------------------------------
-- TABLA: historial_cambios (Auditoría)
-- -----------------------------------------------------------
CREATE TABLE `historial_cambios` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`tabla` VARCHAR(60) NOT NULL,
`registro_id` INT UNSIGNED NOT NULL,
`campo_modificado` VARCHAR(100) DEFAULT NULL,
`valor_anterior` TEXT DEFAULT NULL,
`valor_nuevo` TEXT DEFAULT NULL,
`accion` ENUM('crear','editar','eliminar','restaurar','derivar','escalacion') NOT NULL,
`usuario_id` INT UNSIGNED DEFAULT NULL,
`ip_address` VARCHAR(45) DEFAULT NULL,
`detalle` TEXT DEFAULT NULL,
`created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `idx_historial_tabla_registro` (`tabla`, `registro_id`),
KEY `fk_historial_usuario` (`usuario_id`),
CONSTRAINT `fk_historial_usuario` FOREIGN KEY (`usuario_id`) REFERENCES `usuarios` (`id`) ON DELETE SET NULL ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- -----------------------------------------------------------
-- TABLA: alertas_config
-- -----------------------------------------------------------
CREATE TABLE `alertas_config` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`nombre` VARCHAR(100) NOT NULL,
`dias_antes` INT NOT NULL DEFAULT 3 COMMENT 'Días antes del vencimiento para alertar',
`enviar_email` TINYINT(1) NOT NULL DEFAULT 1,
`enviar_notificacion` TINYINT(1) NOT NULL DEFAULT 1,
`activo` TINYINT(1) NOT NULL DEFAULT 1,
`created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
INSERT INTO `alertas_config` (`nombre`, `dias_antes`, `enviar_email`, `enviar_notificacion`, `activo`) VALUES
('Alerta 3 días antes', 3, 1, 1, 1),
('Alerta 1 día antes', 1, 1, 1, 1),
('Alerta día de vencimiento', 0, 1, 1, 1),
('Alerta día después (vencido)', -1, 1, 1, 1);
-- -----------------------------------------------------------
-- TABLA: notificaciones
-- -----------------------------------------------------------
CREATE TABLE `notificaciones` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`usuario_id` INT UNSIGNED NOT NULL,
`oficio_id` INT UNSIGNED DEFAULT NULL,
`tipo` ENUM('vencimiento','derivacion','escalacion','sistema','tarea') NOT NULL DEFAULT 'sistema',
`titulo` VARCHAR(200) NOT NULL,
`mensaje` TEXT NOT NULL,
`leida` TINYINT(1) NOT NULL DEFAULT 0,
`leida_at` DATETIME DEFAULT NULL,
`created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `idx_notif_usuario_leida` (`usuario_id`, `leida`),
KEY `fk_notif_oficio` (`oficio_id`),
CONSTRAINT `fk_notif_usuario` FOREIGN KEY (`usuario_id`) REFERENCES `usuarios` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `fk_notif_oficio` FOREIGN KEY (`oficio_id`) REFERENCES `oficios` (`id`) ON DELETE SET NULL ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- -----------------------------------------------------------
-- TABLA: comentarios
-- -----------------------------------------------------------
CREATE TABLE `comentarios` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`oficio_id` INT UNSIGNED NOT NULL,
`usuario_id` INT UNSIGNED NOT NULL,
`comentario` TEXT NOT NULL,
`es_privado` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '1=solo admins y supervisores',
`created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `fk_coment_oficio` (`oficio_id`),
KEY `fk_coment_usuario` (`usuario_id`),
CONSTRAINT `fk_coment_oficio` FOREIGN KEY (`oficio_id`) REFERENCES `oficios` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `fk_coment_usuario` FOREIGN KEY (`usuario_id`) REFERENCES `usuarios` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- -----------------------------------------------------------
-- TABLA: log_actividad
-- -----------------------------------------------------------
CREATE TABLE `log_actividad` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`usuario_id` INT UNSIGNED DEFAULT NULL,
`accion` VARCHAR(100) NOT NULL,
`modulo` VARCHAR(60) NOT NULL,
`descripcion` TEXT DEFAULT NULL,
`ip_address` VARCHAR(45) DEFAULT NULL,
`user_agent` VARCHAR(500) DEFAULT NULL,
`created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `idx_log_usuario` (`usuario_id`),
KEY `idx_log_modulo` (`modulo`),
KEY `idx_log_created` (`created_at`),
CONSTRAINT `fk_log_usuario` FOREIGN KEY (`usuario_id`) REFERENCES `usuarios` (`id`) ON DELETE SET NULL ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
SET FOREIGN_KEY_CHECKS = 1;
-- ============================================================
-- VISTA: v_oficios_completo (para reportes y listados)
-- ============================================================
CREATE OR REPLACE VIEW `v_oficios_completo` AS
SELECT
o.id,
o.numero_oficio,
o.tipo,
o.remitente,
o.destinatario,
o.asunto,
o.fecha_recepcion,
o.fecha_vencimiento,
o.prioridad,
o.estado,
o.es_confidencial,
o.deleted_at,
o.created_at,
o.updated_at,
CONCAT(u_resp.nombre, ' ', u_resp.apellido) AS responsable_nombre,
u_resp.email AS responsable_email,
CONCAT(u_crea.nombre, ' ', u_crea.apellido) AS creado_por_nombre,
DATEDIFF(o.fecha_vencimiento, CURDATE()) AS dias_para_vencer,
CASE
WHEN o.estado = 'respondido' OR o.estado = 'archivado' THEN 'completado'
WHEN o.fecha_vencimiento IS NULL THEN 'sin_vencimiento'
WHEN DATEDIFF(o.fecha_vencimiento, CURDATE()) < 0 THEN 'vencido'
WHEN DATEDIFF(o.fecha_vencimiento, CURDATE()) <= 3 THEN 'proximo'
ELSE 'vigente'
END AS semaforo,
(SELECT COUNT(*) FROM documentos_adjuntos da WHERE da.oficio_id = o.id) AS total_adjuntos,
(SELECT COUNT(*) FROM comentarios c WHERE c.oficio_id = o.id) AS total_comentarios,
(SELECT GROUP_CONCAT(e.nombre ORDER BY e.nombre SEPARATOR ', ')
FROM oficio_etiquetas oe
JOIN etiquetas e ON e.id = oe.etiqueta_id
WHERE oe.oficio_id = o.id) AS etiquetas
FROM oficios o
LEFT JOIN usuarios u_resp ON u_resp.id = o.responsable_id
LEFT JOIN usuarios u_crea ON u_crea.id = o.creado_por
WHERE o.deleted_at IS NULL;
-- ============================================================
-- VISTA: v_dashboard_kpis
-- ============================================================
CREATE OR REPLACE VIEW `v_dashboard_kpis` AS
SELECT
(SELECT COUNT(*) FROM oficios WHERE deleted_at IS NULL) AS total_oficios,
(SELECT COUNT(*) FROM oficios WHERE deleted_at IS NULL AND estado NOT IN ('respondido','archivado') AND fecha_vencimiento < CURDATE()) AS total_vencidos,
(SELECT COUNT(*) FROM oficios WHERE deleted_at IS NULL AND estado NOT IN ('respondido','archivado') AND fecha_vencimiento BETWEEN CURDATE() AND DATE_ADD(CURDATE(), INTERVAL 3 DAY)) AS total_por_vencer,
(SELECT COUNT(*) FROM oficios WHERE deleted_at IS NULL AND estado IN ('respondido','archivado') AND MONTH(updated_at) = MONTH(CURDATE()) AND YEAR(updated_at) = YEAR(CURDATE())) AS completados_este_mes,
(SELECT COUNT(*) FROM oficios WHERE deleted_at IS NULL AND estado = 'en_proceso') AS en_proceso,
(SELECT COUNT(*) FROM usuarios WHERE activo = 1 AND deleted_at IS NULL) AS total_usuarios;