mirror of
https://github.com/koloideal/DutyLog.git
synced 2026-06-10 10:25:29 +03:00
commit
This commit is contained in:
@@ -1,11 +1,11 @@
|
||||
from aiogram.types import User
|
||||
from aiogram_dialog import Dialog, Window, DialogManager
|
||||
from aiogram_dialog.widgets.text import Format, Const
|
||||
from aiogram_dialog.widgets.kbd import SwitchTo, Back
|
||||
from aiogram_dialog.widgets.kbd import SwitchTo, Back, Start
|
||||
from dishka import FromDishka
|
||||
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, RegistrationSG
|
||||
from dutylog.infrastructure.database.repositories.users_repository import UsersRepository
|
||||
from dutylog.infrastructure.database.repositories.residents_repository import ResidentsRepository
|
||||
from dutylog.infrastructure.database.repositories.hours_transactions_repository import HoursTransactionsRepository
|
||||
@@ -49,6 +49,7 @@ async def get_main_menu_data(
|
||||
Вы еще не привязаны к резиденту.
|
||||
Обратитесь к администратору для регистрации.
|
||||
"""
|
||||
has_resident = False
|
||||
else:
|
||||
content = f"""
|
||||
{greeting}
|
||||
@@ -59,6 +60,7 @@ async def get_main_menu_data(
|
||||
━━━━━━━━━━━━━━━━
|
||||
🔴 Неотработанные часы: <code>{resident.inactive_hours}</code> ч</blockquote>
|
||||
"""
|
||||
has_resident = True
|
||||
else:
|
||||
content = f"""
|
||||
{greeting}
|
||||
@@ -67,11 +69,12 @@ async def get_main_menu_data(
|
||||
|
||||
Добро пожаловать в систему учета дежурств!
|
||||
"""
|
||||
has_resident = False
|
||||
|
||||
return {
|
||||
"content": content,
|
||||
"is_regular_user": not is_admin and not is_creator,
|
||||
"has_resident": resident is not None if not is_admin and not is_creator else False,
|
||||
"has_resident": has_resident,
|
||||
}
|
||||
|
||||
|
||||
@@ -128,6 +131,12 @@ main_menu_dialog = Dialog(
|
||||
state=MainMenuSG.history,
|
||||
when="has_resident",
|
||||
),
|
||||
Start(
|
||||
Const("🔄 Перерегистрация"),
|
||||
id="reregister_btn",
|
||||
state=RegistrationSG.select_floor,
|
||||
when="is_regular_user",
|
||||
),
|
||||
state=MainMenuSG.main,
|
||||
getter=get_main_menu_data,
|
||||
),
|
||||
@@ -138,3 +147,4 @@ main_menu_dialog = Dialog(
|
||||
getter=get_history_data,
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@@ -0,0 +1,169 @@
|
||||
from aiogram.types import CallbackQuery
|
||||
from magic_filter import F
|
||||
from aiogram_dialog import Dialog, Window, DialogManager
|
||||
from aiogram_dialog.widgets.text import Format, Const
|
||||
from aiogram_dialog.widgets.kbd import Select, Cancel, Group
|
||||
from dishka import FromDishka
|
||||
from dishka.integrations.aiogram_dialog import inject
|
||||
|
||||
from dutylog.application.bot.user_dialogs.states import RegistrationSG, MainMenuSG
|
||||
from dutylog.infrastructure.database.repositories.floors_repository import FloorsRepository
|
||||
from dutylog.infrastructure.database.repositories.rooms_repository import RoomsRepository
|
||||
from dutylog.infrastructure.database.repositories.residents_repository import ResidentsRepository
|
||||
|
||||
|
||||
@inject
|
||||
async def get_floors_data(
|
||||
floors_repository: FromDishka[FloorsRepository],
|
||||
rooms_repository: FromDishka[RoomsRepository],
|
||||
residents_repository: FromDishka[ResidentsRepository],
|
||||
**kwargs,
|
||||
):
|
||||
all_floors = await floors_repository.get_all_floors()
|
||||
available_residents = await residents_repository.get_available_residents()
|
||||
|
||||
if not available_residents:
|
||||
return {
|
||||
"has_available": False,
|
||||
"floors": [],
|
||||
}
|
||||
|
||||
available_room_ids = {r.room for r in available_residents}
|
||||
all_rooms = await rooms_repository.get_all_rooms()
|
||||
available_rooms = [r for r in all_rooms if r.id in available_room_ids]
|
||||
available_floor_ids = {r.on_floor for r in available_rooms}
|
||||
|
||||
available_floors = [f for f in all_floors if f.id in available_floor_ids]
|
||||
available_floors.sort(key=lambda f: f.number)
|
||||
|
||||
return {
|
||||
"has_available": True,
|
||||
"floors": [(f.id, f"Этаж {f.number}") for f in available_floors],
|
||||
}
|
||||
|
||||
|
||||
@inject
|
||||
async def get_rooms_data(
|
||||
dialog_manager: DialogManager,
|
||||
rooms_repository: FromDishka[RoomsRepository],
|
||||
residents_repository: FromDishka[ResidentsRepository],
|
||||
**kwargs,
|
||||
):
|
||||
floor_id = dialog_manager.dialog_data["floor_id"]
|
||||
|
||||
rooms = await rooms_repository.get_rooms_by_floor(floor_id)
|
||||
available_residents = await residents_repository.get_available_residents()
|
||||
available_room_ids = {r.room for r in available_residents}
|
||||
|
||||
available_rooms = [r for r in rooms if r.id in available_room_ids]
|
||||
available_rooms.sort(key=lambda r: r.number)
|
||||
|
||||
return {
|
||||
"rooms": [(r.id, str(r.number)) for r in available_rooms],
|
||||
}
|
||||
|
||||
|
||||
@inject
|
||||
async def get_residents_data(
|
||||
dialog_manager: DialogManager,
|
||||
residents_repository: FromDishka[ResidentsRepository],
|
||||
**kwargs,
|
||||
):
|
||||
room_id = dialog_manager.dialog_data["room_id"]
|
||||
|
||||
residents = await residents_repository.get_residents_by_room(room_id)
|
||||
available_residents = [r for r in residents if not r.is_busy]
|
||||
|
||||
return {
|
||||
"residents": [(r.id, r.real_name or f"Резидент #{r.id}") for r in available_residents],
|
||||
}
|
||||
|
||||
|
||||
async def on_floor_selected(
|
||||
callback: CallbackQuery,
|
||||
widget: Select,
|
||||
dialog_manager: DialogManager,
|
||||
floor_id: str,
|
||||
):
|
||||
dialog_manager.dialog_data["floor_id"] = int(floor_id)
|
||||
await dialog_manager.switch_to(RegistrationSG.select_room)
|
||||
|
||||
|
||||
async def on_room_selected(
|
||||
callback: CallbackQuery,
|
||||
widget: Select,
|
||||
dialog_manager: DialogManager,
|
||||
room_id: str,
|
||||
):
|
||||
dialog_manager.dialog_data["room_id"] = int(room_id)
|
||||
await dialog_manager.switch_to(RegistrationSG.select_resident)
|
||||
|
||||
|
||||
@inject
|
||||
async def on_resident_selected(
|
||||
callback: CallbackQuery,
|
||||
widget: Select,
|
||||
dialog_manager: DialogManager,
|
||||
item_id: str,
|
||||
residents_repository: FromDishka[ResidentsRepository],
|
||||
):
|
||||
user_id = callback.from_user.id
|
||||
resident_id = int(item_id)
|
||||
|
||||
await residents_repository.bind_user_to_resident(resident_id, user_id)
|
||||
|
||||
await callback.answer("✅ Вы успешно зарегистрированы!")
|
||||
await dialog_manager.start(MainMenuSG.main)
|
||||
|
||||
|
||||
registration_dialog = Dialog(
|
||||
Window(
|
||||
Const("<blockquote>🏢 <b>Выбор этажа</b></blockquote>\n\nВыберите этаж, на котором вы живете:", when="has_available"),
|
||||
Const("<blockquote>⚠️ <b>Нет доступных резидентов</b></blockquote>\n\nВсе резиденты уже заняты.\nОбратитесь к администратору.", when=~F["has_available"]),
|
||||
Group(
|
||||
Select(
|
||||
Format("{item[1]}"),
|
||||
id="floor_select",
|
||||
item_id_getter=lambda x: x[0],
|
||||
items="floors",
|
||||
on_click=on_floor_selected,
|
||||
),
|
||||
width=2,
|
||||
when="has_available",
|
||||
),
|
||||
state=RegistrationSG.select_floor,
|
||||
getter=get_floors_data,
|
||||
),
|
||||
Window(
|
||||
Const("<blockquote>🚪 <b>Выбор комнаты</b></blockquote>\n\nВыберите вашу комнату:"),
|
||||
Group(
|
||||
Select(
|
||||
Format("{item[1]}"),
|
||||
id="room_select",
|
||||
item_id_getter=lambda x: x[0],
|
||||
items="rooms",
|
||||
on_click=on_room_selected,
|
||||
),
|
||||
width=3,
|
||||
),
|
||||
Cancel(Const("◀️ Назад")),
|
||||
state=RegistrationSG.select_room,
|
||||
getter=get_rooms_data,
|
||||
),
|
||||
Window(
|
||||
Const("<blockquote>👤 <b>Выбор резидента</b></blockquote>\n\nВыберите себя из списка:"),
|
||||
Group(
|
||||
Select(
|
||||
Format("{item[1]}"),
|
||||
id="resident_select",
|
||||
item_id_getter=lambda x: x[0],
|
||||
items="residents",
|
||||
on_click=on_resident_selected,
|
||||
),
|
||||
width=1,
|
||||
),
|
||||
Cancel(Const("◀️ Назад")),
|
||||
state=RegistrationSG.select_resident,
|
||||
getter=get_residents_data,
|
||||
),
|
||||
)
|
||||
@@ -11,3 +11,9 @@ class AdminMenuSG(StatesGroup):
|
||||
users_list = State()
|
||||
statistics = State()
|
||||
broadcast = State()
|
||||
|
||||
|
||||
class RegistrationSG(StatesGroup):
|
||||
select_floor = State()
|
||||
select_room = State()
|
||||
select_resident = State()
|
||||
|
||||
@@ -4,8 +4,9 @@ from aiogram.types import Message
|
||||
from aiogram_dialog import DialogManager, StartMode
|
||||
from dishka import FromDishka
|
||||
|
||||
from dutylog.application.bot.user_dialogs.states import MainMenuSG, AdminMenuSG
|
||||
from dutylog.application.bot.user_dialogs.states import MainMenuSG, AdminMenuSG, RegistrationSG
|
||||
from dutylog.infrastructure.database.repositories.users_repository import UsersRepository
|
||||
from dutylog.infrastructure.database.repositories.residents_repository import ResidentsRepository
|
||||
from dutylog.infrastructure.utils.config import Config
|
||||
|
||||
router = Router()
|
||||
@@ -16,20 +17,23 @@ async def start_handler(
|
||||
message: Message,
|
||||
dialog_manager: DialogManager,
|
||||
users_repository: FromDishka[UsersRepository],
|
||||
residents_repository: FromDishka[ResidentsRepository],
|
||||
config: FromDishka[Config],
|
||||
):
|
||||
assert message.from_user is not None
|
||||
user = await users_repository.get_or_create_user(
|
||||
user_id=message.from_user.id,
|
||||
username=message.from_user.username,
|
||||
first_name=message.from_user.first_name,
|
||||
last_name=message.from_user.last_name,
|
||||
)
|
||||
user = await users_repository.get_user_by_id(message.from_user.id)
|
||||
|
||||
is_creator = message.from_user.id == config.bot.creator_id
|
||||
is_admin = user.is_admin
|
||||
is_admin = user.is_admin if user else False
|
||||
|
||||
if is_admin or is_creator:
|
||||
await dialog_manager.start(AdminMenuSG.main, mode=StartMode.RESET_STACK)
|
||||
else:
|
||||
await dialog_manager.start(MainMenuSG.main, mode=StartMode.RESET_STACK)
|
||||
return
|
||||
|
||||
if user:
|
||||
resident = await residents_repository.get_resident_by_user_id(message.from_user.id)
|
||||
if resident:
|
||||
await dialog_manager.start(MainMenuSG.main, mode=StartMode.RESET_STACK)
|
||||
return
|
||||
|
||||
await dialog_manager.start(RegistrationSG.select_floor, mode=StartMode.RESET_STACK)
|
||||
|
||||
Reference in New Issue
Block a user