This commit is contained in:
2026-03-17 20:36:51 +03:00
parent c80faeb665
commit f59791caf1
9 changed files with 106 additions and 6 deletions
-1
View File
@@ -55,7 +55,6 @@ async def main():
setup_dialogs(dp) setup_dialogs(dp)
setup_dishka(container, dp, auto_inject=True) setup_dishka(container, dp, auto_inject=True)
# Устанавливаем команды бота
await set_bot_commands(bot) await set_bot_commands(bot)
await dp.start_polling(bot) await dp.start_polling(bot)
@@ -1,5 +1,8 @@
from dutylog.application.bot.creator_dialogs.creator_menu_dialog import ( from dutylog.application.bot.creator_dialogs.creator_menu_dialog import (
creator_menu_dialog, creator_menu_dialog,
) )
from dutylog.application.bot.creator_dialogs.transactions_history import (
transactions_history_window,
)
__all__ = ["creator_menu_dialog"] __all__ = ["creator_menu_dialog", "transactions_history_window"]
@@ -289,6 +289,21 @@ admins_list_window = Window(
id="add_admin_btn", id="add_admin_btn",
on_click=on_add_admin_click, 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,
),
Button( Button(
Const("◀️ Назад"), Const("◀️ Назад"),
id="back_to_main_from_admins", id="back_to_main_from_admins",
@@ -7,6 +7,9 @@ from dutylog.application.bot.creator_dialogs.admins_management import (
add_admin_select_user_window, add_admin_select_user_window,
add_admin_confirm_window, add_admin_confirm_window,
) )
from dutylog.application.bot.creator_dialogs.transactions_history import (
transactions_history_window,
)
creator_menu_dialog = Dialog( creator_menu_dialog = Dialog(
@@ -15,4 +18,5 @@ creator_menu_dialog = Dialog(
remove_admin_confirm_window, remove_admin_confirm_window,
add_admin_select_user_window, add_admin_select_user_window,
add_admin_confirm_window, add_admin_confirm_window,
transactions_history_window,
) )
@@ -0,0 +1,79 @@
from aiogram_dialog import Window
from aiogram_dialog.widgets.text import Format, Const
from aiogram_dialog.widgets.kbd import Back, NumberedPager, Group
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.hours_transactions_repository import (
HoursTransactionsRepository,
)
from dutylog.infrastructure.database.repositories.residents_repository import (
ResidentsRepository,
)
from dutylog.infrastructure.database.repositories.rooms_repository import (
RoomsRepository,
)
from dutylog.infrastructure.utils.datetime import msk_now
@inject
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
page_transactions = all_transactions[start_idx:end_idx]
if not page_transactions:
content = "<blockquote>📜 <b>История всех транзакций</b></blockquote>\n\n<i>Нет транзакций</i>"
else:
content = "<blockquote>📜 <b>История всех транзакций</b></blockquote>\n\n"
for tx in page_transactions:
resident = await residents_repository.get_by_id(tx.resident_id)
if not resident:
continue
room = await rooms_repository.get_by_id(resident.room)
room_number = room.number if room else "???"
operation = "Начислено" if tx.transaction_type == "increase" else "Списано"
emoji = "+" if tx.transaction_type == "increase" else ""
room_mark = " 🚪" if tx.per_room 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 ""
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,
}
transactions_history_window = Window(
Format("{content}"),
Group(
NumberedPager(scroll="transactions_pager", when="pages"),
width=8,
),
Back(Const("◀️ Назад")),
state=CreatorMenuSG.transactions_history,
getter=get_transactions_history_data,
)
@@ -67,6 +67,7 @@ class CreatorMenuSG(StatesGroup):
remove_admin_confirm = State() remove_admin_confirm = State()
add_admin_select_user = State() add_admin_select_user = State()
add_admin_confirm = State() add_admin_confirm = State()
transactions_history = State()
class RegistrationSG(StatesGroup): class RegistrationSG(StatesGroup):
@@ -1,3 +1,5 @@
from datetime import datetime, time
from sqlalchemy import select, delete from sqlalchemy import select, delete
from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.ext.asyncio import AsyncSession
@@ -41,8 +43,6 @@ class HoursTransactionsDAO:
await self.session.commit() await self.session.commit()
async def get_by_period(self, start_date, end_date) -> list[HoursTransaction]: async def get_by_period(self, start_date, end_date) -> list[HoursTransaction]:
from datetime import datetime, time
start_datetime = datetime.combine(start_date, time.min) start_datetime = datetime.combine(start_date, time.min)
end_datetime = datetime.combine(end_date, time.max) end_datetime = datetime.combine(end_date, time.max)
@@ -2,6 +2,7 @@ from sqlalchemy import select, update, delete
from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.ext.asyncio import AsyncSession
from dutylog.infrastructure.database.models.resident import Resident from dutylog.infrastructure.database.models.resident import Resident
from dutylog.infrastructure.database.models.room import Room
class ResidentsDAO: class ResidentsDAO:
@@ -37,7 +38,6 @@ class ResidentsDAO:
return list(result.scalars().all()) return list(result.scalars().all())
async def search_by_room_number(self, room_number: int) -> list[Resident]: async def search_by_room_number(self, room_number: int) -> list[Resident]:
from dutylog.infrastructure.database.models.room import Room
result = await self.session.execute( result = await self.session.execute(
select(Resident) select(Resident)
.join(Room, Resident.room == Room.id) .join(Room, Resident.room == Room.id)
-1
View File
@@ -43,7 +43,6 @@ class ReportService:
start_date, end_date start_date, end_date
) )
# Разделяем транзакции на личные и комнатные
resident_transactions = [t for t in all_transactions if not t.per_room] resident_transactions = [t for t in all_transactions if not t.per_room]
room_transactions = [t for t in all_transactions if t.per_room] room_transactions = [t for t in all_transactions if t.per_room]