From e2fd7d26bd8cb47137260adc49932361b6024dd6 Mon Sep 17 00:00:00 2001 From: trevor Date: Wed, 25 Dec 2024 12:01:19 +0900 Subject: [PATCH] ECVI, RealtyCalendar Pliugins bugfix Reports displaying --- bot/operations/hotels.py | 68 ++- pms_integration/plugins/ecvi_pms.py | 62 ++- pms_integration/plugins/realtycalendar_pms.py | 455 +++++++++++++++--- 3 files changed, 490 insertions(+), 95 deletions(-) diff --git a/bot/operations/hotels.py b/bot/operations/hotels.py index 3ec5371c..21c8f0cd 100644 --- a/bot/operations/hotels.py +++ b/bot/operations/hotels.py @@ -78,6 +78,53 @@ async def delete_hotel(update: Update, context): await query.edit_message_text("Отель не найден.") +# async def check_pms(update, context): +# query = update.callback_query + +# try: +# # Получение ID отеля из callback_data +# hotel_id = query.data.split("_")[2] +# logger.debug(f"Hotel ID: {hotel_id}") +# logger.debug(f"Hotel ID type : {type(hotel_id)}") +# # Получение конфигурации отеля и PMS +# hotel = await sync_to_async(Hotel.objects.select_related('pms').get)(id=hotel_id) +# pms_config = hotel.pms + +# if not pms_config: +# await query.edit_message_text("PMS конфигурация не найдена.") +# return + +# # Создаем экземпляр PMSIntegrationManager +# pms_manager = PMSIntegrationManager(hotel_id=hotel_id) +# await pms_manager.load_hotel() +# await sync_to_async(pms_manager.load_plugin)() + +# # Проверяем, какой способ интеграции использовать +# if hasattr(pms_manager.plugin, 'fetch_data') and callable(pms_manager.plugin.fetch_data): +# # Плагин поддерживает метод fetch_data +# report = await pms_manager.plugin._fetch_data() + +# else: +# await query.edit_message_text("Подходящий способ интеграции с PMS не найден.") +# return + +# # Формируем сообщение о результатах +# result_message = ( +# f"Интеграция PMS завершена успешно.\n" +# f"Обработано интервалов: {report['processed_intervals']}\n" +# f"Обработано записей: {report['processed_items']}\n" +# f"Ошибки: {len(report['errors'])}" +# ) +# logger.info(f'Result_Message: {result_message}\n Result_meaage_type: {type(result_message)}') +# if report["errors"]: +# result_message += "\n\nСписок ошибок:\n" + "\n".join(report["errors"]) + +# await query.edit_message_text(result_message) +# except Exception as e: +# # Обрабатываем и логируем ошибки +# await query.edit_message_text(f"❌ Ошибка: {str(e)}") + + async def check_pms(update, context): query = update.callback_query @@ -86,6 +133,7 @@ async def check_pms(update, context): hotel_id = query.data.split("_")[2] logger.debug(f"Hotel ID: {hotel_id}") logger.debug(f"Hotel ID type : {type(hotel_id)}") + # Получение конфигурации отеля и PMS hotel = await sync_to_async(Hotel.objects.select_related('pms').get)(id=hotel_id) pms_config = hotel.pms @@ -103,29 +151,37 @@ async def check_pms(update, context): if hasattr(pms_manager.plugin, 'fetch_data') and callable(pms_manager.plugin.fetch_data): # Плагин поддерживает метод fetch_data report = await pms_manager.plugin._fetch_data() - + logger.debug(f"REPORT: {report}, TYPE: {type(report)}") else: await query.edit_message_text("Подходящий способ интеграции с PMS не найден.") return + # Проверяем результат выполнения fetch_data + if not report or not isinstance(report, dict): + logger.error(f"Некорректный отчет от fetch_data: {report}") + await query.edit_message_text("Ошибка: Отчет fetch_data отсутствует или имеет некорректный формат.") + return + # Формируем сообщение о результатах result_message = ( f"Интеграция PMS завершена успешно.\n" - f"Обработано интервалов: {report['processed_intervals']}\n" - f"Обработано записей: {report['processed_items']}\n" - f"Ошибки: {len(report['errors'])}" + f"Обработано интервалов: {report.get('processed_intervals', 0)}\n" + f"Обработано записей: {report.get('processed_items', 0)}\n" + f"Ошибки: {len(report.get('errors', []))}" ) - logger.info(f'Result_Message: {result_message}\n Result_meaage_type: {type(result_message)}') - if report["errors"]: + if report.get("errors"): result_message += "\n\nСписок ошибок:\n" + "\n".join(report["errors"]) + logger.info(f"Result_Message: {result_message}") await query.edit_message_text(result_message) except Exception as e: # Обрабатываем и логируем ошибки + logger.error(f"Ошибка в методе check_pms: {str(e)}", exc_info=True) await query.edit_message_text(f"❌ Ошибка: {str(e)}") + async def setup_rooms(update: Update, context): """Настроить номера отеля.""" query = update.callback_query diff --git a/pms_integration/plugins/ecvi_pms.py b/pms_integration/plugins/ecvi_pms.py index 41b14230..7e7fff48 100644 --- a/pms_integration/plugins/ecvi_pms.py +++ b/pms_integration/plugins/ecvi_pms.py @@ -57,7 +57,8 @@ class EcviPMSPlugin(BasePMSPlugin): now = datetime.now() current_date = now.strftime('%Y-%m-%d') yesterday_date = (now - timedelta(days=1)).strftime('%Y-%m-%d') - + processed_items = 0 + errors = [] headers = { "Content-Type": "application/json", } @@ -76,25 +77,48 @@ class EcviPMSPlugin(BasePMSPlugin): return [] # Фильтрация данных - filtered_data = [ - { - 'reservation_id': item.get('task_id'), - 'room_number': item.get('room_name'), - 'room_type': item.get('room_type'), - 'checkin': datetime.strptime(item.get('checkin'), '%Y-%m-%d %H:%M:%S'), - 'checkout': datetime.strptime(item.get('checkout'), '%Y-%m-%d %H:%M:%S'), - 'status': item.get('occupancy') - } for item in data if isinstance(item, dict) and item.get('occupancy') in ['проживание', 'под выезд', 'под заезд'] - ] - - self.logger.debug(f"filtered_data: {filtered_data}") - + filtered_data = [] + for item in data: + try: + if not isinstance(item, dict): + raise ValueError(f"Некорректный формат элемента: {item}") + + reservation_id = item.get('task_id') + if not reservation_id: + raise ValueError("Отсутствует task_id в записи") + + checkin = datetime.strptime(item.get('checkin'), '%Y-%m-%d %H:%M:%S') + checkout = datetime.strptime(item.get('checkout'), '%Y-%m-%d %H:%M:%S') + + filtered_data.append({ + 'reservation_id': reservation_id, + 'room_number': item.get('room_name'), + 'room_type': item.get('room_type'), + 'checkin': checkin, + 'checkout': checkout, + 'status': item.get('occupancy') + }) + processed_items += 1 + except Exception as e: + self.logger.error(f"Ошибка обработки элемента: {e}") + errors.append(str(e)) + # Сохранение данных в базу данных - for item in filtered_data: - await self._save_to_db(item) - - self.logger.debug(f"Данные успешно сохранены.") - return filtered_data + try: + for item in filtered_data: + await self._save_to_db(item) + except Exception as e: + self.logger.error(f"Ошибка сохранения данных в БД: {e}") + errors.append(f"Ошибка сохранения данных в БД: {str(e)}") + + # Формирование отчета + report = { + "processed_intervals": 1, + "processed_items": processed_items, + "errors": errors + } + self.logger.debug(f"Сформированный отчет: {report}") + return report async def _save_to_db(self, item): """ diff --git a/pms_integration/plugins/realtycalendar_pms.py b/pms_integration/plugins/realtycalendar_pms.py index f29fa2cc..d7955ff2 100644 --- a/pms_integration/plugins/realtycalendar_pms.py +++ b/pms_integration/plugins/realtycalendar_pms.py @@ -1,3 +1,194 @@ +# import requests +# import hashlib +# import json +# from .base_plugin import BasePMSPlugin +# from datetime import datetime, timedelta +# from asgiref.sync import sync_to_async +# from touchh.utils.log import CustomLogger +# from hotels.models import Hotel, Reservation +# from app_settings.models import GlobalHotelSettings +# from django.utils import timezone +# class RealtyCalendarPlugin(BasePMSPlugin): +# def __init__(self, config): +# super().__init__(config) +# self.public_key = config.public_key +# self.private_key = config.private_key +# self.api_url = config.url.rstrip("/") +# self.logger = CustomLogger(name="RealtyCalendarPlugin", log_level="DEBUG").get_logger() +# if not self.public_key or not self.private_key: +# raise ValueError("Публичный или приватный ключ отсутствует для RealtyCalendar") + +# def get_default_parser_settings(self): +# """ +# Возвращает настройки по умолчанию для обработки данных. +# """ +# return { +# "date_format": "%Y-%m-%dT%H:%M:%S", +# "timezone": "UTC" +# } + +# def _get_sorted_keys(self, obj): +# """ +# Возвращает отсортированный по имени список ключей. +# """ +# sorted_keys = sorted(obj.keys()) +# self.logger.debug(f"Отсортированные ключи: {sorted_keys}") +# return sorted_keys + +# def _generate_data_string(self, obj): +# """ +# Формирует строку параметров для подписи. +# """ +# sorted_keys = self._get_sorted_keys(obj) +# string = "".join(f"{key}={obj[key]}" for key in sorted_keys) +# self.logger.debug(f"Сформированная строка данных: {string}") +# return string + self.private_key + +# def _generate_md5(self, string): +# """ +# Генерирует MD5-хеш от строки. +# """ +# md5_hash = hashlib.md5(string.encode("utf-8")).hexdigest() +# self.logger.debug(f"Сформированный MD5-хеш: {md5_hash}") +# return md5_hash + +# def _generate_sign(self, data): +# """ +# Генерирует подпись для данных запроса. +# """ +# data_string = self._generate_data_string(data) +# self.logger.debug(f"Строка для подписи: {data_string}") +# sign = self._generate_md5(data_string) +# self.logger.debug(f"Подпись: {sign}") +# return sign + +# async def _fetch_data(self): +# """ +# Выполняет запрос к API RealtyCalendar для получения данных о бронированиях. +# """ +# self.logger.debug("Начало выполнения функции _fetch_data") +# base_url = f"{self.api_url}/api/v1/bookings/{self.public_key}/" +# headers = { +# "Accept": "application/json", +# "Content-Type": "application/json", +# } + +# now = datetime.now() +# data = { +# "begin_date": (now - timedelta(days=7)).strftime("%Y-%m-%d"), +# "end_date": now.strftime("%Y-%m-%d"), +# } +# data["sign"] = self._generate_sign(data) + +# response = requests.post(url=base_url, headers=headers, json=data) +# self.logger.debug(f"Статус ответа: {response.status_code}") + +# if response.status_code != 200: +# self.logger.error(f"Ошибка API: {response.status_code}, {response.text}") +# raise ValueError(f"Ошибка API RealtyCalendar: {response.status_code}") + +# try: +# response_data = response.json() +# bookings = response_data.get("bookings", []) +# if not isinstance(bookings, list): +# raise ValueError(f"Ожидался список, но получен {type(bookings)}") +# except Exception as e: +# self.logger.error(f"Ошибка обработки ответа API: {e}") +# raise + +# # Получаем глобальные настройки отеля +# hotel = await sync_to_async(Hotel.objects.get)(pms=self.pms_config) +# hotel_tz = hotel.timezone +# try: +# hotel_settings = await sync_to_async(GlobalHotelSettings.objects.first)() +# check_in_time = hotel_settings.check_in_time.strftime("%H:%M:%S") +# check_out_time = hotel_settings.check_out_time.strftime("%H:%M:%S") +# except AttributeError: +# # Используем значения по умолчанию, если настроек нет +# check_in_time = "14:00:00" +# check_out_time = "12:00:00" + +# filtered_data = [ +# { +# 'reservation_id': item.get('id'), +# 'checkin': timezone.make_aware( +# datetime.strptime( +# f"{item.get('begin_date')} {check_in_time}", +# "%Y-%m-%d %H:%M:%S" +# ) +# ), +# 'checkout': timezone.make_aware( +# datetime.strptime( +# f"{item.get('end_date')} {check_out_time}", +# "%Y-%m-%d %H:%M:%S" +# ) +# ), +# 'room_number': item.get('apartment_id'), +# 'room_type': item.get('notes', 'Описание отсутствует'), +# 'status': item.get('status') +# } +# for item in bookings +# if isinstance(item, dict) and item.get("status") in ["booked", "request"] +# ] + +# await self._save_to_db(filtered_data) + +# async def _save_to_db(self, data): +# """ +# Сохраняет данные в БД (например, информацию о номере). +# """ +# if not isinstance(data, list): +# self.logger.error(f"Ожидался список записей, но получен {type(data).__name__}") +# return + +# for index, item in enumerate(data, start=1): +# try: +# hotel = await sync_to_async(Hotel.objects.get)(pms=self.pms_config) +# reservation_id = item.get('reservation_id') +# if not reservation_id: +# self.logger.error(f"Пропущена запись {index}: отсутствует 'id'") +# continue + +# existing_reservation = await sync_to_async(Reservation.objects.filter)(reservation_id=reservation_id) +# existing_reservation = await sync_to_async(existing_reservation.first)() + +# defaults = { +# 'room_number': item['room_number'], +# 'room_type': item['room_type'], +# 'check_in': item['checkin'], +# 'check_out': item['checkout'], +# 'status': item['status'], +# 'hotel': hotel +# } + +# if existing_reservation: +# await sync_to_async(Reservation.objects.update_or_create)( +# reservation_id=reservation_id, defaults=defaults +# ) +# self.logger.debug(f"Резервация {reservation_id} обновлена.") +# else: +# await sync_to_async(Reservation.objects.create)( +# reservation_id=reservation_id, **defaults +# ) +# self.logger.debug(f"Создана новая резервация {reservation_id}") + +# except Exception as e: +# self.logger.error(f"Ошибка при обработке записи {index}: {e}") + +# def validate_plugin(self): +# """ +# Проверка на соответствие требованиям. +# Можно проверить наличие методов или полей. +# """ +# # Проверяем наличие обязательных методов +# required_methods = ["fetch_data", "get_default_parser_settings", "_fetch_data"] +# for m in required_methods: +# if not hasattr(self, m): +# raise ValueError(f"Плагин {type(self).__name__} не реализует метод {m}.") +# self.logger.debug(f"Плагин {self.__class__.__name__} прошел валидацию.") +# return True + + import requests import hashlib import json @@ -8,6 +199,7 @@ from touchh.utils.log import CustomLogger from hotels.models import Hotel, Reservation from app_settings.models import GlobalHotelSettings from django.utils import timezone + class RealtyCalendarPlugin(BasePMSPlugin): def __init__(self, config): super().__init__(config) @@ -26,46 +218,123 @@ class RealtyCalendarPlugin(BasePMSPlugin): "date_format": "%Y-%m-%dT%H:%M:%S", "timezone": "UTC" } - def _get_sorted_keys(self, obj): - """ - Возвращает отсортированный по имени список ключей. - """ sorted_keys = sorted(obj.keys()) self.logger.debug(f"Отсортированные ключи: {sorted_keys}") return sorted_keys def _generate_data_string(self, obj): - """ - Формирует строку параметров для подписи. - """ sorted_keys = self._get_sorted_keys(obj) string = "".join(f"{key}={obj[key]}" for key in sorted_keys) self.logger.debug(f"Сформированная строка данных: {string}") return string + self.private_key def _generate_md5(self, string): - """ - Генерирует MD5-хеш от строки. - """ md5_hash = hashlib.md5(string.encode("utf-8")).hexdigest() self.logger.debug(f"Сформированный MD5-хеш: {md5_hash}") return md5_hash def _generate_sign(self, data): - """ - Генерирует подпись для данных запроса. - """ data_string = self._generate_data_string(data) self.logger.debug(f"Строка для подписи: {data_string}") sign = self._generate_md5(data_string) self.logger.debug(f"Подпись: {sign}") return sign + # async def _fetch_data(self): + # self.logger.debug("Начало выполнения функции _fetch_data") + # base_url = f"{self.api_url}/api/v1/bookings/{self.public_key}/" + # headers = { + # "Accept": "application/json", + # "Content-Type": "application/json", + # } + + # now = datetime.now() + # data = { + # "begin_date": (now - timedelta(days=7)).strftime("%Y-%m-%d"), + # "end_date": now.strftime("%Y-%m-%d"), + # } + # data["sign"] = self._generate_sign(data) + + # try: + # response = requests.post(url=base_url, headers=headers, json=data) + # self.logger.debug(f"Статус ответа: {response.status_code}") + + # if response.status_code != 200: + # self.logger.error(f"Ошибка API: {response.status_code}, {response.text}") + # raise ValueError(f"Ошибка API RealtyCalendar: {response.status_code}") + + # try: + # response_data = response.json() + # bookings = response_data.get("bookings", []) + # # self.logger.debug(f"Полученные данные: {bookings}") + + # if not isinstance(bookings, list): + # self.logger.error(f"Ожидался список, но получен: {type(bookings)}") + # raise ValueError("Некорректный формат данных для bookings") + # except json.JSONDecodeError as e: + # self.logger.error(f"Ошибка декодирования JSON: {e}") + # raise ValueError("Ответ не является корректным JSON.") + # except Exception as e: + # self.logger.error(f"Ошибка обработки ответа API: {e}") + # raise + + # except Exception as e: + # self.logger.error(f"Ошибка запроса к API RealtyCalendar: {e}") + # raise + + # try: + # hotel = await sync_to_async(Hotel.objects.get)(pms=self.pms_config) + # hotel_tz = hotel.timezone + # self.logger.debug(f"Настройки отеля: {hotel.name}, Timezone: {hotel_tz}") + + # hotel_settings = await sync_to_async(GlobalHotelSettings.objects.first)() + # check_in_time = hotel_settings.check_in_time.strftime("%H:%M:%S") if hotel_settings else "14:00:00" + # check_out_time = hotel_settings.check_out_time.strftime("%H:%M:%S") if hotel_settings else "12:00:00" + # except Exception as e: + # self.logger.error(f"Ошибка получения настроек отеля: {e}") + # check_in_time, check_out_time = "14:00:00", "12:00:00" + + # filtered_data = [] + # for item in bookings: + # try: + # if not isinstance(item, dict): + # self.logger.error(f"Некорректный формат элемента: {item}") + # continue + + # reservation_id = item.get('id') + # if not reservation_id: + # self.logger.error(f"ID резервации отсутствует: {item}") + # continue + + # begin_date = item.get('begin_date') + # end_date = item.get('end_date') + # if not begin_date or not end_date: + # self.logger.error(f"Отсутствуют даты в записи: {item}") + # continue + + # checkin = timezone.make_aware( + # datetime.strptime(f"{begin_date} {check_in_time}", "%Y-%m-%d %H:%M:%S") + # ) + # checkout = timezone.make_aware( + # datetime.strptime(f"{end_date} {check_out_time}", "%Y-%m-%d %H:%M:%S") + # ) + + # filtered_data.append({ + # 'reservation_id': reservation_id, + # 'checkin': checkin, + # 'checkout': checkout, + # 'room_number': item.get('apartment_id'), + # 'room_type': item.get('notes', 'Описание отсутствует'), + # 'status': item.get('status') + # }) + # except Exception as e: + # self.logger.error(f"Ошибка обработки элемента: {e}") + + # # self.logger.debug(f"Отфильтрованные данные: {filtered_data}") + # await self._save_to_db(filtered_data) + async def _fetch_data(self): - """ - Выполняет запрос к API RealtyCalendar для получения данных о бронированиях. - """ self.logger.debug("Начало выполнения функции _fetch_data") base_url = f"{self.api_url}/api/v1/bookings/{self.public_key}/" headers = { @@ -80,63 +349,114 @@ class RealtyCalendarPlugin(BasePMSPlugin): } data["sign"] = self._generate_sign(data) - response = requests.post(url=base_url, headers=headers, json=data) - self.logger.debug(f"Статус ответа: {response.status_code}") - - if response.status_code != 200: - self.logger.error(f"Ошибка API: {response.status_code}, {response.text}") - raise ValueError(f"Ошибка API RealtyCalendar: {response.status_code}") - try: + response = requests.post(url=base_url, headers=headers, json=data) + self.logger.debug(f"Статус ответа: {response.status_code}") + + if response.status_code != 200: + self.logger.error(f"Ошибка API: {response.status_code}, {response.text}") + return { + "processed_intervals": 0, + "processed_items": 0, + "errors": [f"Ошибка API RealtyCalendar: {response.status_code}"] + } + response_data = response.json() bookings = response_data.get("bookings", []) + if not isinstance(bookings, list): - raise ValueError(f"Ожидался список, но получен {type(bookings)}") - except Exception as e: - self.logger.error(f"Ошибка обработки ответа API: {e}") - raise + self.logger.error(f"Ожидался список, но получен: {type(bookings)}") + return { + "processed_intervals": 0, + "processed_items": 0, + "errors": ["Некорректный формат данных для bookings"] + } - # Получаем глобальные настройки отеля - hotel = await sync_to_async(Hotel.objects.get)(pms=self.pms_config) - hotel_tz = hotel.timezone - try: - hotel_settings = await sync_to_async(GlobalHotelSettings.objects.first)() - check_in_time = hotel_settings.check_in_time.strftime("%H:%M:%S") - check_out_time = hotel_settings.check_out_time.strftime("%H:%M:%S") - except AttributeError: - # Используем значения по умолчанию, если настроек нет - check_in_time = "14:00:00" - check_out_time = "12:00:00" - - filtered_data = [ - { - 'reservation_id': item.get('id'), - 'checkin': timezone.make_aware( - datetime.strptime( - f"{item.get('begin_date')} {check_in_time}", - "%Y-%m-%d %H:%M:%S" - ) - ), - 'checkout': timezone.make_aware( - datetime.strptime( - f"{item.get('end_date')} {check_out_time}", - "%Y-%m-%d %H:%M:%S" - ) - ), - 'room_number': item.get('apartment_id'), - 'room_type': item.get('notes', 'Описание отсутствует'), - 'status': item.get('status') + except json.JSONDecodeError as e: + self.logger.error(f"Ошибка декодирования JSON: {e}") + return { + "processed_intervals": 0, + "processed_items": 0, + "errors": ["Ответ не является корректным JSON."] + } + except Exception as e: + self.logger.error(f"Ошибка запроса к API RealtyCalendar: {e}") + return { + "processed_intervals": 0, + "processed_items": 0, + "errors": [str(e)] } - for item in bookings - if isinstance(item, dict) and item.get("status") in ["booked", "request"] - ] - await self._save_to_db(filtered_data) + # Получение настроек отеля + try: + hotel = await sync_to_async(Hotel.objects.get)(pms=self.pms_config) + hotel_tz = hotel.timezone + self.logger.debug(f"Настройки отеля: {hotel.name}, Timezone: {hotel_tz}") + + hotel_settings = await sync_to_async(GlobalHotelSettings.objects.first)() + check_in_time = hotel_settings.check_in_time.strftime("%H:%M:%S") if hotel_settings else "14:00:00" + check_out_time = hotel_settings.check_out_time.strftime("%H:%M:%S") if hotel_settings else "12:00:00" + except Exception as e: + self.logger.error(f"Ошибка получения настроек отеля: {e}") + check_in_time, check_out_time = "14:00:00", "12:00:00" + + # Обработка записей + processed_items = 0 + errors = [] + filtered_data = [] + + for item in bookings: + try: + if not isinstance(item, dict): + raise ValueError(f"Некорректный формат элемента: {item}") + + reservation_id = item.get('id') + if not reservation_id: + raise ValueError(f"ID резервации отсутствует: {item}") + + begin_date = item.get('begin_date') + end_date = item.get('end_date') + if not begin_date or not end_date: + raise ValueError(f"Отсутствуют даты в записи: {item}") + + checkin = timezone.make_aware( + datetime.strptime(f"{begin_date} {check_in_time}", "%Y-%m-%d %H:%M:%S") + ) + checkout = timezone.make_aware( + datetime.strptime(f"{end_date} {check_out_time}", "%Y-%m-%d %H:%M:%S") + ) + + filtered_data.append({ + 'reservation_id': reservation_id, + 'checkin': checkin, + 'checkout': checkout, + 'room_number': item.get('apartment_id'), + 'room_type': item.get('notes', 'Описание отсутствует'), + 'status': item.get('status') + }) + processed_items += 1 + except Exception as e: + self.logger.error(f"Ошибка обработки элемента: {e}") + errors.append(str(e)) + + # Сохранение в БД + try: + await self._save_to_db(filtered_data) + except Exception as e: + self.logger.error(f"Ошибка сохранения данных в БД: {e}") + errors.append(f"Ошибка сохранения данных в БД: {str(e)}") + + # Формирование отчета + report = { + "processed_intervals": 1, # Пример значения + "processed_items": processed_items, + "errors": errors + } + self.logger.debug(f"Сформированный отчет: {report}") + return report + async def _save_to_db(self, data): - """ - Сохраняет данные в БД (например, информацию о номере). - """ if not isinstance(data, list): self.logger.error(f"Ожидался список записей, но получен {type(data).__name__}") return @@ -165,7 +485,7 @@ class RealtyCalendarPlugin(BasePMSPlugin): await sync_to_async(Reservation.objects.update_or_create)( reservation_id=reservation_id, defaults=defaults ) - self.logger.debug(f"Резервация {reservation_id} обновлена.") + self.logger.debug(f"Резервация {reservation_id} обновлена. ") else: await sync_to_async(Reservation.objects.create)( reservation_id=reservation_id, **defaults @@ -176,11 +496,6 @@ class RealtyCalendarPlugin(BasePMSPlugin): self.logger.error(f"Ошибка при обработке записи {index}: {e}") def validate_plugin(self): - """ - Проверка на соответствие требованиям. - Можно проверить наличие методов или полей. - """ - # Проверяем наличие обязательных методов required_methods = ["fetch_data", "get_default_parser_settings", "_fetch_data"] for m in required_methods: if not hasattr(self, m):