import logging import requests import json from datetime import datetime, timedelta from asgiref.sync import sync_to_async from pms_integration.models import PMSConfiguration from hotels.models import Hotel, Reservation from .base_plugin import BasePMSPlugin class EcviPMSPlugin(BasePMSPlugin): """ Плагин для интеграции с PMS Ecvi (интерфейс для получения данных об отеле). """ def __init__(self, pms_config): # Инициализация родительского конструктора super().__init__(pms_config) # Инициализация логгера self.logger = logging.getLogger(self.__class__.__name__) # Логгер с именем класса handler = logging.StreamHandler() # Потоковый обработчик для вывода в консоль formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s') handler.setFormatter(formatter) self.logger.addHandler(handler) self.logger.setLevel(logging.DEBUG) # Уровень логирования # Инициализация параметров API self.api_url = pms_config.url self.token = pms_config.token self.username = pms_config.username self.password = pms_config.password self.pagination_count = 50 # Максимальное количество записей на страницу (если используется пагинация) def get_default_parser_settings(self): """ Возвращает настройки парсера по умолчанию. """ return { "field_mapping": { "check_in": "checkin", "check_out": "checkout", "room_number": "room_name", # Заменили на room_number "room_type_name": "room_type", "status": "occupancy", }, "date_format": "%Y-%m-%dT%H:%M:%S" } async def _fetch_data(self): """ Получает данные из PMS API, фильтрует и сохраняет в базу данных. """ now = datetime.now() current_date = now.strftime('%Y-%m-%d') yesterday_date = (now - timedelta(days=1)).strftime('%Y-%m-%d') headers = { "Content-Type": "application/json", } data = { "token": self.token, } try: # Запрос данных из PMS API response = await sync_to_async(requests.post)(self.api_url, headers=headers, json=data, auth=(self.username, self.password)) response.raise_for_status() # Если ошибка, выбросит исключение data = response.json() # Преобразуем ответ в JSON self.logger.debug(f"Получены данные с API: {data}") except requests.exceptions.RequestException as e: self.logger.error(f"Ошибка запроса: {e}") return [] # Фильтрация данных filtered_data = [ { 'checkin': datetime.strptime(item.get('checkin'), '%Y-%m-%d %H:%M:%S'), 'checkout': datetime.strptime(item.get('checkout'), '%Y-%m-%d %H:%M:%S'), 'room_name': item.get('room_name'), 'room_type': item.get('room_type'), 'status': item.get('occupancy') } for item in data if item.get('occupancy') in ['проживание', 'под выезд', 'под заезд'] ] # Сохранение данных в базу данных for item in filtered_data: await self._save_to_db(item) self.logger.debug(f"Данные успешно сохранены.") return filtered_data async def _save_to_db(self, item): """ Сохраняет данные в БД (например, информацию о номере). """ try: # Получаем отель по настройкам PMS hotel = await sync_to_async(Hotel.objects.get)(pms=self.pms_config) self.logger.debug(f"Отель найден: {hotel.name}") # Сохраняем данные бронирования room_number = item.get("room_name") check_in = item.get("checkin") check_out = item.get("checkout") room_type = item.get("room_type") # Проверяем, существует ли запись с таким номером и датой заезда existing_reservation = await sync_to_async( Reservation.objects.filter(room_number=room_number, check_in=check_in).first )() if existing_reservation: self.logger.debug(f"Резервация с таким номером и датой заезда уже существует. Обновляем...") await sync_to_async(Reservation.objects.update_or_create)( room_number=room_number, check_in=check_in, defaults={ "check_out": check_out, "hotel": hotel, "room_type": room_type, }, ) self.logger.debug(f"Обновлена существующая резервация.") else: self.logger.debug(f"Резервация не найдена, создаем новую...") await sync_to_async(Reservation.objects.create)( room_number=room_number, check_in=check_in, check_out=check_out, hotel=hotel, room_type=room_type, ) self.logger.debug(f"Создана новая резервация.") except Exception as e: self.logger.error(f"Ошибка сохранения данных: {e}")