142 lines
6.3 KiB
Python
142 lines
6.3 KiB
Python
from datetime import timedelta
|
||
from urllib.parse import parse_qs
|
||
from django.utils import timezone
|
||
from django.db.models import Q
|
||
from hotels.models import Reservation, Hotel
|
||
from .models import UserActivityLog, ViolationLog
|
||
from touchh.utils.log import CustomLogger
|
||
# Настройка логирования
|
||
logger = CustomLogger(__name__).get_logger()
|
||
|
||
|
||
class ReservationChecker:
|
||
"""
|
||
Класс для проверки несоответствий между бронированиями и логами заселения.
|
||
"""
|
||
|
||
def __init__(self):
|
||
"""
|
||
Инициализация времени проверки и списка нарушений.
|
||
"""
|
||
self.start_time = timezone.now() - timedelta(days=30)
|
||
self.end_time = timezone.now()
|
||
self.violations = []
|
||
|
||
def log_info(self, message):
|
||
logger.info(message)
|
||
|
||
def log_warning(self, message):
|
||
logger.warning(message)
|
||
|
||
def log_error(self, message):
|
||
logger.error(message)
|
||
|
||
def fetch_user_logs(self):
|
||
try:
|
||
self.log_info("Начинается извлечение логов активности пользователей.")
|
||
user_logs = UserActivityLog.objects.filter(created__range=(self.start_time, self.end_time))
|
||
self.log_info(f"Найдено {user_logs.count()} логов активности для анализа.")
|
||
return user_logs
|
||
except Exception as e:
|
||
self.log_error(f"Ошибка при извлечении логов активности: {e}")
|
||
return UserActivityLog.objects.none()
|
||
|
||
def fetch_reservations(self):
|
||
try:
|
||
self.log_info("Начинается извлечение бронирований.")
|
||
reservations = Reservation.objects.filter(
|
||
Q(check_in__lte=self.end_time) & Q(check_out__gte=self.start_time)
|
||
)
|
||
self.log_info(f"Найдено {reservations.count()} бронирований для анализа.")
|
||
return reservations
|
||
except Exception as e:
|
||
self.log_error(f"Ошибка при извлечении бронирований: {e}")
|
||
return Reservation.objects.none()
|
||
|
||
def find_violations(self):
|
||
self.log_info("Начинается анализ несоответствий.")
|
||
user_logs = self.fetch_user_logs()
|
||
reservations = self.fetch_reservations()
|
||
|
||
log_lookup = {}
|
||
for log in user_logs:
|
||
params = parse_qs(log.url_parameters or "")
|
||
hotel_id = params.get("utm_content", [None])[0]
|
||
room_number = params.get("utm_term", [None])[0]
|
||
if hotel_id and room_number:
|
||
key = (hotel_id, room_number)
|
||
log_lookup.setdefault(key, []).append(log)
|
||
|
||
for reservation in reservations:
|
||
key = (reservation.hotel.hotel_id, reservation.room_number)
|
||
logs = log_lookup.get(key, [])
|
||
|
||
if reservation.status == "заселен" and not logs:
|
||
self.record_violation(
|
||
hotel=reservation.hotel,
|
||
room_number=reservation.room_number,
|
||
violation_type="no_qr_scan",
|
||
details=f"Бронирование для номера {reservation.room_number} в отеле '{reservation.hotel.name}' "
|
||
f"не имеет записи сканирования QR."
|
||
)
|
||
|
||
for log in logs:
|
||
if log.created < reservation.check_in:
|
||
self.record_violation(
|
||
hotel=reservation.hotel,
|
||
room_number=reservation.room_number,
|
||
violation_type="early_check_in",
|
||
details=f"Раннее заселение: сканирование QR {log.created} раньше времени заезда "
|
||
f"{reservation.check_in} для номера {reservation.room_number}."
|
||
)
|
||
|
||
for (hotel_id, room_number), logs in log_lookup.items():
|
||
matching_reservations = reservations.filter(
|
||
hotel__hotel_id=hotel_id,
|
||
room_number=room_number
|
||
)
|
||
if not matching_reservations.exists():
|
||
for log in logs:
|
||
self.record_violation(
|
||
hotel=Hotel.objects.filter(hotel_id=hotel_id).first(),
|
||
room_number=room_number,
|
||
violation_type="no_reservation",
|
||
details=f"Сканирование QR {log.created} для номера {room_number} в отеле с ID '{hotel_id}' "
|
||
f"не соответствует ни одному бронированию."
|
||
)
|
||
|
||
def record_violation(self, hotel, room_number, violation_type, details):
|
||
if hotel:
|
||
self.violations.append(ViolationLog(
|
||
hotel=hotel,
|
||
room_number=room_number,
|
||
violation_type=violation_type,
|
||
violation_details=details
|
||
))
|
||
self.log_warning(f"Зафиксировано нарушение: {details}")
|
||
|
||
def save_violations(self):
|
||
if self.violations:
|
||
ViolationLog.objects.bulk_create(self.violations)
|
||
self.log_info(f"Создано {len(self.violations)} записей в ViolationLog.")
|
||
else:
|
||
self.log_info("Нарушений не обнаружено.")
|
||
|
||
def run_check(self):
|
||
self.log_info(f"Запуск проверки с {self.start_time} по {self.end_time}.")
|
||
try:
|
||
self.find_violations()
|
||
self.save_violations()
|
||
except Exception as e:
|
||
self.log_error(f"Ошибка при выполнении проверки: {e}")
|
||
self.log_info("Проверка завершена.")
|
||
|
||
# Функция для запуска из планировщика
|
||
def run_reservation_check():
|
||
logger.info("Планировщик вызывает run_reservation_check.")
|
||
try:
|
||
checker = ReservationChecker()
|
||
checker.run_check()
|
||
except Exception as e:
|
||
logger.error(f"Ошибка при запуске проверки: {e}")
|
||
logger.info("run_reservation_check завершена.") |