class Payment(Base): __tablename__ = "payment" payment_id = Column(Integer, primary_key=True) payment_date = Column(DateTime, default=datetime.now(), nullable=False) payment_method_id = Column(Integer, ForeignKey("payments_methods.id"), index=True, nullable=False) payment_method = relationship("PaymentMethods", backref="payment") order_id = Column(Integer, ForeignKey("order.id"), index=True, nullable=False) order = relationship("Order", uselist=False, backref="payment") def __call__(self, **kwargs): try: self.payment_method_id = kwargs.get("payment_method_id") self.order_id = kwargs.get("order_id") session.add(self) session.commit() return True except Exception as e: print("Error whilst adding payment record: ", e) session.rollback() return False
class DeliveryDetails(Base): __tablename__ = "delivery_details" id = Column(Integer, primary_key=True) county = Column(String(50), nullable=False) sub_county = Column(String(50), nullable=False) village = Column(String(50), nullable=False) other_details = Column(String(500), nullable=False) courier_id = Column(Integer, ForeignKey("courier.id"), index=True, nullable=True) courier = relationship("Courier", backref="delivery_details") customer_id = Column(Integer, ForeignKey("customer.id"), index=True, nullable=False) customer = relationship("Customer", backref="delivery_details") order_id = Column(Integer, ForeignKey("order.id"), index=True, nullable=False) order = relationship("Order", uselist=False, backref="delivery_details") date = Column(DateTime, default=datetime.now()) def __call__(self, **kwargs): try: self.county = kwargs.get("county") self.sub_county = kwargs.get("sub_county") self.village = kwargs.get("village") self.other_details = kwargs.get("other_details") self.order_id = kwargs.get("order_id") self.customer_id = kwargs.get("customer_id") session.add(self) session.commit() return True except Exception as e: print("Error whilst recording delivery details: ", e) session.rollback() return False @classmethod def assign_courier(cls, courier_id, order_id): order = cls.query.filter_by(order_id=order_id).first() order.courier_id = courier_id session.commit() @classmethod def get_order_delivery_address(cls, order_id): return cls.query.filter_by(order_id=order_id).first()
class CashOnDelivery(Base): __tablename__ = "cash_on_delivery" transaction_id = Column(Integer, primary_key=True) payment_id = Column(Integer, ForeignKey("payment.payment_id"), index=True, nullable=False) payment = relationship("Payment", backref="cash_on_delivery") transaction_ref = Column(String(50), nullable=False) status = Column(Enum("pending", "failed", "confirmed", "cancelled"), nullable=False) def __call__(self, **kwargs): try: self.payment_id = kwargs.get("payment_id") self.transaction_ref = kwargs.get("transaction_ref") self.status = "pending" session.add(self) session.commit() return True except Exception as e: print("Error whilst recording transaction: ", e) session.rollback() return False @classmethod def read_cash_on_delivery(cls, **kwargs): return cls.query.filter_by(**kwargs).first()
class SubCategory(Base): __tablename__ = "sub_category" sub_category_id = Column(Integer, primary_key=True) name = Column(String(50), unique=True, nullable=False) category_id = Column(Integer, ForeignKey("category.category_id"), index=True, nullable=False) category = relationship("Category", backref="sub_category") def __repr__(self): return self.name def __call__(self, name, category): try: self.name = name self.category = category session.add(self) session.commit() return True except Exception as e: print("Adding subcategory error: ", e) session.rollback() return False def serialize(self): return { "sub_category_id": self.sub_category_id, "name": self.name, "category_id": self.category_id } @classmethod def read_sub_cat(cls): try: return [sub.serialize() for sub in cls.query.all()] except: session.rollback() @classmethod def read_drink_sub_categories(cls): try: return session.query(cls).join( cls.category).filter_by(name="Drinks").all() except: session.rollback() @classmethod def read_all_subcategories_filter_by(cls, *args, **kwargs) -> list: """ returns tuple objects tuples are made of attributes specified as args """ query = session.query(*[getattr(cls, i) for i in args]).filter_by(**kwargs).all() if len(args) == 1 and query: query = [i[0] for i in query] return query
class TrackProducts(Base): __tablename__ = "trackprodcuts" id = Column(Integer, primary_key=True) quantity = Column(BigInteger, nullable=False) date = Column(DateTime, default=datetime.now, nullable=False) product_id = Column(Integer, ForeignKey("products.product_id"),index=True, nullable=False) product = relationship("Products", backref="trackproducts") def __repr__(self): """ String representation """ return self.product_id def __call__(self, **kwargs): try: self.quantity = kwargs.get("quantity") self.product_id = kwargs.get("product_id") session.add(self) session.commit() return True except Exception as e: print("Error whilst adding tracking product detail: ", e) session.rollback() return False
class CouponPayment(Base): __tablename__ = "coupon_payment" transaction_id = Column(Integer, primary_key=True) payment_id = Column(Integer, ForeignKey("payment.payment_id"), index=True, nullable=False) payment = relationship("Payment", backref="coupon_payment") transaction_ref = Column(String(50), nullable=False) status = Column(Enum("pending", "failed", "confirmed", "cancelled"), nullable=False) def __repr__(self): return self.transaction_id def __call__(self, **kwargs): try: self.payment_id = kwargs.get("payment_id") self.transaction_ref = kwargs.get("transaction_ref") self.status = "pending" session.add(self) session.commit() return True except Exception as e: print("Error whilst recording transaction: ", e) session.rollback() return False
class Sales(Base): __tablename__ = "sales" sales_id = Column(Integer, primary_key=True) product_id = Column(Integer, ForeignKey("products.product_id"), index=True, nullable=False) products = relationship("Products", backref="sales") quantity = Column(BigInteger, nullable=False) amount = Column(BigInteger, nullable=False) commision_amount = Column(BigInteger, nullable=False) date = Column(DateTime, default=datetime.now(), nullable=False) def __repr__(self): return str(self.product_id) def __call__(self, **kwargs): try: self.product_id = kwargs.get("product_id") self.quantity = kwargs.get("quantity") self.amount = kwargs.get("amount") self.commision_amount = kwargs.get("commission_amount", 0) session.add(self) return True except Exception as e: session.rollback() print("Error whilst adding a sale :", e) return False @classmethod def read_sales_sum(cls, attr, *args): sales_sum = session.query(func.sum(attr)).filter(*args).scalar() return sales_sum if sales_sum else 0 @hybrid_property def sales_day(self): return self.date.day @sales_day.expression def sales_day(cls): return extract("day", cls.date) @hybrid_property def sales_month(self): return self.date.month @sales_month.expression def sales_month(cls): return extract("month", cls.date) @hybrid_property def sales_year(self): return self.date.year @sales_year.expression def sales_year(cls): return extract("year", cls.date)
class MobileMoney(Base): __tablename__ = "mobile_money" transaction_id = Column(Integer, primary_key=True) payment_id = Column(Integer, ForeignKey("payment.payment_id"), index=True, nullable=False) payment = relationship("Payment", backref="mobile_money") name = Column(String(50), nullable=False) email = Column(String(50), nullable=False) amount = Column(BigInteger, nullable=False) contact = Column(String(13), nullable=False) status = Column(Enum("pending", "failed", "confirmed", "cancelled"), nullable=False) transaction_ref = Column(String(50), nullable=False)
class StaffAccounts(Base, UserMixin): __tablename__ = "staff_accounts" id = Column(Integer, primary_key=True) username = Column(String(50), nullable=False, unique=True) password = Column(String(255), nullable=False) email = Column(String(50), unique=True, nullable=False) name = Column(String(100), nullable=False) contact = Column(String(13), nullable=False, unique=True) address = Column(String(255), nullable=False) account_active = Column(Boolean, default=True, nullable=False) account_type_id = Column(Integer, ForeignKey("account_type.id"), index=True, nullable=False) account_type = relationship("AccountType", backref="staff_accounts") # def __repr__(self): # return self.username def __call__(self, **kwargs): try: self.username = kwargs.get("username") self.hash_password(kwargs.get("password")) self.email = kwargs.get("email") self.name = kwargs.get("name") self.contact = kwargs.get("contact") self.address = kwargs.get("address") self.account_type_id = kwargs.get("account_type_id") session.add(self) session.commit() return True except Exception as e: print("Error whilst adding user account: ", e) session.rollback() return False def update_employee_details(self, **kwargs): try: self.email = kwargs.get("email", self.email) self.name = kwargs.get("name", self.name) self.contact = kwargs.get("contact", self.contact) self.address = kwargs.get("address", self.address) session.commit() except Exception as e: session.rollback() raise Exception(f"Updating user error: {e}") def verify_password(self, password): return pwd_context.verify(password, self.password) @property def is_employee(self): return True @classmethod def read_user(cls, **kwargs): return cls.query.filter_by(**kwargs).first() @classmethod def admin_exists(cls): return session.query(cls).join("account_type").filter( AccountType.type_name == "administrator").first() def hash_password(self, password): self.password = pwd_context.hash(password)
class Cart(Base): __tablename__ = "cart" id = Column(Integer, primary_key=True) product_id = Column(Integer) product_image = Column(String(50), nullable=False) product_name = Column(String(50), nullable=False) quantity = Column(BigInteger, nullable=False) unit_price = Column(BigInteger, nullable=False) commision_amount = Column(BigInteger, nullable=True) served_with = Column(String(1000), nullable=False, default="none") date = Column(DateTime, default=datetime.now(), nullable=False) is_ordered = Column(Boolean, default=False, nullable=False) customer_id = Column(Integer, ForeignKey("customer.id"), index=True, nullable=False) customer = relationship("Customer", backref="cart") order_id = Column(Integer, ForeignKey("order.id"), index=True) order = relationship("Order", backref="cart") free_delivery = Column(Boolean, nullable=False, default=False) restaurant = Column(String(100), nullable=False, default="clickEat") def __repr__(self): return self.product_name def __call__(self, **kwargs): try: self.product_id = kwargs.get("product_id") self.customer_id = kwargs.get("customer_id") self.product_name = kwargs.get("product_name") self.product_image = kwargs.get("product_image") self.unit_price = kwargs.get("unit_price") self.quantity = kwargs.get("quantity") self.served_with = kwargs.get("served_with", "none") self.free_delivery = kwargs.get("free_delivery", False) self.restaurant = kwargs.get("restaurant", "clickEat") item_exists = self.query.filter_by( customer_id = self.customer_id, product_id = self.product_id, is_ordered = False ).first() if item_exists: item_exists.quantity += int(self.quantity) session.commit() # if item_exists.quantity > product.quantity: # session.rollback() # print("Product already exists on cart and quantity you are specifying is more than what is available.") # return False # else: # session.commit() else: session.add(self) session.commit() return True except Exception as e: print("Error While adding to Cart: ", e) session.rollback() return False def serialize(self): return { "product_id": self.product_id, "product_name": self.product_name, "product_image": self.product_image, "unit_price": self.unit_price, "quantity": self.quantity, "served_with": self.served_with, "total": self.total, "total_quantity": int(self.cart_total_quantity_or_item_count(self.customer_id)), "cart_total_amount": int(self.cart_total_amount(self.customer_id)), "free_delivery": self.free_delivery, "restaurant": self.restaurant } @hybrid_property def total(self): return self.quantity * self.unit_price @classmethod def customer_order_items_total(cls, order_id): total = session.query(func.sum(cls.total))\ .filter_by( order_id=order_id ).scalar() return total if total else 0 @classmethod def read_customer_cart_items(cls, customer_id): try: cart_items = cls.query.filter_by( customer_id=customer_id, is_ordered=False ).all() return cls.update_cart_items_prices(cart_items) except: session.rollback() @classmethod def update_cart_items_prices(cls, cart_items): try: for item in cart_items: product = pdts.Products.read_all_products(return_query=True, product_id=item.product_id) if product.promotional_price_set: if product.promotional_price: item.unit_price = product.promotional_price else: item.unit_price = product.price else: item.unit_price = product.price session.commit() customer_cart_items = {"cart_items": [cart_item.serialize() for cart_item in cart_items]} return customer_cart_items except: session.rollback() @classmethod def update_cart_item(cls, **kwargs): item = cls.query.filter_by( customer_id = kwargs.get("customer_id"), product_id = kwargs.get("product_id"), is_ordered = False ).first() if item: item.quantity = kwargs.get("quantity") session.commit() return cls.read_customer_cart_items(kwargs.get("customer_id")) else: return False @classmethod def cart_total_quantity_or_item_count(cls, customer_id): total = session.query(func.sum(cls.quantity))\ .filter_by( customer_id=customer_id, is_ordered=False ).scalar() return total if total else 0 @classmethod def cart_total_amount(cls, customer_id): total = session.query(func.sum(cls.total))\ .filter_by( customer_id=customer_id, is_ordered=False ).scalar() return total if total else 0 @classmethod def customer_order_items_total(cls, order_id): total = session.query(func.sum(cls.total))\ .filter_by( order_id=order_id ).scalar() return total if total else 0 @property def read_item_shop_details(self): shop_details = session.query(shp.Resturant.business_name, shp.Resturant.address, shp.Resturant.contact, shp.Resturant.second_contact).join( "products" ).filter(pdts.Products.product_id == self.product_id).first() shop_details = Markup(f"{shop_details[0]}.<br> <b>Location:</b> {shop_details[1]} <br><b>Contact: </b>{shop_details[2]}/ {shop_details[3]}") if shop_details else "Unkown" return shop_details @classmethod def delete_cart_item(cls, id): try: product = cls.query.filter_by(product_id=id).first() cls.query.filter_by(product_id=id).delete() session.commit() return cls.read_customer_cart_items(product.customer_id) except Exception as e: print("Error whilst deleting cart item!!.", e) session.rollback() return False
class Comments(Base): __tablename__ = "comments" id = Column(Integer, primary_key=True) comment = Column(String(500), nullable=False) date = Column(DateTime, default=datetime.now(), nullable=False) reply = Column(String(500)) customer_id = Column(Integer, ForeignKey("customer.id"), index=True, nullable=False) customer = relationship("Customer", backref="comments") product_id = Column(Integer, ForeignKey("products.product_id"), index=True, nullable=False) products = relationship("Products", backref="comments") def __repr__(self): return str(self.id) def __call__(self, **kwargs): try: self.comment = kwargs.get("comment") self.customer_id = kwargs.get("customer_id") self.product_id = kwargs.get("product_id") session.add(self) session.commit() return True except Exception as e: print("Error whilst adding comment: ", e) session.rollback() return False def serialize(self): return { "product_id": self.product_id, "comment": self.comment, "date": self.date.strftime('%m/%d/%Y'), "reply": self.reply, "customerNames": self.customer.name } @classmethod def get_product_comments(cls, product_id): try: comments = cls.query.filter_by(product_id=product_id).order_by( desc(cls.date)).all() pdt_comments = (comment.serialize() for comment in comments) return pdt_comments except: session.rollback() @classmethod def product_comments(cls, product_id): try: comments = cls.query.filter_by(product_id=product_id).order_by( desc(cls.date)).all() return comments except: session.rollback()
class Order(Base): __tablename__ = "order" id = Column(Integer, primary_key=True) order_ref = Column(String(50), unique=True, nullable=False) order_ref_simple_version = Column(String(50), unique=True, nullable=False) order_date = Column(DateTime, default=datetime.now(), nullable=False) delivery_contact = Column(String(13), unique=False, nullable=False) is_paid = Column(Boolean, default=False, nullable=False) is_prepared = Column(Boolean, default=False, nullable=False) is_terminated = Column(Boolean, default=False, nullable=False) termination_reason = Column(String(500)) customer_received = Column(Boolean, default=False, nullable=False) delivery_fee = Column(BigInteger, default=0) customer_id = Column(Integer, ForeignKey("customer.id"), index=True, nullable=False) customer = relationship("Customer", backref="orders") pre_order = Column(Boolean, default=False, nullable=False) pre_order_time = Column(DateTime, default=datetime(2021, 1, 30, 00, 00, 00), nullable=False) def __repr__(self): return self.order_ref_simple_version def __call__(self, **kwargs): try: self.order_ref = kwargs.get("order_ref") self.customer_id = kwargs.get("customer_id") session.add(self) session.commit() return True except Exception as e: print("Error whilst adding order record: ", e) session.rollback() return False def serialize(self): return { "id": self.id, "order_ref": self.order_ref, "order_ref_simple_version": self.order_ref_simple_version, "order_date": self.order_date.strftime('%m/%d/%Y'), "is_paid": self.is_paid, "is_prepared": self.is_prepared, "is_terminated": self.is_terminated, "termination_reason": self.termination_reason, "customer_received": self.customer_received, "delivery_fee": self.delivery_fee, "order_items": [item.serialize() for item in self.cart] } @property def delivery_address(self): try: return delivery_detials.DeliveryDetails.get_order_delivery_address( self.id) except: session.rollback() @property def read_order_total_amount(self): return cart.Cart.customer_order_items_total(self.id) @classmethod def customer_order_count(cls, customer_id): try: count = session.query(func.count(cls.id)).filter_by( is_paid=True, is_terminated=False).scalar() return count except: session.rollback() @classmethod def read_order(cls, **kwargs): try: return cls.query.filter_by(**kwargs).options(lazyload("*")).first() except: session.rollback() @classmethod def read_customer_orders(cls, customer_id): try: customer_orders = cls.query.filter_by( customer_id=customer_id).order_by(desc(cls.order_date)).all() return [item.serialize() for item in customer_orders] except: session.rollback() @classmethod def customer_order_exists(cls, customer_id): try: return session.query(cls).filter_by(customer_id=customer_id, is_paid=False, is_terminated=False).first() except: session.rollback() @classmethod def delete_order(self, id): try: self.query.filter_by(id=id).delete() session.commit() except: session.rollback() @classmethod def read_orders_count(cls): try: return session.query(func.count(cls.id)).filter_by( is_paid=False, is_terminated=False).scalar() except: session.rollback() @classmethod def read_all_orders(cls): try: return cls.query.order_by(Order.id.desc()) except: session.rollback() @property def read_cart_items_total_amount(self): try: return pdts.Cart.customer_order_items_total(self.id) except: session.rollback() @classmethod def read_all_orders_filter(cls, *args): try: return cls.query.filter(*args).order_by(Order.id.desc()).all() except: session.rollback() @classmethod def read_all_orders_delivery_details_filter(cls, *args): try: return session.query(cls).join(cls.delivery_details)\ .filter( *args ).order_by(cls.id.desc()).options( lazyload("*")).all() except: session.rollback() @classmethod def read_orders_not_prepared_count(cls): try: return session.query(func.count(cls.id))\ .filter( and_( cls.is_prepared==False, cls.is_terminated == False ) ).scalar() except: session.rollback() def customer_care_terminate_order(self, reason): try: self.is_terminated = True self.termination_reason = reason cash_on_delivery = pym.CashOnDelivery.read_cash_on_delivery( payment_id=self.payment[0].payment_id) if cash_on_delivery: cash_on_delivery.status = "cancelled" if self.customer.email: mail_ = order_cancelled_email mail_.recipients = [self.customer.email] mail_.text = "We have cancelled the following order:{order}, because of the following reason: \n{reason}".format( order=self.order_ref_simple_version, reason=reason) mail_.send() session.commit() return True else: session.commit() return True except Exception as e: session.rollback() print("Terminating order error: ", e) return False @classmethod def terminate_order(cls, **kwargs): try: order = cls.read_order(customer_id=kwargs.get("customer_id"), is_paid=False, is_prepared=False, is_terminated=False, customer_received=False) if order: order.is_terminated = True order.termination_reason = kwargs.get("reason") cash_on_delivery = pym.CashOnDelivery.read_cash_on_delivery( payment_id=order.payment[0].payment_id) if cash_on_delivery: cash_on_delivery.status = "cancelled" if order.customer.email: mail_ = order_cancelled_email mail_.recipients = [order.customer.email] mail_.text = "You have cancelled the following order:{order}, because of this reason: \n{reason}".format( order=order.order_ref_simple_version, reason=kwargs.get("reason")) mail_.send() session.commit() return True else: session.commit() return True else: return False except Exception as e: print("Terminating order error: ", e) session.rollback() return False @classmethod def place_customer_order(cls, **kwargs): with current_app.app_context(): try: method = kwargs.get("payment_method") customer_id = kwargs.get("customer_id") delivery_contact = kwargs.get("delivery_contact") delivery_fee = kwargs.get("delivery_fee") pre_order = kwargs.get("pre_order") pre_order_time = kwargs.get("pre_order_time") county = kwargs.get("county"), sub_county = kwargs.get("sub_county"), village = kwargs.get("village"), other_details = kwargs.get("other_details"), customer_object = customer.Customer.read_customer( id=customer_id) payment_method = pym.PaymentMethods.read_method(method=method) if payment_method: new_ref = ReferenceGenerator() order_ref = new_ref.unique_id order_ref_simple_version = new_ref.simple_version order_ = Order( order_ref=order_ref, order_ref_simple_version=order_ref_simple_version, delivery_contact=delivery_contact, delivery_fee=delivery_fee, customer_id=customer_id, pre_order=pre_order, pre_order_time=pre_order_time) items = session.query(pdts.Cart).filter_by( customer_id=customer_id, is_ordered=False).all() for item in items: item.is_ordered = True item.order = order_ delivery = delivery_detials.DeliveryDetails( county=county, sub_county=sub_county, village=village, other_details=other_details, customer_id=customer_id, order=order_) session.add(delivery) payment = pym.Payment(payment_method_id=payment_method.id, order=order_) session.add(payment) if payment_method.method == "Cash on delivery": cash_on_delivery = pym.CashOnDelivery( payment=payment, transaction_ref=order_ref, status="pending") session.add(cash_on_delivery) else: session.rollback() return False #customer_care email cart_items_total = [] items_str = "" item_string = "" for i in items: item = i.serialize() item_string = f"<li>Item: {item['product_name']} from {item['restaurant']} Quantity: {item['quantity']} <b>SubTotal: {'{:,} Ugx'.format(item['total'])}</b></li>" items_str += item_string cart_items_total.append(item['total']) total = items[0].serialize() items_total = sum(cart_items_total) subject_customer_care = """ <html> <p>The following customer: <b>{customer_name}</b> has placed an order with the following details:</p> <p>Order Reference: {order_ref}</p> <p>Order Date: {order_date}</p> <p>Contact: {contact}</p> <hr> <ul style='list-style-type: none;display: block;width: 100%;padding: 0px 10px;overflow: hidden;'> {items_str} </ul> <hr> <p>Items Total: {total}</p> <hr> <p>Payment Method: <b>{payment_method}</b></p> <p>Delivery Price: <b>{delivery_fee}</b></p> <p>Total: <b>{order_total}</b></p> <hr> <p>Delivery Address: {delivery_address}</p> </html> """.format( customer_name=customer_object.name, order_ref=order_ref_simple_version, order_date="{: %d/%m/%Y}".format(datetime.now()), contact=customer_object.contact, items_str=items_str, total='{:,} Ugx'.format(items_total), payment_method=payment_method.method, delivery_fee='{:,} Ugx'.format(delivery_fee), order_total='{:,} Ugx'.format(delivery_fee + items_total), delivery_address= f"<br>County: {county}<br>,Sub County: {sub_county}<br>,Village: {village}<br>,Other_details: {other_details}<br>" ) customer_care_mail_ = customer_care_email customer_care_mail_.recipients = [ "*****@*****.**", "*****@*****.**", "*****@*****.**" ] # customer_care_mail_.context = dict( # customer_name=customer_object.name, # customer_contact=customer_object.contact, # order_ref=order_ref_simple_version, # order_date="{: %d/%m/%Y}".format(datetime.now()), # items=[i.serialize() for i in items], # delivery_method="Home delivery", # delivery_fee=delivery_fee, # payment_method=payment_method.method, # delivery_address= f"County: {county}\n,Sub County: {sub_county}\n,Village: {village}\n,Other_details: {other_details}" # ) customer_care_mail_.text = subject_customer_care customer_care_mail_.send() if customer_object.email: subject_customer = """ <html> <p>Written by: [email protected]<br> <b>Office Address:</b><br> Afra Road,<br> Near Hindu Temple,<br> Room 08,<br> Arua City, Uganda. </p> <p>You have successfully made an order for the following items.</p> <p>Order Reference: <b>{order_ref}</b></p> <p>Order Date: <b>{order_date}</b></p> <hr> <ul style='list-style-type: none;display: block;width: 100%;padding: 0px 10px;overflow: hidden;'> {items_str} </ul> <hr> <p>Items Total: <b>{total}</b></p> <hr> <p>Payment Method: <b>{payment_method}</b></p> <p>Delivery Price: <b>{delivery_fee}</b></p> <p>Total: <b>{order_total}</b></p> <p>Delivery Address: {delivery_address}</p> <hr> <p>You have received this email because you are a registered customer of ClickEat.</p> <p>For any help please contact us on: <b>0785857000/0777758880</b></p> </html> """.format( order_ref=order_ref_simple_version, order_date="{: %d/%m/%Y}".format(datetime.now()), items_str=items_str, total='{:,} Ugx'.format(items_total), payment_method=payment_method.method, delivery_fee='{:,} Ugx'.format(delivery_fee), order_total='{:,} Ugx'.format(delivery_fee + items_total), delivery_address= f"<br>County: {county}<br>,Sub County: {sub_county}<br>,Village: {village}<br>,Other_details: {other_details}<br>" ) mail_ = order_placed_email mail_.recipients = [customer_object.email] mail_.text = subject_customer # mail_.context = dict( # customer_name=customer_object.name, # customer_contact=customer_object.contact, # order_ref=order_ref_simple_version, # order_date="{: %d/%m/%Y}".format(datetime.now()), # items=[i.serialize() for i in items], # delivery_method="Home delivery", # delivery_fee=delivery_fee, # payment_method=payment_method.method, # delivery_address= f"County: {county}\n,Sub County: {sub_county}\n,Village: {village}\n,Other_details: {other_details}" # ) # mail_.text = "You have placed the following order with reference number: {order_ref_simple_version}".format( # order_ref_simple_version=order_ref_simple_version # ) mail_.send() session.commit() return True else: session.commit() return True else: print("No payment method") return False except Exception as e: print("Placing Order Error: ", e) session.rollback() return False @classmethod def customer_care_register_order_sales(cls, **kwargs): with current_app.app_context(): try: order = kwargs.get("order") data = kwargs.get("data") if "order_id" not in data: abort(403) if int(data["order_id"]) != int(order.id): abort(403) if "customer_received" in data: if order.is_prepared == False: flash("Order has to first be prepared", "danger") return jsonify() if order.is_paid == False: flash("Order has to first be paid", "danger") return jsonify() if data["customer_received"] == True and order.customer_received == False: order.customer_received = True session.commit() flash("Order status 'Customer received' has been set", "success") else: flash( "Order status 'Customer received' was already set", "info") elif "is_prepared" in data: if data["is_prepared"] == True and order.is_prepared == False: order.is_prepared = True session.commit() flash("Order status 'Prepared' has been set", "success") else: flash("Order status 'Prepared' was already set", "info") elif "courier_id" in data: if order.is_prepared == False: flash("Order has to be first prepared", "danger") return jsonify() delivery_detials.DeliveryDetails.assign_courier( int(data["courier_id"]), int(order.id)) flash("Courier has been set for this order successfully", "success") elif "is_paid" in data: if order.is_prepared == False: flash("Order has to first be prepared", "danger") return jsonify() if data["is_paid"] == True and order.is_paid == False: order.is_paid = True cash_on_delivery = pym.CashOnDelivery.read_cash_on_delivery( payment_id=order.payment[0].payment_id) delivery_details = order.delivery_details[0] if delivery_details.courier_id == None: flash( "Order paid can only be set when courier has been set.", "danger") session.rollback() return jsonify() if not cash_on_delivery: flash( "Order paid can only be set for cash on delivery items.", "danger") session.rollback() return jsonify() else: cash_on_delivery.status = "confirmed" for pdt_ in order.cart: product = session.query(pdts.Products).filter_by( product_id=pdt_.product_id).first() if product: sales.Sales()( product_id=pdt_.product_id, quantity=pdt_.quantity, amount=pdt_.total, commission_amount=product.commission_amount if product.commission_amount else 0) if order.customer.email: items = order.cart cart_items_total = [] items_str = "" item_string = "" for i in items: item = i.serialize() item_string = f"<li>Item: {item['product_name']} from {item['restaurant']} Quantity: {item['quantity']} <b>SubTotal: {'{:,} Ugx'.format(item['total'])}</b></li>" items_str += item_string cart_items_total.append(item['total']) total = items[0].serialize() items_total = sum(cart_items_total) subject_customer = """ <html> <p>Written by [email protected]<br> Office Address:<br> Afra Road,<br> Near Hindu Temple,<br> Room 08,<br> Arua City, Uganda. </p> <p>Dear <b>{user_name}</b></p>, <p>You have made a payment for the following items.</p> <p>Order Reference: <b>{order_ref}</b></p> <p>Order Date: {order_date}</p> <hr> <ul style='list-style-type: none;display: block;width: 100%;padding: 0px 10px;overflow: hidden;'> {items_str} </ul> <hr> <p>Items Total: <b>{total}</b></p> <p>Payment Method: {payment_method}</p> <p>Delivery Price: {delivery_fee}</p> <p>Total: {order_total}</p> <p>Status: <b>Paid</b></p> <hr> <p><b>Thank you for buying on ClickEat, please come gain :)</b></p> <p>You have received this email because you are a member of ClickEat.</p> <p>For any help please contact us by clicking 0785857000/0777758880</p> </html> """.format( user_name=order.customer.name, order_ref=order.order_ref_simple_version, order_date="{: %d/%m/%Y}".format( order.order_date), items_str=items_str, total='{:,} Ugx'.format(items_total), payment_method=order.payment[0].payment_method. serialize(), delivery_fee='{:,} Ugx'.format( order.delivery_fee), order_total='{:,} Ugx'.format( order.delivery_fee + items_total)) mail_ = order_receipt_email mail_.recipients = [order.customer.email] mail_.text = subject_customer # mail_.context = dict( # items = [i.serialize() for i in order.cart], # order_ref = order.order_ref_simple_version, # order_date="{: %d/%m/%Y}".format(order.order_date), # user_name = order.customer.name, # delivery_fees = order.delivery_fee, # payment_method = order.payment[0].payment_method.serialize(), # customer_received = order.customer_received # ) mail_.send() session.commit() flash("Order status has been set to paid", "success") else: session.commit() flash("Order status has been set to paid", "success") else: session.rollback() flash("Order status already set to paid", "info") except Exception as e: session.rollback() print("Updating Order statuses error: ", e) flash(f"Error: {e}", "danger")
class Products(Base): __tablename__ = "products" product_id = Column(Integer, primary_key=True) name = Column(String(50), nullable=False) product_picture = Column(String(100), nullable=False) description = Column(String(1000), nullable=False) price = Column(BigInteger, nullable=False) buying_price = Column(BigInteger, nullable=False, default=0) selling_price = Column(BigInteger, nullable=False, default=0) served_with = Column(String(1000), nullable=False, default="none") # promotional_price = Column(BigInteger, nullable=True) promotional_price_set = Column(Boolean, default=False, nullable=False) commission_fee = Column(Float, default=0.0) resturant_id = Column(Integer, ForeignKey("resturant.id"), nullable=True) resturant = relationship("Resturant", backref="products") brand_id = Column(Integer, ForeignKey("brand.brand_id"), index=True, nullable=False) brand = relationship("Brand", backref="products") sub_category_id = Column(Integer, ForeignKey("sub_category.sub_category_id"), index=True, nullable=False) sub_category = relationship("SubCategory", backref="products") approved = Column(Boolean, nullable=False, default=False) suspend = Column(Boolean, nullable=False, default=False) headsup = Column(String(100), nullable=False, default="clickEat") free_delivery = Column(Boolean, nullable=False, default=False) def __repr__(self): return str(self.name) def __call__(self, **kwargs): try: self.name = kwargs.get("name") self.product_picture = kwargs.get("product_picture") self.description = kwargs.get("description") self.price = kwargs.get("price") self.resturant_id = kwargs.get("resturant_id") brand_name = kwargs.get("brand") self.sub_category_id = kwargs.get("sub_category_id") brand_exists = brnd.Brand.read_brand_filter( brnd.Brand.name.like("%{}%".format(brand_name))) if brand_exists: self.brand = brand_exists else: brand = brnd.Brand(name=brand_name) self.brand = brand self.buying_price = kwargs.get("buying_price", 0) self.selling_price = kwargs.get("selling_price", 0) self.served_with = kwargs.get("served_with", 'none') self.commission_fee = kwargs.get("commission_fee", 0.0) self.headsup = kwargs.get("headsup", "clickEat") session.add(self) session.commit() return True except Exception as e: print("Error while adding product: ", e) session.rollback() return False def serialize(self): return { "product_id": self.product_id, "name": self.name, "product_picture": self.product_picture, "description": self.description, "price": self.product_price, "resturant_id": self.resturant_id, "resturant": self.resturant.business_name, "brand_id": self.brand_id, "brand": self.brand.name, "sub_category_id": self.sub_category_id, "sub_category": self.sub_category.name, "promotional_price_set": self.promotional_price_set, "promotional_price": self.promotional_price, "headsup": self.headsup, "served_with": self.served_with, "free_delivery": self.free_delivery, "available": False } @property def product_price(self): if self.commission_fee != 0.0: product_price = self.commission_amount + self.price return product_price else: return self.price @property def promotional_price(self): if self.promotional_price_set: price = session.query(pdtds.ProductDiscounts).filter_by( product_id=self.product_id).first() return (price.price + self.commission_amount) if price else None else: return None @property def commission_amount(self): commission_amount = ((self.commission_fee) / 100) * self.price return math.ceil(commission_amount) @classmethod def read_products(cls): try: return cls.query.all() except: session.rollback() @classmethod def read_product(cls, id): try: product = cls.query.filter_by(product_id=id).first() if product: return product except: session.rollback() @classmethod def read_product_by_sub_cat(cls, sub_category_id): try: product = cls.query.filter_by( sub_category_id=sub_category_id).first() if product.approved and product.suspend != True: return product else: return None except: session.rollback() @classmethod def read_products_based_on_sub_cat(cls, sub_category_id): try: return cls.query.filter_by(sub_category_id=sub_category_id).all() except: session.rollback() @classmethod def read_products_count(cls): try: return session.query(func.count(cls.product_id)).scalar() except: session.rollback() @classmethod def home_products(cls): try: home_products = [] home_products.append({ "id": 1, "title": "Favorite Food & Snacks", "products": sample(list(food_snacks_generator(cls.query.all())), 2) }) home_products.append({ "id": 2, "title": "Drinks & Beverages", "products": sample( list( drinks_generator( cls.query.filter_by(sub_category_id=6).all())), 2) }) return home_products except: session.rollback() @classmethod def read_all_products(cls, return_query=False, **kwargs): """ if return_query is set to True, will return query object, otherwise returns list. """ if return_query: try: return cls.query.filter_by(**kwargs).first() except: session.rollback() else: try: _date = datetime.now(ni_timezone) current_time = _date.astimezone(timezone) products_based_on_sub_cat_dict = {} product_based_on_sub_cat_list = [] restaurant_products = [ product for product in cls.query.filter_by(**kwargs).all() ] for product in restaurant_products: if product.resturant.approved: _start_date = ni_timezone.localize( product.resturant.operation_start_time) _end_date = ni_timezone.localize( product.resturant.operation_stop_time) operation_start_time = _start_date.astimezone(timezone) operation_stop_time = _end_date.astimezone(timezone) if product.approved and product.suspend != True: if f"{product.sub_category}" in products_based_on_sub_cat_dict: if product not in products_based_on_sub_cat_dict[ f"{product.sub_category}"]: #Avoid duplicates if current_time.hour >= operation_start_time.hour and current_time.hour <= operation_stop_time.hour: pdt = product.serialize() pdt["available"] = True products_based_on_sub_cat_dict[ f"{product.sub_category}"] += [ pdt ] #Add the product to this group else: products_based_on_sub_cat_dict[ f"{product.sub_category}"] += [ product.serialize() ] else: if current_time.hour >= operation_start_time.hour and current_time.hour <= operation_stop_time.hour: pdt = product.serialize() pdt["available"] = True products_based_on_sub_cat_dict[ f"{product.sub_category}"] = [pdt] else: products_based_on_sub_cat_dict[ f"{product.sub_category}"] = [ product.serialize() ] for sub_cat, products in products_based_on_sub_cat_dict.items( ): banch = {"sub_category": sub_cat, "products": products} product_based_on_sub_cat_list.append(banch) return product_based_on_sub_cat_list except: session.rollback()
class CustomerAddress(Base): __tablename__ = "customer_addresses" id = Column(Integer, primary_key=True) county = Column(String(50), nullable=False) sub_county = Column(String(50), nullable=False) village = Column(String(50), nullable=False) other_details = Column(String(500), nullable=False) is_default = Column(Boolean) customer_id = Column(Integer, ForeignKey("customer.id"), index=True, nullable=False) customer = relationship("Customer", backref="customer_addresses") def __call__(self, **kwargs): try: self.county = kwargs.get("county") self.sub_county = kwargs.get("sub_county") self.village = kwargs.get("village") self.other_details = kwargs.get("other_details") self.is_default = kwargs.get("is_default", self.is_default) self.customer_id = kwargs.get("customer_id") if self.is_default: self.query.filter_by(customer_id=self.customer_id).update( {"is_default": False}) if not self.query.filter_by(customer_id=self.customer_id).first(): self.is_default = True session.add(self) session.commit() return True except Exception as e: print("Error whilst saving customer address: ", e) session.rollback() return None def serialize(self): return { "id": self.id, "county": self.county, "sub_county": self.sub_county, "village": self.village, "other_details": self.other_details, "is_default": self.is_default, "customer_id": self.customer_id } @classmethod def get_customer_addresses(cls, customer_id): try: customer_addresses = cls.query.filter_by( customer_id=customer_id).all() return [ customer_address.serialize() for customer_address in customer_addresses ] except: session.rollback() @classmethod def update_customer_address(cls, **kwargs): try: address = cls.query.filter_by(id=kwargs.get("address_id")).first() address.county = kwargs.get("county") address.sub_county = kwargs.get("sub_county") address.village = kwargs.get("village") address.other_details = kwargs.get("other_details") session.commit() return True except Exception as e: print("Error: >>>>>>>>>>>>>>>>", e) session.rollback() return False @classmethod def delete_customer_address(cls, id): try: session.query(cls).filter_by(id=id).delete() session.commit() return True except Exception as e: print("Error: >>>>>>>>>>>>>", e) session.rollback() return False
class Rate(Base): __tablename__ = "rate" id = Column(Integer, primary_key=True) rate = Column(BigInteger, nullable=False) customer_id = Column(Integer, ForeignKey("customer.id"), index=True, nullable=False) product_id = Column(Integer, ForeignKey("products.product_id"), index=True, nullable=False) customer = relationship("Customer", backref="rate") products = relationship("Products", backref="rate") def __repr__(self): return str(self.product_id) def __call__(self, **kwargs): try: self.rate = kwargs.get("rate") self.customer_id = kwargs.get("customer_id") self.product_id = kwargs.get("product_id") session.add(self) session.commit() return True except Exception as e: print("Error while rating a product :", e) session.rollback() return False @classmethod def read_product_rate(cls, product_id): try: pdt_ratings = session.query(func.count(cls.rate), cls.rate)\ .group_by(cls.rate).filter_by(product_id=product_id).all() numerator = 0 denomenator = 0 for rate in pdt_ratings: denomenator += rate[0] if rate[1] == 5: numerator += rate[0] * 100 elif rate[1] == 4: numerator += rate[0] * 80 elif rate[1] == 3: numerator += rate[0] * 60 elif rate[1] == 2: numerator += rate[0] * 40 elif rate[1] == 1: numerator += rate[0] * 20 if pdt_ratings: return int(((numerator / denomenator) / 100) * 5) else: return 0 except: session.rollback()