This commit is contained in:
2026-03-03 22:27:11 +03:00
parent 4783735308
commit 69995cf099
5 changed files with 91 additions and 12 deletions
+4
View File
@@ -21,6 +21,7 @@ from dutylog.infrastructure.ioc import (
ServiceProvider, ServiceProvider,
) )
from dutylog.infrastructure.utils.config import load_config from dutylog.infrastructure.utils.config import load_config
from dutylog.infrastructure.utils.bot_commands import set_bot_commands
async def main(): async def main():
@@ -54,6 +55,9 @@ async def main():
setup_dialogs(dp) setup_dialogs(dp)
setup_dishka(container, dp, auto_inject=True) setup_dishka(container, dp, auto_inject=True)
# Устанавливаем команды бота
await set_bot_commands(bot)
await dp.start_polling(bot) await dp.start_polling(bot)
@@ -13,6 +13,9 @@ from dutylog.infrastructure.database.repositories.users_repository import (
from dutylog.infrastructure.database.repositories.residents_repository import ( from dutylog.infrastructure.database.repositories.residents_repository import (
ResidentsRepository, ResidentsRepository,
) )
from dutylog.infrastructure.database.repositories.rooms_repository import (
RoomsRepository,
)
from dutylog.infrastructure.database.repositories.reporting_periods_repository import ( from dutylog.infrastructure.database.repositories.reporting_periods_repository import (
ReportingPeriodsRepository, ReportingPeriodsRepository,
) )
@@ -68,8 +71,6 @@ async def get_admin_menu_data(
days_passed = (datetime.now().date() - start_date).days days_passed = (datetime.now().date() - start_date).days
period_info = f""" period_info = f"""
━━━━━━━━━━━━━━━━━━━━
📅 <b>Активный отчётный период</b> 📅 <b>Активный отчётный период</b>
<blockquote>Месяц: <b>{reporting_month} {reporting_year}</b> <blockquote>Месяц: <b>{reporting_month} {reporting_year}</b>
Начало: <code>{start_date.strftime('%d.%m.%Y')}</code> Начало: <code>{start_date.strftime('%d.%m.%Y')}</code>
@@ -81,7 +82,7 @@ async def get_admin_menu_data(
content = f""" content = f"""
{greeting} {greeting}
<blockquote>📋 <b>Панель управления</b></blockquote> 📋 <i>Панель управления</i>
{period_info} {period_info}
Выберите действие: Выберите действие:
""" """
@@ -93,33 +94,47 @@ async def get_admin_menu_data(
async def get_statistics_data( async def get_statistics_data(
users_repository: FromDishka[UsersRepository], users_repository: FromDishka[UsersRepository],
residents_repository: FromDishka[ResidentsRepository], residents_repository: FromDishka[ResidentsRepository],
rooms_repository: FromDishka[RoomsRepository],
**kwargs, **kwargs,
): ):
all_users = await users_repository.get_all_users() all_users = await users_repository.get_all_users()
all_residents = await residents_repository.get_all_residents() all_residents = await residents_repository.get_all_residents()
all_rooms = await rooms_repository.get_all_rooms()
total_users = len(all_users) total_users = len(all_users)
total_residents = len(all_residents) total_residents = len(all_residents)
busy_residents = len([r for r in all_residents if r.is_busy]) busy_residents = len([r for r in all_residents if r.is_busy])
total_active_hours = sum(r.active_hours for r in all_residents) total_residents_active_hours = sum(r.active_hours for r in all_residents)
total_inactive_hours = sum(r.inactive_hours for r in all_residents) total_residents_inactive_hours = sum(r.inactive_hours for r in all_residents)
admins_count = len([u for u in all_users if u.is_admin]) admins_count = len([u for u in all_users if u.is_admin])
total_rooms = len(all_rooms)
total_rooms_active_hours = sum(r.active_hours for r in all_rooms)
total_rooms_inactive_hours = sum(r.inactive_hours for r in all_rooms)
stats_text = f""" stats_text = f"""
<blockquote>📊 <b>Статистика системы</b></blockquote> <blockquote>📊 <b>Статистика системы</b></blockquote>
👥 <b>Всего пользователей:</b> <code>{total_users}</code> 👥 <b>Всего пользователей:</b> <code>{total_users}</code>
👨‍💼 <b>Администраторов:</b> <code>{admins_count}</code> 👨‍💼 <b>Администраторов:</b> <code>{admins_count}</code>
<b>👤 РЕЗИДЕНТЫ</b>
🏠 <b>Всего резидентов:</b> <code>{total_residents}</code> 🏠 <b>Всего резидентов:</b> <code>{total_residents}</code>
✅ <b>Привязано к пользователям:</b> <code>{busy_residents}</code> ✅ <b>Привязано к пользователям:</b> <code>{busy_residents}</code>
❌ <b>Свободных:</b> <code>{total_residents - busy_residents}</code> ❌ <b>Свободных:</b> <code>{total_residents - busy_residents}</code>
━━━━━━━━━━━━━━━━━━━━ 🟢 <b>Отработанных часов:</b> <code>{total_residents_inactive_hours}</code> ч
🔴 <b>Неотработанных часов:</b> <code>{total_residents_active_hours}</code> ч
📊 <b>Итого:</b> <code>{total_residents_active_hours + total_residents_inactive_hours}</code> ч
🟢 <b>Всего отработанных часов:</b> <code>{total_inactive_hours}</code> ч <b>🚪 КОМНАТЫ</b>
🔴 <b>Всего неотработанных часов:</b> <code>{total_active_hours}</code> ч
📊 <b>Общий итог:</b> <code>{total_active_hours + total_inactive_hours}</code> ч 🏠 <b>Всего комнат:</b> <code>{total_rooms}</code>
🟢 <b>Отработанных часов:</b> <code>{total_rooms_inactive_hours}</code> ч
🔴 <b>Неотработанных часов:</b> <code>{total_rooms_active_hours}</code> ч
📊 <b>Итого:</b> <code>{total_rooms_active_hours + total_rooms_inactive_hours}</code> ч
""" """
return {"stats_content": stats_text} return {"stats_content": stats_text}
@@ -9,9 +9,15 @@ from dutylog.application.bot.user_dialogs.states import MainMenuSG
from dutylog.infrastructure.database.repositories.residents_repository import ( from dutylog.infrastructure.database.repositories.residents_repository import (
ResidentsRepository, ResidentsRepository,
) )
from dutylog.infrastructure.database.repositories.rooms_repository import (
RoomsRepository,
)
from dutylog.infrastructure.database.repositories.hours_transactions_repository import ( from dutylog.infrastructure.database.repositories.hours_transactions_repository import (
HoursTransactionsRepository, HoursTransactionsRepository,
) )
from dutylog.infrastructure.database.repositories.room_hours_transactions_repository import (
RoomHoursTransactionsRepository,
)
from dutylog.infrastructure.utils.datetime import msk_now from dutylog.infrastructure.utils.datetime import msk_now
@@ -19,7 +25,9 @@ from dutylog.infrastructure.utils.datetime import msk_now
async def get_history_data( async def get_history_data(
event_from_user: User, event_from_user: User,
residents_repository: FromDishka[ResidentsRepository], residents_repository: FromDishka[ResidentsRepository],
rooms_repository: FromDishka[RoomsRepository],
transactions_repository: FromDishka[HoursTransactionsRepository], transactions_repository: FromDishka[HoursTransactionsRepository],
room_transactions_repository: FromDishka[RoomHoursTransactionsRepository],
**kwargs, **kwargs,
) -> dict[str, str]: ) -> dict[str, str]:
resident = await residents_repository.get_resident_by_user_id(event_from_user.id) resident = await residents_repository.get_resident_by_user_id(event_from_user.id)
@@ -31,20 +39,25 @@ async def get_history_data(
⚠️ <i>Профиль не найден</i> ⚠️ <i>Профиль не найден</i>
""" """
else: else:
# История резидента
transactions = await transactions_repository.get_resident_history(resident.id) transactions = await transactions_repository.get_resident_history(resident.id)
transactions_sorted = sorted(transactions, key=lambda x: x.created_at) transactions_sorted = sorted(transactions, key=lambda x: x.created_at)
last_10 = transactions_sorted[-10:] last_10 = transactions_sorted[-10:]
if not last_10: if not last_10:
history_text = """ history_text = """
<blockquote>📜 <b>История операций</b></blockquote> 📜 <b>История операций</b>
<b>👤 Ваши операции:</b>
<i>История операций пуста</i> <i>История операций пуста</i>
""" """
else: else:
history_text = """ history_text = """
📜 <b>История операций</b> 📜 <b>История операций</b>
<b>👤 Ваши операции:</b>
""" """
for tx in last_10: for tx in last_10:
operation = "Начислено" if tx.transaction_type == "increase" else "Списано" operation = "Начислено" if tx.transaction_type == "increase" else "Списано"
@@ -57,6 +70,34 @@ async def get_history_data(
history_text += f"<blockquote><b>{operation}</b> {emoji}<code>{tx.amount}</code> ч\n📅 {date_str}{remark_text}</blockquote>\n" history_text += f"<blockquote><b>{operation}</b> {emoji}<code>{tx.amount}</code> ч\n📅 {date_str}{remark_text}</blockquote>\n"
# История комнаты
room = await rooms_repository.get_room_by_id(resident.room)
if room:
room_transactions = await room_transactions_repository.get_room_history(room.id)
room_transactions_sorted = sorted(room_transactions, key=lambda x: x.created_at)
last_10_room = room_transactions_sorted[-10:]
if not last_10_room:
history_text += """
<b>🚪 Операции комнаты:</b>
<i>История операций пуста</i>
"""
else:
history_text += """
<b>🚪 Операции комнаты:</b>
"""
for tx in last_10_room:
operation = "Начислено" if tx.transaction_type == "increase" else "Списано"
emoji = "+" if tx.transaction_type == "increase" else ""
msk_time = tx.created_at.astimezone(msk_now().tzinfo).replace(tzinfo=None)
date_str = msk_time.strftime("%d.%m.%Y %H:%M")
remark_text = f"\n💬 <i>{tx.remark}</i>" if tx.remark else ""
history_text += f"<blockquote><b>{operation}</b> {emoji}<code>{tx.amount}</code> ч\n📅 {date_str}{remark_text}</blockquote>\n"
return {"history_content": history_text} return {"history_content": history_text}
@@ -73,14 +73,23 @@ async def get_main_menu_data(
""" """
has_resident = False has_resident = False
else: else:
room = await rooms_repository.get_room_by_id(resident.room)
room_active = room.active_hours if room else 0
room_inactive = room.inactive_hours if room else 0
content = f""" content = f"""
{greeting} {greeting}
━━━━━━━━━━━━━━━━━━━━
📊 <b>Статус отработки:</b>
📊 <i>Статус отработки:</i>
<b>👤 Ваши часы:</b>
<blockquote>✅ Выполнено: <b>{resident.inactive_hours}</b> ч. <blockquote>✅ Выполнено: <b>{resident.inactive_hours}</b> ч.
⏳ Осталось: <b>{resident.active_hours}</b> ч.</blockquote> ⏳ Осталось: <b>{resident.active_hours}</b> ч.</blockquote>
<b>🚪 Часы комнаты:</b>
<blockquote>✅ Выполнено: <b>{room_inactive}</b> ч.
⏳ Осталось: <b>{room_active}</b> ч.</blockquote>
<code>made by kolo</code> <code>made by kolo</code>
""" """
has_resident = True has_resident = True
@@ -0,0 +1,10 @@
from aiogram import Bot
from aiogram.types import BotCommand, BotCommandScopeDefault
async def set_bot_commands(bot: Bot):
commands = [
BotCommand(command="start", description="🏠 Начало работы"),
]
await bot.set_my_commands(commands, scope=BotCommandScopeDefault())