예제 #1
0
class MProduct(db.Model):
    __tablename__ = 'marketplace_products'
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    name = db.Column(db.String())
    images = db.Column(db.Text)
    description = db.Column(db.String())
    availability = db.Column(db.Boolean, default=True)
    min_order_quantity = db.Column(db.Integer, default=1)
    length = db.Column(db.Float)
    weight = db.Column(db.Float)
    height = db.Column(db.Float)
    price = db.Column(db.Float)
    price_currency_id = db.Column(db.Integer, db.ForeignKey('marketplace_currency.id', ondelete="CASCADE"))
    seller_id = db.Column(db.Integer, db.ForeignKey('users.id', ondelete="CASCADE"))
    is_featured = db.Column(db.Boolean, default=False)
    lead_time = db.Column(db.String())
    created_at = db.Column(db.DateTime, default=db.func.now())
    updated_at = db.Column(db.DateTime, default=db.func.now(), onupdate=db.func.now())

    categories = db.relationship("MCategory", secondary='marketplace_product_categories',
                                 backref=backref("products"),
                                 primaryjoin=(MProductCategory.product_id == id),
                                 secondaryjoin=(MProductCategory.category_id == MCategory.id))

    price_currency = db.relationship("MCurrency")
    seller = db.relationship("User", backref="products")

    @property
    def image_items(self):
        return [url_for('_uploads.uploaded_file', setname='images',
                        filename=image, _external=True) for image in json.loads(self.images)]
예제 #2
0
class BlogPost(db.Model):
    __tablename__ = 'blog_posts'
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String())
    image = db.Column(db.String(), default=None, nullable=False)
    text = db.Column(db.Text(), default=None)
    comments = db.relationship('BlogComment',
                               backref=backref('post'),
                               lazy='dynamic',
                               cascade="all, delete-orphan")
    user_id = db.Column(db.Integer,
                        db.ForeignKey('users.id', ondelete="CASCADE"))
    creator = db.relationship('User')
    categories = db.relationship(
        "BlogCategory",
        secondary='blog_post_categories',
        backref=backref("posts"),
        primaryjoin=(BlogPostCategory.post_id == id),
        secondaryjoin=(BlogPostCategory.category_id == BlogCategory.id))
    tags = db.relationship("BlogTag",
                           secondary='blog_post_tags',
                           backref=backref("posts"),
                           primaryjoin=(BlogPostTag.post_id == id),
                           secondaryjoin=(BlogPostTag.tag_id == BlogTag.id))

    created_at = db.Column(db.DateTime, default=db.func.now())
    updated_at = db.Column(db.DateTime,
                           default=db.func.now(),
                           onupdate=db.func.now())
예제 #3
0
class MReview(db.Model):
    __tablename__ = 'product_reviews'

    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    user_id = db.Column(db.Integer,
                        db.ForeignKey('users.id', ondelete="CASCADE"),
                        nullable=False)
    product_id = db.Column(db.Integer,
                           db.ForeignKey('marketplace_products.id',
                                         ondelete="CASCADE"),
                           nullable=True)
    score = db.Column(db.Float)
    message = db.Column(db.Text)
    timestamp = db.Column(db.DateTime,
                          default=db.func.now(),
                          onupdate=db.func.now())
    created_at = db.Column(db.DateTime, default=db.func.now())
    updated_at = db.Column(db.DateTime,
                           default=db.func.now(),
                           onupdate=db.func.now())

    user = db.relationship("User", backref="reviews")
    product = db.relationship("MProduct",
                              cascade="all,delete",
                              backref="reviews")
예제 #4
0
class MProduct(db.Model):
    __tablename__ = 'marketplace_products'

    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    name = db.Column(db.String())
    images = db.Column(db.Text)
    description = db.Column(db.String())
    availability = db.Column(db.Boolean, default=True)
    min_order_quantity = db.Column(db.Integer, default=1)
    length = db.Column(db.Float)
    weight = db.Column(db.Float)
    height = db.Column(db.Float)
    price = db.Column(db.Float)
    price_currency_id = db.Column(
        db.Integer, db.ForeignKey('marketplace_currency.id',
                                  ondelete="CASCADE"))
    seller_id = db.Column(db.Integer,
                          db.ForeignKey('users.id', ondelete="CASCADE"))
    brand_id = db.Column(
        db.Integer, db.ForeignKey('marketplace_brands.id', ondelete="CASCADE"))
    is_featured = db.Column(db.Boolean, default=False)
    condition = db.Column(db.String())
    lead_time = db.Column(db.String())
    created_at = db.Column(db.DateTime, default=db.func.now())
    updated_at = db.Column(db.DateTime,
                           default=db.func.now(),
                           onupdate=db.func.now())

    # categories = db.relationship("MCategory", secondary='marketplace_product_categories',
    #                              backref=backref("products"),
    #                              primaryjoin=(MProductCategory.product_id == id),
    #                              secondaryjoin=(MProductCategory.category_id == MCategory.id))
    categories = db.relationship("MCategory",
                                 secondary='marketplace_product_categories',
                                 backref=db.backref('products'))
    # variants = db.relationship("MVariant", secondary='marketplace_product_variants',
    #                              backref=backref("products"),
    #                              primaryjoin=(MProductVariant.product_id == id),
    #                              secondaryjoin=(MProductVariant.variant_id == MVariant.id))
    variants = db.relationship("MVariant",
                               secondary='marketplace_product_variants',
                               backref=db.backref('products'))
    brand = db.relationship("MBrand", backref="products")
    price_currency = db.relationship("MCurrency")
    seller = db.relationship("User", backref="products")
    score = query_expression()

    @property
    def rating(self):
        return db.session.query(db.func.avg(
            MReview.score)).filter(MReview.product_id == self.id).scalar()

    @property
    def image_items(self):
        return [
            url_for('_uploads.uploaded_file',
                    setname='images',
                    filename=image,
                    _external=True) for image in json.loads(self.images)
        ]
예제 #5
0
class MOrder(db.Model):
    __tablename__ = 'marketplace_orders'
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    order_number = db.Column(db.String())
    charge_id = db.Column(db.String(), default=None, nullable=True)
    order_status = db.Column(db.Integer, default=0)
    products_total = db.Column(db.Float, default=0)
    shipping_cost = db.Column(db.Float, default=0)
    order_total = db.Column(db.Float, default=0)
    order_discount = db.Column(db.Float, default=0)
    order_pay_amount = db.Column(db.Float, default=0)
    buyer_id = db.Column(db.Integer, db.ForeignKey('users.id', ondelete="CASCADE"))
    price_currency_id = db.Column(db.Integer, db.ForeignKey('marketplace_currency.id', ondelete="CASCADE"))
    first_name = db.Column(db.String(64), index=True)
    last_name = db.Column(db.String(64), index=True)
    email = db.Column(db.String(64), index=True)
    mobile_phone = db.Column(db.BigInteger, index=True)
    zip = db.Column(db.String(10), index=True)
    city = db.Column(db.String(64), index=True)
    state = db.Column(db.String(64), index=True)
    country = db.Column(db.String(64), index=True)

    created_at = db.Column(db.DateTime, default=db.func.now())
    updated_at = db.Column(db.DateTime, default=db.func.now(), onupdate=db.func.now())

    buyer = db.relationship("User", backref="orders")
    price_currency = db.relationship("MCurrency")

    @property
    def order_status_explained(self):
        if self.order_status == 0:
            return 'Pending'
        return self.order_status

    @hybrid_property
    def full_name(self):
        if self.buyer:
            return self.buyer.full_name
        first = ''
        last = ''
        if self.first_name:
            first = self.first_name
        if self.last_name:
            last = self.last_name
        return first + " " + last

    @property
    def sellers(self):
        sellers = []
        for seller_order in self.order_seller_orders:
            if seller_order.seller not in sellers:
                sellers.append(seller_order.seller)
        return sellers

    def order_items_grouped(self):
        orders = []
        for seller_order in self.order_seller_orders:
            items = MOrderItem.query.filter_by(seller_order=seller_order).filter_by(order=self).all()
            orders.append({'seller': seller_order.seller, 'items': items, 'shipping': seller_order.shipping_method})
        return orders
예제 #6
0
class MOrderStatusChange(db.Model):
    __tablename__ = 'marketplace_order_status_changes'
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    order_id = db.Column(db.Integer, db.ForeignKey('marketplace_orders.id', ondelete="CASCADE"), nullable=True,
                         default=None)
    seller_order_id = db.Column(db.Integer, db.ForeignKey('marketplace_seller_orders.id', ondelete="CASCADE"), nullable=True,
                                default=None)
    changed_from = db.Column(db.Integer, default=0)
    changed_to = db.Column(db.Integer, default=0)

    order = db.relationship("MOrder", backref="order_statuses")
    seller_order = db.relationship("MSellerOrder", backref="order_status_changes")

    created_at = db.Column(db.DateTime, default=db.func.now())
    updated_at = db.Column(db.DateTime, default=db.func.now(), onupdate=db.func.now())

    @property
    def order_status_explained(self):
        if self.changed_to == 0:
            return 'Pending', 'Your Order is still pending', ''
        elif self.changed_to == 1:
            return 'Received', 'The seller received your order', 'envelope open outline'
        elif self.changed_to == 2:
            return 'Processing', 'The seller is working on your order now', 'spinner'
        elif self.changed_to == 3:
            return "Shipping", 'Your Order is on the way to you', 'truck'
        elif self.changed_to == 4:
            return "Completed", 'Order Delivered', 'thumbs up'
        return self.changed_to
예제 #7
0
class MSellerOrder(db.Model):
    __tablename__ = 'marketplace_seller_orders'
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    order_id = db.Column(db.Integer, db.ForeignKey('marketplace_orders.id', ondelete="CASCADE"))
    seller_id = db.Column(db.Integer, db.ForeignKey('users.id', ondelete="CASCADE"))
    order_status = db.Column(db.Integer, default=0)
    shipping_method_id = db.Column(db.Integer, db.ForeignKey('marketplace_shipping_methods.id', ondelete="CASCADE"),
                                   nullable=True, default=None)
    buyer_id = db.Column(db.Integer, db.ForeignKey('users.id', ondelete="CASCADE"))
    current_currency_id = db.Column(db.Integer, db.ForeignKey('marketplace_currency.id', ondelete="CASCADE"))
    shipping_cost = db.Column(db.Float, default=0)
    created_at = db.Column(db.DateTime, default=db.func.now())
    updated_at = db.Column(db.DateTime, default=db.func.now(), onupdate=db.func.now())

    order = db.relationship("MOrder", backref="order_seller_orders")
    seller = db.relationship("User", backref="seller_orders_sold", primaryjoin="User.id == MSellerOrder.seller_id")
    buyer = db.relationship("User", backref="seller_orders_bought", primaryjoin="User.id == MSellerOrder.buyer_id")
    currency = db.relationship("MCurrency")
    shipping_method = db.relationship("MShippingMethod", backref="seller_order_shipping")

    @property
    def order_status_explained(self):
        if self.order_status == 0:
            return 'Pending'
        elif self.order_status == 1:
            return 'Received'
        elif self.order_status == 2:
            return 'Processing'
        elif self.order_status == 3:
            return "Shipping"
        elif self.order_status == 4:
            return "Completed"
        return self.order_status

    @property
    def next_action(self):
        if self.order_status == 0:
            return 1, 'Received'
        elif self.order_status == 1:
            return 2, "Processing"
        elif self.order_status == 2:
            return 3, "Shipping"
        elif self.order_status == 3:
            return 4, "Completed"

        return False

    @property
    def product_total(self):
        sum = 0
        for item in self.order_items:
            sum += item.current_total_price
        return sum

    @property
    def total_price(self):
        return self.product_total + self.shipping_cost
예제 #8
0
class MShippingMethodPrice(db.Model):
    __tablename__ = 'marketplace_shipping_method_prices'
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    shipping_method_id = db.Column(db.Integer, db.ForeignKey('marketplace_shipping_methods.id', ondelete="CASCADE"))
    seller_id = db.Column(db.Integer, db.ForeignKey('users.id', ondelete="CASCADE"), default=None, nullable=True)
    price_currency_id = db.Column(db.Integer, db.ForeignKey('marketplace_currency.id', ondelete="CASCADE"))
    price = db.Column(db.Float)

    created_at = db.Column(db.DateTime, default=db.func.now())
    updated_at = db.Column(db.DateTime, default=db.func.now(), onupdate=db.func.now())
    seller = db.relationship("User", backref="shipping_methods_prices")
    shipping_method = db.relationship("MShippingMethod", backref="prices")
    price_currency = db.relationship("MCurrency")
예제 #9
0
class MCategory(db.Model):
    __tablename__ = 'marketplace_categories'
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    parent_id = db.Column(db.Integer, db.ForeignKey('marketplace_categories.id', ondelete="CASCADE"), nullable=True,
                          default=None)
    name = db.Column(db.String(), default=None, nullable=False)
    image = db.Column(db.String(), default=None, nullable=False)
    order = db.Column(db.Integer, default=0)
    is_featured = db.Column(db.Boolean, default=False)
    created_at = db.Column(db.DateTime, default=db.func.now())
    updated_at = db.Column(db.DateTime, default=db.func.now(), onupdate=db.func.now())

    parent = db.relationship("MCategory", remote_side=[id])
    children = db.relationship("MCategory")
예제 #10
0
class MOrderStatusChange(db.Model):
    __tablename__ = 'marketplace_order_status_changes'
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    order_id = db.Column(db.Integer, db.ForeignKey('marketplace_orders.id', ondelete="CASCADE"), nullable=True,
                         default=None)
    order_item_id = db.Column(db.Integer, db.ForeignKey('marketplace_order_items.id', ondelete="CASCADE"), nullable=True,
                         default=None)
    changed_from = db.Column(db.Integer, default=0)
    changed_to = db.Column(db.Integer, default=0)
    order = db.relationship("MOrder", backref="order_statuses")
    order_item = db.relationship("MOrderItem", backref="order_item_statuses")

    created_at = db.Column(db.DateTime, default=db.func.now())
    updated_at = db.Column(db.DateTime, default=db.func.now(), onupdate=db.func.now())
예제 #11
0
class MCategory(db.Model):
    __tablename__ = 'marketplace_categories'
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    parent_id = db.Column(db.Integer,
                          db.ForeignKey('marketplace_categories.id',
                                        ondelete="CASCADE"),
                          nullable=True,
                          default=None)
    name = db.Column(db.String(), default=None, nullable=False)
    image = db.Column(db.String(), default=None, nullable=True)
    order = db.Column(db.Integer, default=0)
    is_featured = db.Column(db.Boolean, default=False)
    created_at = db.Column(db.DateTime, default=db.func.now())
    updated_at = db.Column(db.DateTime,
                           default=db.func.now(),
                           onupdate=db.func.now())

    parent = db.relationship("MCategory", remote_side=[id])
    children = db.relationship("MCategory")
    # products = db.relationship(
    #     'MProduct',
    #     secondary=subscribers,
    #     backref=db.backref('user', passive_deletes=True, lazy='dynamic')
    # )
    # products = db.relationship("MProduct", backref="categories")
    @staticmethod
    def insert_data():
        names = ('Animals & Pet Supplies', 'Apparel & Accessories',
                 'Arts & Entertainment', 'Baby & Toddler',
                 'Business & Industrial', 'Cameras & Optics', 'Electronics',
                 'Food, Beverages & Tobacco', 'Furniture', 'Hardware',
                 'Health & Beauty', 'Home & Garden', 'Luggage & Bags',
                 'Mature', 'Media', 'Office Supplies',
                 'Religious & Ceremonial', 'Software & Information Technology',
                 'Sporting Goods', 'Toys & Games', 'Vehicles & Parts',
                 'Housing', 'Hobbies', 'Classifieds')

        for name in names:
            name = MCategory(name=name)
            db.session.add(name)
        db.session.commit()
        print('Added Marketplace Categories')

    @property
    def image_url(self):
        return url_for('_uploads.uploaded_file',
                       setname='images',
                       filename=self.image,
                       external=True)
예제 #12
0
class Role(db.Model):
    __tablename__ = 'roles'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(64), unique=True)
    index = db.Column(db.String(64))
    default = db.Column(db.Boolean, default=False, index=True)
    permissions = db.Column(db.Integer)
    users = db.relationship('User', backref='role', lazy='dynamic')

    @staticmethod
    def insert_roles():
        roles = {
            'User': (Permission.GENERAL, 'main', True),
            'Administrator': (
                Permission.ADMINISTER,
                'admin',
                False  # grants all permissions
            )
        }
        for r in roles:
            role = Role.query.filter_by(name=r).first()
            if role is None:
                role = Role(name=r)
            role.permissions = roles[r][0]
            role.index = roles[r][1]
            role.default = roles[r][2]
            db.session.add(role)
        db.session.commit()

    def __repr__(self):
        return '<Role \'%s\'>' % self.name
예제 #13
0
class MCartDetails(db.Model):
    __tablename__ = 'marketplace_cart_details'
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    cart_id = db.Column(db.Integer,
                        db.ForeignKey('marketplace_carts.id',
                                      ondelete="CASCADE"),
                        nullable=True,
                        default=None)
    first_name = db.Column(db.String(64), index=True)
    last_name = db.Column(db.String(64), index=True)
    email = db.Column(db.String(64), unique=True, index=True)
    mobile_phone = db.Column(db.BigInteger, unique=True, index=True)
    zip = db.Column(db.String(10), index=True)
    city = db.Column(db.String(64), index=True)
    state = db.Column(db.String(64), index=True)
    country = db.Column(db.String(64), index=True)

    created_at = db.Column(db.DateTime, default=db.func.now())
    updated_at = db.Column(db.DateTime,
                           default=db.func.now(),
                           onupdate=db.func.now())

    cart = db.relationship("MCart",
                           uselist=False,
                           back_populates="cart_details")
예제 #14
0
class MSellerCart(db.Model):
    __tablename__ = 'marketplace_seller_carts'
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    cart_id = db.Column(db.Integer, db.ForeignKey('marketplace_carts.id', ondelete="CASCADE"))
    seller_id = db.Column(db.Integer, db.ForeignKey('users.id', ondelete="CASCADE"))
    shipping_method_id = db.Column(db.Integer, db.ForeignKey('marketplace_shipping_methods.id', ondelete="CASCADE"),
                                   nullable=True, default=None)
    buyer_id = db.Column(db.Integer, db.ForeignKey('users.id', ondelete="CASCADE"), nullable=True, default=None)
    current_currency_id = db.Column(db.Integer, db.ForeignKey('marketplace_currency.id', ondelete="CASCADE"))

    created_at = db.Column(db.DateTime, default=db.func.now())
    updated_at = db.Column(db.DateTime, default=db.func.now(), onupdate=db.func.now())

    cart = db.relationship("MCart", backref="seller_carts")
    seller = db.relationship("User", backref="seller_carts_active", primaryjoin="User.id == MSellerCart.seller_id")
    buyer = db.relationship("User", backref="my_seller_carts", primaryjoin="User.id == MSellerCart.buyer_id")
    currency = db.relationship("MCurrency")
    shipping_method = db.relationship("MShippingMethod", backref="seller_cart_shipping")
예제 #15
0
class User(db.Model):
    __table_args__ = ({'mysql_character_set': 'utf8mb4', 'mysql_collate': 'utf8mb4_unicode_520_ci'})
    id: int = Column('id', Integer, primary_key=True)
    guid: str = Column('guid', String(36), unique=True, nullable=False)
    username: str = Column('username', String(64), unique=True, nullable=False)
    displayName: str = Column('displayName', String(128), unique=True, nullable=True)
    email: str = Column('email', String(64), nullable=False)
    _password: str = Column('password', String(512), nullable=False)
    created: datetime = Column('created', DateTime, nullable=False, default=datetime.utcnow())
    last_login: datetime = Column('lastLogin', DateTime)

    role_id: int = Column('role', Integer, ForeignKey('role.id'), nullable=False)
    role = db.relationship('Role', backref=db.backref('users', lazy=True))

    totp_enabled: bool = Column('2fa_enabled', Boolean, nullable=False, default=False)
    totp_secret: str = Column('2fa_secret', String(128), nullable=True, default=None)

    def __init__(self, *args: list, **kwargs: dict) -> "User":
        kwargs['_password']: str = generate_password_hash(kwargs['password'], method='sha512')
        super().__init__(*args, **kwargs, guid=str(uuid4()))

    def jsonify(self) -> dict:
        return {
            'guid': self.guid,
            'username': self.username,
            'displayName': self.displayName if self.displayName else self.username,
            'email': self.email,
            'created': self.created.isoformat(),
            'lastLogin': self.last_login.isoformat()if self.last_login else None,
            'role': self.role.jsonify(),
            '2fa': self.totp_enabled
        }

    def verify_password(self, password: str) -> bool:
        return check_password_hash(self._password, password)

    def get_totp_uri(self) -> str:
        return f'otpauth://totp/PythonFlaskLogin:{self.username}?secret={self.totp_secret}&issuer=PythonFlaskLogin'

    def verify_totp(self, token: str) -> bool:
        """
        This method will return true if the totp secret is none,
        maybe 2fa has been enabled in the database without providing a totp secret by an admin
        """
        ret = True
        if self.totp_secret:
            ret = onetimepass.valid_totp(token, self.totp_secret)
        return ret

    @property
    def password(self):
        raise AttributeError('password is not a readable attribute')

    @password.setter
    def password(self, password: str):
        self._password = generate_password_hash(password, method=current_app.config.get('HASH_METHOD'))
예제 #16
0
class OrgStaff(db.Model):
    __tablename__ = 'org_staff'
    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.Integer,
                        db.ForeignKey('users.id', ondelete="CASCADE"))
    invited_by = db.Column(db.Integer,
                           db.ForeignKey('users.id', ondelete="CASCADE"))
    org_id = db.Column(db.Integer,
                       db.ForeignKey('organisations.id', ondelete="CASCADE"))
    user = db.relationship("User", primaryjoin="User.id==OrgStaff.user_id")
    referer = db.relationship("User",
                              primaryjoin="User.id==OrgStaff.invited_by")
    org = db.relationship("Organisation",
                          primaryjoin="Organisation.id==OrgStaff.org_id",
                          backref='staff')
    created_at = db.Column(db.DateTime, default=db.func.now())
    updated_at = db.Column(db.DateTime,
                           default=db.func.now(),
                           onupdate=db.func.now())
예제 #17
0
class MCartItem(db.Model):
    __tablename__ = 'marketplace_cart_items'
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    cart_id = db.Column(db.Integer, db.ForeignKey('marketplace_carts.id', ondelete="CASCADE"), nullable=True,
                        default=None)
    seller_cart_id = db.Column(db.Integer, db.ForeignKey('marketplace_seller_carts.id', ondelete="CASCADE"), nullable=True,
                        default=None)
    product_id = db.Column(db.Integer, db.ForeignKey('marketplace_products.id', ondelete="CASCADE"))
    seller_id = db.Column(db.Integer, db.ForeignKey('users.id', ondelete="CASCADE"))
    buyer_id = db.Column(db.Integer, db.ForeignKey('users.id', ondelete="CASCADE"), nullable=True, default=None)
    count = db.Column(db.Integer, default=1)

    created_at = db.Column(db.DateTime, default=db.func.now())
    updated_at = db.Column(db.DateTime, default=db.func.now(), onupdate=db.func.now())

    cart = db.relationship("MCart", backref=backref("cart_items", lazy='joined'))
    seller_cart = db.relationship("MSellerCart", backref="cart_items")
    seller = db.relationship("User", backref="items_in_cart", primaryjoin="User.id == MCartItem.seller_id")
    buyer = db.relationship("User", backref="my_cart_items", primaryjoin="User.id == MCartItem.buyer_id")
    product = db.relationship("MProduct", backref="product_cart_items")
예제 #18
0
class Organisation(db.Model):
    __tablename__ = 'organisations'
    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.Integer,
                        db.ForeignKey('users.id', ondelete="CASCADE"),
                        nullable=False)
    image_filename = db.Column(db.String, default=None, nullable=True)
    image_url = db.Column(db.String, default=None, nullable=True)
    org_name = db.Column(db.String(255))
    org_city = db.Column(db.String(255))
    org_state = db.Column(db.String(255))
    org_country = db.Column(db.String(255))
    org_website = db.Column(db.String(255))
    org_industry = db.Column(db.String(255))
    org_description = db.Column(db.Text)
    logos = db.relationship('Logo', backref='organisation', lazy='dynamic')
    user = db.relationship('User',
                           backref='organisations',
                           cascade='all, delete')
    created_at = db.Column(db.DateTime, default=datetime.now)
    updated_at = db.Column(db.DateTime,
                           default=datetime.now,
                           onupdate=datetime.now)

    def __repr__(self):
        return u'<{self.__class__.__name__}: {self.id}>'.format(self=self)

    def get_staff(self):
        ids = [user.user_id for user in self.staff]
        return User.query.filter(User.id.in_(ids)).all()

    def get_photo(self):
        if self.image_filename:
            return url_for('_uploads.uploaded_file',
                           setname='images',
                           filename=self.image_filename,
                           _external=True)
        else:
            return url_for('static', filename="images/medium_logo_default.png")
예제 #19
0
class MOrderItem(db.Model):
    __tablename__ = 'marketplace_order_items'
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    order_id = db.Column(db.Integer, db.ForeignKey('marketplace_seller_orders.id', ondelete="CASCADE"), nullable=True,
                         default=None)
    seller_order_id = db.Column(db.Integer, db.ForeignKey('marketplace_orders.id', ondelete="CASCADE"), nullable=True,
                         default=None)
    seller_id = db.Column(db.Integer, db.ForeignKey('users.id', ondelete="CASCADE"))
    buyer_id = db.Column(db.Integer, db.ForeignKey('users.id', ondelete="CASCADE"))
    product_id = db.Column(db.Integer, db.ForeignKey('marketplace_products.id', ondelete="CASCADE"))
    count = db.Column(db.Integer, default=1)
    current_price = db.Column(db.Float, default=0)
    current_total_price = db.Column(db.Integer, default=0)

    created_at = db.Column(db.DateTime, default=db.func.now())
    updated_at = db.Column(db.DateTime, default=db.func.now(), onupdate=db.func.now())

    order = db.relationship("MOrder", backref="order_items")
    seller_order = db.relationship("MSellerOrder", backref="order_items")
    seller = db.relationship("User", backref="orders_sold", primaryjoin="User.id == MOrderItem.seller_id")
    buyer = db.relationship("User", backref="orders_bought", primaryjoin="User.id == MOrderItem.buyer_id")
    product = db.relationship("MProduct", backref="product_orders")
예제 #20
0
class ContactMessage(db.Model):
    __tablename__ = 'contact_messages'
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    user_id = db.Column(db.Integer,
                        db.ForeignKey('users.id', ondelete="CASCADE"),
                        nullable=True)
    name = db.Column(db.String(), default=None, nullable=True)
    email = db.Column(db.String(64), default=None, nullable=True)
    text = db.Column(db.Text)
    user = db.relationship("User")
    created_at = db.Column(db.DateTime, default=db.func.now())
    updated_at = db.Column(db.DateTime,
                           default=db.func.now(),
                           onupdate=db.func.now())
예제 #21
0
class MShippingMethod(db.Model):
    __tablename__ = 'marketplace_shipping_methods'
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    name = db.Column(db.String(), default=None, nullable=False)
    seller_id = db.Column(db.Integer, db.ForeignKey('users.id', ondelete="CASCADE"), default=None, nullable=True)
    created_at = db.Column(db.DateTime, default=db.func.now())
    updated_at = db.Column(db.DateTime, default=db.func.now(), onupdate=db.func.now())

    seller = db.relationship("User", backref="shipping_methods")

    def get_price(self, currency, seller):
        price = None
        shipping_method_price = MShippingMethodPrice.query.filter_by(shipping_method=self).filter_by(price_currency=currency).filter_by(seller=seller).first()
        if shipping_method_price:
            price = shipping_method_price.price
        return price
예제 #22
0
class Message(db.Model):
    __tablename__ = 'messages'
    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.Integer,
                        db.ForeignKey('users.id', ondelete='cascade'))
    recipient_id = db.Column(db.Integer,
                             db.ForeignKey('users.id', ondelete="CASCADE"))
    body = db.Column(db.Text)
    timestamp = db.Column(db.DateTime, index=True, default=db.func.now())
    created_at = db.Column(db.DateTime, default=db.func.now())
    updated_at = db.Column(db.DateTime,
                           default=db.func.now(),
                           onupdate=db.func.now())
    read_at = db.Column(db.DateTime, default=None, nullable=True)

    user = db.relationship('User', primaryjoin="Message.user_id==User.id")

    def __repr__(self):
        return '<Message {}>'.format(self.body)
예제 #23
0
class BlogComment(db.Model, BaseNestedSets):
    __tablename__ = 'blog_post_comments'
    id = db.Column(db.Integer, primary_key=True)
    text = db.Column(db.String(), default=None)
    user_id = db.Column(db.Integer,
                        db.ForeignKey('users.id', ondelete="CASCADE"))
    post_id = db.Column(db.Integer,
                        db.ForeignKey('blog_posts.id', ondelete="CASCADE"))
    author = db.relationship('User')
    depth = db.Column(db.Integer, default=1)
    created_at = db.Column(db.DateTime, default=db.func.now())
    updated_at = db.Column(db.DateTime,
                           default=db.func.now(),
                           onupdate=db.func.now())

    def __init__(self, post_id, user_id, text, parent_id=None):
        self.post_id = post_id
        self.user_id = user_id
        self.text = text
        self.parent_id = parent_id
예제 #24
0
class MCart(db.Model):
    __tablename__ = 'marketplace_carts'
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    session_id = db.Column(db.String())
    user_id = db.Column(db.Integer, db.ForeignKey('users.id', ondelete="CASCADE"), nullable=True, default=None)
    step = db.Column(db.Integer, default=1)

    created_at = db.Column(db.DateTime, default=db.func.now())
    updated_at = db.Column(db.DateTime, default=db.func.now(), onupdate=db.func.now())

    user = db.relationship("User", backref="cart")
    cart_details = db.relationship("MCartDetails", uselist=False, back_populates="cart")

    @property
    def products_count(self):
        return len(self.products())

    @property
    def currency(self):
        if len(self.cart_items) > 0:
            first_product = self.cart_items[0].product
            return first_product.price_currency
        return None

    def product_count(self, product_id):
        product = MProduct.query.get(product_id)
        if product:
            cart_item = MCartItem.query.filter_by(cart=self).filter_by(product=product).first()
            if cart_item:
                return cart_item.count
        return 0

    def products(self):
        prods = []
        for cart_item in self.cart_items:
            prods.append({'product_id': cart_item.product_id, 'count': cart_item.count, 'object': cart_item.product, 'variant': cart_item.variant})

        return prods

    def sellers(self):
        sellers = []
        for cart_item in self.cart_items:
            if cart_item.seller not in sellers:
                sellers.append(cart_item.seller)
        return sellers

    def orders(self):
        orders = []
        for seller in self.sellers():
            items = MCartItem.query.filter_by(seller=seller).filter_by(cart=self).all()
            prods = []
            for cart_item in items:
                prods.append(
                    {'product_id': cart_item.product_id, 'count': cart_item.count, 'object': cart_item.product, 'variant': cart_item.variant})
            seller_cart = MSellerCart.query.filter_by(cart=self).filter_by(seller=seller).first()
            shipping = None
            if seller_cart:
                shipping = seller_cart.shipping_method
            orders.append({'seller': seller, 'items': prods, 'shipping': shipping})
        return orders

    @property
    def products_total(self):
        sum = 0
        for order in self.orders():
            for prod in order['items']:
                sum += prod['object'].price * prod['count']
        return sum

    def price_paid(self):
        sum = 0
        for order in self.orders():
            for prod in order['items']:
                sum += prod['object'].price * prod['count']
            if order['shipping']:
                sum += order['shipping'].get_price(self.currency, order['seller'])
        return sum

    def price_shipping(self):
        sum = 0
        for order in self.orders():
            if order['shipping']:
                sum += order['shipping'].get_price(self.currency, order['seller'])
        return sum

    def generate_order_number(self):
        if self.user_id is not None:
            user_part = str(self.user_id)
        else:
            user_part = self.session_id[:4]
        return random_char(4) + user_part + hex(int(time.time()))
예제 #25
0
class User(UserMixin, db.Model):
    __tablename__ = 'users'
    id = db.Column(db.Integer, primary_key=True)
    recruiter_id = db.Column(db.Integer,
                             db.ForeignKey("users.id"),
                             default=None,
                             nullable=True)
    confirmed = db.Column(db.Boolean, default=False)
    verified = db.Column(db.Boolean, default=False)
    is_seller = db.Column(db.Boolean, default=False)
    first_name = db.Column(db.String(64), index=True)
    last_name = db.Column(db.String(64), index=True)
    email = db.Column(db.String(64), unique=True, index=True)
    gender = db.Column(db.String(64), index=True)
    profession = db.Column(db.String(64), index=True)
    area_code = db.Column(db.String(6), index=True)
    mobile_phone = db.Column(db.BigInteger, unique=True, index=True)
    summary_text = db.Column(db.Text)
    zip = db.Column(db.String(10), index=True)
    city = db.Column(db.String(64), index=True)
    state = db.Column(db.String(64), index=True)
    country = db.Column(db.String(64), index=True)
    password_hash = db.Column(db.String(128))
    socket_id = db.Column(db.Text())
    online = db.Column(db.String(1), default='N')
    invited_by = db.Column(db.String(128))
    role_id = db.Column(db.Integer,
                        db.ForeignKey('roles.id', ondelete="CASCADE"))
    photos = db.relationship('Photo', backref='user', lazy='dynamic')

    messages_received = db.relationship('Message',
                                        foreign_keys='Message.recipient_id',
                                        backref='recipient',
                                        lazy='dynamic')
    last_message_read_time = db.Column(db.DateTime)
    notifications = db.relationship('Notification',
                                    backref='user',
                                    lazy='dynamic')
    created_at = db.Column(db.DateTime, default=db.func.now())
    updated_at = db.Column(db.DateTime,
                           default=db.func.now(),
                           onupdate=db.func.now())

    def __init__(self, **kwargs):
        super(User, self).__init__(**kwargs)
        if self.role is None:
            if self.email == current_app.config['ADMIN_EMAIL']:
                self.role = Role.query.filter_by(
                    permissions=Permission.ADMINISTER).first()
            if self.role is None:
                self.role = Role.query.filter_by(default=True).first()

    def toJson(self):
        return jsonify_object(self)

    def serialize(self):
        return jsonify_object(self)

    @hybrid_property
    def full_name(self):
        return self.first_name + " " + self.last_name

    def can(self, permissions):
        return self.role is not None and \
               (self.role.permissions & permissions) == permissions

    def is_admin(self):
        return self.can(Permission.ADMINISTER)

    @property
    def created_day(self):
        return self.created_at.date()

    @property
    def password(self):
        raise AttributeError('`password` is not a readable attribute')

    @password.setter
    def password(self, password):
        self.password_hash = generate_password_hash(password)

    def verify_password(self, password):
        return check_password_hash(self.password_hash, password)

    def generate_confirmation_token(self, expiration=604800):
        s = Serializer(current_app.config['SECRET_KEY'], expiration)
        return str(s.dumps({'confirm': self.id}).decode())

    def generate_email_change_token(self, new_email, expiration=3600):
        s = Serializer(current_app.config['SECRET_KEY'], expiration)
        return s.dumps({'change_email': self.id, 'new_email': new_email})

    def generate_password_reset_token(self, expiration=3600):
        s = Serializer(current_app.config['SECRET_KEY'], expiration)
        return str(s.dumps({'reset': self.id}).decode())

    def confirm_account(self, token):
        s = Serializer(current_app.config['SECRET_KEY'])
        try:
            data = s.loads(token)
        except (BadSignature, SignatureExpired):
            return False
        if data.get('confirm') != self.id:
            return False
        self.confirmed = True
        db.session.add(self)
        db.session.commit()
        return True

    def change_email(self, token):
        s = Serializer(current_app.config['SECRET_KEY'])
        try:
            data = s.loads(token)
        except (BadSignature, SignatureExpired):
            return False
        if data.get('change_email') != self.id:
            return False
        new_email = data.get('new_email')
        if new_email is None:
            return False
        if self.query.filter_by(email=new_email).first() is not None:
            return False
        self.email = new_email
        db.session.add(self)
        db.session.commit()
        return True

    def reset_password(self, token, new_password):
        s = Serializer(current_app.config['SECRET_KEY'])
        try:
            data = s.loads(token)
        except (BadSignature, SignatureExpired):
            return False
        if data.get('reset') != self.id:
            return False
        self.password_hash = generate_password_hash(new_password)
        db.session.add(self)
        db.session.commit()
        return True

    @staticmethod
    def generate_fake(count=100, **kwargs):
        from sqlalchemy.exc import IntegrityError
        from random import seed, choice
        from faker import Faker

        fake = Faker()
        roles = Role.query.all()
        if len(roles) <= 0:
            Role.insert_roles()
            roles = Role.query.all()

        seed()
        for i in range(count):
            u = User(first_name=fake.first_name(),
                     last_name=fake.last_name(),
                     email=fake.email(),
                     profession=fake.job(),
                     city=fake.city(),
                     country=fake.country(),
                     zip=fake.postcode(),
                     state=fake.state(),
                     summary_text=fake.text(),
                     password='******',
                     confirmed=True,
                     role=choice(roles),
                     **kwargs)
            db.session.add(u)
            try:
                db.session.commit()
            except IntegrityError:
                db.session.rollback()

    def last_message(self, user_id):
        message = Message.query.order_by(Message.timestamp.desc()). \
            filter(or_(and_(Message.recipient_id == user_id, Message.user_id == self.id),
                       and_(Message.recipient_id == self.id, Message.user_id == user_id))).first()
        return message

    def history(self, user_id, unread=False):
        messages = Message.query.order_by(Message.timestamp.asc()). \
            filter(or_(and_(Message.recipient_id == user_id, Message.user_id == self.id),
                       and_(Message.recipient_id == self.id, Message.user_id == user_id))).all()
        return messages

    def new_messages(self, user_id=None):
        if not user_id:
            return Message.query.filter_by(recipient=self).filter(
                Message.read_at == None).distinct('user_id').count()
        else:
            return Message.query.filter_by(recipient=self).filter(
                Message.read_at == None).filter(
                    Message.user_id == user_id).count()

    def add_notification(self, name, data, related_id=0, permanent=False):
        from app.email import send_email
        if not permanent:
            self.notifications.filter_by(name=name).delete()
        n = Notification(name=name,
                         payload_json=json.dumps(data),
                         user=self,
                         related_id=related_id)
        db.session.add(n)
        db.session.commit()
        n = Notification.query.get(n.id)
        kwargs = data
        kwargs['related'] = related_id
        get_queue().enqueue(send_email,
                            recipient=self.email,
                            subject='You Have a new notification on Mediville',
                            template='account/email/notification',
                            user=self.id,
                            link=url_for('main.notifications', _external=True),
                            notification=n.id,
                            **kwargs)
        if not current_app.config['DEBUG']:
            ws_url = "https://www.mediville.com"
            path = 'sockets/socket.io'
        else:
            get_queue().empty()
            ws_url = "http://localhost:3000"
            path = "socket.io"
        sio = socketio.Client()
        sio.connect(
            ws_url +
            "?token={}".format(create_access_token(identity=current_user.id)),
            socketio_path=path)
        data = n.parsed()
        u = jsonify_object(data['user'])
        tu = jsonify_object(self)
        data['user'] = {
            key: u[key]
            for key in u.keys()
            & {'first_name', 'id', 'email', 'socket_id'}
        }
        data['touser'] = {
            key: tu[key]
            for key in tu.keys()
            & {'first_name', 'id', 'email', 'socket_id'}
        }
        sio.emit('new_notification', {'notification': data})
        return n

    def get_photo(self):
        photos = self.photos.all()
        if len(photos) > 0:
            return url_for('_uploads.uploaded_file',
                           setname='images',
                           filename=photos[0].image_filename,
                           _external=True)
        else:
            if self.gender == 'Female':
                return "https://1.semantic-ui.com/images/avatar/large/veronika.jpg"
            else:
                return "https://1.semantic-ui.com/images/avatar/large/jenny.jpg"

    def __repr__(self):
        return '<User \'%s\'>' % self.full_name