$usuario_id]; if ($estado) { $sql .= " AND m.estado_pago = :estado"; $params[':estado'] = $estado; } $sql .= " ORDER BY m.fecha_emision DESC"; $stmt = $pdo->prepare($sql); $stmt->execute($params); } else { // Modo admin: TODAS las multas con datos del cliente $sql = "SELECT m.id, m.codigo, m.importe, m.motivo, m.estado_pago, m.fecha_emision, m.fecha_limite_pago, m.fecha_pago, u.id AS usuario_id, u.nombre AS cliente_nombre, u.apellidos AS cliente_apellidos, u.email AS cliente_email, u.telefono AS cliente_telefono, r.codigo AS reserva_codigo, r.fecha AS reserva_fecha FROM multas m JOIN usuarios u ON m.usuario_id = u.id JOIN reservas r ON m.reserva_id = r.id"; $params = []; if ($estado) { $sql .= " WHERE m.estado_pago = :estado"; $params[':estado'] = $estado; } $sql .= " ORDER BY m.fecha_emision DESC"; $stmt = $pdo->prepare($sql); $stmt->execute($params); } $multas = $stmt->fetchAll(); // Calcular estadísticas $stats = [ 'total' => count($multas), 'pendientes' => 0, 'pagadas' => 0, 'vencidas' => 0, 'importe_total' => 0, 'importe_pendiente' => 0 ]; foreach ($multas as $m) { if ($m['estado_pago'] === 'pendiente') { $stats['pendientes']++; $stats['importe_pendiente'] += floatval($m['importe']); // Verificar si está vencida if ($m['fecha_limite_pago'] && strtotime($m['fecha_limite_pago']) < time()) { $stats['vencidas']++; } } else if ($m['estado_pago'] === 'pagada') { $stats['pagadas']++; } $stats['importe_total'] += floatval($m['importe']); } echo json_encode([ 'success' => true, 'message' => 'Multas obtenidas correctamente', 'data' => $multas, 'stats' => $stats, 'total' => count($multas) ], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE); break; // ========================================== // 2. POST: Crear nueva multa // ========================================== case 'POST': $input = getJsonInput(); $campos_requeridos = ['usuario_id', 'reserva_id', 'importe', 'motivo']; foreach ($campos_requeridos as $campo) { if (!isset($input[$campo]) || empty($input[$campo])) { http_response_code(400); echo json_encode(['success' => false, 'message' => "Falta el campo obligatorio: $campo"]); exit(); } } $usuario_id = (int)$input['usuario_id']; $reserva_id = (int)$input['reserva_id']; $importe = floatval($input['importe']); $motivo = trim($input['motivo']); $fecha_limite_pago = isset($input['fecha_limite_pago']) ? $input['fecha_limite_pago'] : null; // Validar que la reserva existe y pertenece al usuario $stmtReserva = $pdo->prepare(" SELECT id FROM reservas WHERE id = :id AND usuario_id = :usuario_id "); $stmtReserva->execute([':id' => $reserva_id, ':usuario_id' => $usuario_id]); if (!$stmtReserva->fetch()) { http_response_code(403); echo json_encode(['success' => false, 'message' => 'La reserva no existe o no pertenece al usuario']); exit(); } // Verificar que no existe ya una multa para esta reserva $stmtCheck = $pdo->prepare(" SELECT id FROM multas WHERE reserva_id = :reserva_id LIMIT 1 "); $stmtCheck->execute([':reserva_id' => $reserva_id]); if ($stmtCheck->fetch()) { http_response_code(409); echo json_encode(['success' => false, 'message' => 'Ya existe una multa para esta reserva']); exit(); } // Generar código único $codigo = generarCodigoMulta(); // Si no se especifica fecha límite, calcular 15 días desde hoy if (!$fecha_limite_pago) { $fecha_limite_pago = date('Y-m-d', strtotime('+15 days')); } $stmtInsert = $pdo->prepare(" INSERT INTO multas (codigo, usuario_id, reserva_id, importe, motivo, estado_pago, fecha_emision, fecha_limite_pago) VALUES (:codigo, :usuario_id, :reserva_id, :importe, :motivo, 'pendiente', NOW(), :fecha_limite_pago) "); $stmtInsert->execute([ ':codigo' => $codigo, ':usuario_id' => $usuario_id, ':reserva_id' => $reserva_id, ':importe' => $importe, ':motivo' => $motivo, ':fecha_limite_pago' => $fecha_limite_pago ]); $nuevo_id = $pdo->lastInsertId(); echo json_encode([ 'success' => true, 'message' => 'Multa generada correctamente', 'data' => [ 'id' => (int)$nuevo_id, 'codigo' => $codigo, 'usuario_id' => $usuario_id, 'reserva_id' => $reserva_id, 'importe' => $importe, 'motivo' => $motivo, 'estado_pago' => 'pendiente', 'fecha_emision' => date('Y-m-d H:i:s'), 'fecha_limite_pago' => $fecha_limite_pago ] ], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE); break; // ========================================== // 3. PUT: Actualizar estado de multa (pagada, etc.) // ========================================== case 'PUT': $input = getJsonInput(); if (!isset($input['id'])) { http_response_code(400); echo json_encode(['success' => false, 'message' => 'Falta el campo obligatorio: id']); exit(); } $multa_id = (int)$input['id']; $estado_pago = isset($input['estado_pago']) ? $input['estado_pago'] : null; $motivo = isset($input['motivo']) ? trim($input['motivo']) : null; // Verificar que la multa existe $stmtCheck = $pdo->prepare("SELECT id, estado_pago FROM multas WHERE id = :id"); $stmtCheck->execute([':id' => $multa_id]); $multa = $stmtCheck->fetch(); if (!$multa) { http_response_code(404); echo json_encode(['success' => false, 'message' => 'Multa no encontrada']); exit(); } // Construir UPDATE dinámico $updates = []; $params = [':id' => $multa_id]; if ($estado_pago) { $estados_validos = ['pendiente', 'pagada', 'cancelada', 'en_proceso']; if (!in_array($estado_pago, $estados_validos)) { http_response_code(400); echo json_encode(['success' => false, 'message' => 'Estado de pago no válido']); exit(); } $updates[] = "estado_pago = :estado_pago"; $params[':estado_pago'] = $estado_pago; // Si se marca como pagada, registrar fecha de pago if ($estado_pago === 'pagada') { $updates[] = "fecha_pago = NOW()"; } } if ($motivo !== null) { $updates[] = "motivo = :motivo"; $params[':motivo'] = $motivo; } if (empty($updates)) { http_response_code(400); echo json_encode(['success' => false, 'message' => 'No hay campos para actualizar']); exit(); } $sql = "UPDATE multas SET " . implode(', ', $updates) . " WHERE id = :id"; $stmt = $pdo->prepare($sql); $stmt->execute($params); echo json_encode([ 'success' => true, 'message' => 'Multa actualizada correctamente' ], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE); break; // ========================================== // 4. DELETE: Eliminar multa (solo admin) // ========================================== case 'DELETE': $input = getJsonInput(); if (!isset($input['id'])) { http_response_code(400); echo json_encode(['success' => false, 'message' => 'Falta el campo obligatorio: id']); exit(); } $multa_id = (int)$input['id']; // Verificar que la multa existe $stmtCheck = $pdo->prepare("SELECT id FROM multas WHERE id = :id"); $stmtCheck->execute([':id' => $multa_id]); if (!$stmtCheck->fetch()) { http_response_code(404); echo json_encode(['success' => false, 'message' => 'Multa no encontrada']); exit(); } $stmtDelete = $pdo->prepare("DELETE FROM multas WHERE id = :id"); $stmtDelete->execute([':id' => $multa_id]); echo json_encode([ 'success' => true, 'message' => 'Multa eliminada correctamente' ], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE); break; // ========================================== // Método no permitido // ========================================== default: http_response_code(405); echo json_encode(['success' => false, 'message' => 'Método no permitido. Use GET, POST, PUT o DELETE.']); break; } } catch (PDOException $e) { http_response_code(500); echo json_encode([ 'success' => false, 'message' => 'Error en el servidor', 'error' => $e->getMessage() ]); } catch (Exception $e) { http_response_code(500); echo json_encode([ 'success' => false, 'message' => 'Error inesperado', 'error' => $e->getMessage() ]); } ?>