db = Database::getInstance(); $this->log = new ActividadAdmin(); } // ───────────────────────────────────────────────────────────────────────── // CRUD // ───────────────────────────────────────────────────────────────────────── /** * Lista de enfermeras activas/todas. */ public function listar(bool $soloActivas = true): array { $where = $soloActivas ? 'WHERE is_active = 1' : ''; return $this->db->fetchAll(" SELECT e.*, (SELECT COUNT(*) FROM lab_asignaciones a JOIN lab_domicilios d ON d.id = a.domicilio_id WHERE a.enfermera_id = e.id AND d.fecha_programada = CURDATE() AND a.estado NOT IN ('liberada','completada') ) AS domicilios_hoy FROM lab_enfermeras e $where ORDER BY e.nombre_completo ASC "); } /** * Enfermera por ID. */ public function obtener(int $id): ?array { return $this->db->fetch( 'SELECT * FROM lab_enfermeras WHERE id = ?', [$id] ) ?: null; } /** * Crear enfermera. */ public function crear(array $datos, ?int $adminId = null): int { $campos = $this->filtrarCampos($datos); $id = $this->db->insert('lab_enfermeras', $campos); $this->log->registrar($adminId, 'enfermeras', 'crear', $id, $campos); return $id; } /** * Actualizar enfermera. */ public function actualizar(int $id, array $datos, ?int $adminId = null): bool { $campos = $this->filtrarCampos($datos); $ok = $this->db->update('lab_enfermeras', $campos, 'id = ?', [$id]); $this->log->registrar($adminId, 'enfermeras', 'editar', $id, $campos); return $ok > 0; } /** * Desactivar (soft-delete). */ public function desactivar(int $id, ?int $adminId = null): bool { $ok = $this->db->update('lab_enfermeras', ['is_active' => 0], 'id = ?', [$id]); $this->log->registrar($adminId, 'enfermeras', 'desactivar', $id); return $ok > 0; } // ───────────────────────────────────────────────────────────────────────── // Agenda // ───────────────────────────────────────────────────────────────────────── /** * Agenda completa de una enfermera (domicilios asignados con detalle). * * @param int $enfermeraId * @param string $fecha YYYY-MM-DD, por defecto hoy */ public function agenda(int $enfermeraId, string $fecha = ''): array { $fecha = $fecha ?: date('Y-m-d'); $rows = $this->db->fetchAll(" SELECT d.id AS domicilio_id, d.fecha_programada, d.hora_programada, d.estado AS domicilio_estado, d.direccion, d.barrio, d.ciudad, d.indicaciones_dir, d.notas_admin, d.tipo_servicio, d.examenes_solicitados, d.tipo_cliente, d.seguro_nombre, d.orden_id, d.valor_domicilio, d.valor_copago, d.copago_laboratorio, d.autorizacion, d.pago_estado, d.pago_modo, d.pago_monto, d.pago_notas, d.hora_llegada, d.temperatura_inicio, d.hora_salida, d.temperatura_salida, p.id AS paciente_id, p.nombre_completo AS paciente_nombre, p.telefono AS paciente_telefono, p.email AS paciente_email, p.fecha_nacimiento AS paciente_fecha_nacimiento, p.tipo_documento AS paciente_tipo_documento, p.numero_documento AS paciente_numero_documento, p.eps AS paciente_eps, COALESCE( om.local_file, (SELECT om2.local_file FROM lab_ordenes_medicas om2 WHERE om2.paciente_id = p.id AND om2.local_file IS NOT NULL ORDER BY om2.created_at DESC LIMIT 1) ) AS orden_local_file, COALESCE( d.orden_id, (SELECT om2.id FROM lab_ordenes_medicas om2 WHERE om2.paciente_id = p.id AND om2.local_file IS NOT NULL ORDER BY om2.created_at DESC LIMIT 1) ) AS orden_id_display, a.estado AS asignacion_estado, a.id AS asignacion_id, d.creado_por FROM lab_asignaciones a JOIN lab_domicilios d ON d.id = a.domicilio_id JOIN lab_pacientes p ON p.id = d.paciente_id LEFT JOIN lab_ordenes_medicas om ON om.id = d.orden_id WHERE a.enfermera_id = ? AND d.fecha_programada = ? ORDER BY d.hora_programada IS NULL ASC, d.hora_programada ASC ", [$enfermeraId, $fecha]); // Bulk-load todos los archivos de órdenes vinculados a estos domicilios $domIds = array_values(array_filter(array_column($rows, 'domicilio_id'))); if (!empty($domIds)) { $ph = implode(',', array_fill(0, count($domIds), '?')); $archivos = $this->db->fetchAll( "SELECT domicilio_id, id AS orden_id, local_file FROM lab_ordenes_medicas WHERE domicilio_id IN ($ph) AND local_file IS NOT NULL ORDER BY id ASC", $domIds ); $archivosPorDom = []; foreach ($archivos as $a) { $archivosPorDom[$a['domicilio_id']][] = $a; } foreach ($rows as &$row) { $did = $row['domicilio_id']; if (!empty($archivosPorDom[$did])) { $row['archivos_ordenes'] = $archivosPorDom[$did]; } elseif (!empty($row['orden_local_file'])) { // Fallback: domicilio creado antes de la migración $row['archivos_ordenes'] = [[ 'orden_id' => $row['orden_id_display'] ?? $row['orden_id'], 'local_file' => $row['orden_local_file'], ]]; } else { $row['archivos_ordenes'] = []; } } unset($row); } else { foreach ($rows as &$row) { if (!empty($row['orden_local_file'])) { $row['archivos_ordenes'] = [[ 'orden_id' => $row['orden_id_display'] ?? $row['orden_id'], 'local_file' => $row['orden_local_file'], ]]; } else { $row['archivos_ordenes'] = []; } } unset($row); } return $rows; } /** * Carga de trabajo por período: domicilios asignados por día. */ public function cargaTrabajo(int $enfermeraId, string $desde, string $hasta): array { return $this->db->fetchAll(" SELECT d.fecha_programada, COUNT(*) AS total, SUM(d.estado = 'completado') AS completados FROM lab_asignaciones a JOIN lab_domicilios d ON d.id = a.domicilio_id WHERE a.enfermera_id = ? AND d.fecha_programada BETWEEN ? AND ? GROUP BY d.fecha_programada ORDER BY d.fecha_programada ASC ", [$enfermeraId, $desde, $hasta]); } // ───────────────────────────────────────────────────────────────────────── // Helpers // ───────────────────────────────────────────────────────────────────────── private function filtrarCampos(array $datos): array { $permitidos = [ 'numero_documento', 'tipo_documento', 'nombre_completo', 'telefono', 'telefono_alt', 'email', 'zona', 'notas', 'is_active', ]; return array_intersect_key($datos, array_flip($permitidos)); } }