Files
telegram-bot-for-manipulate…/app/handlers/orders.py
ronis_0505 6549c3d70b
All checks were successful
continuous-integration/drone/push Build is passing
fix state value
2025-09-26 22:21:47 +03:00

217 lines
11 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import os
import re
from pathlib import Path
from aiogram import Router, Bot, F
from aiogram.filters import Command
from aiogram.types import Message, CallbackQuery, FSInputFile, InputMediaPhoto, InputMediaVideo, ReplyKeyboardRemove
from aiogram.exceptions import AiogramError
from aiogram.fsm.context import FSMContext
from sqlalchemy import select
from loguru import logger
from keyboards import create_inline_kb, button_create
from database import async_session_, Order, Worker
from FSM import SearchForm, OrderForm
orders_router = Router()
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": "Найти заказ", "create_order": "Создать заказ"}
order_main_update = {"create_order": "Создать заказ"}
find_order_params = {"search_by_name": "Поиск по названию", "search_by_description": "Поиск по описанию ",
"search_by_id": "Поиск по номеру заказа", "search_by_customer": "Поиск по заказчику"}
@orders_router.message(Command(commands="orders"))
async def orders_menu(message: Message):
await message.answer(text="Доступные действия с заказами:",
reply_markup=create_inline_kb(width=1, **order_main))
await message.delete()
@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:
result = await session.execute(select(Worker.name, Worker.telegram_id).where(Worker.job_title == "Сборщик"))
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}))
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())
@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)
await state.set_state(OrderForm.customer)
@orders_router.message(OrderForm.customer)
async def order_description(message: Message, state: FSMContext):
await message.answer("Введите описание заказа в виде ключевых слов (АВР, ПСС, НКУ и т.д.) )")
await message.delete()
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())
@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()
if selected_orders:
await message.answer(text="Список найденных заказов: ")
sent_messages = []
for order in selected_orders:
sent_messages.append(await message.answer(text=f"Номер заказа: {order.id}\n"
f"Заказчик: {order.customer}\n"
f"Статус: {order.status_id}\n"
f"Дата отгрузки: {order.end_work}\n"
f"Дата создания: {order.created_at}\n"
f"Описание: {order.description}",
reply_markup=create_inline_kb(width=1, **{
f"show_order_{order.id}": f"Заказ: №{order.id}"})))
await state.update_data(sent_messages=sent_messages)
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 and (lambda x: "show_order_" in x.data))
async def show_order(callback: CallbackQuery, state: FSMContext, bot: Bot):
order_id = int(re.search(r"(\d+)", callback.data).group())
order = next(filter(lambda item: order_id == item.id, await state.get_value("selected_orders")), None)
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()))
)
for message in await state.get_value("sent_messages"):
await bot.delete_message(chat_id=callback.message.chat.id, message_id=message.message_id)
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_group = []
order_photos_path = Path(f"/app/photos/{order_id}/")
os.makedirs(order_photos_path, exist_ok=True)
media_path = order_photos_path.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 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)
try:
await callback.message.delete()
except:
pass
@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 = 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