275 lines
9.4 KiB
Markdown
275 lines
9.4 KiB
Markdown
# Проект управления отелями
|
||
|
||
## Описание
|
||
|
||
Проект для управления отелями, пользователями, интеграциями с PMS, а также для контроля статистики и уведомлений. Включает веб-админку, REST API для управления данными и Telegram-бота для взаимодействия с пользователями.
|
||
|
||
## Стек технологий
|
||
|
||
- Django (для бэкенда)
|
||
- Jazzmin (для кастомизации админки)
|
||
- MySQL (для хранения данных)
|
||
- python-telegram-bot (для Telegram-бота)
|
||
- Docker (для контейнеризации базы данных и проекта)
|
||
|
||
## Установка
|
||
|
||
### 1. Клонирование репозитория
|
||
|
||
```bash
|
||
git clone <repo url>
|
||
cd yourrepository
|
||
````
|
||
|
||
### 2. Установка зависимостей
|
||
|
||
```bash
|
||
|
||
python -m venv .venv
|
||
source .venv/bin/activate # Для Linux/MacOS
|
||
.venv\Scripts\activate # Для Windows
|
||
|
||
pip install -r requirements.txt
|
||
```
|
||
### 3. Настройка базы данных MySQL
|
||
#### 3.1. Запуск контейнера с MySQL
|
||
|
||
Используем Docker для поднятия MySQL контейнера:
|
||
|
||
``` bash
|
||
docker-compose up -d mysql
|
||
```
|
||
#### 3.2. Создание базы данных и пользователя
|
||
|
||
После поднятия контейнера с MySQL, создайте базу данных и пользователя:
|
||
|
||
### 3.2. Настройка базы данных
|
||
|
||
После поднятия контейнера с MySQL, создайте таблицы и загрузите дамп:
|
||
|
||
```
|
||
docker exec -it mysql_container bash
|
||
mysql -u root -p
|
||
```
|
||
|
||
Введите пароль от MySQL, а затем загрузите ваш дамп:
|
||
|
||
```bash
|
||
mysql -u root -p your_database_name < /path/to/your_dump.sql
|
||
```
|
||
### 3.3. Применение миграций
|
||
|
||
После настройки базы данных выполните миграции для вашего Django-проекта:
|
||
|
||
```bash
|
||
python manage.py migrate
|
||
```
|
||
|
||
### 4. Настройка админки
|
||
|
||
Для настройки админки с использованием Dazzling и Jazzmin, добавьте соответствующие настройки в settings.py:
|
||
|
||
```python
|
||
INSTALLED_APPS = [
|
||
'dazzle',
|
||
'jazzmin',
|
||
...
|
||
]
|
||
|
||
JAZZMIN_SETTINGS = {
|
||
"site_title": "My Admin",
|
||
"site_header": "My Administration",
|
||
"site_brand": "My Brand",
|
||
"footer": {
|
||
"copyright": False,
|
||
"version": False,
|
||
},
|
||
}
|
||
```
|
||
|
||
### 5. Запуск проекта
|
||
|
||
Запустите сервер Django:
|
||
|
||
```bash
|
||
python manage.py runserver
|
||
```
|
||
|
||
Теперь проект будет доступен по адресу http://127.0.0.1:8000.
|
||
|
||
##### Структура проекта
|
||
|
||
hotel_manager/ — основная директория проекта.
|
||
hotel_manager/settings.py — настройки Django.
|
||
hotel_manager/models.py — модели данных для отелей, пользователей и статистики.
|
||
hotel_manager/views.py — представления для работы с данными.
|
||
hotel_manager/urls.py — маршруты проекта.
|
||
bot/ — директория для бота, использующего python-telegram-bot.
|
||
|
||
##### Модели
|
||
|
||
Отель (Hotel)
|
||
Название отеля
|
||
ID отеля
|
||
PMS (Bnovo, Travel Line, Realty)
|
||
Статус интеграции с PMS
|
||
|
||
Пользователь (User)
|
||
Имя пользователя
|
||
Роль (Admin или Hotel User)
|
||
Связь с отелем
|
||
|
||
Настройки уведомлений (Notification Settings)
|
||
Включено/выключено уведомление
|
||
Часовой пояс
|
||
Время отправки уведомлений
|
||
|
||
Статистика (Statistics)
|
||
Количество несанкционированных заселений за период
|
||
Статус ошибок
|
||
Даты и номера нарушений
|
||
|
||
##### API
|
||
|
||
Администратор:
|
||
Добавить/удалить отель
|
||
Добавить/удалить пользователя
|
||
Проверка статуса интеграции с PMS
|
||
Управление уведомлениями
|
||
|
||
Пользователь отеля:
|
||
Получение статистики по заселениям
|
||
Управление уведомлениями
|
||
|
||
##### Интеграция с Telegram-ботом
|
||
|
||
Бот для администраторов позволяет управлять отелями, пользователями, уведомлениями и проверять статус интеграций.
|
||
|
||
Бот для пользователей отелей позволяет получать статистику по заселениям и управлять уведомлениями.
|
||
|
||
##### Пример команды для администратора
|
||
|
||
Добавить отель
|
||
Список отелей
|
||
Удалить отель
|
||
Проверить статус PMS
|
||
|
||
##### Пример команды для пользователя отеля
|
||
|
||
Показать статистику за вчера
|
||
Управление уведомлениями
|
||
|
||
#### Проверка интеграции с PMS
|
||
|
||
Для каждого отеля можно проверять статус интеграции с 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}
|
||
|
||
```
|