mirror of
https://github.com/koloideal/DutyLog.git
synced 2026-06-10 10:25:29 +03:00
889 lines
28 KiB
Python
889 lines
28 KiB
Python
from aiogram.types import Message, CallbackQuery
|
||
from aiogram_dialog import Window, DialogManager
|
||
from aiogram_dialog.widgets.text import Format, Const
|
||
from aiogram_dialog.widgets.kbd import SwitchTo, Button, ScrollingGroup, Select, Row, Group
|
||
from aiogram_dialog.widgets.input import MessageInput
|
||
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.rooms_repository import (
|
||
RoomsRepository,
|
||
)
|
||
from dutylog.infrastructure.database.repositories.floors_repository import (
|
||
FloorsRepository,
|
||
)
|
||
from dutylog.infrastructure.database.repositories.residents_repository import (
|
||
ResidentsRepository,
|
||
)
|
||
from dutylog.infrastructure.database.repositories.room_hours_transactions_repository import (
|
||
RoomHoursTransactionsRepository,
|
||
)
|
||
from dutylog.infrastructure.database.repositories.users_repository import (
|
||
UsersRepository,
|
||
)
|
||
from dutylog.infrastructure.utils.datetime import msk_now
|
||
|
||
|
||
async def on_rooms_click(
|
||
callback: CallbackQuery,
|
||
button: Button,
|
||
dialog_manager: DialogManager,
|
||
):
|
||
await dialog_manager.switch_to(AdminMenuSG.rooms_select_floor)
|
||
|
||
|
||
@inject
|
||
async def get_rooms_floors_data(
|
||
floors_repository: FromDishka[FloorsRepository],
|
||
**kwargs,
|
||
):
|
||
all_floors = await floors_repository.get_all_floors()
|
||
all_floors.sort(key=lambda f: f.number)
|
||
|
||
floors_data = [(f"🏢 Этаж {f.number}", f.id) for f in all_floors]
|
||
|
||
content = """
|
||
<blockquote>🚪 <b>Комнаты</b></blockquote>
|
||
|
||
Выберите этаж для просмотра комнат:
|
||
"""
|
||
|
||
return {
|
||
"content": content,
|
||
"floors": floors_data,
|
||
}
|
||
|
||
|
||
async def on_rooms_floor_selected(
|
||
callback: CallbackQuery,
|
||
widget: Select,
|
||
dialog_manager: DialogManager,
|
||
item_id: str,
|
||
):
|
||
dialog_manager.dialog_data["selected_floor_id"] = int(item_id)
|
||
await dialog_manager.switch_to(AdminMenuSG.rooms_list)
|
||
|
||
|
||
@inject
|
||
async def get_rooms_list_data(
|
||
dialog_manager: DialogManager,
|
||
rooms_repository: FromDishka[RoomsRepository],
|
||
floors_repository: FromDishka[FloorsRepository],
|
||
**kwargs,
|
||
):
|
||
floor_id = dialog_manager.dialog_data.get("selected_floor_id")
|
||
|
||
if not floor_id:
|
||
return {
|
||
"content": "Ошибка: этаж не выбран",
|
||
"rooms": [],
|
||
"floor_number": "???",
|
||
}
|
||
|
||
floor = await floors_repository.get_floor_by_id(floor_id)
|
||
floor_number = floor.number if floor else "???"
|
||
|
||
rooms = await rooms_repository.get_rooms_by_floor(floor_id)
|
||
rooms.sort(key=lambda r: r.number)
|
||
|
||
rooms_data = [(f"🚪 Комната {r.number}", r.id) for r in rooms]
|
||
|
||
content = f"""
|
||
<blockquote>🚪 <b>Комнаты на этаже {floor_number}</b></blockquote>
|
||
|
||
<b>Всего комнат:</b> <code>{len(rooms)}</code>
|
||
|
||
Выберите комнату для просмотра:
|
||
"""
|
||
|
||
return {
|
||
"content": content,
|
||
"rooms": rooms_data,
|
||
"floor_number": floor_number,
|
||
}
|
||
|
||
|
||
async def on_room_selected(
|
||
callback: CallbackQuery,
|
||
widget: Select,
|
||
dialog_manager: DialogManager,
|
||
item_id: str,
|
||
):
|
||
dialog_manager.dialog_data["selected_room_id"] = int(item_id)
|
||
await dialog_manager.switch_to(AdminMenuSG.room_info)
|
||
|
||
|
||
async def on_add_room_click(
|
||
callback: CallbackQuery,
|
||
button: Button,
|
||
dialog_manager: DialogManager,
|
||
):
|
||
await dialog_manager.switch_to(AdminMenuSG.create_room_select_floor)
|
||
|
||
|
||
@inject
|
||
async def get_create_room_floors_data(
|
||
floors_repository: FromDishka[FloorsRepository],
|
||
**kwargs,
|
||
):
|
||
all_floors = await floors_repository.get_all_floors()
|
||
all_floors.sort(key=lambda f: f.number)
|
||
|
||
floors_data = [(f"🏢 Этаж {f.number}", f.id) for f in all_floors]
|
||
|
||
content = """
|
||
<blockquote>➕ <b>Создание комнаты</b></blockquote>
|
||
|
||
Выберите этаж для новой комнаты:
|
||
"""
|
||
|
||
return {
|
||
"content": content,
|
||
"floors": floors_data,
|
||
}
|
||
|
||
|
||
async def on_create_room_floor_selected(
|
||
callback: CallbackQuery,
|
||
widget: Select,
|
||
dialog_manager: DialogManager,
|
||
item_id: str,
|
||
):
|
||
dialog_manager.dialog_data["new_room_floor_id"] = int(item_id)
|
||
await dialog_manager.switch_to(AdminMenuSG.create_room_input)
|
||
|
||
|
||
async def on_room_number_input(
|
||
message: Message,
|
||
widget: MessageInput,
|
||
dialog_manager: DialogManager,
|
||
):
|
||
if not message.text:
|
||
await message.answer("⚠️ Пожалуйста, введите номер комнаты")
|
||
return
|
||
|
||
try:
|
||
room_number = int(message.text)
|
||
if room_number <= 0:
|
||
await message.answer("⚠️ Номер комнаты должен быть положительным числом")
|
||
return
|
||
|
||
dialog_manager.dialog_data["new_room_number"] = room_number
|
||
await dialog_manager.switch_to(AdminMenuSG.create_room_confirm)
|
||
except ValueError:
|
||
await message.answer("⚠️ Пожалуйста, введите корректное число")
|
||
|
||
|
||
async def get_create_room_confirm_data(
|
||
dialog_manager: DialogManager,
|
||
**kwargs,
|
||
):
|
||
room_number = dialog_manager.dialog_data.get("new_room_number", "???")
|
||
return {"room_number": room_number}
|
||
|
||
|
||
@inject
|
||
async def on_create_room_confirm(
|
||
callback: CallbackQuery,
|
||
button: Button,
|
||
dialog_manager: DialogManager,
|
||
rooms_repository: FromDishka[RoomsRepository],
|
||
):
|
||
room_number = dialog_manager.dialog_data.get("new_room_number")
|
||
floor_id = dialog_manager.dialog_data.get("new_room_floor_id")
|
||
|
||
if room_number and floor_id:
|
||
existing_room = await rooms_repository.get_room_by_number(room_number)
|
||
if existing_room:
|
||
await callback.answer(
|
||
f"⚠️ Комната {room_number} уже существует!",
|
||
show_alert=True
|
||
)
|
||
await dialog_manager.switch_to(AdminMenuSG.rooms_select_floor)
|
||
return
|
||
|
||
await rooms_repository.create_room(room_number, floor_id)
|
||
await callback.answer("✅ Комната создана!")
|
||
|
||
await dialog_manager.switch_to(AdminMenuSG.rooms_select_floor)
|
||
|
||
|
||
async def on_create_room_cancel(
|
||
callback: CallbackQuery,
|
||
button: Button,
|
||
dialog_manager: DialogManager,
|
||
):
|
||
await dialog_manager.switch_to(AdminMenuSG.rooms_select_floor)
|
||
|
||
|
||
@inject
|
||
async def get_room_info_data(
|
||
dialog_manager: DialogManager,
|
||
rooms_repository: FromDishka[RoomsRepository],
|
||
floors_repository: FromDishka[FloorsRepository],
|
||
residents_repository: FromDishka[ResidentsRepository],
|
||
**kwargs,
|
||
):
|
||
room_id = dialog_manager.dialog_data.get("selected_room_id")
|
||
|
||
if not room_id:
|
||
return {"info_content": "Ошибка: комната не выбрана"}
|
||
|
||
room = await rooms_repository.get_room_by_id(room_id)
|
||
|
||
if not room:
|
||
return {"info_content": "Ошибка: комната не найдена"}
|
||
|
||
floor = await floors_repository.get_floor_by_id(room.on_floor)
|
||
floor_number = floor.number if floor else "???"
|
||
|
||
# Получаем резидентов комнаты
|
||
residents = await residents_repository.get_residents_by_room(room_id)
|
||
|
||
residents_info = ""
|
||
if residents:
|
||
residents_info = "\n<b>Проживающие:</b>\n"
|
||
for resident in residents:
|
||
status = "🟢" if resident.is_busy else "⚪️"
|
||
name = resident.real_name if resident.real_name else "Без имени"
|
||
residents_info += f"{status} {name}\n"
|
||
else:
|
||
residents_info = "\n<i>Нет проживающих</i>\n"
|
||
|
||
info_content = f"""
|
||
<blockquote>🚪 <b>Информация о комнате</b></blockquote>
|
||
|
||
<b>Номер:</b> <code>{room.number}</code>
|
||
<b>Этаж:</b> <code>{floor_number}</code>
|
||
{residents_info}
|
||
🟢 <b>Отработанные часы:</b> <code>{room.inactive_hours}</code> ч
|
||
🔴 <b>Неотработанные часы:</b> <code>{room.active_hours}</code> ч
|
||
"""
|
||
|
||
return {
|
||
"info_content": info_content,
|
||
"has_residents": len(residents) > 0,
|
||
}
|
||
|
||
|
||
async def on_room_add_hours_click(
|
||
callback: CallbackQuery,
|
||
button: Button,
|
||
dialog_manager: DialogManager,
|
||
):
|
||
await dialog_manager.switch_to(AdminMenuSG.room_add_hours_select)
|
||
|
||
|
||
async def on_room_remove_hours_click(
|
||
callback: CallbackQuery,
|
||
button: Button,
|
||
dialog_manager: DialogManager,
|
||
):
|
||
await dialog_manager.switch_to(AdminMenuSG.room_remove_hours_select)
|
||
|
||
|
||
async def get_room_hours_select_data(**kwargs):
|
||
hours_options = [
|
||
(5, "5"), (10, "10"), (15, "15"), (20, "20"),
|
||
(25, "25"), (30, "30"), (35, "35"), (40, "40"),
|
||
(45, "45"), (50, "50"), (55, "55"), (60, "60"),
|
||
(65, "65"), (70, "70"), (75, "75"), (80, "80"),
|
||
]
|
||
return {"hours_options": hours_options}
|
||
|
||
|
||
async def on_room_hours_selected(
|
||
callback: CallbackQuery,
|
||
widget: Select,
|
||
dialog_manager: DialogManager,
|
||
item_id: str,
|
||
):
|
||
dialog_manager.dialog_data["selected_hours"] = int(item_id)
|
||
|
||
if dialog_manager.current_context().state == AdminMenuSG.room_add_hours_select:
|
||
await dialog_manager.switch_to(AdminMenuSG.room_add_hours_remark)
|
||
else:
|
||
await dialog_manager.switch_to(AdminMenuSG.room_remove_hours_remark)
|
||
|
||
|
||
async def on_room_custom_hours_click(
|
||
callback: CallbackQuery,
|
||
button: Button,
|
||
dialog_manager: DialogManager,
|
||
):
|
||
if dialog_manager.current_context().state == AdminMenuSG.room_add_hours_select:
|
||
await dialog_manager.switch_to(AdminMenuSG.room_add_hours_custom)
|
||
else:
|
||
await dialog_manager.switch_to(AdminMenuSG.room_remove_hours_custom)
|
||
|
||
|
||
async def on_room_custom_hours_input(
|
||
message: Message,
|
||
widget: MessageInput,
|
||
dialog_manager: DialogManager,
|
||
):
|
||
if not message.text:
|
||
await message.answer("⚠️ Пожалуйста, введите число")
|
||
return
|
||
|
||
try:
|
||
hours = int(message.text)
|
||
if hours <= 0:
|
||
await message.answer("⚠️ Количество часов должно быть положительным числом")
|
||
return
|
||
|
||
dialog_manager.dialog_data["selected_hours"] = hours
|
||
|
||
if dialog_manager.current_context().state == AdminMenuSG.room_add_hours_custom:
|
||
await dialog_manager.switch_to(AdminMenuSG.room_add_hours_remark)
|
||
else:
|
||
await dialog_manager.switch_to(AdminMenuSG.room_remove_hours_remark)
|
||
except ValueError:
|
||
await message.answer("⚠️ Пожалуйста, введите корректное число")
|
||
|
||
|
||
async def on_room_remark_input(
|
||
message: Message,
|
||
widget: MessageInput,
|
||
dialog_manager: DialogManager,
|
||
):
|
||
if message.text and message.text.strip():
|
||
dialog_manager.dialog_data["remark"] = message.text.strip()
|
||
else:
|
||
dialog_manager.dialog_data["remark"] = None
|
||
|
||
if dialog_manager.current_context().state == AdminMenuSG.room_add_hours_remark:
|
||
await dialog_manager.switch_to(AdminMenuSG.room_add_hours_confirm)
|
||
else:
|
||
await dialog_manager.switch_to(AdminMenuSG.room_remove_hours_confirm)
|
||
|
||
|
||
async def on_room_skip_remark(
|
||
callback: CallbackQuery,
|
||
button: Button,
|
||
dialog_manager: DialogManager,
|
||
):
|
||
dialog_manager.dialog_data["remark"] = None
|
||
|
||
if dialog_manager.current_context().state == AdminMenuSG.room_add_hours_remark:
|
||
await dialog_manager.switch_to(AdminMenuSG.room_add_hours_confirm)
|
||
else:
|
||
await dialog_manager.switch_to(AdminMenuSG.room_remove_hours_confirm)
|
||
|
||
|
||
async def get_room_hours_confirm_data(
|
||
dialog_manager: DialogManager,
|
||
**kwargs,
|
||
):
|
||
hours = dialog_manager.dialog_data.get("selected_hours", 0)
|
||
remark = dialog_manager.dialog_data.get("remark", "")
|
||
remark_text = f"\n\n<b>Примечание:</b> {remark}" if remark else ""
|
||
|
||
return {
|
||
"hours": hours,
|
||
"remark_text": remark_text,
|
||
}
|
||
|
||
|
||
@inject
|
||
async def on_room_add_hours_confirm(
|
||
callback: CallbackQuery,
|
||
button: Button,
|
||
dialog_manager: DialogManager,
|
||
room_transactions_repository: FromDishka[RoomHoursTransactionsRepository],
|
||
residents_repository: FromDishka[ResidentsRepository],
|
||
users_repository: FromDishka[UsersRepository],
|
||
**kwargs,
|
||
):
|
||
from aiogram import Bot
|
||
bot: Bot = dialog_manager.middleware_data.get("bot")
|
||
|
||
room_id = dialog_manager.dialog_data.get("selected_room_id")
|
||
hours = dialog_manager.dialog_data.get("selected_hours")
|
||
remark = dialog_manager.dialog_data.get("remark")
|
||
admin_id = callback.from_user.id
|
||
|
||
if room_id and hours:
|
||
transaction, _ = await room_transactions_repository.add_hours(
|
||
room_id=room_id,
|
||
amount=hours,
|
||
admin_id=admin_id,
|
||
is_active=True,
|
||
)
|
||
|
||
# Отправляем уведомления всем проживающим
|
||
residents = await residents_repository.get_residents_by_room(room_id)
|
||
for resident in residents:
|
||
if resident.user_entity:
|
||
user = await users_repository.get_user_by_id(resident.user_entity)
|
||
if user:
|
||
try:
|
||
remark_text = f"\n💬 <i>{remark}</i>" if remark else ""
|
||
await bot.send_message(
|
||
user.id,
|
||
f"<blockquote>📢 <b>Уведомление</b></blockquote>\n\n"
|
||
f"Вашей комнате начислено <b>+{hours}</b> ч{remark_text}"
|
||
)
|
||
except Exception:
|
||
pass
|
||
|
||
await dialog_manager.switch_to(AdminMenuSG.room_info)
|
||
|
||
|
||
@inject
|
||
async def on_room_remove_hours_confirm(
|
||
callback: CallbackQuery,
|
||
button: Button,
|
||
dialog_manager: DialogManager,
|
||
room_transactions_repository: FromDishka[RoomHoursTransactionsRepository],
|
||
rooms_repository: FromDishka[RoomsRepository],
|
||
residents_repository: FromDishka[ResidentsRepository],
|
||
users_repository: FromDishka[UsersRepository],
|
||
**kwargs,
|
||
):
|
||
from aiogram import Bot
|
||
bot: Bot = dialog_manager.middleware_data.get("bot")
|
||
|
||
room_id = dialog_manager.dialog_data.get("selected_room_id")
|
||
hours = dialog_manager.dialog_data.get("selected_hours")
|
||
remark = dialog_manager.dialog_data.get("remark")
|
||
admin_id = callback.from_user.id
|
||
|
||
if room_id and hours:
|
||
room = await rooms_repository.get_room_by_id(room_id)
|
||
if room and room.active_hours < hours:
|
||
await callback.answer(
|
||
f"⚠️ Недостаточно часов! У комнаты {room.active_hours} неотработанных ч, а вы пытаетесь отнять {hours} ч",
|
||
show_alert=True
|
||
)
|
||
await dialog_manager.switch_to(AdminMenuSG.room_info)
|
||
return
|
||
|
||
await room_transactions_repository.move_hours_to_completed(
|
||
room_id=room_id,
|
||
amount=hours,
|
||
admin_id=admin_id,
|
||
)
|
||
|
||
# Отправляем уведомления всем проживающим
|
||
residents = await residents_repository.get_residents_by_room(room_id)
|
||
for resident in residents:
|
||
if resident.user_entity:
|
||
user = await users_repository.get_user_by_id(resident.user_entity)
|
||
if user:
|
||
try:
|
||
remark_text = f"\n💬 <i>{remark}</i>" if remark else ""
|
||
await bot.send_message(
|
||
user.id,
|
||
f"<blockquote>📢 <b>Уведомление</b></blockquote>\n\n"
|
||
f"С вашей комнаты списано <b>-{hours}</b> ч{remark_text}"
|
||
)
|
||
except Exception:
|
||
pass
|
||
|
||
await dialog_manager.switch_to(AdminMenuSG.room_info)
|
||
|
||
|
||
async def on_room_hours_cancel(
|
||
callback: CallbackQuery,
|
||
button: Button,
|
||
dialog_manager: DialogManager,
|
||
):
|
||
await dialog_manager.switch_to(AdminMenuSG.room_info)
|
||
|
||
|
||
@inject
|
||
async def get_room_delete_confirm_data(
|
||
dialog_manager: DialogManager,
|
||
rooms_repository: FromDishka[RoomsRepository],
|
||
**kwargs,
|
||
):
|
||
room_id = dialog_manager.dialog_data.get("selected_room_id")
|
||
|
||
if not room_id:
|
||
return {"room_number": "???"}
|
||
|
||
room = await rooms_repository.get_room_by_id(room_id)
|
||
room_number = room.number if room else "???"
|
||
|
||
return {"room_number": room_number}
|
||
|
||
|
||
@inject
|
||
async def on_delete_room_confirm(
|
||
callback: CallbackQuery,
|
||
button: Button,
|
||
dialog_manager: DialogManager,
|
||
rooms_repository: FromDishka[RoomsRepository],
|
||
):
|
||
room_id = dialog_manager.dialog_data.get("selected_room_id")
|
||
|
||
if room_id:
|
||
await rooms_repository.delete_room(room_id)
|
||
await callback.answer("✅ Комната удалена!")
|
||
|
||
await dialog_manager.switch_to(AdminMenuSG.rooms_list)
|
||
|
||
|
||
async def on_delete_room_cancel(
|
||
callback: CallbackQuery,
|
||
button: Button,
|
||
dialog_manager: DialogManager,
|
||
):
|
||
await dialog_manager.switch_to(AdminMenuSG.room_info)
|
||
|
||
|
||
@inject
|
||
async def get_room_history_data(
|
||
dialog_manager: DialogManager,
|
||
rooms_repository: FromDishka[RoomsRepository],
|
||
room_transactions_repository: FromDishka[RoomHoursTransactionsRepository],
|
||
**kwargs,
|
||
):
|
||
room_id = dialog_manager.dialog_data.get("selected_room_id")
|
||
|
||
if not room_id:
|
||
return {"history_content": "Ошибка: комната не выбрана"}
|
||
|
||
room = await rooms_repository.get_room_by_id(room_id)
|
||
|
||
if not room:
|
||
return {"history_content": "Ошибка: комната не найдена"}
|
||
|
||
transactions = await room_transactions_repository.get_room_history(room_id)
|
||
transactions_sorted = sorted(transactions, key=lambda x: x.created_at)
|
||
last_10 = transactions_sorted[-10:]
|
||
|
||
if not last_10:
|
||
history_text = f"""
|
||
<blockquote>📜 <b>История операций</b></blockquote>
|
||
|
||
<b>Комната:</b> {room.number}
|
||
|
||
<i>История операций пуста</i>
|
||
"""
|
||
else:
|
||
history_text = f"""
|
||
<blockquote>📜 <b>История операций</b></blockquote>
|
||
|
||
<b>Комната:</b> {room.number}
|
||
|
||
"""
|
||
for tx in last_10:
|
||
operation = "Начислено" if tx.transaction_type == "increase" else "Списано"
|
||
emoji = "+" if tx.transaction_type == "increase" else "−"
|
||
|
||
msk_time = tx.created_at.astimezone(msk_now().tzinfo).replace(tzinfo=None)
|
||
date_str = msk_time.strftime("%d.%m.%Y %H:%M")
|
||
|
||
remark_text = f"\n💬 <i>{tx.remark}</i>" if tx.remark else ""
|
||
|
||
history_text += f"<blockquote><b>{operation}</b> {emoji}<code>{tx.amount}</code> ч\n📅 {date_str}{remark_text}</blockquote>\n"
|
||
|
||
return {"history_content": history_text}
|
||
|
||
|
||
rooms_select_floor_window = Window(
|
||
Format("{content}"),
|
||
Group(
|
||
Select(
|
||
Format("{item[0]}"),
|
||
id="rooms_floors_select",
|
||
item_id_getter=lambda x: x[1],
|
||
items="floors",
|
||
on_click=on_rooms_floor_selected,
|
||
),
|
||
width=2,
|
||
),
|
||
Button(
|
||
Const("➕ Добавить комнату"),
|
||
id="add_room_btn",
|
||
on_click=on_add_room_click,
|
||
),
|
||
SwitchTo(
|
||
Const("◀️ Назад"),
|
||
id="back_to_admin_menu_from_rooms",
|
||
state=AdminMenuSG.main,
|
||
),
|
||
state=AdminMenuSG.rooms_select_floor,
|
||
getter=get_rooms_floors_data,
|
||
)
|
||
|
||
rooms_list_window = Window(
|
||
Format("{content}"),
|
||
ScrollingGroup(
|
||
Select(
|
||
Format("{item[0]}"),
|
||
id="rooms_select",
|
||
item_id_getter=lambda x: x[1],
|
||
items="rooms",
|
||
on_click=on_room_selected,
|
||
),
|
||
id="rooms_scroll",
|
||
width=1,
|
||
height=7,
|
||
),
|
||
SwitchTo(
|
||
Const("◀️ Назад к этажам"),
|
||
id="back_to_rooms_floors",
|
||
state=AdminMenuSG.rooms_select_floor,
|
||
),
|
||
state=AdminMenuSG.rooms_list,
|
||
getter=get_rooms_list_data,
|
||
)
|
||
|
||
room_info_window = Window(
|
||
Format("{info_content}"),
|
||
Row(
|
||
Button(
|
||
Const("Добавить часы"),
|
||
id="room_add_hours_btn",
|
||
on_click=on_room_add_hours_click,
|
||
),
|
||
Button(
|
||
Const("Отнять часы"),
|
||
id="room_remove_hours_btn",
|
||
on_click=on_room_remove_hours_click,
|
||
),
|
||
),
|
||
Button(
|
||
Const("📜 История"),
|
||
id="room_history_btn",
|
||
on_click=lambda c, b, m: m.switch_to(AdminMenuSG.room_history),
|
||
),
|
||
Button(
|
||
Const("🗑 Удалить комнату"),
|
||
id="delete_room_btn",
|
||
on_click=lambda c, b, m: m.switch_to(AdminMenuSG.room_delete_confirm),
|
||
),
|
||
SwitchTo(
|
||
Const("◀️ Назад к списку"),
|
||
id="back_to_rooms_list",
|
||
state=AdminMenuSG.rooms_list,
|
||
),
|
||
state=AdminMenuSG.room_info,
|
||
getter=get_room_info_data,
|
||
)
|
||
|
||
room_delete_confirm_window = Window(
|
||
Format("<blockquote>⚠️ <b>Подтверждение удаления</b></blockquote>\n\nВы точно хотите удалить комнату <code>{room_number}</code>?\nЭто действие необратимо и удалит всех резидентов в этой комнате!"),
|
||
Row(
|
||
Button(
|
||
Const("✅ Да, удалить"),
|
||
id="confirm_delete_room",
|
||
on_click=on_delete_room_confirm,
|
||
),
|
||
Button(
|
||
Const("❌ Отмена"),
|
||
id="cancel_delete_room",
|
||
on_click=on_delete_room_cancel,
|
||
),
|
||
),
|
||
state=AdminMenuSG.room_delete_confirm,
|
||
getter=get_room_delete_confirm_data,
|
||
)
|
||
|
||
room_add_hours_select_window = Window(
|
||
Const("<blockquote>➕ <b>Добавить часы комнате</b></blockquote>\n\nВыберите количество часов:"),
|
||
Group(
|
||
Select(
|
||
Format("{item[1]} ч"),
|
||
id="room_hours_select_add",
|
||
item_id_getter=lambda x: x[0],
|
||
items="hours_options",
|
||
on_click=on_room_hours_selected,
|
||
),
|
||
width=4,
|
||
),
|
||
Button(
|
||
Const("✏️ Ввести свое количество"),
|
||
id="room_custom_hours_add_btn",
|
||
on_click=on_room_custom_hours_click,
|
||
),
|
||
SwitchTo(
|
||
Const("◀️ Отмена"),
|
||
id="cancel_room_add_hours",
|
||
state=AdminMenuSG.room_info,
|
||
),
|
||
state=AdminMenuSG.room_add_hours_select,
|
||
getter=get_room_hours_select_data,
|
||
)
|
||
|
||
room_remove_hours_select_window = Window(
|
||
Const("<blockquote>➖ <b>Отнять часы у комнаты</b></blockquote>\n\nВыберите количество часов:"),
|
||
Group(
|
||
Select(
|
||
Format("{item[1]} ч"),
|
||
id="room_hours_select_remove",
|
||
item_id_getter=lambda x: x[0],
|
||
items="hours_options",
|
||
on_click=on_room_hours_selected,
|
||
),
|
||
width=4,
|
||
),
|
||
Button(
|
||
Const("✏️ Ввести свое количество"),
|
||
id="room_custom_hours_remove_btn",
|
||
on_click=on_room_custom_hours_click,
|
||
),
|
||
SwitchTo(
|
||
Const("◀️ Отмена"),
|
||
id="cancel_room_remove_hours",
|
||
state=AdminMenuSG.room_info,
|
||
),
|
||
state=AdminMenuSG.room_remove_hours_select,
|
||
getter=get_room_hours_select_data,
|
||
)
|
||
|
||
room_add_hours_custom_window = Window(
|
||
Const("<blockquote>✏️ <b>Добавить часы</b></blockquote>\n\nВведите количество часов:"),
|
||
MessageInput(on_room_custom_hours_input),
|
||
SwitchTo(
|
||
Const("◀️ Отмена"),
|
||
id="cancel_room_custom_add",
|
||
state=AdminMenuSG.room_add_hours_select,
|
||
),
|
||
state=AdminMenuSG.room_add_hours_custom,
|
||
)
|
||
|
||
room_remove_hours_custom_window = Window(
|
||
Const("<blockquote>✏️ <b>Отнять часы</b></blockquote>\n\nВведите количество часов:"),
|
||
MessageInput(on_room_custom_hours_input),
|
||
SwitchTo(
|
||
Const("◀️ Отмена"),
|
||
id="cancel_room_custom_remove",
|
||
state=AdminMenuSG.room_remove_hours_select,
|
||
),
|
||
state=AdminMenuSG.room_remove_hours_custom,
|
||
)
|
||
|
||
room_add_hours_remark_window = Window(
|
||
Const("<blockquote>💬 <b>Примечание</b></blockquote>\n\nВведите примечание к операции (или пропустите):"),
|
||
MessageInput(on_room_remark_input),
|
||
Button(
|
||
Const("⏭ Пропустить"),
|
||
id="skip_room_add_remark",
|
||
on_click=on_room_skip_remark,
|
||
),
|
||
SwitchTo(
|
||
Const("◀️ Отмена"),
|
||
id="cancel_room_add_remark",
|
||
state=AdminMenuSG.room_info,
|
||
),
|
||
state=AdminMenuSG.room_add_hours_remark,
|
||
)
|
||
|
||
room_remove_hours_remark_window = Window(
|
||
Const("<blockquote>💬 <b>Примечание</b></blockquote>\n\nВведите примечание к операции (или пропустите):"),
|
||
MessageInput(on_room_remark_input),
|
||
Button(
|
||
Const("⏭ Пропустить"),
|
||
id="skip_room_remove_remark",
|
||
on_click=on_room_skip_remark,
|
||
),
|
||
SwitchTo(
|
||
Const("◀️ Отмена"),
|
||
id="cancel_room_remove_remark",
|
||
state=AdminMenuSG.room_info,
|
||
),
|
||
state=AdminMenuSG.room_remove_hours_remark,
|
||
)
|
||
|
||
room_add_hours_confirm_window = Window(
|
||
Format("<blockquote>➕ <b>Подтверждение</b></blockquote>\n\nВы уверены, что хотите добавить <code>{hours}</code> часов?{remark_text}"),
|
||
Row(
|
||
Button(
|
||
Const("✅ Да"),
|
||
id="confirm_room_add_hours",
|
||
on_click=on_room_add_hours_confirm,
|
||
),
|
||
Button(
|
||
Const("❌ Нет"),
|
||
id="cancel_room_add_hours_confirm",
|
||
on_click=on_room_hours_cancel,
|
||
),
|
||
),
|
||
state=AdminMenuSG.room_add_hours_confirm,
|
||
getter=get_room_hours_confirm_data,
|
||
)
|
||
|
||
room_remove_hours_confirm_window = Window(
|
||
Format("<blockquote>➖ <b>Подтверждение</b></blockquote>\n\nВы уверены, что хотите отнять <code>{hours}</code> часов?{remark_text}"),
|
||
Row(
|
||
Button(
|
||
Const("✅ Да"),
|
||
id="confirm_room_remove_hours",
|
||
on_click=on_room_remove_hours_confirm,
|
||
),
|
||
Button(
|
||
Const("❌ Нет"),
|
||
id="cancel_room_remove_hours_confirm",
|
||
on_click=on_room_hours_cancel,
|
||
),
|
||
),
|
||
state=AdminMenuSG.room_remove_hours_confirm,
|
||
getter=get_room_hours_confirm_data,
|
||
)
|
||
|
||
create_room_select_floor_window = Window(
|
||
Format("{content}"),
|
||
Group(
|
||
Select(
|
||
Format("{item[0]}"),
|
||
id="create_room_floors_select",
|
||
item_id_getter=lambda x: x[1],
|
||
items="floors",
|
||
on_click=on_create_room_floor_selected,
|
||
),
|
||
width=2,
|
||
),
|
||
SwitchTo(
|
||
Const("◀️ Отмена"),
|
||
id="cancel_create_room_floor",
|
||
state=AdminMenuSG.rooms_select_floor,
|
||
),
|
||
state=AdminMenuSG.create_room_select_floor,
|
||
getter=get_create_room_floors_data,
|
||
)
|
||
|
||
create_room_input_window = Window(
|
||
Const("<blockquote>➕ <b>Создание комнаты</b></blockquote>\n\nВведите номер комнаты:"),
|
||
MessageInput(on_room_number_input),
|
||
SwitchTo(
|
||
Const("◀️ Назад"),
|
||
id="back_to_create_room_floor",
|
||
state=AdminMenuSG.create_room_select_floor,
|
||
),
|
||
state=AdminMenuSG.create_room_input,
|
||
)
|
||
|
||
create_room_confirm_window = Window(
|
||
Format("<blockquote>✅ <b>Подтверждение</b></blockquote>\n\nСоздать комнату <code>{room_number}</code>?"),
|
||
Row(
|
||
Button(
|
||
Const("✅ Да"),
|
||
id="confirm_create_room",
|
||
on_click=on_create_room_confirm,
|
||
),
|
||
Button(
|
||
Const("❌ Нет"),
|
||
id="cancel_create_room",
|
||
on_click=on_create_room_cancel,
|
||
),
|
||
),
|
||
state=AdminMenuSG.create_room_confirm,
|
||
getter=get_create_room_confirm_data,
|
||
)
|
||
|
||
room_history_window = Window(
|
||
Format("{history_content}"),
|
||
SwitchTo(
|
||
Const("◀️ Назад"),
|
||
id="back_to_room_info",
|
||
state=AdminMenuSG.room_info,
|
||
),
|
||
state=AdminMenuSG.room_history,
|
||
getter=get_room_history_data,
|
||
)
|