settings application

.env db params+global settings in admin model
ECVI plugin module
This commit is contained in:
2024-12-14 20:50:11 +09:00
parent 09eb249d68
commit 93994ed929
328 changed files with 190143 additions and 538 deletions

View File

@@ -1,39 +1,162 @@
from .base_plugin import BasePMSPlugin
import logging
from datetime import datetime, timedelta
import requests
from asgiref.sync import sync_to_async
from hotels.models import Hotel, Reservation
from .base_plugin import BasePMSPlugin
class EcviPMS(BasePMSPlugin):
class EcviPMSPlugin(BasePMSPlugin):
"""
Плагин для PMS ECVI.
Плагин для интеграции с PMS Ecvi (интерфейс для получения данных об отеле).
"""
def _fetch_data(self):
print("Fetching data from Ecvi PMS...")
# Реализация метода получения данных из PMS Shelter
response = requests.get(self.pms_config.url, headers={"Authorization": f"Bearer {self.pms_config.token}"})
print("Response status:", response.status_code)
response.raise_for_status()
data = response.json()
print("Number of rooms:", len(data))
return data
json_schema = {
"type": "object",
"properties": {
"id": {"type": "integer"},
"number": {"type": "integer"},
"roomTypeName": {"type": "string"},
"checkInStatus": {"type": "string"},
"guests": {"type": "array"},
},
"required": ["id", "number", "roomTypeName", "checkInStatus", "guests"]
}
def __init__(self, pms_config):
super().__init__(pms_config)
# Инициализация логгера
self.logger = logging.getLogger(self.__class__.__name__) # Логгер с именем класса
handler_console = logging.StreamHandler() # Потоковый обработчик для вывода в консоль
handler_file = logging.FileHandler('ecvi_pms_plugin.log') # Обработчик для записи в файл
formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
handler_console.setFormatter(formatter)
handler_file.setFormatter(formatter)
# Добавляем оба обработчика к логгеру
self.logger.addHandler(handler_console)
self.logger.addHandler(handler_file)
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):
"""
Возвращает настройки парсера по умолчанию.
"""
self.logger.debug(f"get_default_parser_settings. pms_config: {self.pms_config}")
return {
"field_mapping": {
"room_name": "roomNumber",
"check_in": "from",
"check_out": "until",
"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 []
self.logger.debug(f"\n\n\n\n\ndata: {data}\n\n\n\n\n")
# Фильтрация данных
filtered_data = [
{
'reservation_id': item.get('task_id'),
'room_number': item.get('room_number'),
'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}")
# Сохранение данных в базу данных
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}")
# Проверяем, существует ли уже резервация с таким внешним ID
reservation_id = item.get('reservation_id')
self.logger.debug(f"-----\n\n\nITEM : {item}\n\n\n---")
if not reservation_id:
self.logger.error("Ошибка: 'reservation_id' отсутствует в данных.")
return
existing_reservation = await sync_to_async(Reservation.objects.filter)(reservation_id=reservation_id)
# Теперь вызываем .first() после асинхронного вызова
existing_reservation = await sync_to_async(existing_reservation.first)()
if existing_reservation:
self.logger.debug(f"Резервация {reservation_id} уже существует. Обновляем...")
await sync_to_async(Reservation.objects.update_or_create)(
reservation_id=reservation_id,
defaults={
'room_number': item.get('room_number'),
'room_type': item.get('room_type'),
'check_in': item.get('checkin'),
'check_out': item.get('checkout'),
'status': item.get('status'),
'hotel': hotel
}
)
self.logger.debug(f"Резервация обновлена.")
else:
self.logger.debug(f"Резервация не найдена, создаем новую...")
reservation = await sync_to_async(Reservation.objects.create)(
reservation_id=reservation_id,
room_number=item.get('room_number'),
room_type=item.get('room_type'),
check_in=item.get('checkin'),
check_out=item.get('checkout'),
status=item.get('status'),
hotel=hotel
)
self.logger.debug(f"Новая резервация создана с ID: {reservation.reservation_id}")
except Exception as e:
self.logger.error(f"Ошибка сохранения данных: {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