antifroud_check

This commit is contained in:
2024-12-17 21:39:33 +09:00
parent 66750015e2
commit 0bf2bb8dff
17 changed files with 1298 additions and 524 deletions

View File

@@ -1,79 +1,160 @@
import logging
from datetime import datetime, timedelta
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
# Настройка логирования
logging.basicConfig(level=logging.INFO) # Устанавливаем уровень логирования
logger = logging.getLogger(__name__) # Создаем логгер для текущего модуля
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
def check_reservations_and_generate_report():
now = datetime.now()
start_time = (now - timedelta(hours=12))
end_time = now
logger.info(f"Starting reservation check from {start_time} to {end_time}")
class ReservationChecker:
"""
Класс для проверки несоответствий между бронированиями и логами заселения.
"""
# Получаем логи активности за период
user_logs = UserActivityLog.objects.filter(created__range=(start_time, end_time))
logger.info(f"Found {len(user_logs)} logs for analysis.")
def __init__(self):
"""
Инициализация времени проверки и списка нарушений.
"""
self.start_time = timezone.now() - timedelta(days=30)
self.end_time = timezone.now()
self.violations = []
violations = [] # Список для записи нарушений
def log_info(self, message):
"""Логирование информационных сообщений."""
logger.info(message)
for i, log in enumerate(user_logs, start=1):
logger.debug(f"Processing log {i}: {log}")
def log_warning(self, message):
"""Логирование предупреждений."""
logger.warning(message)
if not log.url_parameters:
logger.warning(f"Log {i} skipped due to missing URL parameters.")
continue # Пропускаем записи без параметров URL
def log_error(self, message):
"""Логирование ошибок."""
logger.error(message)
# Парсим параметры URL
params = parse_qs(log.url_parameters)
external_id = params.get("utm_content", [None])[0] # ID отеля
room_number = params.get("utm_term", [None])[0] # Номер комнаты
def fetch_user_logs(self):
"""
Извлекает записи из UserActivityLog за последние 12 часов.
"""
print(f"Fetching user logs from {self.start_time} to {self.end_time}")
user_logs = UserActivityLog.objects.filter(created__range=(self.start_time, self.end_time))
print(f"Found {user_logs.count()} logs for analysis.")
return user_logs
logger.debug(f"Log {i} parsed parameters: external_id={external_id}, room_number={room_number}")
def fetch_hotels(self, hotel_ids):
"""
Извлекает отели по hotel_id из логов.
"""
hotels = {hotel.hotel_id: hotel for hotel in Hotel.objects.filter(hotel_id__in=hotel_ids)}
self.log_info(f"Найдено {len(hotels)} отелей для сверки.")
return hotels
if not external_id or not room_number:
logger.warning(f"Log {i} skipped due to missing external_id or room_number.")
continue # Пропускаем, если данные не извлечены
def find_violations(self, user_logs, hotels):
"""
Сопоставляет логи активности с бронированиями и фиксирует нарушения.
"""
for log in user_logs:
if not log.url_parameters:
self.log_warning(f"Пропущена запись ID {log.id}: отсутствуют URL-параметры.")
continue
try:
# Находим отель по external_id
hotel = Hotel.objects.get(external_id=external_id)
logger.debug(f"Log {i}: Found hotel {hotel.name} with external_id {external_id}.")
except Hotel.DoesNotExist:
logger.error(f"Log {i} skipped: No hotel found with external_id {external_id}.")
continue
# Парсинг параметров URL
params = parse_qs(log.url_parameters)
hotel_id = params.get("utm_content", [None])[0]
room_number = params.get("utm_term", [None])[0]
# Ищем бронирование в Reservation
matching_reservations = Reservation.objects.filter(
hotel=hotel,
room_number=room_number,
check_in__lte=log.created,
check_out__gte=log.created
)
logger.debug(f"Log {i}: Found {len(matching_reservations)} matching reservations.")
print(f"Processing log ID {log.id} with hotel ID {hotel_id} and room number {room_number}")
if not matching_reservations.exists():
# Если бронирование не найдено — записываем нарушение
violation_details = (
f"Log {i}: No reservation found for room {room_number} in hotel {external_id} at {log.created}."
)
violations.append(ViolationLog(
if not hotel_id or not room_number:
self.log_warning(f"Пропущена запись ID {log.id}: некорректные параметры URL.")
continue
if hotel_id not in hotels:
self.log_warning(f"Пропущена запись ID {log.id}: отель с ID {hotel_id} не найден.")
continue
hotel = hotels[hotel_id]
log_time = timezone.localtime(log.created)
# Проверка существования бронирования
matching_reservations = Reservation.objects.filter(
hotel=hotel,
room_number=room_number,
violation_type="missed",
violation_details=violation_details
))
logger.warning(f"Log {i}: Violation recorded - {violation_details}")
check_in__lte=log_time,
check_out__gte=log_time
)
# Сохраняем все нарушения в базу
if violations:
ViolationLog.objects.bulk_create(violations)
logger.info(f"Created {len(violations)} records in violation log.")
else:
logger.info("No violations found during this check.")
print(f"Found {matching_reservations.count()} matching reservations")
logger.info("Reservation check completed.")
if not matching_reservations.exists():
violation_details = (
f"Не найдено бронирование для номера {room_number} в отеле '{hotel.name}' на {log_time}."
)
# Добавляем нарушение, если его ещё нет в базе
if not ViolationLog.objects.filter(
hotel=hotel,
room_number=room_number,
violation_type="missed",
violation_details=violation_details
).exists():
self.violations.append(ViolationLog(
hotel=hotel,
room_number=room_number,
violation_type="missed",
violation_details=violation_details
))
self.log_warning(f"Зафиксировано нарушение: {violation_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:
# Получаем логи пользователей
user_logs = self.fetch_user_logs()
# Извлекаем hotel_id из логов
hotel_ids = set()
for log in user_logs:
if log.url_parameters:
params = parse_qs(log.url_parameters)
hotel_id = params.get("utm_content", [None])[0]
if hotel_id:
hotel_ids.add(hotel_id)
# Предзагружаем отели
hotels = self.fetch_hotels(hotel_ids)
# Сравниваем логи с бронированиями
self.find_violations(user_logs, hotels)
# Сохраняем результаты
self.save_violations()
except Exception as e:
self.log_error(f"Произошла ошибка при выполнении проверки: {e}")
self.log_info("Проверка бронирований завершена.")
# Функция для запуска проверки из планировщика
def run_reservation_check():
"""
Функция для запуска проверки бронирований.
"""
checker = ReservationChecker()
checker.run_check()