diff --git a/.drone.yml b/.drone.yml index 89e94830..86cbc35c 100644 --- a/.drone.yml +++ b/.drone.yml @@ -7,13 +7,13 @@ steps: - name: test image: python:3.10 environment: - DATABASE_URL: mysql://root@R0sebud:0.0.0.0:3306/w1510415_wp832 + DATABASE_URL: mysql://root@R0sebud:0.0.0.0:3308/w1510415_wp832 commands: - - python -m venv .venv + - python3 -m venv .venv - source .venv/bin/activate - - pip install --upgrade pip - - pip install -r requirements.txt - - python manage.py migrate + - pip3 install --upgrade pip + - pip3 install -r requirements.txt + - python3 manage.py migrate - flake8 . # Линтер - pytest # Запуск тестов @@ -21,15 +21,15 @@ steps: - name: bot-check image: python:3.10 environment: - DATABASE_URL: mysql://root@R0sebud:0.0.0.0:3306/w1510415_wp832 + DATABASE_URL: mysql://root@R0sebud:0.0.0.0:3308/w1510415_wp832 commands: - - python -m venv .venv + - python3 -m venv .venv - source .venv/bin/activate - - pip install --upgrade pip - - pip install -r requirements.txt - - python manage.py run_bot & # Запуск бота в фоне + - pip3 install --upgrade pip + - pip3 install -r requirements.txt + - python3 manage.py run_bot & # Запуск бота в фоне - sleep 5 # Ждём, чтобы бот запустился - - python test_bot.py # Проверка работы бота + - python3 test_bot.py # Проверка работы бота # services: # # Шаг 3: Сервис базы данных MySQL diff --git a/README.md b/README.md index 3c9ac9ae..7df2d18f 100644 --- a/README.md +++ b/README.md @@ -161,4 +161,114 @@ python manage.py runserver #### Проверка интеграции с PMS -Для каждого отеля можно проверять статус интеграции с PMS (Bnovo, Travel Line, Realty) и получать ответ о доступности PMS. \ No newline at end of file +Для каждого отеля можно проверять статус интеграции с PMS (Bnovo, Travel Line, Realty) и получать ответ о доступности PMS. + + +#### Разработка плагинов для интеграции с PMS + +Для разработки плагина используются следующие инструменты: + +- Django +- Python +- Pydantic + +*код примера для плагина* + +```python +from datetime import datetime, timedelta +import requests +from asgiref.sync import sync_to_async +from hotels.models import Reservation +from .base_plugin import BasePMSPlugin +import logging + +class ExamplePMSPlugin(BasePMSPlugin): + """ + Плагин для интеграции с PMS Example. + """ + + def __init__(self, hotel): + super().__init__(hotel.pms) + self.hotel = hotel + self.api_url = self.hotel.pms.url + self.token = self.hotel.pms.token + self.logger = self._configure_logger() + + def _configure_logger(self): + logger = logging.getLogger(self.__class__.__name__) + handler_console = logging.StreamHandler() + handler_file = logging.FileHandler(f'{self.__class__.__name__.lower()}.log') + formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s') + handler_console.setFormatter(formatter) + handler_file.setFormatter(formatter) + logger.addHandler(handler_console) + logger.addHandler(handler_file) + logger.setLevel(logging.DEBUG) + return logger + + def get_default_parser_settings(self): + """ + Возвращает настройки для обработки данных. + """ + return { + "field_mapping": { + "check_in": "arrival_date", + "check_out": "departure_date", + "room_number": "room", + "status": "status", + }, + "date_format": "%Y-%m-%d %H:%M:%S" + } + + async def _fetch_data(self): + """ + Получает данные из API Example PMS. + """ + headers = { + "Authorization": f"Bearer {self.token}", + "Content-Type": "application/json", + } + now = datetime.now() + payload = { + "from_date": (now - timedelta(days=7)).strftime("%Y-%m-%d"), + "to_date": now.strftime("%Y-%m-%d"), + } + + try: + response = await sync_to_async(requests.post)( + self.api_url, json=payload, headers=headers + ) + response.raise_for_status() + data = response.json() + return await self._process_data(data) + except requests.exceptions.RequestException as e: + self.logger.error(f"Ошибка API: {e}") + return {"processed_items": 0, "errors": [str(e)]} + + async def _process_data(self, data): + """ + Обрабатывает и сохраняет данные в базу. + """ + processed_items = 0 + errors = [] + + for item in data.get("bookings", []): + try: + reservation, created = await sync_to_async(Reservation.objects.update_or_create)( + reservation_id=item['id'], + defaults={ + 'room_number': item['room'], + 'check_in': datetime.strptime(item['arrival_date'], "%Y-%m-%d"), + 'check_out': datetime.strptime(item['departure_date'], "%Y-%m-%d"), + 'status': item['status'], + 'hotel': self.hotel, + } + ) + processed_items += 1 + except Exception as e: + self.logger.error(f"Ошибка обработки записи {item['id']}: {e}") + errors.append(str(e)) + + return {"processed_items": processed_items, "errors": errors} + +```