Author: Pedro Lucas Porcellis <pedrolucasporcellis@gmail.com>
Wrap up all the role of order and cycles
core/types/cycle.py | 57 +++++++++++++++++++++++++++++ core/types/order.py | 76 +++++++++++++++++++++++++++++++++++++++ core/types/order_product.py | 19 +++++++++
diff --git a/core/types/cycle.py b/core/types/cycle.py new file mode 100644 index 0000000000000000000000000000000000000000..796fdee35e8dc1d8da9c2c5af0d759dff7efa878 --- /dev/null +++ b/core/types/cycle.py @@ -0,0 +1,57 @@ +from core.database import Base +from sqlalchemy import Column, String, Integer, Text, DateTime, Numeric +from sqlalchemy.orm import relationship +from datetime import datetime as dt +from sqlalchemy_utils import ChoiceType +from enum import Enum + +from core.database import Base + +class CycleStatus(Enum): + draft = "draft" + published = "published" + closed = "closed" + delivered = "delivered" + +class Cycle(Base): + __tablename__ = "cycles" + + id = Column(Integer, primary_key=True) + name = Column(String(255), nullable=False) + description = Column(Text) + + start_at = Column(DateTime, nullable=False) + end_at = Column(DateTime, nullable=False) + + delivery_start_at = Column(DateTime, nullable=False) + delivery_end_at = Column(DateTime, nullable=False) + + status = Column(ChoiceType(CycleStatus, impl=String(150)), server_default='draft') + + price_margin = Column(Numeric(10, 2), nullable=False, default=0.0) + + created_at = Column(DateTime, nullable=False) + updated_at = Column(DateTime, nullable=False) + + orders = relationship("Order", backref="cycle", lazy=True) + + def __init__(self, name, description, start_at, end_at, delivery_start_at, delivery_end_at, status, price_margin): + self.name = name + self.description = description + self.start_at = start_at + self.end_at = end_at + self.delivery_start_at = delivery_start_at + self.delivery_end_at = delivery_end_at + self.status = status + self.price_margin = price_margin + + def close(self): + self.status = CycleStatus.closed.value + + def to_json(self): + return { + "name": self.name, + "description": self.description, + "start_at": self.start_at.__str__(), + "end_at": self.end_at.__str__(), + } diff --git a/core/types/order.py b/core/types/order.py new file mode 100644 index 0000000000000000000000000000000000000000..64cb3d834788fed668a06201b079e6947e037d73 --- /dev/null +++ b/core/types/order.py @@ -0,0 +1,76 @@ +from sqlalchemy import Column, String, Integer, DateTime, ForeignKey +from sqlalchemy.orm import relationship +from datetime import datetime as dt +from core.types.order_product import OrderProduct +from core.types.product import Product +from sqlalchemy.sql import func +from sqlalchemy_utils import ChoiceType +from enum import Enum + +from core.database import db, Base + +class OrderStatus(Enum): + draft = 'draft' + confirmed = 'confirmed' + +class Order(Base): + __tablename__ = 'orders' + + id = Column(Integer, primary_key=True) + user_id = Column(Integer, ForeignKey('users.id'), nullable=False) + cycle_id = Column(Integer, ForeignKey('cycles.id'), nullable=False) + status = Column(ChoiceType(OrderStatus, impl=String(150)), server_default='draft') + + created_at = Column(DateTime, nullable=False) + updated_at = Column(DateTime, nullable=False) + + order_products = relationship('OrderProduct', backref="order", lazy=True, cascade="save-update, merge, delete") + + def __init__(self, user_id, cycle_id): + self.user_id = user_id + self.cycle_id = cycle_id + + @classmethod + def create_for(class_object, user, cycle): + order = class_object(user.id, cycle.id) + db.add(order) + db.commit() + + return order + + def add_products(self, product_ids): + # Delete the current products for this order + for product in self.order_products: + db.delete(product) + db.commit() + + # Create the new entries + for product_id in product_ids: + order_product = OrderProduct(self.id, product_id, 1) + db.add(order_product) + db.commit() + + def reopen(self): + self.status = OrderStatus.draft + + def confirm(self): + self.status = OrderStatus.confirmed + + def selected_product_ids(self): + return list(map(lambda entry: entry.product_id, self.order_products)) + + def products(self): + return list(map(lambda entry_id: Product.query.get(entry_id), self.selected_product_ids())) + + def total(self): + prices = list(map(lambda product: product.price_on(self.cycle), self.products())) + + return sum(prices, 0) + + def to_json(self): + return { + "id": self.id, + "user_id": self.user_id, + "cycle_id": self.cycle_id, + "products": self.selected_product_ids() + } diff --git a/core/types/order_product.py b/core/types/order_product.py new file mode 100644 index 0000000000000000000000000000000000000000..861325a5306d3cd3f5b4276faaacb93dfbb2fdab --- /dev/null +++ b/core/types/order_product.py @@ -0,0 +1,19 @@ +from core.database import Base +from sqlalchemy import Integer, Column, ForeignKey, DateTime +from datetime import datetime as dt + +class OrderProduct(Base): + __tablename__ = "order_products" + + id = Column(Integer, primary_key=True) + product_id = Column(Integer, ForeignKey('products.id'), nullable=False) + order_id = Column(Integer, ForeignKey('orders.id'), nullable=False) + quantity = Column(Integer, default=1, nullable=False) + + created_at = Column(DateTime, nullable=False) + updated_at = Column(DateTime, nullable=False) + + def __init__(self, order_id, product_id, quantity): + self.order_id = order_id + self.product_id = product_id + self.quantity = quantity