Files
telegram-bot-for-manipulate…/app/handlers/orders.py

245 lines
11 KiB
Python
Raw Normal View History

2025-07-27 22:17:28 +03:00
import asyncio
import os
from pathlib import Path
import re
from aiogram import Router, Bot, F
from aiogram.filters import CommandStart, Command
from aiogram.types import Message, CallbackQuery, FSInputFile, InputMediaPhoto, InputMediaVideo, ReplyKeyboardRemove
2025-07-27 22:17:28 +03:00
from aiogram.exceptions import AiogramError
from aiogram.fsm.state import State, StatesGroup
from aiogram.fsm.context import FSMContext
2025-07-27 22:17:28 +03:00
from sqlalchemy import select, insert
from loguru import logger
from filters import IsAdmin
from keyboards import create_inline_kb, commands, button_create
from database import async_session_, Order, Worker
orders_router = Router()
# orders_router.message.filter()
order_operation_base = {"add_order_photo": "Добавить фото",
"get_order_photo": "Получить фото",
"get_order_components": "Получить список комплектующих",
"get_order_documentation": "Получить документацию"
}
order_operation_update = {"add_order_documentation": "Добавить документацию"}
order_main = {"find_orders": "Найти заказ"}
order_main_update = {"create_order": "Создать заказ"}
find_order_params = {"search_by_name": "Поиск по названию", "search_by_description": "Поиск по описанию ",
"search_by_id": "Поиск по номеру заказа", "search_by_customer": "Поиск по заказчику"}
class SearchForm(StatesGroup):
search_option = State()
data_to_search = State()
search_result = State()
class OrderForm(StatesGroup):
id = State()
worker_id = State()
status_id = State()
counterparty = State()
customer = State()
commencement_work = State()
end_work = State()
description = State()
@orders_router.message(Command(commands="orders"))
async def orders_menu(message: Message):
order_main_upd = order_main_update if await IsAdmin()(message) else {}
await message.answer(text="Доступные действия с заказами:",
reply_markup=create_inline_kb(width=1, **order_main, **order_main_upd))
@orders_router.callback_query(lambda x: x.data.startswith("create_order"))
async def get_order_worker_id(callback: CallbackQuery, state: FSMContext):
await state.set_state(OrderForm.worker_id)
async with async_session_() as session:
async with session.begin():
result = await session.execute(select(Worker.name, Worker.telegram_id))
workers = result.all()
await callback.message.answer("Введите сборщика ответственного за заказ:",
reply_markup=create_inline_kb(
**{f"set_worker_in_order_{tg_id}": name for name, tg_id in workers}))
2025-07-27 22:17:28 +03:00
await callback.message.delete()
@orders_router.message(F.text == "❌ Прервать создание заказа")
async def order_description(message: Message, state: FSMContext):
await state.clear()
await message.answer("Создание заказа прервано", reply_markup=ReplyKeyboardRemove())
2025-07-27 22:17:28 +03:00
@orders_router.callback_query(OrderForm.worker_id)
async def get_order_customer(callback: CallbackQuery, state: FSMContext):
worker_tg_id = int(re.search(r"(\d+)", callback.data).group())
await callback.message.answer("Введите данные заказчика ",
reply_markup=button_create(["❌ Прервать создание заказа"]))
await callback.message.delete()
await state.update_data(worker_id=worker_tg_id)
2025-07-27 22:17:28 +03:00
await state.set_state(OrderForm.customer)
# @orders_router.callback_query(OrderForm.counterparty)
# async def get_order_customer(message: Message, state: FSMContext):
#
@orders_router.message(OrderForm.customer)
async def order_description(message: Message, state: FSMContext):
2025-07-27 22:17:28 +03:00
await message.answer("Введите описание заказа в виде ключевых слов (АВР, ПСС, НКУ и т.д.) )")
await message.delete()
2025-07-27 22:17:28 +03:00
await state.update_data(customer=message.text)
await state.set_state(OrderForm.description)
@orders_router.message(OrderForm.description)
async def create_order(message: Message, state: FSMContext):
await state.update_data(description=message.text)
order_ = await state.get_data()
async with async_session_() as session:
async with session.begin():
session.add(Order(**order_))
await state.clear()
await message.answer("Заказ успешно создан ", reply_markup=ReplyKeyboardRemove())
2025-07-27 22:17:28 +03:00
@orders_router.callback_query(lambda x: x.data == "find_orders")
async def find_orders_menu(callback: CallbackQuery, state: FSMContext):
await callback.message.edit_text(text="Выберите параметры поиска:")
await callback.message.edit_reply_markup(reply_markup=create_inline_kb(width=1, **find_order_params))
await state.set_state(SearchForm.search_option)
@orders_router.callback_query(SearchForm.search_option)
async def search_by_item(callback: CallbackQuery, state: FSMContext):
search_option = re.search(r"^search_by_(\w+)", callback.data).group(1)
await state.update_data(search_option=search_option)
await state.set_state(SearchForm.data_to_search)
await callback.message.answer(text="🔍 Введите данные для поиска")
await callback.message.delete()
@orders_router.message(SearchForm.data_to_search)
async def search_by_item(message: Message, state: FSMContext):
async with async_session_() as local_session:
search_opt = await state.get_value("search_option")
col = getattr(Order, search_opt)
result = await local_session.execute(
select(Order).where(col.ilike(f"%{message.text}%") if search_opt != "id" else col == int(message.text)))
selected_orders = result.scalars().all()
2025-07-27 22:17:28 +03:00
if selected_orders:
await message.answer(text="Список найденных заказов: ",
reply_markup=create_inline_kb(width=1, **dict(
(f"show_order_{order.id}", f"Описание: {order.description or "Отсутствует"}"
f"Заказ: №{order.id}\n"
f"Заказчик: {order.customer}\n"
) for order in
selected_orders)))
2025-07-27 22:17:28 +03:00
await state.update_data(search_result=selected_orders)
await state.set_state(SearchForm.search_result)
else:
await message.answer(text="Заказов по вашему запросу не найдено")
await state.clear()
@orders_router.callback_query(SearchForm.search_result)
async def show_order(callback: CallbackQuery, state: FSMContext):
order_id = int(re.search(r"(\d+)", callback.data).group())
try:
async with async_session_() as local_session:
result = await local_session.execute(select(Order).filter(Order.id == order_id))
order = result.scalars().first()
except Exception as err:
logger.warning(err)
order_operation_upd = order_operation_update if await IsAdmin()(callback) else {}
if order:
await callback.message.answer(text=f"Номер заказа: {order.id}\n"
f"Заказчик: {order.customer}\n"
f"Статус: {order.status_id}\n"
f"Дата начала работ: {order.commencement_work}\n"
f"Дата отгрузки: {order.end_work}\n"
f"Дата создания: {order.created_at}\n"
f"Описание: {order.description}",
reply_markup=create_inline_kb(width=2, **dict(
(f"{clbk}_{order.id}", text) for clbk, text in order_operation_base.items()))
)
await callback.message.delete()
await state.clear()
@orders_router.callback_query(lambda x: x.data.startswith("get_order_photo"))
async def send_order_photos(callback: CallbackQuery, bot: Bot):
order_id = callback.data.split("_")[-1]
media_item: Path
media_group = []
os.makedirs(Path(f"./photos/{order_id}/"), exist_ok=True)
media_path = Path(f"./photos/{order_id}/").iterdir()
if not (media_item := next(media_path, None)):
text = f"Фото по заказу \"{order_id}\" отсутствуют "
else:
text = (f"Заказ: №{order_id}\n"
f"")
await bot.send_message(chat_id=callback.from_user.id, text=text)
while media_item or media_group:
if len(media_group) == 10 or (media_group and not media_item):
await bot.send_media_group(chat_id=callback.from_user.id, media=media_group)
media_group.clear()
if media_item:
try:
input_type = InputMediaPhoto if media_item.suffix == ".jpg" else InputMediaVideo
media_group.append(input_type(media=FSInputFile(media_item)))
except Exception as err:
logger.error(f"Ошибка при обработке {media_path}: {err}")
media_item = next(media_path, None)
await asyncio.sleep(600)
await callback.message.delete()
@orders_router.callback_query(lambda x: x.data.startswith("add_order_photo"))
async def reply_for_photo(callback: CallbackQuery, bot: Bot):
await bot.send_message(text=f"Заказ: {callback.data.split("_")[-1]}\n"
"Прикрепите файлы ответив на это сообщение сдвинув его влево, либо выберите 'ответить'",
chat_id=callback.from_user.id)
await callback.message.delete()
@orders_router.message(
F.reply_to_message)
async def add_order_photo(message: Message, bot: Bot):
order_id = re.search(r"(\d+)", message.reply_to_message.text).group()
order_photos_path = f"/app/photos/{order_id}/"
os.makedirs(order_photos_path, exist_ok=True)
item = message.video or message.photo[-1]
file_extension = "jpg" if message.photo else "mp4"
try:
file = await bot.get_file(item.file_id)
await bot.download_file(file.file_path, destination=f"{order_photos_path}/{file.file_id}.{file_extension}",
timeout=3600)
await message.answer(f"Медиа файл {file.file_id[:10]} успешно прикреплен к заказу №{order_id}")
except AiogramError as err:
logger.error(err)
await message.delete()
try:
await bot.delete_message(chat_id=message.chat.id, message_id=message.reply_to_message.message_id)
except:
pass