mirror of
https://github.com/koloideal/DutyLog.git
synced 2026-06-10 02:15:30 +03:00
update
This commit is contained in:
@@ -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):
|
||||
|
||||
Reference in New Issue
Block a user