示例#1
0
class Page(Model):
    __tablename__ = "public_page"
    title = Column(db.String(255), nullable=False)
    slug = Column(db.String(255))
    content = Column(db.Text())
    is_visible = Column(db.Boolean(), default=True)
    if Config.USE_REDIS:
        content = PropsItem("content", "")

    def get_absolute_url(self):
        identity = self.slug or self.id
        return url_for("public.show_page", identity=identity)

    @classmethod
    @cache(MC_KEY_PAGE_ID.format("{identity}"))
    def get_by_identity(cls, identity):
        try:
            int(identity)
        except ValueError:
            return Page.query.filter(Page.slug == identity).first()
        return Page.get_by_id(identity)

    @property
    def url(self):
        return self.get_absolute_url()

    def __str__(self):
        return self.title

    @classmethod
    def __flush_after_update_event__(cls, target):
        super().__flush_after_update_event__(target)
        rdb.delete(MC_KEY_PAGE_ID.format(target.id))
        rdb.delete(MC_KEY_PAGE_ID.format(target.slug))
示例#2
0
class OrderPayment(Model):
    __tablename__ = "order_payment"
    order_id = Column(db.Integer())
    status = Column(TINYINT)
    total = Column(db.DECIMAL(10, 2))
    delivery = Column(db.DECIMAL(10, 2))
    description = Column(db.Text())
    customer_ip_address = Column(db.String(100))
    token = Column(db.String(100))
    payment_method = Column(db.String(255))
    payment_no = Column(db.String(255), unique=True)
    paid_at = Column(db.DateTime())

    def pay_success(self, paid_at):
        self.paid_at = paid_at
        self.status = PaymentStatusKinds.confirmed.value
        order = Order.get_by_id(self.order_id)
        order.pay_success(payment=self)
示例#3
0
class Site(Model):
    __tablename__ = "public_setting"
    header_text = Column(db.String(255), nullable=False)
    description = Column(db.Text())
    top_menu_id = Column(db.Integer())
    bottom_menu_id = Column(db.Integer())

    @cache(MC_KEY_MENU_ITEMS.format("{self.id}", "{menu_id}"))
    def get_menu_items(self, menu_id):
        return (MenuItem.query.filter(MenuItem.site_id == menu_id).filter(
            MenuItem.parent_id == 0).order_by(MenuItem.order).all())

    @property
    def top_menu_items(self):
        return self.get_menu_items(self.top_menu_id)

    @property
    def bottom_menu_items(self):
        return self.get_menu_items(self.bottom_menu_id)
示例#4
0
class OrderPayment(Model):
    __tablename__ = "order_payment"
    order_id = Column(db.Integer())
    status = Column(db.Integer)
    total = Column(db.DECIMAL(10, 2))
    delivery = Column(db.DECIMAL(10, 2))
    description = Column(db.Text())
    customer_ip_address = Column(db.String(100))
    token = Column(db.String(100))
    payment_method = Column(db.String(255))
    payment_no = Column(db.String(255), unique=True)
    paid_at = Column(db.DateTime())

    def pay_success(self, paid_at):
        self.paid_at = paid_at
        self.status = PaymentStatusKinds.confirmed.value
        self.save(commit=False)
        order = Order.get_by_id(self.order_id)
        order.pay_success(payment=self)

    @property
    def status_human(self):
        return PaymentStatusKinds(int(self.status)).name
示例#5
0
class OrderNote(Model):
    __tablename__ = "order_note"
    order_id = Column(db.Integer())
    user_id = Column(db.Integer())
    content = Column(db.Text())
    is_public = Column(db.Boolean(), default=True)
示例#6
0
class Product(Model):
    __tablename__ = "product_product"
    title = Column(db.String(255), nullable=False)
    on_sale = Column(db.Boolean(), default=True)
    rating = Column(db.DECIMAL(8, 2), default=5.0)
    sold_count = Column(db.Integer(), default=0)
    review_count = Column(db.Integer(), default=0)
    basic_price = Column(db.DECIMAL(10, 2))
    category_id = Column(db.Integer())
    is_featured = Column(db.Boolean(), default=False)
    product_type_id = Column(db.Integer())
    attributes = Column(MutableDict.as_mutable(db.JSON()))
    description = Column(db.Text())
    if Config.USE_REDIS:
        description = PropsItem("description")

    def __str__(self):
        return self.title

    def __iter__(self):
        return iter(self.variants)

    def get_absolute_url(self):
        return url_for("product.show", id=self.id)

    @property
    @cache(MC_KEY_PRODUCT_IMAGES.format("{self.id}"))
    def images(self):
        return ProductImage.query.filter(
            ProductImage.product_id == self.id).all()

    @property
    def first_img(self):
        if self.images:
            return str(self.images[0])
        return ""

    @property
    def is_in_stock(self):
        return any(variant.is_in_stock for variant in self)

    @property
    def category(self):
        return Category.get_by_id(self.category_id)

    @property
    def product_type(self):
        return ProductType.get_by_id(self.product_type_id)

    @property
    def is_discounted(self):
        if float(self.discounted_price) > 0:
            return True
        return False

    @property
    @cache(MC_KEY_PRODUCT_DISCOUNT_PRICE.format("{self.id}"))
    def discounted_price(self):
        from flaskshop.discount.models import Sale

        return Sale.get_discounted_price(self)

    @property
    def price(self):
        if self.is_discounted:
            return self.basic_price - self.discounted_price
        return self.basic_price

    @property
    def price_human(self):
        return "$" + str(self.price)

    @property
    def on_sale_human(self):
        return "Y" if self.on_sale else "N"

    @property
    @cache(MC_KEY_PRODUCT_VARIANT.format("{self.id}"))
    def variant(self):
        return ProductVariant.query.filter(
            ProductVariant.product_id == self.id).all()

    @property
    def attribute_map(self):
        items = {
            ProductAttribute.get_by_id(k): AttributeChoiceValue.get_by_id(v)
            for k, v in self.attributes.items()
        }
        return items

    @classmethod
    # @cache(MC_KEY_FEATURED_PRODUCTS.format("{num}"))
    def get_featured_product(cls, num=8):  # 首頁的 featured products
        return cls.query.filter_by(is_featured=True).limit(num).all()

    def update_images(self, new_images):
        origin_ids = (ProductImage.query.with_entities(
            ProductImage.product_id).filter_by(product_id=self.id).all())
        origin_ids = set(i for i, in origin_ids)
        new_images = set(int(i) for i in new_images)
        need_del = origin_ids - new_images
        need_add = new_images - origin_ids
        for id in need_del:
            ProductImage.get_by_id(id).delete(commit=False)
        for id in need_add:
            image = ProductImage.get_by_id(id)
            image.product_id = self.id
            image.save(commit=False)
        db.session.commit()

    def update_attributes(self, attr_values):
        attr_entries = [
            str(item.id) for item in self.product_type.product_attributes
        ]
        attributes = dict(zip(attr_entries, attr_values))
        self.attributes = attributes

    def generate_variants(self):
        if not self.product_type.has_variants:
            ProductVariant.create(sku=str(self.id) + "-1337",
                                  product_id=self.id)
        else:
            sku_id = 1337
            variant_attributes = self.product_type.variant_attributes[0]
            for value in variant_attributes.values:
                sku = str(self.id) + "-" + str(sku_id)
                attributes = {str(variant_attributes.id): str(value.id)}
                ProductVariant.create(
                    sku=sku,
                    title=value.title,
                    product_id=self.id,
                    attributes=attributes,
                )
                sku_id += 1

    def delete(self):
        need_del_collection_products = ProductCollection.query.filter_by(
            product_id=self.id).all()
        for item in itertools.chain(self.images, self.variant,
                                    need_del_collection_products):
            item.delete(commit=False)
        db.session.delete(self)
        db.session.commit()

    @staticmethod
    def clear_mc(target):
        rdb.delete(MC_KEY_PRODUCT_DISCOUNT_PRICE.format(target.id))
        keys = rdb.keys(MC_KEY_FEATURED_PRODUCTS.format("*"))
        for key in keys:
            rdb.delete(key)

    @staticmethod
    def clear_category_cache(target):
        keys = rdb.keys(
            MC_KEY_CATEGORY_PRODUCTS.format(target.category_id, "*"))
        for key in keys:
            rdb.delete(key)

    @classmethod
    def __flush_insert_event__(cls, target):
        super().__flush_insert_event__(target)

        if current_app.config["USE_ES"]:
            from flaskshop.public.search import Item

            Item.add(target)

    @classmethod
    def __flush_before_update_event__(cls, target):

        super().__flush_before_update_event__(target)
        target.clear_category_cache(target)

    @classmethod
    def __flush_after_update_event__(cls, target):

        super().__flush_after_update_event__(target)
        target.clear_mc(target)
        target.clear_category_cache(target)
        if current_app.config["USE_ES"]:
            from flaskshop.public.search import Item

            Item.update_item(target)

    @classmethod
    def __flush_delete_event__(cls, target):
        from flaskshop.public.search import Item

        super().__flush_delete_event__(target)
        target.clear_mc(target)
        target.clear_category_cache(target)
        Item.delete(target)