From 25237f11edc16e7e09a4a655f3bcf89c88ee3687 Mon Sep 17 00:00:00 2001 From: Kseninia Mikhaylova Date: Wed, 17 Jul 2024 16:49:30 +0300 Subject: [PATCH] part of new tg logic --- back/tgbot/admin.py | 4 +- back/tgbot/models.py | 25 ++--- back/tgbot/tgbot.py | 247 +++++++++++++++++++++++++++++-------------- 3 files changed, 178 insertions(+), 98 deletions(-) diff --git a/back/tgbot/admin.py b/back/tgbot/admin.py index 3033ca3..150d3a1 100644 --- a/back/tgbot/admin.py +++ b/back/tgbot/admin.py @@ -1,6 +1,6 @@ from django.contrib import admin -from .models import TgItem, Element +from .models import TgItem, TmcElement # Register your models here. admin.site.register(TgItem) -admin.site.register(Element) \ No newline at end of file +admin.site.register(TmcElement) \ No newline at end of file diff --git a/back/tgbot/models.py b/back/tgbot/models.py index 88eff52..7a3466b 100644 --- a/back/tgbot/models.py +++ b/back/tgbot/models.py @@ -1,7 +1,7 @@ import uuid from django.db import models -from tmc.models import CustomTable +from tmc.models import CustomTable, BaseCustomField import logging @@ -15,15 +15,11 @@ def group_based_upload_to(instance, filename): ) -class Element(models.Model): +class TmcElement(models.Model): tmc = models.ForeignKey(CustomTable, models.RESTRICT) - name = models.CharField() - photoid = models.CharField() - # photo = models.ImageField(null=True, upload_to=group_based_upload_to) - text = models.TextField(blank=True, null=True) - - def __str__(self): - return f"Element {self.tmc} {self.name}" + name = models.CharField(null=True, blank=True) + element = models.ManyToManyField(BaseCustomField) + class TgItem(models.Model): id = models.UUIDField( @@ -35,10 +31,9 @@ class TgItem(models.Model): ) user_id = models.BigIntegerField() name = models.CharField(max_length=255) - # created_at = models.DateTimeField(auto_now_add=True) - # updated_at = models.DateTimeField(auto_now=True) - tmc = models.ManyToManyField(CustomTable) - element = models.ManyToManyField(Element) - + created_at = models.DateTimeField(auto_now_add=True, null=True, blank=True) + updated_at = models.DateTimeField(auto_now=True, null=True, blank=True) + tmc = models.ManyToManyField(TmcElement) + def __str__(self): - return f"Tg item {self.id}" \ No newline at end of file + return f"Tg item {self.id}" diff --git a/back/tgbot/tgbot.py b/back/tgbot/tgbot.py index f5a45fe..9f92361 100644 --- a/back/tgbot/tgbot.py +++ b/back/tgbot/tgbot.py @@ -11,6 +11,8 @@ from telegram import ( ReplyKeyboardMarkup, ReplyKeyboardRemove, KeyboardButton, + InlineKeyboardMarkup, + InlineKeyboardButton, ) from telegram.ext import ( ApplicationBuilder, @@ -26,8 +28,8 @@ from telegram.constants import ParseMode from django.conf import settings from .apps import TgBotUpdater -from .models import Element, TgItem -from tmc.models import CustomTable +from .models import TmcElement, TgItem +from tmc.models import CustomTable, BaseCustomField logger = logging.getLogger(__name__) @@ -39,7 +41,7 @@ def chunk(n, l): class TgBot: _app = None - + def __init__(self) -> None: self.token = settings.TGBOT["TOKEN"] self.baseurl = settings.TGBOT["BASE_URL"] @@ -58,17 +60,24 @@ class TgBot: async def start_app(self): await TgBot.app.initialize() - + async def admin_action(self, name, queryset): pass - + async def set_handlers(self): - TgBot.app.add_handler(CommandHandler("start", self.start, filters.ChatType.PRIVATE)) + TgBot.app.add_handler( + CommandHandler("start", self.start, filters.ChatType.PRIVATE) + ) TgBot.app.add_handler(CommandHandler("my", self.my, filters.ChatType.PRIVATE)) TgBot.app.add_handler(CommandHandler("inv", self.inv, filters.ChatType.PRIVATE)) TgBot.app.add_handler(MessageHandler(filters.ChatType.PRIVATE, self.inv)) + TgBot.app.add_handler(CallbackQueryHandler(self.get_inv, r"get_inv@(.*?)")) + TgBot.app.add_handler(CallbackQueryHandler(self.add_tmc, r"add_tmc@(.*?)")) + TgBot.app.add_handler( + CallbackQueryHandler(self.add_element, r"add_element@(.*?)") + ) TgBot.app.add_error_handler(self.error_handler) - + async def start(self, update: Update, context: CallbackContext): await update.message.reply_markdown_v2( ( @@ -87,122 +96,198 @@ class TgBot: inv = [] async for e in TgItem.objects.filter(user_id=user.id): - inv.append(e.name) + inv.append({"name": e.name, "id": str(e.id)}) keys = chunk(1, inv) + if len(inv) > 0: + await update.message.reply_markdown_v2( + ("Ваши инвентаризации"), + reply_markup=InlineKeyboardMarkup( + [ + [ + InlineKeyboardButton( + i["name"], + callback_data=f'get_inv@{i["id"]}', + ) + for i in arr + ] + for arr in keys + ] + ), + reply_parameters=ReplyParameters(message_id=update.message.message_id), + ) + else: + await update.message.reply_markdown_v2( + "У вас нет доступных для редактирования инвентаризаций" + ) - await update.message.reply_markdown_v2( - ("Ваши инвентаризации"), - reply_markup=ReplyKeyboardMarkup( - [[KeyboardButton(i) for i in arr] for arr in keys] - ), - reply_parameters=ReplyParameters(message_id=update.message.message_id), - ) - if len(inv): - context.chat_data["step"] = "get_inv" + async def get_inv(self, update: Update, context: CallbackContext): + query = update.callback_query + await update.effective_message.edit_reply_markup(InlineKeyboardMarkup([])) + await query.answer() + + inv_id = query.data.split("@")[-1] + inv = await TgItem.objects.aget(id=inv_id) + + context.chat_data["inv"] = inv.id + context.chat_data["step"] = "name" + + await self.inv(update, context) + + async def add_tmc(self, update: Update, context: CallbackContext): + query = update.callback_query + await update.effective_message.edit_reply_markup(InlineKeyboardMarkup([])) + await query.answer() + + tmc_id = query.data.split("@")[-1] + tmc = await CustomTable.objects.aget(id=tmc_id) + inv = await TgItem.objects.aget(id=context.chat_data["inv"]) + + await inv.tmc.aadd(tmc) + + context.chat_data["tmc"] = tmc.id + context.chat_data["step"] = "add_tmc" + + await self.inv(update, context) + + async def add_element(self, update: Update, context: CallbackContext): + query = update.callback_query + await update.effective_message.edit_reply_markup(InlineKeyboardMarkup([])) + await query.answer() + + inv = await TgItem.objects.aget(id=context.chat_data["inv"]) + tmc = await CustomTable.objects.aget(id=context.chat_data["tmc"]) + + field_id = query.data.split("@")[-1] + name = await BaseCustomField.objects.aget(id=field_id) + element = await TmcElement.objects.acreate(name=name, tmc=tmc) + + await inv.element.aadd(element) + + context.chat_data["element"] = element.id + context.chat_data["step"] = "add_element" + + await self.inv(update, context) async def inv(self, update: Update, context: CallbackContext): user = update.effective_user current_step = context.chat_data.get("step", None) - if not update.message: - return True - logger.info(update.message) - logger.info(f"Step {current_step} from user {user.full_name}") - if current_step == "get_inv": - inv = await TgItem.objects.aget(name=update.message.text) - context.chat_data["inv"] = inv.id - context.chat_data["step"] = "name" - current_step = context.chat_data["step"] + logger.info( + f"Step {current_step} from user {user.full_name} in {update.message}" + ) if not current_step and update.message.text == "/inv": - inv = await TgItem.objects.acreate(user_id=user.id) - await update.message.reply_markdown_v2( + context.chat_data["step"] = "name" + await update.effective_message.reply_markdown_v2( ( f"Специалист {user.name or user.full_name}, ID {user.id}\n" - f"Начинаем инвентаризацию `#{inv.id}`\n" f"Введите название объекта" ), - reply_parameters=ReplyParameters(message_id=update.message.message_id), + reply_parameters=ReplyParameters( + message_id=update.effective_message.message_id + ), ) - context.chat_data["inv"] = inv.id - context.chat_data["step"] = "name" elif current_step == "name": - inv = await TgItem.objects.aget(id=context.chat_data["inv"]) - inv.name = update.message.text - await inv.asave() + if not context.chat_data.get("inv", None): + inv = await TgItem.objects.acreate(user_id=user.id) + inv.name = update.message.text + await inv.asave() + else: + inv = await TgItem.objects.aget(id=context.chat_data["inv"]) tmc = [] async for e in CustomTable.objects.all(): - tmc.append(e.name) - keys = chunk(3, tmc) + tmc.append({"name": e.name, "id": e.id}) + keys = chunk(2, tmc) - await update.message.reply_markdown_v2( - ( - f"Инвентаризация `#{inv.id}`\n" - f"Название объекта `{inv.name}`\n" - f"Количество ТМЦ {await inv.tmc.acount()}" - ), - reply_parameters=ReplyParameters(message_id=update.message.message_id), - reply_markup=ReplyKeyboardMarkup( - [[KeyboardButton(i) for i in arr] for arr in keys] - ), - ) - logger.info(tmc) + context.chat_data["inv"] = inv.id context.chat_data["step"] = "add_tmc" - elif current_step == "add_tmc": - tmc_name = update.message.text - tmc = await CustomTable.objects.aget(name=tmc_name) + await update.effective_message.reply_markdown_v2( + ( + f"Инвентаризация `{inv.name}` от `{inv.created_at.strftime('%x')}`\n" + f"Количество ТМЦ {await inv.tmc.acount()}\n\n" + "Выберите, какую ТМЦ вы осматриваете:" + ), + reply_parameters=ReplyParameters( + message_id=update.effective_message.message_id + ), + reply_markup=InlineKeyboardMarkup( + [ + [ + InlineKeyboardButton( + i["name"], + callback_data=f'{context.chat_data["step"]}@{i["id"]}', + ) + for i in arr + ] + for arr in keys + ] + ), + ) + elif current_step == "add_tmc": inv = await TgItem.objects.aget(id=context.chat_data["inv"]) + tmc = await CustomTable.objects.aget(id=context.chat_data["tmc"]) await inv.tmc.aadd(tmc) fields = [] async for e in tmc.fields.all(): - fields.append(e.name) + fields.append({"name": e.name, "id": e.id}) keys = chunk(1, fields) - await update.message.reply_markdown_v2( + context.chat_data["tmc"] = tmc.id + context.chat_data["step"] = "add_element" + + await update.effective_message.reply_markdown_v2( ( - f"Инвентаризация `#{inv.id}`\n" - f"Название объекта `{inv.name}`\n" + f"Инвентаризация `{inv.name}` от `{inv.created_at.strftime('%x')}`\n" + f"Количество ТМЦ {await inv.tmc.acount()}\n\n" f"Название ТМЦ `{tmc.name}`\n" f"Что вы загружаете?" ), - reply_parameters=ReplyParameters(message_id=update.message.message_id), - reply_markup=ReplyKeyboardMarkup( - [[KeyboardButton(i) for i in arr] for arr in keys] + reply_parameters=ReplyParameters( + message_id=update.effective_message.message_id + ), + reply_markup=InlineKeyboardMarkup( + [ + [ + InlineKeyboardButton( + i["name"], + callback_data=f'{context.chat_data["step"]}@{i["id"]}', + ) + for i in arr + ] + for arr in keys + ] ), ) - context.chat_data["tmc"] = tmc.id - context.chat_data["step"] = "add_field" - elif current_step == "add_field": - tmc = await CustomTable.objects.aget(id=context.chat_data["tmc"]) - - element_name = update.message.text - element = await Element.objects.acreate(name=element_name, tmc=tmc) + elif current_step == "add_element": inv = await TgItem.objects.aget(id=context.chat_data["inv"]) - await inv.element.aadd(element) + tmc = inv.tmc.aget(id=context.chat_data["tmc"]) + element = inv.element.aget(id=context.chat_data["element"]) - await update.message.reply_markdown_v2( + context.chat_data["step"] = "add_element_data" + + await update.effective_message.reply_markdown_v2( ( - f"Инвентаризация `#{inv.id}`\n" - f"Название объекта `{inv.name}`\n" + f"Инвентаризация `{inv.name}` от `{inv.created_at.strftime('%x')}`\n" + f"Количество ТМЦ {await inv.tmc.acount()}\n\n" f"Название ТМЦ `{tmc.name}`\n" - f"Название элемента `{element.name}`\n" + f"Элемент `{element.name}`\n" f"Загрузите фото или пришлите текст" ), - reply_parameters=ReplyParameters(message_id=update.message.message_id), + reply_parameters=ReplyParameters( + message_id=update.effective_message.message_id + ), reply_markup=ReplyKeyboardRemove(), ) - context.chat_data["element"] = element.id - context.chat_data["step"] = "add_field_data" - elif current_step == "add_field_data": + elif current_step == "add_element_data": inv = await TgItem.objects.aget(id=context.chat_data["inv"]) - tmc = await CustomTable.objects.aget(id=inv.tmc) - element = await Element.objects.aget(id=inv.element) + tmc = inv.tmc.aget(id=context.chat_data["tmc"]) + element = inv.element.aget(id=context.chat_data["element"]) if update.message.photo: element.photoid = update.message.photo[-1].file_id @@ -213,17 +298,17 @@ class TgBot: await update.message.reply_markdown_v2( ( - f"Инвентаризация `#{inv.id}`\n" - f"Название объекта `{inv.name}`\n" + f"Инвентаризация `{inv.name}` от `{inv.created_at.strftime('%x')}`\n" + f"Количество ТМЦ {await inv.tmc.acount()}\n\n" f"Название ТМЦ `{tmc.name}`\n" - f"Название элемента `{element.name}`\n" + f"Элемент `{element.name}`\n" f"Данные загружены" ), reply_parameters=ReplyParameters(message_id=update.message.message_id), reply_markup=ReplyKeyboardRemove(), ) context.chat_data["element"] = element.id - context.chat_data["step"] = "add_field_data" + context.chat_data["step"] = "add_element_data" else: logger.info(update.message.entities) logger.info(f"no step for update {update}")