diff --git a/database.py b/database.py index 6daab40..cc022a7 100644 --- a/database.py +++ b/database.py @@ -71,8 +71,8 @@ class Product(TableDeclarativeBase): price = Column(Integer) # Image data image = Column(LargeBinary) - # Product is an option (example: express shipping) - boolean_product = Column(Boolean, nullable=False) + # Product has been deleted + deleted = Column(Boolean, nullable=False) # Stock quantity, if null product has infinite stock stock = Column(Integer) @@ -98,7 +98,7 @@ class Product(TableDeclarativeBase): return f"{escape(self.name)}\n" \ f"{escape(self.description)}\n" \ f"{strings.in_stock_format_string.format(quantity=self.stock) if self.stock is not None else ''}\n" \ - f"{strings.currency_format_string.format(symbol=strings.currency_symbol, value=self.price / (10 ** int(configloader.config['Payments']['currency_exp'])))}\n" \ + f"{str(Price(self.price))}\n" \ f"{strings.in_cart_format_string.format(quantity=cart_qty) if cart_qty is not None else ''}" else: raise ValueError("style is not an accepted value") diff --git a/strings.py b/strings.py index 9decc26..f39e6c1 100644 --- a/strings.py +++ b/strings.py @@ -32,7 +32,10 @@ conversation_open_admin_menu = "Sei un amministratore di greed!\n" \ conversation_payment_method = "Come vuoi aggiungere fondi al tuo portafoglio?" # Conversation: select a product to edit -conversation_admin_select_product = "Che prodotto vuoi modificare?" +conversation_admin_select_product = "✏️ Che prodotto vuoi modificare?" + +# Conversation: select a product to delete +conversation_admin_select_product_to_delete = "❌ Che prodotto vuoi eliminare?" # Conversation: add extra notes to the order conversation_extra_notes = "Che messaggio vuoi lasciare insieme al tuo ordine?" @@ -81,6 +84,9 @@ menu_user_mode = "👤 Passa alla modalità utente" # Admin menu: add product menu_add_product = "✨ Nuovo prodotto" +# Admin menu: delete product +menu_delete_product = "❌ Elimina prodotto" + # Menu: cancel menu_cancel = "🔙 Annulla" @@ -153,6 +159,9 @@ bot_info = 'Questo bot utilizza gree # Success: product has been added/edited to the database success_product_edited = "✅ Il prodotto è stato aggiunto/modificato con successo!" +# Success: product has been added/edited to the database +success_product_deleted = "✅ Il prodotto è stato eliminato con successo!" + # Success: order has been created success_order_created = "✅ L'ordine è stato inviato con successo!" diff --git a/utils.py b/utils.py index 5bc3d31..ff1b39c 100644 --- a/utils.py +++ b/utils.py @@ -12,7 +12,7 @@ class Price: self.value = int(value * (10 ** int(config["Payments"]["currency_exp"]))) elif isinstance(value, str): # Remove decimal points, then cast to int - self.value = int(value.replace(".", "").replace(",", "")) + self.value = int(float(value.replace(",", ".")) * (10 ** int(config["Payments"]["currency_exp"]))) elif isinstance(value, Price): # Copy self self.value = value.value diff --git a/worker.py b/worker.py index 35c30c5..a7974e6 100644 --- a/worker.py +++ b/worker.py @@ -229,7 +229,7 @@ class ChatWorker(threading.Thread): def __order_menu(self): """User menu to order products from the shop.""" # Get the products list from the db - products = self.session.query(db.Product).all() + products = self.session.query(db.Product).filter_by(deleted=False).all() # Create a dict to be used as 'cart' # The key is the message id of the product list cart: typing.Dict[typing.List[db.Product, int]] = {} @@ -246,9 +246,9 @@ class ChatWorker(threading.Thread): inline_keyboard = telegram.InlineKeyboardMarkup([[telegram.InlineKeyboardButton(strings.menu_add_to_cart, callback_data="cart_add")]]) # Edit the sent message and add the inline keyboard if product.image is None: - self.bot.edit_message_text(chat_id=self.chat.id, message_id=message['result']['message_id'], text=str(product), parse_mode="HTML", reply_markup=inline_keyboard) + self.bot.edit_message_text(chat_id=self.chat.id, message_id=message['result']['message_id'], text=product.text(), parse_mode="HTML", reply_markup=inline_keyboard) else: - self.bot.edit_message_caption(chat_id=self.chat.id, message_id=message['result']['message_id'], caption=str(product), parse_mode="HTML", reply_markup=inline_keyboard) + self.bot.edit_message_caption(chat_id=self.chat.id, message_id=message['result']['message_id'], caption=product.text(style="image"), parse_mode="HTML", reply_markup=inline_keyboard) # Create the keyboard with the cancel button inline_keyboard = telegram.InlineKeyboardMarkup([[telegram.InlineKeyboardButton(strings.menu_cancel, callback_data="cart_cancel")]]) # Send a message containing the button to cancel or pay @@ -537,12 +537,13 @@ class ChatWorker(threading.Thread): def __products_menu(self): """Display the admin menu to select a product to edit.""" # Get the products list from the db - products = self.session.query(db.Product).all() + products = self.session.query(db.Product).filter_by(deleted=False).all() # Create a list of product names product_names = [product.name for product in products] - # Insert at the start of the list the add product option and the Cancel option + # Insert at the start of the list the add product option, the remove product option and the Cancel option product_names.insert(0, strings.menu_cancel) product_names.insert(1, strings.menu_add_product) + product_names.insert(2, strings.menu_delete_product) # Create a keyboard using the product names keyboard = [[telegram.KeyboardButton(product_name)] for product_name in product_names] # Send the previously created keyboard to the user (ensuring it can be clicked only 1 time) @@ -558,10 +559,14 @@ class ChatWorker(threading.Thread): elif selection == strings.menu_add_product: # Open the add product menu self.__edit_product_menu() + # If the user has selected the Remove Product option... + elif selection == strings.menu_delete_product: + # Open the delete product menu + self.__delete_product_menu() # If the user has selected a product else: # Find the selected product - product = self.session.query(db.Product).filter_by(name=selection).one() + product = self.session.query(db.Product).filter_by(name=selection, deleted=False).one() # Open the edit menu for that specific product self.__edit_product_menu(product=product) @@ -579,7 +584,7 @@ class ChatWorker(threading.Thread): # Wait for an answer name = self.__wait_for_regex(r"(.*)", cancellable=bool(product)) # Ensure a product with that name doesn't already exist - if (product and isinstance(name, CancelSignal)) or self.session.query(db.Product).filter_by(name=name).one_or_none() in [None, product]: + if (product and isinstance(name, CancelSignal)) or self.session.query(db.Product).filter_by(name=name, deleted=False).one_or_none() in [None, product]: # Exit the loop break self.bot.send_message(self.chat.id, strings.error_duplicate_name) @@ -614,7 +619,7 @@ class ChatWorker(threading.Thread): product = db.Product(name=name, description=description, price=int(price), - boolean_product=False) + deleted=False) # Add the record to the database self.session.add(product) # If a product is being edited... @@ -642,6 +647,32 @@ class ChatWorker(threading.Thread): # Notify the user self.bot.send_message(self.chat.id, strings.success_product_edited) + def __delete_product_menu(self): + # Get the products list from the db + products = self.session.query(db.Product).filter_by(deleted=False).all() + # Create a list of product names + product_names = [product.name for product in products] + # Insert at the start of the list the Cancel button + product_names.insert(0, strings.menu_cancel) + # Create a keyboard using the product names + keyboard = [[telegram.KeyboardButton(product_name)] for product_name in product_names] + # Send the previously created keyboard to the user (ensuring it can be clicked only 1 time) + self.bot.send_message(self.chat.id, strings.conversation_admin_select_product_to_delete, + reply_markup=telegram.ReplyKeyboardMarkup(keyboard, one_time_keyboard=True)) + # Wait for a reply from the user + selection = self.__wait_for_specific_message(product_names) + if selection == strings.menu_cancel: + # Exit the menu + return + else: + # Find the selected product + product = self.session.query(db.Product).filter_by(name=selection, deleted=False).one() + # "Delete" the product by setting the deleted flag to true + product.deleted = True + self.session.commit() + # Notify the user + self.bot.send_message(self.chat.id, strings.success_product_deleted) + def __orders_menu(self): raise NotImplementedError()