mirror of
https://github.com/koloideal/DutyLog.git
synced 2026-06-10 10:25:29 +03:00
update
This commit is contained in:
@@ -3,7 +3,7 @@ from aiogram import Bot
|
|||||||
from aiogram.exceptions import TelegramForbiddenError, TelegramBadRequest
|
from aiogram.exceptions import TelegramForbiddenError, TelegramBadRequest
|
||||||
from aiogram_dialog import Dialog, Window, DialogManager
|
from aiogram_dialog import Dialog, Window, DialogManager
|
||||||
from aiogram_dialog.widgets.text import Format, Const
|
from aiogram_dialog.widgets.text import Format, Const
|
||||||
from aiogram_dialog.widgets.kbd import Row, SwitchTo, Button
|
from aiogram_dialog.widgets.kbd import Row, SwitchTo, Button, ScrollingGroup, Select
|
||||||
from aiogram_dialog.widgets.input import MessageInput
|
from aiogram_dialog.widgets.input import MessageInput
|
||||||
from dishka import FromDishka
|
from dishka import FromDishka
|
||||||
from dishka.integrations.aiogram_dialog import inject
|
from dishka.integrations.aiogram_dialog import inject
|
||||||
@@ -11,6 +11,7 @@ from dishka.integrations.aiogram_dialog import inject
|
|||||||
from dutylog.application.bot.user_dialogs.states import AdminMenuSG
|
from dutylog.application.bot.user_dialogs.states import AdminMenuSG
|
||||||
from dutylog.infrastructure.database.repositories.users_repository import UsersRepository
|
from dutylog.infrastructure.database.repositories.users_repository import UsersRepository
|
||||||
from dutylog.infrastructure.database.repositories.residents_repository import ResidentsRepository
|
from dutylog.infrastructure.database.repositories.residents_repository import ResidentsRepository
|
||||||
|
from dutylog.infrastructure.database.repositories.rooms_repository import RoomsRepository
|
||||||
from dutylog.infrastructure.utils.config import Config
|
from dutylog.infrastructure.utils.config import Config
|
||||||
|
|
||||||
|
|
||||||
@@ -152,6 +153,156 @@ async def on_broadcast_cancel(
|
|||||||
await dialog_manager.switch_to(AdminMenuSG.main)
|
await dialog_manager.switch_to(AdminMenuSG.main)
|
||||||
|
|
||||||
|
|
||||||
|
@inject
|
||||||
|
async def get_residents_list_data(
|
||||||
|
residents_repository: FromDishka[ResidentsRepository],
|
||||||
|
rooms_repository: FromDishka[RoomsRepository],
|
||||||
|
**kwargs,
|
||||||
|
):
|
||||||
|
all_residents = await residents_repository.get_all_residents()
|
||||||
|
|
||||||
|
residents_with_rooms = []
|
||||||
|
for resident in all_residents:
|
||||||
|
room = await rooms_repository.get_room_by_id(resident.room)
|
||||||
|
room_number = room.number if room else 999999
|
||||||
|
residents_with_rooms.append((resident, room_number))
|
||||||
|
|
||||||
|
residents_with_rooms.sort(key=lambda x: x[1])
|
||||||
|
|
||||||
|
residents_data = []
|
||||||
|
for resident, room_number in residents_with_rooms:
|
||||||
|
status = "🟢" if resident.is_busy else "⚪️"
|
||||||
|
name = resident.real_name if resident.real_name else "Без имени"
|
||||||
|
|
||||||
|
residents_data.append((
|
||||||
|
f"{name} | Комната {room_number} | {status}",
|
||||||
|
resident.id
|
||||||
|
))
|
||||||
|
|
||||||
|
content = f"""
|
||||||
|
<blockquote>🏠 <b>Резиденты</b></blockquote>
|
||||||
|
|
||||||
|
<b>Всего резидентов:</b> <code>{len(all_residents)}</code>
|
||||||
|
|
||||||
|
Выберите резидента для просмотра информации:
|
||||||
|
"""
|
||||||
|
|
||||||
|
return {
|
||||||
|
"content": content,
|
||||||
|
"residents": residents_data,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@inject
|
||||||
|
async def get_resident_info_data(
|
||||||
|
dialog_manager: DialogManager,
|
||||||
|
residents_repository: FromDishka[ResidentsRepository],
|
||||||
|
rooms_repository: FromDishka[RoomsRepository],
|
||||||
|
users_repository: FromDishka[UsersRepository],
|
||||||
|
**kwargs,
|
||||||
|
):
|
||||||
|
resident_id = dialog_manager.dialog_data.get("selected_resident_id")
|
||||||
|
|
||||||
|
if not resident_id:
|
||||||
|
return {"info_content": "Ошибка: резидент не выбран"}
|
||||||
|
|
||||||
|
resident = await residents_repository.get_resident_by_id(resident_id)
|
||||||
|
|
||||||
|
if not resident:
|
||||||
|
return {"info_content": "Ошибка: резидент не найден"}
|
||||||
|
|
||||||
|
room = await rooms_repository.get_room_by_id(resident.room)
|
||||||
|
room_number = room.number if room else "???"
|
||||||
|
|
||||||
|
name = resident.real_name if resident.real_name else "Без имени"
|
||||||
|
status = "🟢 Занят" if resident.is_busy else "⚪️ Свободен"
|
||||||
|
|
||||||
|
user_info = "Не привязан"
|
||||||
|
if resident.user_entity:
|
||||||
|
user = await users_repository.get_user_by_id(resident.user_entity)
|
||||||
|
if user:
|
||||||
|
username = f"@{user.username}" if user.username else "без username"
|
||||||
|
user_info = f"{user.first_name} ({username})"
|
||||||
|
|
||||||
|
info_content = f"""
|
||||||
|
<blockquote>👤 <b>Информация о резиденте</b></blockquote>
|
||||||
|
|
||||||
|
<b>ID:</b> <code>{resident.id}</code>
|
||||||
|
<b>Имя:</b> {name}
|
||||||
|
<b>Комната:</b> <code>{room_number}</code>
|
||||||
|
<b>Статус:</b> {status}
|
||||||
|
<b>Пользователь:</b> {user_info}
|
||||||
|
|
||||||
|
━━━━━━━━━━━━━━━━━━━━
|
||||||
|
|
||||||
|
🟢 <b>Активные часы:</b> <code>{resident.active_hours}</code> ч
|
||||||
|
🔴 <b>Неактивные часы:</b> <code>{resident.inactive_hours}</code> ч
|
||||||
|
📊 <b>Всего часов:</b> <code>{resident.active_hours + resident.inactive_hours}</code> ч
|
||||||
|
"""
|
||||||
|
|
||||||
|
return {
|
||||||
|
"info_content": info_content,
|
||||||
|
"is_busy": resident.is_busy,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async def on_resident_selected(
|
||||||
|
callback: CallbackQuery,
|
||||||
|
widget: Select,
|
||||||
|
dialog_manager: DialogManager,
|
||||||
|
item_id: str,
|
||||||
|
):
|
||||||
|
dialog_manager.dialog_data["selected_resident_id"] = int(item_id)
|
||||||
|
await dialog_manager.switch_to(AdminMenuSG.resident_info)
|
||||||
|
|
||||||
|
|
||||||
|
async def on_add_resident(
|
||||||
|
callback: CallbackQuery,
|
||||||
|
button: Button,
|
||||||
|
dialog_manager: DialogManager,
|
||||||
|
):
|
||||||
|
await callback.answer("⚠️ Функционал в разработке", show_alert=True)
|
||||||
|
|
||||||
|
|
||||||
|
async def on_filter_residents(
|
||||||
|
callback: CallbackQuery,
|
||||||
|
button: Button,
|
||||||
|
dialog_manager: DialogManager,
|
||||||
|
):
|
||||||
|
await callback.answer("⚠️ Функционал в разработке", show_alert=True)
|
||||||
|
|
||||||
|
|
||||||
|
async def on_search_residents(
|
||||||
|
callback: CallbackQuery,
|
||||||
|
button: Button,
|
||||||
|
dialog_manager: DialogManager,
|
||||||
|
):
|
||||||
|
await callback.answer("⚠️ Функционал в разработке", show_alert=True)
|
||||||
|
|
||||||
|
|
||||||
|
@inject
|
||||||
|
async def on_logout_resident_confirm(
|
||||||
|
callback: CallbackQuery,
|
||||||
|
button: Button,
|
||||||
|
dialog_manager: DialogManager,
|
||||||
|
residents_repository: FromDishka[ResidentsRepository],
|
||||||
|
):
|
||||||
|
resident_id = dialog_manager.dialog_data.get("selected_resident_id")
|
||||||
|
|
||||||
|
if resident_id:
|
||||||
|
await residents_repository.unbind_user_from_resident(resident_id)
|
||||||
|
|
||||||
|
await dialog_manager.switch_to(AdminMenuSG.resident_info)
|
||||||
|
|
||||||
|
|
||||||
|
async def on_logout_resident_cancel(
|
||||||
|
callback: CallbackQuery,
|
||||||
|
button: Button,
|
||||||
|
dialog_manager: DialogManager,
|
||||||
|
):
|
||||||
|
await dialog_manager.switch_to(AdminMenuSG.resident_info)
|
||||||
|
|
||||||
|
|
||||||
admin_menu_dialog = Dialog(
|
admin_menu_dialog = Dialog(
|
||||||
Window(
|
Window(
|
||||||
Format("{content}"),
|
Format("{content}"),
|
||||||
@@ -179,9 +330,75 @@ admin_menu_dialog = Dialog(
|
|||||||
getter=get_admin_menu_data,
|
getter=get_admin_menu_data,
|
||||||
),
|
),
|
||||||
Window(
|
Window(
|
||||||
Const("<blockquote>🏠 <b>Резиденты</b></blockquote>\n\n<i>Функционал в разработке</i>"),
|
Format("{content}"),
|
||||||
SwitchTo(Const("◀️ Назад"), id="back_from_residents", state=AdminMenuSG.main),
|
Row(
|
||||||
|
Button(
|
||||||
|
Const("🔍 Поиск"),
|
||||||
|
id="search_residents_btn",
|
||||||
|
on_click=on_search_residents,
|
||||||
|
),
|
||||||
|
Button(
|
||||||
|
Const("🔽 Фильтр"),
|
||||||
|
id="filter_residents_btn",
|
||||||
|
on_click=on_filter_residents,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
ScrollingGroup(
|
||||||
|
Select(
|
||||||
|
Format("{item[0]}"),
|
||||||
|
id="residents_select",
|
||||||
|
item_id_getter=lambda x: x[1],
|
||||||
|
items="residents",
|
||||||
|
on_click=on_resident_selected,
|
||||||
|
),
|
||||||
|
id="residents_scroll",
|
||||||
|
width=1,
|
||||||
|
height=7,
|
||||||
|
),
|
||||||
|
Button(
|
||||||
|
Const("➕ Добавить резидента"),
|
||||||
|
id="add_resident_btn",
|
||||||
|
on_click=on_add_resident,
|
||||||
|
),
|
||||||
|
SwitchTo(
|
||||||
|
Const("◀️ Назад"),
|
||||||
|
id="back_to_admin_menu",
|
||||||
|
state=AdminMenuSG.main,
|
||||||
|
),
|
||||||
state=AdminMenuSG.residents,
|
state=AdminMenuSG.residents,
|
||||||
|
getter=get_residents_list_data,
|
||||||
|
),
|
||||||
|
Window(
|
||||||
|
Format("{info_content}"),
|
||||||
|
Button(
|
||||||
|
Const("🚪 Разлогинить"),
|
||||||
|
id="logout_resident_btn",
|
||||||
|
on_click=lambda c, b, m: m.switch_to(AdminMenuSG.resident_logout_confirm),
|
||||||
|
when="is_busy",
|
||||||
|
),
|
||||||
|
SwitchTo(
|
||||||
|
Const("◀️ Назад к списку"),
|
||||||
|
id="back_to_residents_list",
|
||||||
|
state=AdminMenuSG.residents,
|
||||||
|
),
|
||||||
|
state=AdminMenuSG.resident_info,
|
||||||
|
getter=get_resident_info_data,
|
||||||
|
),
|
||||||
|
Window(
|
||||||
|
Const("<blockquote>⚠️ <b>Подтверждение</b></blockquote>\n\nВы уверены, что хотите разлогинить этого резидента?"),
|
||||||
|
Row(
|
||||||
|
Button(
|
||||||
|
Const("✅ Да"),
|
||||||
|
id="confirm_logout",
|
||||||
|
on_click=on_logout_resident_confirm,
|
||||||
|
),
|
||||||
|
Button(
|
||||||
|
Const("❌ Нет"),
|
||||||
|
id="cancel_logout",
|
||||||
|
on_click=on_logout_resident_cancel,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
state=AdminMenuSG.resident_logout_confirm,
|
||||||
),
|
),
|
||||||
Window(
|
Window(
|
||||||
Const("<blockquote>👥 <b>Пользователи</b></blockquote>\n\n<i>Функционал в разработке</i>"),
|
Const("<blockquote>👥 <b>Пользователи</b></blockquote>\n\n<i>Функционал в разработке</i>"),
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ from dishka.integrations.aiogram_dialog import inject
|
|||||||
from dutylog.application.bot.user_dialogs.states import MainMenuSG
|
from dutylog.application.bot.user_dialogs.states import MainMenuSG
|
||||||
from dutylog.infrastructure.database.repositories.users_repository import UsersRepository
|
from dutylog.infrastructure.database.repositories.users_repository import UsersRepository
|
||||||
from dutylog.infrastructure.database.repositories.residents_repository import ResidentsRepository
|
from dutylog.infrastructure.database.repositories.residents_repository import ResidentsRepository
|
||||||
|
from dutylog.infrastructure.database.repositories.rooms_repository import RoomsRepository
|
||||||
from dutylog.infrastructure.database.repositories.hours_transactions_repository import HoursTransactionsRepository
|
from dutylog.infrastructure.database.repositories.hours_transactions_repository import HoursTransactionsRepository
|
||||||
from dutylog.infrastructure.utils.config import Config
|
from dutylog.infrastructure.utils.config import Config
|
||||||
|
|
||||||
@@ -17,6 +18,7 @@ async def get_main_menu_data(
|
|||||||
event_from_user: User,
|
event_from_user: User,
|
||||||
users_repository: FromDishka[UsersRepository],
|
users_repository: FromDishka[UsersRepository],
|
||||||
residents_repository: FromDishka[ResidentsRepository],
|
residents_repository: FromDishka[ResidentsRepository],
|
||||||
|
rooms_repository: FromDishka[RoomsRepository],
|
||||||
config: FromDishka[Config],
|
config: FromDishka[Config],
|
||||||
**kwargs,
|
**kwargs,
|
||||||
):
|
):
|
||||||
@@ -34,6 +36,13 @@ async def get_main_menu_data(
|
|||||||
greeting = "👑 <b>Создатель</b>"
|
greeting = "👑 <b>Создатель</b>"
|
||||||
elif is_admin:
|
elif is_admin:
|
||||||
greeting = "👨💼 <b>Администратор</b>"
|
greeting = "👨💼 <b>Администратор</b>"
|
||||||
|
else:
|
||||||
|
resident = await residents_repository.get_resident_by_user_id(event_from_user.id)
|
||||||
|
if resident:
|
||||||
|
room = await rooms_repository.get_room_by_id(resident.room)
|
||||||
|
room_number = room.number if room else "???"
|
||||||
|
real_name = resident.real_name if resident.real_name else event_from_user.first_name
|
||||||
|
greeting = f"👋 <b>Привет, {real_name}!</b>\n🚪 Комната <code>{room_number}</code>"
|
||||||
else:
|
else:
|
||||||
greeting = f"👋 <b>Привет, {event_from_user.first_name}!</b>"
|
greeting = f"👋 <b>Привет, {event_from_user.first_name}!</b>"
|
||||||
|
|
||||||
|
|||||||
@@ -112,13 +112,13 @@ async def on_resident_selected(
|
|||||||
|
|
||||||
await residents_repository.bind_user_to_resident(resident_id, user_id)
|
await residents_repository.bind_user_to_resident(resident_id, user_id)
|
||||||
|
|
||||||
await callback.answer("✅ Вы успешно зарегистрированы!")
|
await callback.answer("✅ Регистрация успешна!")
|
||||||
await dialog_manager.start(MainMenuSG.main)
|
await dialog_manager.start(MainMenuSG.main)
|
||||||
|
|
||||||
|
|
||||||
registration_dialog = Dialog(
|
registration_dialog = Dialog(
|
||||||
Window(
|
Window(
|
||||||
Const("<blockquote>🏢 <b>Выбор этажа</b></blockquote>\n\n⚠️ <b>Внимание!</b> Перерегистрацию может выполнить только администратор. Выбирайте внимательно!\n\nВыберите этаж, на котором вы живете:", when="has_available"),
|
Const("<blockquote>🏢 <b>Выбор этажа</b></blockquote>\n\n<blockquote>⚠️ <b>Внимание!</b> Перерегистрацию может выполнить только администратор. Выбирайте внимательно!</blockquote>\n\nВыберите этаж, на котором вы живете:", when="has_available"),
|
||||||
Const("<blockquote>⚠️ <b>Нет доступных резидентов</b></blockquote>\n\nВсе резиденты уже заняты.\nОбратитесь к администратору.", when=~F["has_available"]),
|
Const("<blockquote>⚠️ <b>Нет доступных резидентов</b></blockquote>\n\nВсе резиденты уже заняты.\nОбратитесь к администратору.", when=~F["has_available"]),
|
||||||
Group(
|
Group(
|
||||||
Select(
|
Select(
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ class MainMenuSG(StatesGroup):
|
|||||||
class AdminMenuSG(StatesGroup):
|
class AdminMenuSG(StatesGroup):
|
||||||
main = State()
|
main = State()
|
||||||
residents = State()
|
residents = State()
|
||||||
|
resident_info = State()
|
||||||
|
resident_logout_confirm = State()
|
||||||
users = State()
|
users = State()
|
||||||
statistics = State()
|
statistics = State()
|
||||||
broadcast = State()
|
broadcast = State()
|
||||||
|
|||||||
Reference in New Issue
Block a user