remote changes
This commit is contained in:
@@ -1,26 +1,149 @@
|
||||
# import json
|
||||
# from datetime import timedelta
|
||||
# from django.utils import timezone
|
||||
# from django.db.models import Q
|
||||
# from hotels.models import Reservation, Hotel
|
||||
# from .models import UserActivityLog, 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("Запуск проверки фродовых данных.")
|
||||
# try:
|
||||
# check_in_diff = timedelta(hours=self.checkin_diff_hours)
|
||||
|
||||
# # Кэшируем отели в словарь для быстрого доступа
|
||||
# hotels_map = {hotel.hotel_id: hotel for hotel in Hotel.objects.all()}
|
||||
|
||||
# # Загружаем бронирования и активности пользователей
|
||||
# user_logs = UserActivityLog.objects.filter(fraud_checked=False)
|
||||
# reservations = Reservation.objects.filter(fraud_checked=False).select_related('hotel')
|
||||
|
||||
# # Преобразуем бронирования в словарь для быстрого поиска
|
||||
# reservations_map = {
|
||||
# (res.hotel.hotel_id, res.room_number): res for res in reservations
|
||||
# }
|
||||
|
||||
# violations = []
|
||||
# missing_reservations = set(reservations) # Сет для поиска пропавших бронирований
|
||||
|
||||
# for user_log in user_logs:
|
||||
# try:
|
||||
# params = json.loads(user_log.url_parameters.replace("'", '"')) if user_log.url_parameters else {}
|
||||
# hotel_id = params.get('utm_content')
|
||||
# room = params.get('utm_term')
|
||||
|
||||
# if not hotel_id or not room:
|
||||
# continue # Пропускаем записи без нужных параметров
|
||||
|
||||
# key = (hotel_id, room)
|
||||
# reserv = reservations_map.get(key)
|
||||
|
||||
# discrepancy_type = None
|
||||
|
||||
# if reserv:
|
||||
# if reserv in missing_reservations:
|
||||
# missing_reservations.remove(reserv)
|
||||
|
||||
# if user_log.date_time < reserv.check_in:
|
||||
# discrepancy_type = 'early'
|
||||
# elif user_log.date_time > reserv.check_in + check_in_diff:
|
||||
# discrepancy_type = 'late'
|
||||
# else:
|
||||
# discrepancy_type = 'no_booking'
|
||||
|
||||
# if discrepancy_type:
|
||||
# violations.append(RoomDiscrepancy(
|
||||
# hotel=hotels_map.get(hotel_id),
|
||||
# room_number=room,
|
||||
# discrepancy_type=discrepancy_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 json.JSONDecodeError:
|
||||
# self.log_error(f"Ошибка декодирования JSON в URL-параметрах: {user_log.url_parameters}")
|
||||
# except Exception as e:
|
||||
# self.log_error(f"Ошибка при обработке логов: {e}")
|
||||
|
||||
# # Добавляем пропущенные бронирования
|
||||
# for miss_reserv in missing_reservations:
|
||||
# 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,
|
||||
# ))
|
||||
|
||||
# # Массово сохраняем нарушения
|
||||
# if violations:
|
||||
# RoomDiscrepancy.objects.bulk_create(violations)
|
||||
# self.log_info(f"Записано {len(violations)} новых несоответствий.")
|
||||
|
||||
# # Обновляем флаги fraud_checked
|
||||
# UserActivityLog.objects.filter(id__in=[log.id for log in user_logs]).update(fraud_checked=True)
|
||||
# Reservation.objects.filter(id__in=[res.id for res in reservations]).update(fraud_checked=True)
|
||||
|
||||
# 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 завершена.")
|
||||
|
||||
|
||||
|
||||
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 .models import UserActivityLog, RoomDiscrepancy
|
||||
from touchh.utils.log import CustomLogger
|
||||
|
||||
# Настройка логирования
|
||||
logger = CustomLogger(__name__).get_logger()
|
||||
|
||||
|
||||
class ReservationChecker:
|
||||
"""
|
||||
Класс для проверки несоответствий между бронированиями и логами заселения.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
"""
|
||||
Инициализация времени проверки и списка нарушений.
|
||||
"""
|
||||
self.checkin_diff_hours = 3
|
||||
self.checkin_diff_hours = 3 # Разрешенное отклонение от времени заселения
|
||||
|
||||
def log_info(self, message):
|
||||
logger.info(message)
|
||||
@@ -32,80 +155,105 @@ class ReservationChecker:
|
||||
logger.error(message)
|
||||
|
||||
def run_check(self):
|
||||
self.log_info(f"Запуск проверки.")
|
||||
"""Запуск проверки фродовых событий."""
|
||||
self.log_info("🔍 Запуск проверки фродовых данных.")
|
||||
try:
|
||||
hotels_map = {}
|
||||
hotels = Hotel.objects.all()
|
||||
for hotel in hotels:
|
||||
hotels_map[hotel.hotel_id] = hotel
|
||||
check_in_diff = timedelta(hours=self.checkin_diff_hours)
|
||||
|
||||
# Кэшируем отели в словарь для быстрого доступа
|
||||
hotels_map = {hotel.hotel_id: hotel for hotel in Hotel.objects.all()}
|
||||
|
||||
# Загружаем бронирования и активности пользователей
|
||||
user_logs = UserActivityLog.objects.filter(fraud_checked=False)
|
||||
reservations = Reservation.objects.filter(fraud_checked=False).select_related('hotel')
|
||||
missing = list(reservations)
|
||||
|
||||
# Преобразуем бронирования в словарь для быстрого поиска
|
||||
reservations_map = {
|
||||
(res.hotel.hotel_id, res.room_number): res for res in reservations
|
||||
}
|
||||
|
||||
violations = []
|
||||
check_in_diff = timedelta(hours=self.checkin_diff_hours)
|
||||
checked_reservations = set() # Сет для бронирований, которые были проверены
|
||||
|
||||
self.log_info(f"✅ Загружено {len(user_logs)} логов активности и {len(reservations)} бронирований.")
|
||||
|
||||
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
|
||||
params = json.loads(user_log.url_parameters.replace("'", '"')) if user_log.url_parameters else {}
|
||||
hotel_id = params.get('utm_content')
|
||||
room = params.get('utm_term')
|
||||
|
||||
if not hotel_id or not room:
|
||||
self.log_warning(f"🚫 Пропущен лог без hotel_id или room_number: {user_log.url_parameters}")
|
||||
continue # Пропускаем записи без нужных параметров
|
||||
|
||||
key = (hotel_id, room)
|
||||
reserv = reservations_map.get(key)
|
||||
|
||||
discrepancy_type = "match" # По умолчанию считаем, что всё соответствует
|
||||
|
||||
if reserv:
|
||||
if reserv in missing:
|
||||
missing.remove(reserv)
|
||||
checked_reservations.add(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'
|
||||
discrepancy_type = 'early'
|
||||
self.log_warning(f"⚠️ Обнаружено раннее заселение: {user_log.date_time} < {reserv.check_in}")
|
||||
elif user_log.date_time > reserv.check_in + check_in_diff:
|
||||
discrepancy_type = 'late'
|
||||
self.log_warning(f"⚠️ Обнаружено позднее заселение: {user_log.date_time} > {reserv.check_in + check_in_diff}")
|
||||
else:
|
||||
v_type = 'no_booking'
|
||||
discrepancy_type = 'no_booking'
|
||||
self.log_warning(f"🚨 Заселение без бронирования: {user_log.date_time} (Отель {hotel_id}, Комната {room})")
|
||||
|
||||
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,
|
||||
))
|
||||
violations.append(RoomDiscrepancy(
|
||||
hotel=hotels_map.get(hotel_id),
|
||||
room_number=room,
|
||||
discrepancy_type=discrepancy_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
|
||||
user_log.fraud_checked = True # Отмечаем логи как проверенные
|
||||
|
||||
except json.JSONDecodeError:
|
||||
self.log_error(f"❌ Ошибка декодирования JSON в URL-параметрах: {user_log.url_parameters}")
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
self.log_error(f"❌ Ошибка при обработке логов: {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
|
||||
if reserv not in checked_reservations:
|
||||
violations.append(RoomDiscrepancy(
|
||||
hotel=reserv.hotel,
|
||||
room_number=reserv.room_number,
|
||||
discrepancy_type='missed',
|
||||
booking_id=reserv.reservation_id,
|
||||
check_in_date_expected=reserv.check_in,
|
||||
))
|
||||
self.log_warning(f"⚠️ Обнаружена неявка (missed) | Отель: {reserv.hotel.hotel_id}, Номер: {reserv.room_number}, Ожидаемая дата заезда: {reserv.check_in}")
|
||||
|
||||
RoomDiscrepancy.objects.bulk_create(violations)
|
||||
UserActivityLog.objects.bulk_update(user_logs, ['fraud_checked'], 1000)
|
||||
Reservation.objects.bulk_update(reservations, ['fraud_checked'], 1000)
|
||||
# Массово сохраняем все записи, включая корректные совпадения
|
||||
if violations:
|
||||
RoomDiscrepancy.objects.bulk_create(violations)
|
||||
self.log_info(f"✅ Записано {len(violations)} новых записей в RoomDiscrepancy.")
|
||||
|
||||
# Обновляем флаги fraud_checked
|
||||
UserActivityLog.objects.filter(id__in=[log.id for log in user_logs]).update(fraud_checked=True)
|
||||
Reservation.objects.filter(id__in=[res.id for res in reservations]).update(fraud_checked=True)
|
||||
|
||||
except Exception as e:
|
||||
self.log_error(f"Ошибка при выполнении проверки: {e}")
|
||||
self.log_info("Проверка завершена.")
|
||||
self.log_error(f"❌ Ошибка при выполнении проверки: {e}")
|
||||
|
||||
self.log_info("✅ Проверка фродовых данных завершена.")
|
||||
|
||||
# Функция для запуска из планировщика
|
||||
def run_reservation_check():
|
||||
logger.info("Планировщик вызывает 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 завершена.")
|
||||
logger.error(f"❌ Ошибка при запуске проверки: {e}")
|
||||
logger.info("✅ run_reservation_check завершена.")
|
||||
|
||||
Reference in New Issue
Block a user