112 lines
4.4 KiB
Python
112 lines
4.4 KiB
Python
import json
|
|
from datetime import timedelta
|
|
from urllib.parse import parse_qs
|
|
from django.utils import timezone
|
|
from django.db.models import Q
|
|
from django.db import connection
|
|
from hotels.models import Reservation, Hotel
|
|
from .models import UserActivityLog, ViolationLog, RoomDiscrepancy
|
|
from touchh.utils.log import CustomLogger
|
|
# Настройка логирования
|
|
logger = CustomLogger(__name__).get_logger()
|
|
|
|
|
|
class ReservationChecker:
|
|
"""
|
|
Класс для проверки несоответствий между бронированиями и логами заселения.
|
|
"""
|
|
|
|
def __init__(self):
|
|
"""
|
|
Инициализация времени проверки и списка нарушений.
|
|
"""
|
|
self.checkin_diff_hours = 3
|
|
|
|
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 run_check(self):
|
|
self.log_info(f"Запуск проверки.")
|
|
try:
|
|
hotels_map = {}
|
|
hotels = Hotel.objects.all()
|
|
for hotel in hotels:
|
|
hotels_map[hotel.hotel_id] = hotel
|
|
|
|
user_logs = UserActivityLog.objects.filter(fraud_checked=False)
|
|
reservations = Reservation.objects.filter(fraud_checked=False).select_related('hotel')
|
|
missing = list(reservations)
|
|
|
|
violations = []
|
|
check_in_diff = timedelta(hours=self.checkin_diff_hours)
|
|
|
|
for user_log in user_logs:
|
|
try:
|
|
params = json.loads(user_log.url_parameters.replace("'", '"'))
|
|
hotel_id = params['utm_content']
|
|
room = params['utm_term']
|
|
reserv = next((x for x in reservations
|
|
if x.hotel.hotel_id == hotel_id and x.room_number == room
|
|
and user_log.date_time >= x.check_in - check_in_diff and user_log.date_time < x.check_out
|
|
), None)
|
|
v_type = None
|
|
if reserv:
|
|
if reserv in missing:
|
|
missing.remove(reserv)
|
|
if user_log.date_time < reserv.check_in:
|
|
v_type = 'early'
|
|
if user_log.date_time > reserv.check_in + check_in_diff:
|
|
v_type = 'late'
|
|
else:
|
|
v_type = 'no_booking'
|
|
|
|
if v_type:
|
|
violations.append(RoomDiscrepancy(
|
|
hotel=hotels_map[hotel_id],
|
|
room_number=room,
|
|
discrepancy_type=v_type,
|
|
booking_id=reserv.reservation_id if reserv else None,
|
|
check_in_date_expected=reserv.check_in if reserv else None,
|
|
check_in_date_actual=user_log.date_time,
|
|
))
|
|
|
|
user_log.fraud_checked = True
|
|
except Exception as e:
|
|
logger.error(e)
|
|
|
|
for miss_reserv in missing:
|
|
violations.append(RoomDiscrepancy(
|
|
hotel=miss_reserv.hotel,
|
|
room_number=miss_reserv.room_number,
|
|
discrepancy_type='missed',
|
|
booking_id=miss_reserv.reservation_id,
|
|
check_in_date_expected=miss_reserv.check_in,
|
|
))
|
|
for reserv in reservations:
|
|
reserv.fraud_checked = True
|
|
|
|
RoomDiscrepancy.objects.bulk_create(violations)
|
|
UserActivityLog.objects.bulk_update(user_logs, ['fraud_checked'], 1000)
|
|
Reservation.objects.bulk_update(reservations, ['fraud_checked'], 1000)
|
|
|
|
|
|
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 завершена.")
|