bot refactor
This commit is contained in:
0
bot/utils/__init__.py
Normal file
0
bot/utils/__init__.py
Normal file
71
bot/utils/bot_setup.py
Normal file
71
bot/utils/bot_setup.py
Normal file
@@ -0,0 +1,71 @@
|
||||
from telegram.ext import (
|
||||
Application,
|
||||
CommandHandler,
|
||||
CallbackQueryHandler,
|
||||
MessageHandler,
|
||||
filters,
|
||||
)
|
||||
from bot.handlers import (
|
||||
start,
|
||||
handle_button_click,
|
||||
manage_hotels,
|
||||
hotel_actions,
|
||||
delete_hotel,
|
||||
check_pms,
|
||||
setup_rooms,
|
||||
settings_menu,
|
||||
toggle_telegram,
|
||||
toggle_email,
|
||||
show_current_settings,
|
||||
statistics,
|
||||
generate_statistics,
|
||||
stats_select_period,
|
||||
)
|
||||
|
||||
from bot.operations.settings import (
|
||||
settings_menu,
|
||||
toggle_telegram,
|
||||
toggle_email,
|
||||
show_current_settings,
|
||||
set_notification_time,
|
||||
|
||||
)
|
||||
|
||||
from bot.operations.notifications import (
|
||||
handle_notification_time,
|
||||
)
|
||||
|
||||
from bot.operations.users import (
|
||||
|
||||
show_users,
|
||||
|
||||
)
|
||||
|
||||
def setup_bot(application: Application):
|
||||
"""Настройка Telegram бота: регистрация обработчиков."""
|
||||
print("Настройка Telegram приложения...")
|
||||
|
||||
# Регистрация обработчиков команд
|
||||
application.add_handler(CommandHandler("start", start))
|
||||
|
||||
# Регистрация обработчиков кнопок
|
||||
application.add_handler(CallbackQueryHandler(handle_button_click))
|
||||
application.add_handler(CallbackQueryHandler(manage_hotels, pattern="^manage_hotels$"))
|
||||
application.add_handler(CallbackQueryHandler(show_users, pattern="^manage_users$"))
|
||||
application.add_handler(CallbackQueryHandler(settings_menu, pattern="^settings$"))
|
||||
application.add_handler(CallbackQueryHandler(toggle_telegram, pattern="^toggle_telegram$"))
|
||||
application.add_handler(CallbackQueryHandler(toggle_email, pattern="^toggle_email$"))
|
||||
application.add_handler(CallbackQueryHandler(set_notification_time, pattern="^set_notification_time$"))
|
||||
application.add_handler(CallbackQueryHandler(show_current_settings, pattern="^current_settings$"))
|
||||
application.add_handler(CallbackQueryHandler(hotel_actions, pattern="^hotel_"))
|
||||
application.add_handler(CallbackQueryHandler(delete_hotel, pattern="^delete_hotel_"))
|
||||
application.add_handler(CallbackQueryHandler(check_pms, pattern="^check_pms_"))
|
||||
application.add_handler(CallbackQueryHandler(setup_rooms, pattern="^setup_rooms_"))
|
||||
application.add_handler(CallbackQueryHandler(statistics, pattern="^stats$"))
|
||||
application.add_handler(CallbackQueryHandler(stats_select_period, pattern="^stats_hotel_"))
|
||||
application.add_handler(CallbackQueryHandler(generate_statistics, pattern="^stats_period_"))
|
||||
|
||||
# Регистрация обработчиков текстовых сообщений
|
||||
application.add_handler(MessageHandler(filters.TEXT & filters.ChatType.PRIVATE, handle_notification_time))
|
||||
|
||||
print("Обработчики успешно зарегистрированы.")
|
||||
26
bot/utils/database.py
Normal file
26
bot/utils/database.py
Normal file
@@ -0,0 +1,26 @@
|
||||
from users.models import User
|
||||
from hotels.models import Hotel, Reservation
|
||||
from asgiref.sync import sync_to_async
|
||||
|
||||
async def get_user_from_chat_id(chat_id):
|
||||
return await sync_to_async(User.objects.filter(chat_id=chat_id).first)()
|
||||
|
||||
async def get_hotel_by_id(hotel_id):
|
||||
return await sync_to_async(Hotel.objects.get)(id=hotel_id)
|
||||
|
||||
async def get_hotels_for_user(user):
|
||||
"""Получение отелей, связанных с пользователем."""
|
||||
# Проверяем, является ли пользователь сотрудником какого-либо отеля
|
||||
user_hotels = await sync_to_async(list)(
|
||||
Hotel.objects.filter(user_hotel__user=user).distinct()
|
||||
)
|
||||
print(user_hotels)
|
||||
return user_hotels
|
||||
|
||||
async def get_reservations(hotel_id, start_date=None, end_date=None):
|
||||
query = Reservation.objects.filter(hotel_id=hotel_id)
|
||||
if start_date:
|
||||
query = query.filter(check_in__gte=start_date)
|
||||
if end_date:
|
||||
query = query.filter(check_out__lte=end_date)
|
||||
return await sync_to_async(list)(query.prefetch_related('guests'))
|
||||
28
bot/utils/notifications.py
Normal file
28
bot/utils/notifications.py
Normal file
@@ -0,0 +1,28 @@
|
||||
from telegram import Bot
|
||||
from django.core.mail import send_mail
|
||||
|
||||
async def send_telegram_notification(user, message):
|
||||
"""Отправка уведомления через Telegram."""
|
||||
if user.chat_id:
|
||||
try:
|
||||
bot = Bot(token="ВАШ_ТОКЕН")
|
||||
await bot.send_message(chat_id=user.chat_id, text=message)
|
||||
print(f"Telegram-уведомление отправлено пользователю {user.chat_id}: {message}")
|
||||
except Exception as e:
|
||||
print(f"Ошибка отправки Telegram-уведомления пользователю {user.chat_id}: {e}")
|
||||
|
||||
|
||||
def send_email_notification(user, message):
|
||||
"""Отправка уведомления через Email."""
|
||||
if user.email:
|
||||
try:
|
||||
send_mail(
|
||||
subject="Уведомление от системы",
|
||||
message=message,
|
||||
from_email="noreply@yourdomain.com",
|
||||
recipient_list=[user.email],
|
||||
fail_silently=False,
|
||||
)
|
||||
print(f"Email-уведомление отправлено на {user.email}: {message}")
|
||||
except Exception as e:
|
||||
print(f"Ошибка отправки Email-уведомления пользователю {user.email}: {e}")
|
||||
67
bot/utils/pdf_report.py
Normal file
67
bot/utils/pdf_report.py
Normal file
@@ -0,0 +1,67 @@
|
||||
from fpdf import FPDF
|
||||
import os
|
||||
|
||||
|
||||
def generate_pdf_report(hotel_name, reservations, start_date, end_date):
|
||||
"""Генерация PDF отчета."""
|
||||
pdf = FPDF()
|
||||
pdf.add_page()
|
||||
|
||||
# Укажите путь к шрифту
|
||||
font_path = os.path.join("bot", "fonts", "OpenSans-Regular.ttf")
|
||||
if not os.path.exists(font_path):
|
||||
raise FileNotFoundError(f"Шрифт {font_path} не найден. Убедитесь, что он находится в указанной папке.")
|
||||
|
||||
pdf.add_font("OpenSans", "", font_path, uni=True)
|
||||
pdf.set_font("OpenSans", size=12)
|
||||
|
||||
# Заголовки
|
||||
title = f"Отчет по заселениям: {hotel_name}"
|
||||
period = (
|
||||
f"Период: {start_date.strftime('%d.%m.%Y')} - {end_date.strftime('%d.%m.%Y')}"
|
||||
if start_date and end_date
|
||||
else "Период: Все время"
|
||||
)
|
||||
|
||||
pdf.cell(0, 10, txt=title, ln=True, align="C")
|
||||
pdf.cell(0, 10, txt=period, ln=True, align="C")
|
||||
pdf.ln(10)
|
||||
|
||||
# Ширины колонок
|
||||
page_width = pdf.w - 20
|
||||
col_widths = [page_width * 0.2, page_width * 0.2, page_width * 0.15, page_width * 0.25, page_width * 0.1, page_width * 0.1]
|
||||
|
||||
# Заголовки таблицы
|
||||
pdf.set_font("OpenSans", size=10)
|
||||
headers = ["Дата заезда", "Дата выезда", "Номер", "Тип комнаты", "Цена", "Скидка"]
|
||||
for width, header in zip(col_widths, headers):
|
||||
pdf.cell(width, 10, header, border=1, align="C")
|
||||
pdf.ln()
|
||||
|
||||
total_price = 0
|
||||
total_discount = 0
|
||||
|
||||
for res in reservations:
|
||||
price = res.price or 0
|
||||
discount = res.discount or 0
|
||||
total_price += price
|
||||
total_discount += discount
|
||||
|
||||
pdf.cell(col_widths[0], 10, res.check_in.strftime('%d.%m.%Y'), border=1)
|
||||
pdf.cell(col_widths[1], 10, res.check_out.strftime('%d.%m.%Y'), border=1)
|
||||
pdf.cell(col_widths[2], 10, res.room_number, border=1)
|
||||
pdf.cell(col_widths[3], 10, res.room_type, border=1)
|
||||
pdf.cell(col_widths[4], 10, f"{price:.2f} ₽", border=1, align="R")
|
||||
pdf.cell(col_widths[5], 10, f"{discount:.2f} ₽", border=1, align="R")
|
||||
pdf.ln()
|
||||
|
||||
pdf.ln(5)
|
||||
pdf.set_font("OpenSans", size=12)
|
||||
pdf.cell(0, 10, "Итоги:", ln=True)
|
||||
pdf.cell(0, 10, f"Общая сумма цен: {total_price:.2f} ₽", ln=True)
|
||||
pdf.cell(0, 10, f"Общая сумма скидок: {total_discount:.2f} ₽", ln=True)
|
||||
|
||||
file_path = os.path.join("reports", f"{hotel_name}_report.pdf")
|
||||
os.makedirs(os.path.dirname(file_path), exist_ok=True)
|
||||
pdf.output(file_path)
|
||||
return file_path
|
||||
10
bot/utils/scheduler.py
Normal file
10
bot/utils/scheduler.py
Normal file
@@ -0,0 +1,10 @@
|
||||
from apscheduler.schedulers.asyncio import AsyncIOScheduler
|
||||
from bot.operations.notifications import schedule_notifications
|
||||
|
||||
|
||||
def setup_scheduler():
|
||||
"""Настройка планировщика уведомлений."""
|
||||
print("Настройка планировщика...")
|
||||
scheduler = AsyncIOScheduler()
|
||||
scheduler.add_job(schedule_notifications, "cron", minute="*")
|
||||
return scheduler
|
||||
Reference in New Issue
Block a user