show all photos immediately on transaction detail, remove All Photos button, fix bot KeyError

This commit is contained in:
2026-07-15 00:59:23 +03:00
parent 6d5608343a
commit ccd06c99b0
4 changed files with 64 additions and 204 deletions
@@ -1,13 +1,10 @@
from aiogram import Bot from aiogram import Bot
from aiogram.enums import ContentType
from aiogram.types import Message, CallbackQuery, InputMediaPhoto from aiogram.types import Message, CallbackQuery, InputMediaPhoto
from aiogram.utils.markdown import html_decoration as hd from aiogram.utils.markdown import html_decoration as hd
from aiogram_dialog import Window, DialogManager from aiogram_dialog import 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, ScrollingGroup, Select, Group from aiogram_dialog.widgets.kbd import Row, SwitchTo, Button, ScrollingGroup, Select, Group
from aiogram_dialog.widgets.input import MessageInput from aiogram_dialog.widgets.input import MessageInput
from aiogram_dialog.widgets.media import DynamicMedia
from aiogram_dialog.api.entities.media import MediaAttachment, MediaId
from magic_filter import F from magic_filter import F
from dishka import FromDishka from dishka import FromDishka
from dishka.integrations.aiogram_dialog import inject from dishka.integrations.aiogram_dialog import inject
@@ -628,9 +625,23 @@ async def on_transaction_selected(
callback: CallbackQuery, callback: CallbackQuery,
widget: Select, widget: Select,
dialog_manager: DialogManager, dialog_manager: DialogManager,
transactions_repository: FromDishka[HoursTransactionsRepository],
item_id: str, item_id: str,
): ):
dialog_manager.dialog_data["selected_transaction_id"] = int(item_id) dialog_manager.dialog_data["selected_transaction_id"] = int(item_id)
tx = await transactions_repository.get_transaction_by_id(int(item_id))
if tx:
photo_file_ids = HoursTransactionsRepository.get_photo_file_ids(tx)
if photo_file_ids:
bot: Bot = dialog_manager.middleware_data.get("bot")
try:
if len(photo_file_ids) == 1:
await bot.send_photo(callback.message.chat.id, photo_file_ids[0])
else:
media = [InputMediaPhoto(media=fid) for fid in photo_file_ids]
await bot.send_media_group(callback.message.chat.id, media=media)
except Exception:
pass
await dialog_manager.switch_to(AdminMenuSG.resident_history_detail) await dialog_manager.switch_to(AdminMenuSG.resident_history_detail)
@@ -645,12 +656,12 @@ async def get_transaction_detail_data(
tx_id = dialog_manager.dialog_data.get("selected_transaction_id") tx_id = dialog_manager.dialog_data.get("selected_transaction_id")
if not tx_id: if not tx_id:
return {"detail_content": "Ошибка: транзакция не выбрана", "photo_media": None, "has_multiple_photos": False, "photo_count": 0} return {"detail_content": "Ошибка: транзакция не выбрана"}
tx = await transactions_repository.get_transaction_by_id(int(tx_id)) tx = await transactions_repository.get_transaction_by_id(int(tx_id))
if not tx: if not tx:
return {"detail_content": "Ошибка: транзакция не найдена", "photo_media": None, "has_multiple_photos": False, "photo_count": 0} return {"detail_content": "Ошибка: транзакция не найдена"}
operation = "Начислено" if tx.transaction_type == "increase" else "Списано" operation = "Начислено" if tx.transaction_type == "increase" else "Списано"
emoji = "+" if tx.transaction_type == "increase" else "" emoji = "+" if tx.transaction_type == "increase" else ""
@@ -674,50 +685,11 @@ async def get_transaction_detail_data(
📅 <b>Дата:</b> {date_str}{remark_text}{admin_info} 📅 <b>Дата:</b> {date_str}{remark_text}{admin_info}
""" """
photo_file_ids = HoursTransactionsRepository.get_photo_file_ids(tx)
photo_media = None
if photo_file_ids:
photo_media = MediaAttachment(
type=ContentType.PHOTO,
file_id=MediaId(file_id=photo_file_ids[0]),
)
return { return {
"detail_content": content, "detail_content": content,
"photo_media": photo_media,
"has_multiple_photos": len(photo_file_ids) > 1,
"photo_count": len(photo_file_ids),
} }
@inject
async def on_show_all_photos(
callback: CallbackQuery,
button: Button,
dialog_manager: DialogManager,
transactions_repository: FromDishka[HoursTransactionsRepository],
**kwargs,
):
tx_id = dialog_manager.dialog_data.get("selected_transaction_id")
if not tx_id:
return
tx = await transactions_repository.get_transaction_by_id(int(tx_id))
if not tx:
return
photo_file_ids = HoursTransactionsRepository.get_photo_file_ids(tx)
if len(photo_file_ids) <= 1:
return
bot: Bot = kwargs["bot"]
media = [InputMediaPhoto(media=file_id) for file_id in photo_file_ids]
try:
await bot.send_media_group(callback.message.chat.id, media=media)
except Exception:
pass
async def on_search_transactions( async def on_search_transactions(
callback: CallbackQuery, callback: CallbackQuery,
button: Button, button: Button,
@@ -1140,14 +1112,7 @@ resident_history_window = Window(
) )
resident_history_detail_window = Window( resident_history_detail_window = Window(
DynamicMedia("photo_media"),
Format("{detail_content}"), Format("{detail_content}"),
Button(
Format("📷 Все фото ({photo_count})"),
id="show_all_photos_btn",
on_click=on_show_all_photos,
when="has_multiple_photos",
),
SwitchTo( SwitchTo(
Const("◀️ К списку"), Const("◀️ К списку"),
id="back_to_history_from_detail", id="back_to_history_from_detail",
@@ -1,15 +1,12 @@
import json import json
from aiogram import Bot from aiogram import Bot
from aiogram.enums import ContentType
from aiogram.exceptions import TelegramBadRequest, TelegramForbiddenError, TelegramRetryAfter from aiogram.exceptions import TelegramBadRequest, TelegramForbiddenError, TelegramRetryAfter
from aiogram.types import Message, CallbackQuery, InputMediaPhoto from aiogram.types import Message, CallbackQuery, InputMediaPhoto
from aiogram_dialog import Window, DialogManager from aiogram_dialog import Window, DialogManager
from aiogram_dialog.widgets.text import Format, Const from aiogram_dialog.widgets.text import Format, Const
from aiogram_dialog.widgets.kbd import SwitchTo, Button, ScrollingGroup, Select, Row, Group from aiogram_dialog.widgets.kbd import SwitchTo, Button, ScrollingGroup, Select, Row, Group
from aiogram_dialog.widgets.input import MessageInput from aiogram_dialog.widgets.input import MessageInput
from aiogram_dialog.widgets.media import DynamicMedia
from aiogram_dialog.api.entities.media import MediaAttachment, MediaId
from dishka import FromDishka from dishka import FromDishka
from dishka.integrations.aiogram_dialog import inject from dishka.integrations.aiogram_dialog import inject
@@ -509,40 +506,26 @@ async def on_room_transaction_selected(
callback: CallbackQuery, callback: CallbackQuery,
widget: Select, widget: Select,
dialog_manager: DialogManager, dialog_manager: DialogManager,
transactions_repository: FromDishka[HoursTransactionsRepository],
item_id: str, item_id: str,
): ):
dialog_manager.dialog_data["selected_transaction_id"] = int(item_id) dialog_manager.dialog_data["selected_transaction_id"] = int(item_id)
tx = await transactions_repository.get_transaction_by_id(int(item_id))
if tx:
photo_file_ids = HoursTransactionsRepository.get_photo_file_ids(tx)
if photo_file_ids:
bot: Bot = dialog_manager.middleware_data.get("bot")
try:
if len(photo_file_ids) == 1:
await bot.send_photo(callback.message.chat.id, photo_file_ids[0])
else:
media = [InputMediaPhoto(media=fid) for fid in photo_file_ids]
await bot.send_media_group(callback.message.chat.id, media=media)
except Exception:
pass
await dialog_manager.switch_to(AdminMenuSG.room_history_detail) await dialog_manager.switch_to(AdminMenuSG.room_history_detail)
@inject
async def on_show_room_all_photos(
callback: CallbackQuery,
button: Button,
dialog_manager: DialogManager,
transactions_repository: FromDishka[HoursTransactionsRepository],
**kwargs,
):
tx_id = dialog_manager.dialog_data.get("selected_transaction_id")
if not tx_id:
return
tx = await transactions_repository.get_transaction_by_id(int(tx_id))
if not tx:
return
photo_file_ids = HoursTransactionsRepository.get_photo_file_ids(tx)
if len(photo_file_ids) <= 1:
return
bot: Bot = kwargs["bot"]
media = [InputMediaPhoto(media=file_id) for file_id in photo_file_ids]
try:
await bot.send_media_group(callback.message.chat.id, media=media)
except Exception:
pass
@inject @inject
async def get_room_transaction_detail_data( async def get_room_transaction_detail_data(
dialog_manager: DialogManager, dialog_manager: DialogManager,
@@ -553,12 +536,12 @@ async def get_room_transaction_detail_data(
tx_id = dialog_manager.dialog_data.get("selected_transaction_id") tx_id = dialog_manager.dialog_data.get("selected_transaction_id")
if not tx_id: if not tx_id:
return {"detail_content": "Ошибка: транзакция не выбрана", "photo_media": None, "has_multiple_photos": False, "photo_count": 0} return {"detail_content": "Ошибка: транзакция не выбрана"}
tx = await transactions_repository.get_transaction_by_id(int(tx_id)) tx = await transactions_repository.get_transaction_by_id(int(tx_id))
if not tx: if not tx:
return {"detail_content": "Ошибка: транзакция не найдена", "photo_media": None, "has_multiple_photos": False, "photo_count": 0} return {"detail_content": "Ошибка: транзакция не найдена"}
operation = "Начислено" if tx.transaction_type == "increase" else "Списано" operation = "Начислено" if tx.transaction_type == "increase" else "Списано"
emoji = "+" if tx.transaction_type == "increase" else "" emoji = "+" if tx.transaction_type == "increase" else ""
@@ -582,19 +565,8 @@ async def get_room_transaction_detail_data(
📅 <b>Дата:</b> {date_str}{remark_text}{admin_info} 📅 <b>Дата:</b> {date_str}{remark_text}{admin_info}
""" """
photo_file_ids = HoursTransactionsRepository.get_photo_file_ids(tx)
photo_media = None
if photo_file_ids:
photo_media = MediaAttachment(
type=ContentType.PHOTO,
file_id=MediaId(file_id=photo_file_ids[0]),
)
return { return {
"detail_content": content, "detail_content": content,
"photo_media": photo_media,
"has_multiple_photos": len(photo_file_ids) > 1,
"photo_count": len(photo_file_ids),
} }
@@ -837,14 +809,7 @@ room_history_window = Window(
) )
room_history_detail_window = Window( room_history_detail_window = Window(
DynamicMedia("photo_media"),
Format("{detail_content}"), Format("{detail_content}"),
Button(
Format("📷 Все фото ({photo_count})"),
id="show_room_all_photos_btn",
on_click=on_show_room_all_photos,
when="has_multiple_photos",
),
SwitchTo( SwitchTo(
Const("◀️ К списку"), Const("◀️ К списку"),
id="back_to_room_history_from_detail", id="back_to_room_history_from_detail",
@@ -1,13 +1,10 @@
import json import json
from aiogram import Bot from aiogram import Bot
from aiogram.enums import ContentType
from aiogram.types import CallbackQuery, InputMediaPhoto from aiogram.types import CallbackQuery, InputMediaPhoto
from aiogram_dialog import Window from aiogram_dialog import Window
from aiogram_dialog.widgets.text import Format, Const from aiogram_dialog.widgets.text import Format, Const
from aiogram_dialog.widgets.kbd import SwitchTo, ScrollingGroup, Select, Button from aiogram_dialog.widgets.kbd import SwitchTo, ScrollingGroup, Select, Button
from aiogram_dialog.widgets.media import DynamicMedia
from aiogram_dialog.api.entities.media import MediaAttachment, MediaId
from dishka import FromDishka from dishka import FromDishka
from dishka.integrations.aiogram_dialog import inject from dishka.integrations.aiogram_dialog import inject
@@ -76,40 +73,26 @@ async def on_creator_transaction_selected(
callback: CallbackQuery, callback: CallbackQuery,
widget: Select, widget: Select,
dialog_manager, dialog_manager,
transactions_repository: FromDishka[HoursTransactionsRepository],
item_id: str, item_id: str,
): ):
dialog_manager.dialog_data["selected_transaction_id"] = int(item_id) dialog_manager.dialog_data["selected_transaction_id"] = int(item_id)
tx = await transactions_repository.get_transaction_by_id(int(item_id))
if tx:
photo_file_ids = HoursTransactionsRepository.get_photo_file_ids(tx)
if photo_file_ids:
bot: Bot = dialog_manager.middleware_data.get("bot")
try:
if len(photo_file_ids) == 1:
await bot.send_photo(callback.message.chat.id, photo_file_ids[0])
else:
media = [InputMediaPhoto(media=fid) for fid in photo_file_ids]
await bot.send_media_group(callback.message.chat.id, media=media)
except Exception:
pass
await dialog_manager.switch_to(AdminMenuSG.transactions_history_detail) await dialog_manager.switch_to(AdminMenuSG.transactions_history_detail)
@inject
async def on_show_creator_all_photos(
callback: CallbackQuery,
button: Button,
dialog_manager,
transactions_repository: FromDishka[HoursTransactionsRepository],
**kwargs,
):
tx_id = dialog_manager.dialog_data.get("selected_transaction_id")
if not tx_id:
return
tx = await transactions_repository.get_transaction_by_id(int(tx_id))
if not tx:
return
photo_file_ids = HoursTransactionsRepository.get_photo_file_ids(tx)
if len(photo_file_ids) <= 1:
return
bot: Bot = kwargs["bot"]
media = [InputMediaPhoto(media=file_id) for file_id in photo_file_ids]
try:
await bot.send_media_group(callback.message.chat.id, media=media)
except Exception:
pass
@inject @inject
async def get_transaction_detail_data( async def get_transaction_detail_data(
dialog_manager, dialog_manager,
@@ -122,12 +105,12 @@ async def get_transaction_detail_data(
tx_id = dialog_manager.dialog_data.get("selected_transaction_id") tx_id = dialog_manager.dialog_data.get("selected_transaction_id")
if not tx_id: if not tx_id:
return {"detail_content": "Ошибка: транзакция не выбрана", "photo_media": None, "has_multiple_photos": False, "photo_count": 0} return {"detail_content": "Ошибка: транзакция не выбрана"}
tx = await transactions_repository.get_transaction_by_id(int(tx_id)) tx = await transactions_repository.get_transaction_by_id(int(tx_id))
if not tx: if not tx:
return {"detail_content": "Ошибка: транзакция не найдена", "photo_media": None, "has_multiple_photos": False, "photo_count": 0} return {"detail_content": "Ошибка: транзакция не найдена"}
operation = "Начислено" if tx.transaction_type == "increase" else "Списано" operation = "Начислено" if tx.transaction_type == "increase" else "Списано"
emoji = "+" if tx.transaction_type == "increase" else "" emoji = "+" if tx.transaction_type == "increase" else ""
@@ -159,19 +142,8 @@ async def get_transaction_detail_data(
📅 <b>Дата:</b> {date_str}{remark_text} 📅 <b>Дата:</b> {date_str}{remark_text}
""" """
photo_file_ids = HoursTransactionsRepository.get_photo_file_ids(tx)
photo_media = None
if photo_file_ids:
photo_media = MediaAttachment(
type=ContentType.PHOTO,
file_id=MediaId(file_id=photo_file_ids[0]),
)
return { return {
"detail_content": content, "detail_content": content,
"photo_media": photo_media,
"has_multiple_photos": len(photo_file_ids) > 1,
"photo_count": len(photo_file_ids),
} }
@@ -200,14 +172,7 @@ transactions_history_window = Window(
) )
transactions_history_detail_window = Window( transactions_history_detail_window = Window(
DynamicMedia("photo_media"),
Format("{detail_content}"), Format("{detail_content}"),
Button(
Format("📷 Все фото ({photo_count})"),
id="show_creator_all_photos_btn",
on_click=on_show_creator_all_photos,
when="has_multiple_photos",
),
SwitchTo( SwitchTo(
Const("◀️ К списку"), Const("◀️ К списку"),
id="back_to_transactions_from_detail", id="back_to_transactions_from_detail",
@@ -1,11 +1,8 @@
from aiogram import Bot from aiogram import Bot
from aiogram.enums import ContentType
from aiogram.types import User, CallbackQuery, InputMediaPhoto from aiogram.types import User, CallbackQuery, InputMediaPhoto
from aiogram_dialog import Window from aiogram_dialog import Window
from aiogram_dialog.widgets.text import Format, Const from aiogram_dialog.widgets.text import Format, Const
from aiogram_dialog.widgets.kbd import Back, ScrollingGroup, Select, SwitchTo, Button from aiogram_dialog.widgets.kbd import Back, ScrollingGroup, Select, SwitchTo, Button
from aiogram_dialog.widgets.media import DynamicMedia
from aiogram_dialog.api.entities.media import MediaAttachment, MediaId
from dishka import FromDishka from dishka import FromDishka
from dishka.integrations.aiogram_dialog import inject from dishka.integrations.aiogram_dialog import inject
@@ -70,40 +67,26 @@ async def on_user_transaction_selected(
callback: CallbackQuery, callback: CallbackQuery,
widget: Select, widget: Select,
dialog_manager, dialog_manager,
transactions_repository: FromDishka[HoursTransactionsRepository],
item_id: str, item_id: str,
): ):
dialog_manager.dialog_data["selected_transaction_id"] = int(item_id) dialog_manager.dialog_data["selected_transaction_id"] = int(item_id)
tx = await transactions_repository.get_transaction_by_id(int(item_id))
if tx:
photo_file_ids = HoursTransactionsRepository.get_photo_file_ids(tx)
if photo_file_ids:
bot: Bot = dialog_manager.middleware_data.get("bot")
try:
if len(photo_file_ids) == 1:
await bot.send_photo(callback.message.chat.id, photo_file_ids[0])
else:
media = [InputMediaPhoto(media=fid) for fid in photo_file_ids]
await bot.send_media_group(callback.message.chat.id, media=media)
except Exception:
pass
await dialog_manager.switch_to(MainMenuSG.history_detail) await dialog_manager.switch_to(MainMenuSG.history_detail)
@inject
async def on_show_user_all_photos(
callback: CallbackQuery,
button: Button,
dialog_manager,
transactions_repository: FromDishka[HoursTransactionsRepository],
**kwargs,
):
tx_id = dialog_manager.dialog_data.get("selected_transaction_id")
if not tx_id:
return
tx = await transactions_repository.get_transaction_by_id(int(tx_id))
if not tx:
return
photo_file_ids = HoursTransactionsRepository.get_photo_file_ids(tx)
if len(photo_file_ids) <= 1:
return
bot: Bot = kwargs["bot"]
media = [InputMediaPhoto(media=file_id) for file_id in photo_file_ids]
try:
await bot.send_media_group(callback.message.chat.id, media=media)
except Exception:
pass
@inject @inject
async def get_history_detail_data( async def get_history_detail_data(
event_from_user: User, event_from_user: User,
@@ -116,12 +99,12 @@ async def get_history_detail_data(
tx_id = dialog_manager.dialog_data.get("selected_transaction_id") tx_id = dialog_manager.dialog_data.get("selected_transaction_id")
if not tx_id: if not tx_id:
return {"detail_content": "Ошибка: транзакция не выбрана", "photo_media": None, "has_multiple_photos": False, "photo_count": 0} return {"detail_content": "Ошибка: транзакция не выбрана"}
tx = await transactions_repository.get_transaction_by_id(int(tx_id)) tx = await transactions_repository.get_transaction_by_id(int(tx_id))
if not tx: if not tx:
return {"detail_content": "Ошибка: транзакция не найдена", "photo_media": None, "has_multiple_photos": False, "photo_count": 0} return {"detail_content": "Ошибка: транзакция не найдена"}
operation = "Начислено" if tx.transaction_type == "increase" else "Списано" operation = "Начислено" if tx.transaction_type == "increase" else "Списано"
emoji = "+" if tx.transaction_type == "increase" else "" emoji = "+" if tx.transaction_type == "increase" else ""
@@ -145,19 +128,8 @@ async def get_history_detail_data(
📅 <b>Дата:</b> {date_str}{remark_text}{admin_info} 📅 <b>Дата:</b> {date_str}{remark_text}{admin_info}
""" """
photo_file_ids = HoursTransactionsRepository.get_photo_file_ids(tx)
photo_media = None
if photo_file_ids:
photo_media = MediaAttachment(
type=ContentType.PHOTO,
file_id=MediaId(file_id=photo_file_ids[0]),
)
return { return {
"detail_content": content, "detail_content": content,
"photo_media": photo_media,
"has_multiple_photos": len(photo_file_ids) > 1,
"photo_count": len(photo_file_ids),
} }
@@ -182,14 +154,7 @@ history_window = Window(
) )
history_detail_window = Window( history_detail_window = Window(
DynamicMedia("photo_media"),
Format("{detail_content}"), Format("{detail_content}"),
Button(
Format("📷 Все фото ({photo_count})"),
id="show_user_all_photos_btn",
on_click=on_show_user_all_photos,
when="has_multiple_photos",
),
SwitchTo( SwitchTo(
Const("◀️ К списку"), Const("◀️ К списку"),
id="back_to_history_from_detail", id="back_to_history_from_detail",