This commit is contained in:
2026-03-17 21:06:49 +03:00
parent eaeeb7bbce
commit b2eaa79f51
9 changed files with 85 additions and 162 deletions
-2
View File
@@ -11,7 +11,6 @@ from dishka.integrations.aiogram import setup_dishka
from dutylog.application.bot.user_handlers import router as user_router
from dutylog.application.bot.user_dialogs import main_menu_dialog
from dutylog.application.bot.admin_dialogs import admin_menu_dialog
from dutylog.application.bot.creator_dialogs import creator_menu_dialog
from dutylog.application.bot.user_dialogs.registration_dialog import registration_dialog
from dutylog.infrastructure.ioc import (
ConfigProvider,
@@ -49,7 +48,6 @@ async def main():
dp.include_router(user_router)
dp.include_router(main_menu_dialog)
dp.include_router(admin_menu_dialog)
dp.include_router(creator_menu_dialog)
dp.include_router(registration_dialog)
setup_dialogs(dp)
@@ -71,6 +71,16 @@ from dutylog.application.bot.admin_dialogs.faq import (
from dutylog.application.bot.admin_dialogs.top_residents import (
top_residents_window,
)
from dutylog.application.bot.creator_dialogs.admins_management import (
admins_list_window,
admin_info_window,
remove_admin_confirm_window,
add_admin_select_user_window,
add_admin_confirm_window,
)
from dutylog.application.bot.creator_dialogs.transactions_history import (
transactions_history_window,
)
admin_menu_dialog = Dialog(
@@ -125,4 +135,10 @@ admin_menu_dialog = Dialog(
filter_hours_input_window,
filtered_results_window,
top_residents_window,
admins_list_window,
admin_info_window,
remove_admin_confirm_window,
add_admin_select_user_window,
add_admin_confirm_window,
transactions_history_window,
)
@@ -6,7 +6,7 @@ from dishka import FromDishka
from dishka.integrations.aiogram_dialog import inject
from datetime import datetime, timedelta
from dutylog.application.bot.user_dialogs.states import AdminMenuSG, CreatorMenuSG
from dutylog.application.bot.user_dialogs.states import AdminMenuSG
from dutylog.infrastructure.database.repositories.users_repository import (
UsersRepository,
)
@@ -147,7 +147,7 @@ async def on_reporting_period_click(callback, button, dialog_manager):
async def on_admins_click(callback, button, dialog_manager):
await dialog_manager.start(CreatorMenuSG.admins_list)
await dialog_manager.switch_to(AdminMenuSG.admins_list)
main_menu_window = Window(
@@ -174,12 +174,6 @@ main_menu_window = Window(
id="reporting_period_btn",
on_click=on_reporting_period_click,
),
Button(
Const("👨‍💼 Админы"),
id="admins_btn",
on_click=on_admins_click,
when="is_creator",
),
Row(
SwitchTo(
Const("📊 Статистика"),
@@ -192,15 +186,37 @@ main_menu_window = Window(
state=AdminMenuSG.top_residents,
),
),
Row(
SwitchTo(
Const("📢 Рассылка"),
id="broadcast_btn",
state=AdminMenuSG.broadcast,
),
SwitchTo(
Const("❓ FAQ"),
id="faq_btn",
state=AdminMenuSG.faq,
),
),
Button(
Const("━━━━━━━━━━━━━━━━━━"),
id="separator_btn",
on_click=lambda c, b, m: c.answer(),
when="is_creator",
),
Row(
Button(
Const("👨‍💼 Админы"),
id="admins_btn",
on_click=on_admins_click,
when="is_creator",
),
SwitchTo(
Const("📢 Рассылка"),
id="broadcast_btn",
state=AdminMenuSG.broadcast,
Const("📜 История"),
id="history_btn",
state=AdminMenuSG.transactions_history,
when="is_creator",
),
),
state=AdminMenuSG.main,
getter=get_admin_menu_data,
@@ -1,8 +1,5 @@
from dutylog.application.bot.creator_dialogs.creator_menu_dialog import (
creator_menu_dialog,
)
from dutylog.application.bot.creator_dialogs.transactions_history import (
transactions_history_window,
)
__all__ = ["creator_menu_dialog", "transactions_history_window"]
__all__ = ["transactions_history_window"]
@@ -5,7 +5,7 @@ from aiogram_dialog.widgets.kbd import SwitchTo, Button, Select, ScrollingGroup,
from dishka import FromDishka
from dishka.integrations.aiogram_dialog import inject
from dutylog.application.bot.user_dialogs.states import CreatorMenuSG, AdminMenuSG
from dutylog.application.bot.user_dialogs.states import AdminMenuSG
from dutylog.infrastructure.database.repositories.users_repository import UsersRepository
@@ -52,7 +52,7 @@ async def on_admin_selected(
item_id: str,
) -> None:
dialog_manager.dialog_data["selected_admin_id"] = int(item_id)
await dialog_manager.switch_to(CreatorMenuSG.admin_info)
await dialog_manager.switch_to(AdminMenuSG.admin_info)
async def on_add_admin_click(
@@ -60,7 +60,7 @@ async def on_add_admin_click(
button: Button,
dialog_manager: DialogManager,
) -> None:
await dialog_manager.switch_to(CreatorMenuSG.add_admin_select_user)
await dialog_manager.switch_to(AdminMenuSG.add_admin_select_user)
@inject
@@ -101,7 +101,7 @@ async def on_remove_admin_click(
button: Button,
dialog_manager: DialogManager,
) -> None:
await dialog_manager.switch_to(CreatorMenuSG.remove_admin_confirm)
await dialog_manager.switch_to(AdminMenuSG.remove_admin_confirm)
@inject
@@ -148,7 +148,7 @@ async def on_remove_admin_confirm(
await users_repository.update_user(int(admin_id), is_admin=False)
await callback.answer("✅ Администратор удалён!")
await dialog_manager.switch_to(CreatorMenuSG.admins_list)
await dialog_manager.switch_to(AdminMenuSG.admins_list)
async def on_remove_admin_cancel(
@@ -156,7 +156,7 @@ async def on_remove_admin_cancel(
button: Button,
dialog_manager: DialogManager,
) -> None:
await dialog_manager.switch_to(CreatorMenuSG.admin_info)
await dialog_manager.switch_to(AdminMenuSG.admin_info)
@inject
@@ -204,7 +204,7 @@ async def on_user_selected(
item_id: str,
) -> None:
dialog_manager.dialog_data["selected_user_id"] = int(item_id)
await dialog_manager.switch_to(CreatorMenuSG.add_admin_confirm)
await dialog_manager.switch_to(AdminMenuSG.add_admin_confirm)
@inject
@@ -251,7 +251,7 @@ async def on_add_admin_confirm(
await users_repository.update_user(int(user_id), is_admin=True)
await callback.answer("✅ Администратор добавлен!")
await dialog_manager.switch_to(CreatorMenuSG.admins_list)
await dialog_manager.switch_to(AdminMenuSG.admins_list)
async def on_add_admin_cancel(
@@ -259,7 +259,7 @@ async def on_add_admin_cancel(
button: Button,
dialog_manager: DialogManager,
) -> None:
await dialog_manager.switch_to(CreatorMenuSG.add_admin_select_user)
await dialog_manager.switch_to(AdminMenuSG.add_admin_select_user)
async def on_back_to_main(
@@ -267,7 +267,7 @@ async def on_back_to_main(
button: Button,
dialog_manager: DialogManager,
) -> None:
await dialog_manager.done()
await dialog_manager.switch_to(AdminMenuSG.main)
admins_list_window = Window(
@@ -289,32 +289,12 @@ admins_list_window = Window(
id="add_admin_btn",
on_click=on_add_admin_click,
),
Button(
Const("──────────"),
id="separator_btn",
on_click=lambda c, b, m: None,
),
SwitchTo(
Const("👨‍💼 Админы"),
id="admins_btn",
state=CreatorMenuSG.admins_list,
),
SwitchTo(
Const("📜 История"),
id="history_btn",
state=CreatorMenuSG.transactions_history,
),
SwitchTo(
Const("🏆 Топ"),
id="top_btn",
state=CreatorMenuSG.top_residents,
),
Button(
Const("◀️ Назад"),
id="back_to_main_from_admins",
on_click=on_back_to_main,
),
state=CreatorMenuSG.admins_list,
state=AdminMenuSG.admins_list,
getter=get_admins_list_data,
)
@@ -328,9 +308,9 @@ admin_info_window = Window(
SwitchTo(
Const("◀️ Назад"),
id="back_to_admins_list",
state=CreatorMenuSG.admins_list,
state=AdminMenuSG.admins_list,
),
state=CreatorMenuSG.admin_info,
state=AdminMenuSG.admin_info,
getter=get_admin_info_data,
)
@@ -348,7 +328,7 @@ remove_admin_confirm_window = Window(
on_click=on_remove_admin_cancel,
),
),
state=CreatorMenuSG.remove_admin_confirm,
state=AdminMenuSG.remove_admin_confirm,
getter=get_remove_admin_confirm_data,
)
@@ -369,9 +349,9 @@ add_admin_select_user_window = Window(
SwitchTo(
Const("◀️ Назад"),
id="back_to_admins_from_add",
state=CreatorMenuSG.admins_list,
state=AdminMenuSG.admins_list,
),
state=CreatorMenuSG.add_admin_select_user,
state=AdminMenuSG.add_admin_select_user,
getter=get_add_admin_select_user_data,
)
@@ -389,6 +369,6 @@ add_admin_confirm_window = Window(
on_click=on_add_admin_cancel,
),
),
state=CreatorMenuSG.add_admin_confirm,
state=AdminMenuSG.add_admin_confirm,
getter=get_add_admin_confirm_data,
)
@@ -1,26 +0,0 @@
from aiogram_dialog import Dialog
from dutylog.application.bot.creator_dialogs.admins_management import (
admins_list_window,
admin_info_window,
remove_admin_confirm_window,
add_admin_select_user_window,
add_admin_confirm_window,
)
from dutylog.application.bot.creator_dialogs.transactions_history import (
transactions_history_window,
)
from dutylog.application.bot.creator_dialogs.top_residents import (
top_residents_window,
)
creator_menu_dialog = Dialog(
admins_list_window,
admin_info_window,
remove_admin_confirm_window,
add_admin_select_user_window,
add_admin_confirm_window,
transactions_history_window,
top_residents_window,
)
@@ -1,53 +0,0 @@
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,
)
@@ -1,10 +1,10 @@
from aiogram_dialog import Window
from aiogram_dialog.widgets.text import Format, Const
from aiogram_dialog.widgets.kbd import Back, NumberedPager, Group
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 CreatorMenuSG
from dutylog.application.bot.user_dialogs.states import AdminMenuSG
from dutylog.infrastructure.database.repositories.hours_transactions_repository import (
HoursTransactionsRepository,
)
@@ -22,25 +22,19 @@ async def get_transactions_history_data(
transactions_repository: FromDishka[HoursTransactionsRepository],
residents_repository: FromDishka[ResidentsRepository],
rooms_repository: FromDishka[RoomsRepository],
dialog_manager,
**kwargs,
) -> dict:
all_transactions = await transactions_repository.get_all_transactions()
all_transactions.sort(key=lambda t: t.created_at, reverse=True)
page = await dialog_manager.find("transactions_pager").get_page()
per_page = 7
start_idx = page * per_page
end_idx = start_idx + per_page
recent_transactions = all_transactions[:8]
page_transactions = all_transactions[start_idx:end_idx]
if not page_transactions:
content = "<blockquote>📜 <b>История всех транзакций</b></blockquote>\n\n<i>Нет транзакций</i>"
if not recent_transactions:
content = "<blockquote>📜 <b>История транзакций</b></blockquote>\n\n<i>Нет транзакций</i>"
else:
content = "<blockquote>📜 <b>История всех транзакций</b></blockquote>\n\n"
content = "<blockquote>📜 <b>История транзакций</b></blockquote>\n\n<i>Последние 8 транзакций:</i>\n\n"
for tx in page_transactions:
for tx in recent_transactions:
resident = await residents_repository.get_by_id(tx.resident_id)
if not resident:
continue
@@ -59,21 +53,16 @@ async def get_transactions_history_data(
content += f"<blockquote><b>{operation}</b> {emoji}<code>{tx.amount}</code> ч{room_mark}\n👤 {resident.real_name or 'Без имени'} (к. {room_number})\n📅 {date_str}{remark_text}</blockquote>\n"
total_pages = (len(all_transactions) + per_page - 1) // per_page
return {
"content": content,
"pages": total_pages,
}
return {"content": content}
transactions_history_window = Window(
Format("{content}"),
Group(
NumberedPager(scroll="transactions_pager", when="pages"),
width=8,
SwitchTo(
Const("◀️ Назад"),
id="back_to_main",
state=AdminMenuSG.main,
),
Back(Const("◀️ Назад")),
state=CreatorMenuSG.transactions_history,
state=AdminMenuSG.transactions_history,
getter=get_transactions_history_data,
)
@@ -60,6 +60,12 @@ class AdminMenuSG(StatesGroup):
broadcast = State()
broadcast_confirm = State()
top_residents = State()
admins_list = State()
admin_info = State()
remove_admin_confirm = State()
add_admin_select_user = State()
add_admin_confirm = State()
transactions_history = State()
class CreatorMenuSG(StatesGroup):