ciclos

commit 15782be8411f69927c8e0cc284a2083ba643f29f

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