mirror of
https://github.com/Steffo99/greed.git
synced 2025-02-16 13:43:58 +00:00
Order products (temp version)
This commit is contained in:
parent
c97dcaeef4
commit
2415a53c43
3 changed files with 136 additions and 10 deletions
57
database.py
57
database.py
|
@ -1,5 +1,5 @@
|
|||
from sqlalchemy import create_engine, Column, ForeignKey, UniqueConstraint, CheckConstraint
|
||||
from sqlalchemy import Integer, BigInteger, String, Text, LargeBinary
|
||||
from sqlalchemy import create_engine, Column, ForeignKey, UniqueConstraint
|
||||
from sqlalchemy import Integer, BigInteger, String, Text, LargeBinary, DateTime
|
||||
from sqlalchemy.orm import sessionmaker, relationship
|
||||
from sqlalchemy.ext.declarative import declarative_base
|
||||
import configloader
|
||||
|
@ -74,12 +74,14 @@ class Product(TableDeclarativeBase):
|
|||
stock = Column(Integer)
|
||||
|
||||
# Extra table parameters
|
||||
__tablename__ = "product"
|
||||
__tablename__ = "products"
|
||||
|
||||
# No __init__ is needed, the default one is sufficient
|
||||
|
||||
def __str__(self):
|
||||
def __str__(self, one_row=False):
|
||||
"""Return the product details formatted with Telegram HTML. The image is omitted."""
|
||||
if one_row:
|
||||
return f"{escape(self.name)} - {strings.currency_format_string.format(symbol=strings.currency_symbol, value=self.price)}"
|
||||
return f"{escape(self.name)}\n" \
|
||||
f"{escape(self.description)}\n\n" \
|
||||
f"{strings.in_stock_format_string.format(quantity=self.stock) if self.stock is not None else ''}\n" \
|
||||
|
@ -88,7 +90,7 @@ class Product(TableDeclarativeBase):
|
|||
def __repr__(self):
|
||||
return f"<Product {self.name}>"
|
||||
|
||||
def send_as_message(self, chat_id: int) -> dict:
|
||||
def send_as_message(self, chat_id: int) -> requests.Response:
|
||||
"""Send a message containing the product data."""
|
||||
r = requests.post(f"https://api.telegram.org/bot{configloader.config['Telegram']['token']}/sendPhoto",
|
||||
files={"photo": self.image},
|
||||
|
@ -147,7 +149,7 @@ class Transaction(TableDeclarativeBase):
|
|||
return string
|
||||
|
||||
def __repr__(self):
|
||||
return f"<Transaction {self.transaction_id} - User {self.user_id} {str(self)}>"
|
||||
return f"<Transaction {self.transaction_id} for User {self.user_id} {str(self)}>"
|
||||
|
||||
|
||||
class Admin(TableDeclarativeBase):
|
||||
|
@ -166,6 +168,49 @@ class Admin(TableDeclarativeBase):
|
|||
return f"<Admin {self.user_id}>"
|
||||
|
||||
|
||||
class Order(TableDeclarativeBase):
|
||||
"""An order which has been placed by an user.
|
||||
It may include multiple products, available in the OrderItem table."""
|
||||
|
||||
# The unique order id
|
||||
order_id = Column(Integer, primary_key=True)
|
||||
# The user who placed the order
|
||||
user_id = Column(BigInteger, ForeignKey("users.user_id"))
|
||||
user = relationship("User")
|
||||
# Date of creation
|
||||
creation_date = Column(DateTime, nullable=False)
|
||||
# Date of delivery, None if the item hasn't been delivered yet
|
||||
delivery_date = Column(DateTime)
|
||||
# List of items in the order
|
||||
items = relationship("OrderItem")
|
||||
# Extra details specified by the purchasing user
|
||||
notes = Column(Text)
|
||||
|
||||
# Extra table parameters
|
||||
__tablename__ = "orders"
|
||||
|
||||
def __repr__(self):
|
||||
return f"<Order {self.order_id} placed by User {self.user_id}>"
|
||||
|
||||
|
||||
class OrderItem(TableDeclarativeBase):
|
||||
"""A product that has been purchased as part of an order."""
|
||||
|
||||
# The unique item id
|
||||
item_id = Column(Integer, primary_key=True)
|
||||
# The product that is being ordered
|
||||
product_id = Column(Integer, ForeignKey("products.id"), nullable=False)
|
||||
product = relationship("Product")
|
||||
# The order in which this item is being purchased
|
||||
order_id = Column(Integer, ForeignKey("orders.order_id"), nullable=False)
|
||||
|
||||
# Extra table parameters
|
||||
__tablename__ = "orderitems"
|
||||
|
||||
def __repr__(self):
|
||||
return f"<OrderItem {self.item_id}>"
|
||||
|
||||
|
||||
# If this script is ran as main, try to create all the tables in the database
|
||||
if __name__ == "__main__":
|
||||
TableDeclarativeBase.metadata.create_all()
|
15
strings.py
15
strings.py
|
@ -31,6 +31,16 @@ 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: add extra notes to the order
|
||||
conversation_extra_notes = "Che messaggio vuoi lasciare insieme al tuo ordine?"
|
||||
|
||||
# Conversation: confirm the cart contents
|
||||
conversation_confirm_cart = "Il tuo carrello contiene questi prodotti:\n" \
|
||||
"{product_list}\n" \
|
||||
"\n" \
|
||||
"Totale: {total_cost}\n" \
|
||||
"Procedere?"
|
||||
|
||||
# Notification: the conversation has expired
|
||||
conversation_expired = "🕐 Il bot non ha ricevuto messaggi per un po' di tempo, quindi ha chiuso la conversazione.\n" \
|
||||
"Per riavviarne una nuova, invia il comando /start."
|
||||
|
@ -68,6 +78,9 @@ menu_add_product = "✨ Nuovo prodotto"
|
|||
# Menu: cancel
|
||||
menu_cancel = "🔙 Annulla"
|
||||
|
||||
# Menu: done
|
||||
menu_done = "✅️ Fatto"
|
||||
|
||||
# Add product: name?
|
||||
ask_product_name = "Come si deve chiamare il prodotto?"
|
||||
|
||||
|
@ -139,5 +152,3 @@ error_invoice_expired = "⚠️ Questo pagamento è scaduto ed è stato annullat
|
|||
|
||||
# Error: a product with that name already exists
|
||||
error_duplicate_name = "️⚠ Esiste già un prodotto con questo nome."
|
||||
|
||||
|
||||
|
|
74
worker.py
74
worker.py
|
@ -8,7 +8,7 @@ import sys
|
|||
import queue as queuem
|
||||
import database as db
|
||||
import re
|
||||
import requests
|
||||
import datetime
|
||||
from html import escape
|
||||
|
||||
class StopSignal:
|
||||
|
@ -194,7 +194,77 @@ class ChatWorker(threading.Thread):
|
|||
self.__bot_info()
|
||||
|
||||
def __order_menu(self):
|
||||
raise NotImplementedError()
|
||||
"""User menu to order products from the shop."""
|
||||
# Create a list with the requested items
|
||||
order_items = []
|
||||
# Get the products list from the db
|
||||
products = self.session.query(db.Product).all()
|
||||
# TODO: this should be changed
|
||||
# Loop exit reason
|
||||
exit_reason = None
|
||||
# Ask for a list of products to order
|
||||
while True:
|
||||
# Create a list of product names
|
||||
product_names = [product.name for product in products]
|
||||
# Add a Cancel button at the end of the keyboard
|
||||
product_names.append(strings.menu_cancel)
|
||||
# If at least 1 product has been ordered, add a Done button at the start of the keyboard
|
||||
if len(order_items) > 0:
|
||||
product_names.insert(0, strings.menu_done)
|
||||
# Create a keyboard using the product names
|
||||
keyboard = [[telegram.KeyboardButton(product_name)] for product_name in product_names]
|
||||
# Wait for an answer
|
||||
selection = self.__wait_for_specific_message(product_names)
|
||||
# If the user selected the Cancel option...
|
||||
if selection == strings.menu_cancel:
|
||||
exit_reason = "Cancel"
|
||||
break
|
||||
# If the user selected the Done option...
|
||||
elif selection == strings.menu_done:
|
||||
exit_reason = "Done"
|
||||
break
|
||||
# If the user selected a product...
|
||||
else:
|
||||
# Find the selected product
|
||||
product = self.session.query(db.Product).filter_by(name=selection).one()
|
||||
# Add the product to the order_items list
|
||||
order_items.append(product)
|
||||
# Ask for extra notes
|
||||
self.bot.send_message(self.chat.id, strings.conversation_extra_notes)
|
||||
# Wait for an answer
|
||||
notes = self.__wait_for_regex("(.+)")
|
||||
# Create the confirmation message and find the total cost
|
||||
total_cost = 0
|
||||
product_list_string = ""
|
||||
for item in order_items:
|
||||
# Add to the string and the cost
|
||||
product_list_string += f"{str(item)}\n"
|
||||
total_cost += item.price
|
||||
# Send the confirmation message
|
||||
self.bot.send_message(self.chat.id, strings.conversation_confirm_cart.format(product_list=product_list_string, total_cost=strings.currency_format_string.format(symbol=strings.currency_symbol, value=(total_cost / (10 ** int(configloader.config["Payments"]["currency_exp"]))))))
|
||||
# TODO: wait for an answer
|
||||
# TODO: create a new transaction
|
||||
# TODO: test the code
|
||||
# TODO: everything
|
||||
# Create the order record and add it to the session
|
||||
order = db.Order(user=self.user,
|
||||
creation_date=datetime.datetime.now(),
|
||||
notes=notes)
|
||||
self.session.add(order)
|
||||
# Commit the session so the order record gets an id
|
||||
self.session.commit()
|
||||
# Create the orderitems for the selected products
|
||||
for item in order_items:
|
||||
item_record = db.OrderItem(product=item,
|
||||
order_id=order.order_id)
|
||||
# Add the created item to the session
|
||||
self.session.add(item_record)
|
||||
# Commit the session
|
||||
self.session.commit()
|
||||
# Send a confirmation to the user
|
||||
self.bot.send_message(self.chat.id, strings.success_order_created)
|
||||
|
||||
|
||||
|
||||
def __order_status(self):
|
||||
raise NotImplementedError()
|
||||
|
|
Loading…
Add table
Reference in a new issue