Files
Touchh/pms_integration/plugins/bnovo_pms.py
trevor 806c611cc7 bnovo plugin
scheduller
2024-12-10 20:07:23 +09:00

136 lines
6.0 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import requests
import json
from datetime import datetime, timedelta
from .base_plugin import BasePMSPlugin
from asgiref.sync import sync_to_async
from pms_integration.models import PMSConfiguration # Убедитесь, что модель существует
class BnovoPMSPlugin(BasePMSPlugin):
"""Плагин для работы с PMS Bnovo."""
def __init__(self, config):
super().__init__(config)
self.api_url = config.url.rstrip("/") # Убираем лишний `/` в конце URL
self.username = config.username
self.password = config.password
self.token = None # SID
if not self.api_url:
raise ValueError("Не указан URL для работы плагина.")
if not self.username or not self.password:
raise ValueError("Не указаны логин или пароль для авторизации.")
def get_default_parser_settings(self):
"""Возвращает настройки по умолчанию для обработки данных."""
return {
"date_format": "%Y-%m-%dT%H:%M:%S",
"timezone": "UTC"
}
async def _save_token_to_db(self, sid):
"""Сохраняет токен (SID) в базу данных."""
try:
await sync_to_async(PMSConfiguration.objects.update_or_create)(
plugin_name="bnovo",
defaults={"token": sid}
)
print(f"[DEBUG] Токен сохранен в БД: {sid}")
except Exception as e:
print(f"[ERROR] Ошибка сохранения токена в БД: {e}")
def _get_auth_headers(self):
"""Создает заголовки авторизации."""
headers = {
"Content-Type": "application/json",
"Accept": "application/json",
}
if self.token:
headers["Cookie"] = f"SID={self.token}"
return headers
async def _fetch_session(self):
"""Получает идентификатор сессии (SID) через запрос."""
url = f"{self.api_url}/"
payload = {
"username": self.username,
"password": self.password,
}
print(f"[DEBUG] URL авторизации: {url}")
print(f"[DEBUG] Тело запроса: {json.dumps(payload, indent=2)}")
headers = self._get_auth_headers()
session = requests.Session()
response = session.post(url, json=payload, headers=headers, allow_redirects=False)
print(f"[DEBUG] Статус ответа: {response.status_code}")
print(f"[DEBUG] Ответ заголовков: {response.headers}")
print(f"[DEBUG] Cookies: {session.cookies}")
if response.status_code == 302 and "SID" in session.cookies:
sid = session.cookies.get("SID")
self.token = sid
print(f"[DEBUG] Получен SID: {sid}")
# Правильное сохранение в БД через sync_to_async
try:
await self._save_token_to_db(sid)
print(f"[DEBUG] Токен сохранен в БД")
except Exception as e:
print(f"[ERROR] Ошибка сохранения токена в БД: {e}")
else:
raise ValueError(f"Не удалось получить SID из ответа: {response.text}")
async def _fetch_data(self):
"""Получает данные о бронированиях с помощью эндпоинта `/dashboard`."""
await self._fetch_session() # Авторизуемся перед каждым запросом
now = datetime.now()
create_from = (now - timedelta(days=90)).strftime("%d.%m.%Y") # Диапазон: последние 90 дней
create_to = now.strftime("%d.%m.%Y")
params = {
"create_from": create_from,
"create_to": create_to,
"status_ids": "1",
"advanced_search": 2, # Обязательный параметр
"c": 100, # Количество элементов на странице (максимум 100)
"page": 1, # Начальная страница
"order_by": "create_date.asc", # Сортировка по возрастанию даты создания
}
headers = self._get_auth_headers()
all_bookings = [] # Для сохранения всех бронирований
while True:
print(f"[DEBUG] Запрос к /dashboard с параметрами: {json.dumps(params, indent=2)}")
response = requests.get(f"{self.api_url}/dashboard", headers=headers, params=params)
print(f"[DEBUG] Статус ответа: {response.status_code}")
if response.status_code != 200:
raise ValueError(f"Ошибка при получении данных: {response.status_code}, {response.text}")
data = response.json()
print(json.dumps(data, indent=2))
bookings = data.get("bookings", [])
all_bookings.extend(bookings)
print(f"[DEBUG] Получено бронирований: {len(bookings)}")
print(f"[DEBUG] Всего бронирований: {len(all_bookings)}")
# Проверка на наличие следующей страницы
pages_info = data.get("pages", {})
current_page = pages_info.get("current_page", 1)
total_pages = pages_info.get("total_pages", 1)
if current_page >= total_pages:
break # Все страницы загружены
params["page"] += 1 # Переход на следующую страницу
if not all_bookings:
print("[DEBUG] Нет бронирований за указанный период.")
else:
print(f"[DEBUG] Полученные бронирования: {json.dumps(all_bookings, indent=2)}")
return all_bookings