This commit is contained in:
2026-03-17 20:41:01 +03:00
parent f59791caf1
commit eaeeb7bbce
7 changed files with 133 additions and 9 deletions
@@ -68,6 +68,9 @@ from dutylog.application.bot.admin_dialogs.broadcast import (
from dutylog.application.bot.admin_dialogs.faq import ( from dutylog.application.bot.admin_dialogs.faq import (
admin_faq_window, admin_faq_window,
) )
from dutylog.application.bot.admin_dialogs.top_residents import (
top_residents_window,
)
admin_menu_dialog = Dialog( admin_menu_dialog = Dialog(
@@ -121,4 +124,5 @@ admin_menu_dialog = Dialog(
filter_select_window, filter_select_window,
filter_hours_input_window, filter_hours_input_window,
filtered_results_window, filtered_results_window,
top_residents_window,
) )
@@ -109,8 +109,6 @@ async def get_statistics_data(
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 = 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>
@@ -131,10 +129,6 @@ async def get_statistics_data(
<b>🚪 КОМНАТЫ</b> <b>🚪 КОМНАТЫ</b>
🏠 <b>Всего комнат:</b> <code>{total_rooms}</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}
@@ -193,11 +187,16 @@ main_menu_window = Window(
state=AdminMenuSG.statistics, state=AdminMenuSG.statistics,
), ),
SwitchTo( SwitchTo(
Const("❓ FAQ"), Const("🏆 Топ"),
id="faq_btn", id="top_btn",
state=AdminMenuSG.faq, state=AdminMenuSG.top_residents,
), ),
), ),
SwitchTo(
Const("❓ FAQ"),
id="faq_btn",
state=AdminMenuSG.faq,
),
SwitchTo( SwitchTo(
Const("📢 Рассылка"), Const("📢 Рассылка"),
id="broadcast_btn", id="broadcast_btn",
@@ -0,0 +1,57 @@
from aiogram_dialog import Window
from aiogram_dialog.widgets.text import Format, Const
from aiogram_dialog.widgets.kbd import SwitchTo
from dishka import FromDishka
from dishka.integrations.aiogram_dialog import inject
from dutylog.application.bot.user_dialogs.states import AdminMenuSG
from dutylog.infrastructure.database.repositories.residents_repository import (
ResidentsRepository,
)
@inject
async def get_top_residents_data(
residents_repository: FromDishka[ResidentsRepository],
**kwargs,
) -> dict[str, str]:
all_residents = await residents_repository.get_all_residents()
residents_with_hours = [
r for r in all_residents
if (r.inactive_hours + r.active_hours) > 0
]
sorted_residents = sorted(
residents_with_hours,
key=lambda r: r.inactive_hours + r.active_hours,
reverse=True
)
top_residents = sorted_residents[:5]
if not top_residents:
content = "🏆 <b>Топ общежития</b>\n\n⚠️ Нет данных для отображения топа."
else:
content = "🏆 <b>Топ общежития</b>\n\n"
medals = ["🥇", "🥈", "🥉", "4.", "5."]
for idx, resident in enumerate(top_residents):
total_hours = resident.inactive_hours + resident.active_hours
name = resident.real_name or "Без имени"
content += f"<blockquote>{medals[idx]} <b>{name}</b> — <code>{total_hours}</code> ч</blockquote>\n"
return {"content": content}
top_residents_window = Window(
Format("{content}"),
SwitchTo(
Const("◀️ Назад"),
id="back_to_main",
state=AdminMenuSG.main,
),
state=AdminMenuSG.top_residents,
getter=get_top_residents_data,
)
@@ -304,6 +304,11 @@ admins_list_window = Window(
id="history_btn", id="history_btn",
state=CreatorMenuSG.transactions_history, state=CreatorMenuSG.transactions_history,
), ),
SwitchTo(
Const("🏆 Топ"),
id="top_btn",
state=CreatorMenuSG.top_residents,
),
Button( Button(
Const("◀️ Назад"), Const("◀️ Назад"),
id="back_to_main_from_admins", id="back_to_main_from_admins",
@@ -10,6 +10,9 @@ from dutylog.application.bot.creator_dialogs.admins_management import (
from dutylog.application.bot.creator_dialogs.transactions_history import ( from dutylog.application.bot.creator_dialogs.transactions_history import (
transactions_history_window, transactions_history_window,
) )
from dutylog.application.bot.creator_dialogs.top_residents import (
top_residents_window,
)
creator_menu_dialog = Dialog( creator_menu_dialog = Dialog(
@@ -19,4 +22,5 @@ creator_menu_dialog = Dialog(
add_admin_select_user_window, add_admin_select_user_window,
add_admin_confirm_window, add_admin_confirm_window,
transactions_history_window, transactions_history_window,
top_residents_window,
) )
@@ -0,0 +1,53 @@
from aiogram_dialog import Window
from aiogram_dialog.widgets.text import Format, Const
from aiogram_dialog.widgets.kbd import Back
from dishka import FromDishka
from dishka.integrations.aiogram_dialog import inject
from dutylog.application.bot.user_dialogs.states import CreatorMenuSG
from dutylog.infrastructure.database.repositories.residents_repository import (
ResidentsRepository,
)
@inject
async def get_top_residents_data(
residents_repository: FromDishka[ResidentsRepository],
**kwargs,
) -> dict[str, str]:
all_residents = await residents_repository.get_all_residents()
residents_with_hours = [
r for r in all_residents
if (r.inactive_hours + r.active_hours) > 0
]
sorted_residents = sorted(
residents_with_hours,
key=lambda r: r.inactive_hours + r.active_hours,
reverse=True
)
top_residents = sorted_residents[:5]
if not top_residents:
content = "🏆 <b>Топ общежития</b>\n\n⚠️ Нет данных для отображения топа."
else:
content = "🏆 <b>Топ общежития</b>\n\n"
medals = ["🥇", "🥈", "🥉", "4.", "5."]
for idx, resident in enumerate(top_residents):
total_hours = resident.inactive_hours + resident.active_hours
name = resident.real_name or "Без имени"
content += f"<blockquote>{medals[idx]} <b>{name}</b> — <code>{total_hours}</code> ч</blockquote>\n"
return {"content": content}
top_residents_window = Window(
Format("{content}"),
Back(Const("◀️ Назад")),
state=CreatorMenuSG.top_residents,
getter=get_top_residents_data,
)
@@ -59,6 +59,7 @@ class AdminMenuSG(StatesGroup):
faq = State() faq = State()
broadcast = State() broadcast = State()
broadcast_confirm = State() broadcast_confirm = State()
top_residents = State()
class CreatorMenuSG(StatesGroup): class CreatorMenuSG(StatesGroup):
@@ -68,6 +69,7 @@ class CreatorMenuSG(StatesGroup):
add_admin_select_user = State() add_admin_select_user = State()
add_admin_confirm = State() add_admin_confirm = State()
transactions_history = State() transactions_history = State()
top_residents = State()
class RegistrationSG(StatesGroup): class RegistrationSG(StatesGroup):