bot refactor

This commit is contained in:
2024-12-07 17:41:27 +09:00
parent 72cb7a4ef7
commit 626f378303
25 changed files with 1065 additions and 657 deletions

0
bot/utils/__init__.py Normal file
View File

71
bot/utils/bot_setup.py Normal file
View 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
View 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'))

View 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
View 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
View 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