class Transaction(db.Model): id = db.Column(db.Integer(), primary_key=True) date = db.Column(db.DateTime(), nullable=False, default=datetime.utcnow) buyer_id = db.Column(db.Integer(), db.ForeignKey('user.id'), nullable=True) status = db.Column(db.String(), nullable=False) items = db.relationship('TransactionItem', backref='transaction', lazy=True)
class Order(db.Model): """Order model.""" __tablename__ = "order" id = db.Column(db.Integer(), primary_key=True) user = db.Column(db.Integer(), db.ForeignKey("user.id"), nullable=False) _created = db.Column(db.DateTime(), nullable=False) _last_change = db.Column(db.DateTime(), nullable=False) status = db.Column(db.Enum(OrderStateChoices), default=OrderStateChoices.cart, nullable=False) delivery_id = db.Column(db.Integer(), db.ForeignKey("delivery.id"), nullable=True) delivery_sum = db.Column(db.Integer()) contact = db.Column(db.Integer(), db.ForeignKey("contact.id"), nullable=True) customer = relationship("User") delivery = relationship("Delivery") def __init__(self, user, status=None, dt=None, contact=None, delivery=None, id=None): self.id = id self.user = user self._created = datetime.utcnow() self._last_change = dt if dt else datetime.utcnow() self.status = status self.contact = contact self.delivery_id = delivery self.delivery_sum = self._delivery_sum() dt = property() @dt.getter def created(self): return self._created.strftime("%d.%m.%Y %H:%M:%S") @dt.getter def last_change(self): return self._last_change.strftime("%d.%m.%Y %H:%M:%S") def _delivery_sum(self): if self.delivery_id: sellers = (db.session.query(func.count(distinct(OrderItem.shop)), OrderItem.order == self.id).group_by( OrderItem.order).first()[0]) delivery: Delivery = Delivery.query.get(self.delivery_id) k = 1 if sellers > 2: k = 0.85 return delivery.rate * sellers * k
class Product(db.Model): id = db.Column(db.Integer(), primary_key=True) name = db.Column(db.String(80), nullable=False, unique=True) price = db.Column(db.Integer(), nullable=False) # in cents description = db.Column(db.Text(), default='XDDDD', nullable=False) date_added = db.Column(db.DateTime(), nullable=False, default=datetime.utcnow) image = db.Column(db.String(), nullable=False, default='pokemon.jpg') def __init__(self, **kwargs): super(Product, self).__init__(**kwargs) self.description = kwargs.get('description') or f"This is a {self.name}" # act like default def __repr__(self): return f"Product(id={self.id}, name={self.name}, price={self.price})"
class User(db.Model, UserMixin): id = db.Column(db.Integer(), primary_key=True, autoincrement=True) email = db.Column(db.String(80), nullable=True, unique=True) password = db.Column(db.String(), nullable=True) true_user = db.Column(db.Boolean(), default=False, nullable=False) # if false means that User() object is used to store address for transaction only has_address = db.Column(db.Boolean(), default=False, nullable=False) first_name = db.Column(db.String(), nullable=True) last_name = db.Column(db.String(), nullable=True) street = db.Column(db.String(), nullable=True) street_number = db.Column(db.Integer(), nullable=True) apartment_number = db.Column(db.Integer(), nullable=True) city = db.Column(db.String(), nullable=True) country = db.Column(db.String(), nullable=True) postal_code = db.Column(db.String(), nullable=True) transactions = db.relationship('Transaction', backref='buyer', lazy=True) favourites = db.relationship('Product', secondary=favourites, lazy='subquery', backref=db.backref('lover', lazy=True)) def __repr__(self): return f"User(id={self.id}, email={self.email}, has_address={self.has_address})" def get_token(self): serializer = TimedJSONWebSignatureSerializer(app.config['SECRET_KEY']) token = serializer.dumps({'user_id': self.id}) return token @staticmethod def validate_token(token): serializer = TimedJSONWebSignatureSerializer(app.config['SECRET_KEY']) try: data = serializer.loads(token) user_id = data['user_id'] except: return None user = User.query.get(int(user_id)) return user
class Delivery(db.Model): """Shop delivery service model.""" __tablename__ = "delivery" id = db.Column(db.Integer, primary_key=True) title = db.Column(db.String(255), nullable=False, unique=True) rate = db.Column(db.Integer(), nullable=False) url = db.Column(db.String(255), nullable=True, unique=True) user_id = db.Column(db.Integer, db.ForeignKey("user.id"), nullable=False) manager = relationship("User") def __init__(self, title, user_id, rate, id=None, url=None): self.id = id self.title = title self.url = url self.user_id = user_id self.rate = rate def __repr__(self): return self.title
class Contact(db.Model): """User shipping address model.""" __tablename__ = "contact" id = db.Column(db.Integer(), primary_key=True) user = db.Column(db.ForeignKey("user.id"), nullable=False) zip_code = db.Column(db.String(6)) city = db.Column(db.String(50)) street = db.Column(db.String(100)) house = db.Column(db.String(15), nullable=True) structure = db.Column(db.String(15), nullable=True) building = db.Column(db.String(15), nullable=True) apartment = db.Column(db.String(15), nullable=True) phone = db.Column(db.String(20)) addressee = relationship("User") def __init__( self, user, phone, zip_code, city, street, house=None, structure=None, building=None, apartment=None, id=None, ): self.id = id self.user = user self.phone = phone self.zip_code = zip_code self.city = city self.street = street self.house = house self.structure = structure self.building = building self.apartment = apartment
class Product(db.Model): """Product table model.""" __tablename__ = "product" id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(255), nullable=False, unique=True) category = db.Column(db.Integer(), db.ForeignKey("category.id"), nullable=False) cat_rel = relationship("Category") def __init__(self, name, category, id=None): self.id = id self.name = name self.category = self.__set_category(category) @staticmethod def __set_category(name: str) -> int: """Auto set category id for product.""" category = Category.query.filter_by(name=name).first() if category: return category.id raise ValueError("No such category")
class OrderItem(db.Model): """Model for goods in order.""" __tablename__ = "x_order_item" order = db.Column( db.Integer(), db.ForeignKey("order.id"), primary_key=True, nullable=False, ) product = db.Column( db.Integer(), db.ForeignKey("product.id"), primary_key=True, nullable=False, ) shop = db.Column(db.Integer(), db.ForeignKey("shop.id"), primary_key=True, nullable=False) status = db.Column( db.Enum(ItemOrderStateChoices), default=ItemOrderStateChoices.ordered, nullable=False, ) quantity = db.Column(db.Integer(), nullable=False) order_rel = relationship("Order") shop_rel = relationship("Shop") product_rel = relationship("Product") def __init__(self, order, product, shop, quantity, status=None): self.order = order self.product = product self.shop = self.__set_shop(shop) self.quantity = quantity self.status = status if status else ItemOrderStateChoices.ordered @property def discount(self): if self.quantity < 4: return 1 if 4 <= self.quantity < 7: return 0.95 if 7 <= self.quantity < 10: return 0.90 if self.quantity >= 10: return 0.85 @staticmethod def __set_shop(shop_name): if isinstance(shop_name, int): return shop_name shop = Shop.query.filter_by(title=shop_name).first() return shop.id @property def agg_price(self): pr_info = ProductInfo.query.filter_by(product=self.product, shop=self.shop).first() price = discount_price(pr_info.price_rrc, self.discount) * self.quantity if price < pr_info.price * self.quantity: return pr_info.price * self.quantity return price
class ProductParameter(db.Model): """Product parameter x-table model.""" __tablename__ = "x_product_parameter" product_info = db.Column( db.Integer(), db.ForeignKey("product_info.id"), primary_key=True, nullable=False, ) parameter = db.Column( db.Integer(), db.ForeignKey("parameter.id"), primary_key=True, nullable=False, ) value = db.Column(db.String(255), nullable=False) p_info = relationship("ProductInfo") param_rel = relationship("Parameter") def __init__(self, product, parameter, value): self.product_info = self.__set_product(product) self.parameter = self.__set_parameter(parameter) self.value = value def __repr__(self): return (f"{__class__.__name__}(" f"product={self.product_info!r}, " f"parameter={self.parameter!r}, " f"value={self.value!r}" f")") def __hash__(self): return hash((self.product_info, self.parameter, self.value)) def __eq__(self, other): return self.__hash__() == other.__hash__() def __lt__(self, other): return self.product_info < other.product_info @staticmethod def __set_product(name) -> int: """Auto set product_info id for product.""" if isinstance(name, int): return name if not name: print("No name") input() pr_info = Product.query.filter_by(name=name).first() if not pr_info: print("No product") input() if pr_info: return pr_info.id raise ValueError("No such product info") @staticmethod def __set_parameter(name: str) -> int: """Auto set parameter id for product.""" if isinstance(name, int): return name param = Parameter.query.filter_by(name=name).first() if param: return param.id raise ValueError("No such parameter")
class ProductInfo(db.Model): """ProductInfo table model.""" __tablename__ = "product_info" id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(255), nullable=False) product = db.Column(db.Integer(), db.ForeignKey("product.id"), nullable=False) shop = db.Column(db.Integer(), db.ForeignKey("shop.id"), nullable=False) price = db.Column(db.Integer(), nullable=False) price_rrc = db.Column(db.Integer(), nullable=False) quantity = db.Column(db.Integer(), nullable=False) slug = db.Column(db.String(255), nullable=False) product_rel = relationship("Product") shop_rel = relationship("Shop") def __init__(self, name, product, shop, price, price_rrc, quantity, id=None): self.id = id self.name = name self.product = self.__set_product(product) self.shop = self.__set_shop(shop) self.price = int(price * 100) self.price_rrc = int(price_rrc * 100) self.quantity = quantity self.slug = slugify(name + " " + str(self.shop)) def __repr__(self): return (f"{__class__.__name__}(" f"{self.id!r}, " f"{self.name!r}, " f"{self.product!r}, " f"{self.shop!r}, " f"{self.price!r}, " f"{self.price_rrc!r}, " f"{self.quantity!r}, " f"{self.slug!r}" f")") @staticmethod def __set_product(name: str) -> int: """Auto set product id for product.""" if isinstance(name, int): return name product = Product.query.filter_by(name=name).first() if product: return product.id raise ValueError("No such product") @staticmethod def __set_shop(name) -> int: """Auto set shop id for product.""" if isinstance(name, int): return name shop = Shop.query.filter_by(title=name).first() if shop: return shop.id raise ValueError("No such shop")
class TransactionItem(db.Model): id = db.Column(db.Integer(), primary_key=True) transaction_id = db.Column(db.Integer(), db.ForeignKey('transaction.id')) product_id = db.Column(db.Integer()) quantity = db.Column(db.Integer())
from flask_login import UserMixin from itsdangerous import TimedJSONWebSignatureSerializer from web_shop import db, login_manager, app @login_manager.user_loader def load_user(user_id): user = User.query.get(int(user_id)) if user: if user.true_user: # has email and password, is able to log in, otherwise User() only stores address return user favourites = db.Table('favourites', db.Column('user_id', db.Integer(), db.ForeignKey('user.id'), primary_key=True), db.Column('product_id', db.Integer(), db.ForeignKey('product.id'), primary_key=True)) class User(db.Model, UserMixin): id = db.Column(db.Integer(), primary_key=True, autoincrement=True) email = db.Column(db.String(80), nullable=True, unique=True) password = db.Column(db.String(), nullable=True) true_user = db.Column(db.Boolean(), default=False, nullable=False) # if false means that User() object is used to store address for transaction only has_address = db.Column(db.Boolean(), default=False, nullable=False) first_name = db.Column(db.String(), nullable=True) last_name = db.Column(db.String(), nullable=True) street = db.Column(db.String(), nullable=True) street_number = db.Column(db.Integer(), nullable=True)