feat: выбор формата массовой генерации (один XML или множество)

This commit is contained in:
admin i 2025-11-06 14:00:08 +03:00
parent 107c5a82c3
commit b29bf9a354

207
bot.py
View File

@ -56,8 +56,9 @@ logger = logging.getLogger(__name__)
SELECT_FORMAT,
SELECT_TEMPLATE,
DOWNLOAD_DOCUMENT,
BATCH_INPUT
) = range(11)
BATCH_INPUT,
BATCH_FORMAT_CHOICE
) = range(12)
# Менеджер пользователей
user_manager = UserManager()
@ -1307,8 +1308,7 @@ async def batch_generation_prompt(
"Примеры:\n"
" <code>4926,4927,4928</code>\n"
" <code>00001,00002,00003</code>\n\n"
"⚠️ Все отгрузки будут объединены в один XML файл "
"(EnterpriseData 1.20).",
"Максимум 50 отгрузок за раз.",
parse_mode='HTML',
reply_markup=ReplyKeyboardMarkup(
[["⬅️ Назад"]],
@ -1319,11 +1319,11 @@ async def batch_generation_prompt(
return BATCH_INPUT
async def batch_generation_process(
async def batch_format_choice(
update: Update,
context: ContextTypes.DEFAULT_TYPE
):
"""Обработка массовой генерации"""
"""Выбор формата генерации: один файл или множество"""
user_id = update.effective_user.id
text = update.message.text.strip()
@ -1354,9 +1354,72 @@ async def batch_generation_process(
)
return BATCH_INPUT
# Сохраняем номера в контекст
context.user_data['batch_order_numbers'] = order_numbers
# Предлагаем выбор формата
keyboard = [
["📄 Один файл (все документы)"],
["📑 Отдельные файлы (каждый документ)"],
["⬅️ Назад"]
]
await update.message.reply_text(
f"✅ Будет обработано отгрузок: <b>{len(order_numbers)}</b>\n\n"
"Выберите формат генерации:",
parse_mode='HTML',
reply_markup=ReplyKeyboardMarkup(keyboard, resize_keyboard=True)
)
return BATCH_FORMAT_CHOICE
async def batch_generation_process(
update: Update,
context: ContextTypes.DEFAULT_TYPE
):
"""Обработка массовой генерации"""
user_id = update.effective_user.id
text = update.message.text.strip()
# Проверка на отмену
if text == "⬅️ Назад":
await update.message.reply_text(
"Массовая генерация отменена.",
reply_markup=get_main_keyboard()
)
return MAIN_MENU
# Определяем режим генерации
if text == "📄 Один файл (все документы)":
batch_mode = True
elif text == "📑 Отдельные файлы (каждый документ)":
batch_mode = False
else:
await update.message.reply_text(
"❌ Неверный выбор. Попробуйте ещё раз:",
parse_mode='HTML'
)
return BATCH_FORMAT_CHOICE
# Получаем сохранённые номера
order_numbers = context.user_data.get('batch_order_numbers', [])
if not order_numbers:
await update.message.reply_text(
"❌ Ошибка: номера отгрузок не найдены. "
"Начните заново.",
reply_markup=get_main_keyboard()
)
return MAIN_MENU
# Уведомление о начале обработки
mode_text = (
"один общий файл" if batch_mode
else f"{len(order_numbers)} отдельных файлов"
)
progress_msg = await update.message.reply_text(
f"⏳ Обработка {len(order_numbers)} отгрузок...\n"
f"Режим: {mode_text}\n\n"
f"Это может занять некоторое время."
)
@ -1372,7 +1435,8 @@ async def batch_generation_process(
try:
# Обновляем прогресс
await progress_msg.edit_text(
f"⏳ Обработка отгрузки {idx}/{len(order_numbers)}: {order_num}"
f"⏳ Обработка отгрузки {idx}/{len(order_numbers)}: "
f"{order_num}"
)
# Поиск отгрузки
@ -1399,7 +1463,9 @@ async def batch_generation_process(
# Проверка результатов
if not orders_data:
error_text = "❌ <b>Не удалось обработать ни одной отгрузки</b>\n\n"
error_text = (
"❌ <b>Не удалось обработать ни одной отгрузки</b>\n\n"
)
if not_found:
error_text += f"Не найдено: {', '.join(not_found)}\n"
if errors:
@ -1428,39 +1494,89 @@ async def batch_generation_process(
output_dir = Path("temp_documents")
output_dir.mkdir(exist_ok=True)
# Генерируем пакетный XML
xml_filename = f"batch_{len(orders_data)}_orders.xml"
xml_path = str(output_dir / xml_filename)
xml_gen.generate_batch_realization(orders_data, xml_path)
# Формируем отчёт
order_names = [
od['order'].get('name', 'N/A')
for od in orders_data
]
caption = (
f"✅ <b>Пакетный XML создан!</b>\n\n"
f"📦 Документов: {len(orders_data)}\n"
f"📋 Отгрузки: {', '.join(order_names)}\n\n"
)
if not_found:
caption += f"⚠️ Не найдено: {', '.join(not_found)}\n"
if errors:
caption += f"⚠️ Ошибок: {len(errors)}\n"
caption += "\n📄 Формат: 1С EnterpriseData 1.20"
# Отправляем файл
await update.message.reply_document(
document=open(xml_path, 'rb'),
caption=caption,
parse_mode='HTML'
)
# Удаляем временный файл
os.remove(xml_path)
if batch_mode:
# ОДИН ФАЙЛ - все документы в одном XML
xml_filename = f"batch_{len(orders_data)}_orders.xml"
xml_path = str(output_dir / xml_filename)
xml_gen.generate_batch_realization(orders_data, xml_path)
# Формируем отчёт
order_names = [
od['order'].get('name', 'N/A')
for od in orders_data
]
caption = (
f"✅ <b>Пакетный XML создан!</b>\n\n"
f"📦 Документов: {len(orders_data)}\n"
f"📋 Отгрузки: {', '.join(order_names)}\n\n"
)
if not_found:
caption += f"⚠️ Не найдено: {', '.join(not_found)}\n"
if errors:
caption += f"⚠️ Ошибок: {len(errors)}\n"
caption += "\n📄 Формат: 1С EnterpriseData 1.20"
# Отправляем файл
await update.message.reply_document(
document=open(xml_path, 'rb'),
caption=caption,
parse_mode='HTML'
)
# Удаляем временный файл
os.remove(xml_path)
else:
# МНОЖЕСТВО ФАЙЛОВ - каждый документ отдельно
generated_files = []
for idx, order_data in enumerate(orders_data, 1):
order_name = order_data['order'].get('name', f'order_{idx}')
xml_filename = f"order_{order_name}.xml"
xml_path = str(output_dir / xml_filename)
# Генерируем отдельный XML
xml_gen.generate_realization(order_data, xml_path)
generated_files.append((xml_path, order_name))
# Отправляем все файлы
await progress_msg.edit_text(
f"✅ Сгенерировано {len(generated_files)} файлов\n"
f"⏳ Отправка..."
)
for xml_path, order_name in generated_files:
caption = (
f"📄 <b>Отгрузка {order_name}</b>\n"
f"Формат: 1С EnterpriseData 1.20"
)
await update.message.reply_document(
document=open(xml_path, 'rb'),
caption=caption,
parse_mode='HTML'
)
# Удаляем временный файл
os.remove(xml_path)
# Итоговая статистика
summary = (
f"✅ <b>Массовая генерация завершена!</b>\n\n"
f"📦 Отправлено файлов: {len(generated_files)}\n"
)
if not_found:
summary += f"⚠️ Не найдено: {', '.join(not_found)}\n"
if errors:
summary += f"⚠️ Ошибок: {len(errors)}\n"
await update.message.reply_text(
summary,
parse_mode='HTML'
)
# Показываем главное меню
await update.message.reply_text(
@ -1470,6 +1586,9 @@ async def batch_generation_process(
await progress_msg.delete()
# Очищаем контекст
context.user_data.pop('batch_order_numbers', None)
return MAIN_MENU
except Exception as e:
@ -1580,6 +1699,12 @@ def main():
MessageHandler(filters.TEXT & ~filters.COMMAND, handle_text),
],
BATCH_INPUT: [
MessageHandler(
filters.TEXT & ~filters.COMMAND,
batch_format_choice
),
],
BATCH_FORMAT_CHOICE: [
MessageHandler(
filters.TEXT & ~filters.COMMAND,
batch_generation_process