class UserRoleModel(BasicModel):
    user = Fields.ApplicationUserProperty(verbose_name=u'使用者')
    role = Fields.KeyProperty(verbose_name=u'角色', kind=RoleModel)

    @classmethod
    def get_user_roles(cls, user):
        return cls.query(cls.user == user.key)

    @classmethod
    def get_role(cls, role):
        if isinstance(role, basestring):
            role = RoleModel.get_by_name(role)
        return role

    @classmethod
    def set_role(cls, user, role):
        role = cls.get_role(role)
        if role is None:
            return None
        n = cls.query(cls.user == user.key, cls.role == role.key).get()
        if n is None:
            n = cls()
            n.user = user.key
            n.role = role.key
            n.put()
        return n

    @classmethod
    def remove_role(cls, user, role):
        role = cls.get_role(role)
        if role is None:
            return False
        n = cls.query(cls.user == user.key, cls.role == role.key).get(keys_only=True)
        if n is not None:
            ndb.delete_multi([n])
        return True

    @classmethod
    def has_role(cls, user, role):
        role = cls.get_role(role)
        if role is None:
            return False
        n = cls.query(cls.user == user.key, cls.role == role.key).get(keys_only=True)
        if n:
            return True
        return False
Exemplo n.º 2
0
class AlbumModel(BasicModel):
    name = Fields.StringProperty(verbose_name=u'識別名稱')
    title = Fields.StringProperty(verbose_name=u'相簿名稱')
    creator = Fields.ApplicationUserProperty(verbose_name=u'建立者')
    count = Fields.IntegerProperty(verbose_name=u'相片數量', default=0)

    @property
    def get_first_img(self):
        return '/plugins/album/static/empty-album.png'

    def insert_photo(self, ndb_item):
        from ..models.album_relation_model import AlbumRelationModel
        if ndb_item is None:
            return
        n = AlbumRelationModel()
        n.album = self.key
        n.file = ndb_item.key
        n.put()
        self.count += 1
        self.put()

    def all_photo(self):
        from ..models.album_relation_model import get_all_file_with_album
        return get_all_file_with_album(self.key)
class ShoppingCartItemModel(BasicModel):
    cart = Fields.KeyProperty(verbose_name=u'購物車', kind=ShoppingCartModel)
    spec = Fields.KeyProperty(verbose_name=u'產品規格',
                              kind=ProductSpecificationModel)
    user = Fields.ApplicationUserProperty(verbose_name=u'使用者')
    product_object = Fields.KeyProperty(verbose_name=u'所屬產品',
                                        kind=ProductModel)
    title = Fields.StringProperty(verbose_name=u'產品名稱', default=u'')
    product_name = Fields.StringProperty(verbose_name=u'產品名稱(系統)', default=u'')
    product_no = Fields.StringProperty(verbose_name=u'產品型號', default=u'')
    product_image = Fields.StringProperty(verbose_name=u'產品圖片', default=u'')
    price = Fields.FloatProperty(verbose_name=u'銷售價格', default=-1)
    cost = Fields.FloatProperty(verbose_name=u'成本', default=0.0)
    spec_full_name = Fields.StringProperty(verbose_name=u'完整規格名稱', default=u'')

    # 庫存相關
    try:
        from plugins.product_stock.models.stock_keeping_unit_model import StockKeepingUnitModel
    except ImportError:

        class StockKeepingUnitModel(BasicModel):
            pass

    sku = Fields.KeyProperty(verbose_name=u'最小庫存單位',
                             kind=StockKeepingUnitModel)
    sku_full_name = Fields.StringProperty(verbose_name=u'產品最小庫存名稱')
    expired_time = Fields.FloatProperty(verbose_name=u'庫存回收時間')
    quantity = Fields.IntegerProperty(verbose_name=u'數量', default=0)
    quantity_has_count = Fields.IntegerProperty(verbose_name=u'已計入庫存的數量',
                                                default=0)
    can_add_to_order = Fields.BooleanProperty(verbose_name=u'加至訂單中',
                                              default=False)

    try:
        from plugins.supplier.models.supplier_model import SupplierModel
    except ImportError:

        class SupplierModel(BasicModel):
            pass

    supplier = Fields.CategoryProperty(kind=SupplierModel, verbose_name=u'供應商')

    #  0=訂購(無庫存), 1=現貨, 2預購
    order_type = Fields.StringProperty(verbose_name=u'訂購方式')
    order_type_value = Fields.IntegerProperty(verbose_name=u'訂購方式(值)')

    size_1 = Fields.FloatProperty(verbose_name=u'長度(公分)', default=10.0)
    size_2 = Fields.FloatProperty(verbose_name=u'寬度(公分)', default=10.0)
    size_3 = Fields.FloatProperty(verbose_name=u'高度(公分)', default=10.0)
    weight = Fields.FloatProperty(verbose_name=u'重量(公斤)', default=10.0)

    @classmethod
    def get_or_create(cls, cart, user, product, spec, order_type=0):
        try:
            user_key = user.key
        except AttributeError:
            user_key = user
        item = cls.query(cls.cart == cart.key, cls.user == user_key,
                         cls.product_object == product.key,
                         cls.spec == spec.key,
                         cls.order_type_value == order_type).get()
        need_put = False
        if item is None:
            item = cls()
            item.cart = cart.key
            item.user = user_key
            item.product_object = product.key
            item.spec = spec.key
            item.order_type_value = order_type
            item.order_type = [u'訂購', u'現貨', u'預購'][order_type]
            item.spec_full_name = spec.full_name
            item.product_name = product.name
            item.product_image = product.image
            need_put = True
            if order_type == 0:
                item.can_add_to_order = True
        for field_name in [
                'title', 'product_no', 'price', 'cost', 'size_1', 'size_2',
                'size_3', 'weight'
        ]:
            if getattr(item, field_name) != getattr(product, field_name):
                setattr(item, field_name, getattr(product, field_name))
                need_put = True
        if need_put:
            item.put()
        return item

    @classmethod
    def get(cls, user, sku, order_type_value=0):
        return cls.query(cls.sku == sku.key, cls.user == user.key,
                         cls.order_type_value == order_type_value).get()

    @classmethod
    def get_or_create_with_spec(cls,
                                user,
                                spec,
                                quantity=0,
                                order_type_value=0):
        product = spec.product_object.get()
        item = cls.query(cls.sku == spec.key, cls.user == user.key,
                         cls.order_type_value == order_type_value).get()
        if item is None:
            item = cls()
            item.spec = spec.key
            item.user = user.key
            item.order_type_value = order_type_value
            item.product_object = product.key
            try:
                item.supplier = product.supplier.get().key
            except:
                pass
            if order_type_value == 0:
                item.order_type = u'訂購'
            else:
                item.order_type = u'預購'
        item._spec = spec
        item._product = product
        item.title = product.title
        item.product_no = product.product_no
        item.product_image = product.image
        item.spec_full_name = spec.spec_full_name
        item.change_quantity(quantity)
        item.put()
        return item

    @classmethod
    def all_with_user(cls, user):
        key = None
        if user is not None:
            key = user.key
        return cls.query(cls.user == key).order(-cls.sort)

    @classmethod
    def before_delete(cls, key):
        item = key.get()
        if item.order_type_value == 0:
            if item.quantity > 0:
                try:
                    sku = item.sku_instance
                    sku.change_estimate_quantity(item.quantity_has_count)
                    sku.put()
                except:
                    pass

    def volumetric_weight(self, divisor=6000.0):
        n = self.size_1 * self.size_2 * self.size_3 / float(divisor)
        return n

    @property
    def spec_instance(self):
        if not hasattr(self, '_spec'):
            self._spec = self.spec.get()
        return self._spec

    @property
    def sku_instance(self):
        if not hasattr(self, '_sku'):
            self._sku = self.sku.get()
        return self._sku

    @property
    def product_instance(self):
        if not hasattr(self, '_product'):
            self._product = self.spec_instance.product_object.get()
        return self._product

    def change_quantity(self, quantity):
        spec = self.spec_instance
        product = self.product_instance
        if self.order_type_value == 0:
            config = ConfigModel.get_config()
            if config.stock_recover:
                self.expired_time = time() + config.stock_recover_time
            else:
                self.expired_time = time() + 525600
            can_use_quantity = spec.quantity_can_be_used + int(
                self.quantity_has_count)
            old_quantity_has_count = self.quantity_has_count
            if can_use_quantity >= quantity and product.can_order:
                self.can_add_to_order = True
                self.quantity = quantity
                self.quantity_has_count = quantity
            else:
                self.can_add_to_order = False
                self.quantity = 0
                self.quantity_has_count = 0
            spec.change_estimate_quantity(sub_quantity=old_quantity_has_count,
                                          add_quantity=self.quantity)
            spec.put()
        else:
            if product.can_pre_order:
                self.can_add_to_order = True
                self.quantity = quantity
            else:
                self.can_add_to_order = False
                self.quantity = 0
            spec.change_pre_order_quantity(sub_quantity=int(
                self.quantity_has_count),
                                           add_quantity=self.quantity)
            spec.put()

    def quantity_can_be_order(self, user=None, sku=None):
        if sku is None:
            sku = self.sku.get()
        if self.order_type_value > 0:
            return 999
        if user and self.quantity is not None:
            c = sku.quantity_can_be_used + self.quantity
            if c > 0:
                return c
        return sku.quantity_can_be_used
class UserShopPointModel(BasicModel):
    class Meta:
        label_name = {
            'modified': u'最後變動時間',
        }

    name = Fields.StringProperty(verbose_name=u'識別名稱')
    user = Fields.ApplicationUserProperty(verbose_name=u'使用者')
    user_name_proxy = Fields.StringProperty(verbose_name=u'使用者名稱')
    user_email_proxy = Fields.StringProperty(verbose_name=u'E-Mail')
    point = Fields.FloatProperty(verbose_name=u'現餘點數', default=0.0)
    used_point = Fields.FloatProperty(verbose_name=u'已使用點數', default=0.0)

    @classmethod
    def get_or_create(cls, user):
        r = cls.query(cls.user == user.key).get()
        if r is None:
            r = cls(user=user.key)
            r._user = user
            r.user_name_proxy = r._user.name
            r.user_email_proxy = r._user.email
            r.put()
        r.user_name_proxy = user.name
        r.user_email_proxy = user.email
        return r

    @classmethod
    def after_get(cls, key, item):
        super(UserShopPointModel, cls).after_get(key, item)
        item._user = item.user.get()
        if item._user:
            item.user_name_proxy = item._user.name
            item.user_email_proxy = item._user.email
        else:
            item.user_name_proxy = u'該帳號已被刪除'

    def increase_point(self,
                       point,
                       remark=u'',
                       order_no=u'',
                       order_amount=None):
        from user_shop_point_history_model import UserShopPointHistoryModel
        point = int(point)
        history = UserShopPointHistoryModel()
        history.shop_point_target = self.key
        history.remark = remark
        history.increase_point = point
        history.order_no = order_no
        if order_amount is not None:
            history.order_amount = str(order_amount)
        if self.point is None:
            self.point = 0.0
        history.point = self.point + point
        history.put()
        self.point += point

    def decrease_point(self, point, remark, order_no=u'', order_amount=None):
        from user_shop_point_history_model import UserShopPointHistoryModel
        point = point
        history = UserShopPointHistoryModel()
        history.shop_point_target = self.key
        history.remark = remark
        history.decrease_point = point
        history.order_no = order_no
        if order_amount is not None:
            history.order_amount = str(order_amount)
        if self.point is None:
            self.point = 0.0
        history.point = self.point - point
        history.put()
        self.point -= point
        self.used_point += point

    def get_max_usable_point(self, total):
        from ..models.config_model import ConfigModel
        config = ConfigModel.get_config()
        if total > config.min_amount:
            n = total * (config.max_use_point_for_order /
                         100.0) * (config.discount_ratio / 100.0) // 1.0
            if n > self.point:
                return self.point
            return n
        else:
            return 0.0
class UserContactDataModel(BasicModel):
    user = Fields.ApplicationUserProperty(verbose_name=u'使用者', is_lock=True)
    user_name_proxy = Fields.StringProperty(verbose_name=u'使用者名稱')
    user_email_proxy = Fields.StringProperty(verbose_name=u'E-Mail')
    user_avatar_proxy = Fields.ImageProperty(verbose_name=u'頭像')
    telephone = Fields.StringProperty(verbose_name=u'電話', default=u'')
    mobile = Fields.StringProperty(verbose_name=u'手機', default=u'')
    sex = Fields.StringProperty(verbose_name=u'性別', default=u'保密')
    address_country = Fields.StringProperty(verbose_name=u'國家', default=u'')
    address_city = Fields.StringProperty(verbose_name=u'縣市', default=u'')
    address_district = Fields.StringProperty(verbose_name=u'鄉鎮', default=u'')
    address_detail = Fields.StringProperty(verbose_name=u'地址', default=u'')
    address_zip = Fields.StringProperty(verbose_name=u'郵遞區號', default=u'')

    birthday_year = Fields.IntegerProperty(verbose_name=u'出生年', default=0)
    birthday_month = Fields.IntegerProperty(verbose_name=u'出生月', default=0)
    birthday_day = Fields.IntegerProperty(verbose_name=u'出生日', default=0)
    referrals = Fields.StringProperty(verbose_name=u'推薦人', default=u'')
    is_referrals_change = Fields.BooleanProperty(verbose_name=u'推薦人已修改', default=False)

    mobile_verification_code = Fields.HiddenProperty(verbose_name=u'手機驗証碼', default=u'')
    is_mobile_verified = Fields.BooleanProperty(verbose_name=u'手機是否已驗証', default=False)
    need_verification_mobile = Fields.HiddenProperty(verbose_name=u'需驗証的手機', default=u'')
    last_verified_mobile = Fields.HiddenProperty(verbose_name=u'最後驗証成功的手機', default=u'')

    email_verification_code = Fields.HiddenProperty(verbose_name=u'信箱驗証碼', default=u'')
    is_email_verified_proxy = Fields.BooleanProperty(verbose_name=u'信箱是否已驗証', default=False)
    need_verification_email = Fields.HiddenProperty(verbose_name=u'需驗証的信箱', default=u'')
    last_verified_email = Fields.HiddenProperty(verbose_name=u'最後驗証成功的信箱', default=u'')

    address_verification_code = Fields.HiddenProperty(verbose_name=u'地址驗証碼', default=u'')
    is_address_verified = Fields.BooleanProperty(verbose_name=u'地址是否已驗証', default=False)

    @classmethod
    def get_or_create(cls, user):
        r = cls.query(cls.user==user.key).get()
        if r is None:
            r = cls(user=user.key)
            r.user_name_proxy = user.name
            r.user_email_proxy = user.email
            r.user_avatar_proxy = user.avatar
            r.is_email_verified_proxy = user.is_email_verified
            r.put()
        r._user = user
        r.password = r._user.password
        r.old_password = r._user.password
        return r

    @property
    def user_instance(self):
        if not hasattr(self, '_user'):
            self._user = self.user.get()
        return self._user

    def update_user(self, user=None):
        if user is None:
            user = self.user_instance
        if user is None:
            return

        if hasattr(self, 'old_password') and self.old_password != self.password:
            user.password = self.password
            user.bycrypt_password()
            self.password = user.password
            self.old_password = user.password
        try:
            user.name = self.user_name_proxy
            user.email = self.user_email_proxy
            user.avatar = self.user_avatar_proxy
            user.is_email_verified = self.is_email_verified_proxy
        except:
            pass
        user.put()

    @property
    def user_name(self):
        if self.user_instance:
            return self.user_instance.name
        return u'該帳號已被刪除'

    @user_name.setter
    def user_name(self, value):
        self.user_name_proxy = value

    @property
    def email(self):
        if self.user_instance:
            return self.user_instance.email
        return u''

    @email.setter
    def email(self, value):
        self.user_email_proxy = value

    @property
    def avatar(self):
        if self.user_instance:
            return self.user_instance.avatar
        return u''

    @avatar.setter
    def avatar(self, value):
        self.user_avatar_proxy = value

    @property
    def is_email_verified(self):
        if self.user_instance:
            return self.user_instance.is_email_verified
        return False

    @is_email_verified.setter
    def is_email_verified(self, value):
        self.is_email_verified_proxy = value

    @classmethod
    def after_get(cls, key, item):
        if item.user_instance:
            item.user_name_proxy = item.user_instance.name
            item.user_email_proxy = item.user_instance.email
            item.user_avatar_proxy = item.user_instance.avatar
            item.is_email_verified_proxy = item.user_instance.is_email_verified
        else:
            item.user_name_proxy = u'該帳號已被刪除'

    def gen_email_verification_code(self, email):
        import random, string
        r = ''.join(random.choice(string.lowercase) for i in range(25))
        self.need_verification_email = email
        self.email_verification_code = u'%s-%s-%s-%s' % (r[0:4], r[5:9], r[10:14], r[15:19])

    def gen_mobile_verification_code(self, mobile):
        import random
        self.need_verification_mobile = mobile
        self.mobile_verification_code = u'%s' % (random.randint(100000, 999999))

    def verify_email(self, code):
        if self.email_verification_code == code:
            self.last_verified_email = self.need_verification_email
            self.is_email_verified_proxy = True
            self.user_email_proxy = self.last_verified_email
            self.user_instance.email = self.last_verified_email
            self.user_instance.is_email_verified = True
            self.user_instance.put()
            self.email_verification_code = ''
            self.put()
            return True
        return False

    def verify_mobile(self, code):
        if self.mobile_verification_code == code:
            self.last_verified_mobile = self.need_verification_mobile
            self.is_mobile_verified = True
            self.mobile_verification_code = ''
            self.put()
            return True
        return False

    @property
    def birthday(self):
        return '%d-%02d-%02d' % (self.birthday_year, self.birthday_month, self.birthday_day)
Exemplo n.º 6
0
class ShoppingCartModel(BasicModel):
    title = Fields.StringProperty(verbose_name=u'購物車名稱', default=u'預設')
    user = Fields.ApplicationUserProperty(verbose_name=u'使用者')
    total_size = Fields.FloatProperty(verbose_name=u'尺寸合計', default=0.0)
    total_volume = Fields.FloatProperty(verbose_name=u'體積合計', default=0.0)
    total_price = Fields.FloatProperty(verbose_name=u'金額合計', default=0.0)
    total_weight = Fields.FloatProperty(verbose_name=u'重量總重', default=0.0)
    total_volumetric_weight = Fields.FloatProperty(verbose_name=u'材積總重',
                                                   default=0.0)
    cost_for_items = Fields.FloatProperty(verbose_name=u'成本(項目)',
                                          default=0.0,
                                          tab_page=4)
    freight = Fields.FloatProperty(verbose_name=u'運費', default=0.0)
    freight_type = Fields.KeyProperty(verbose_name=u'運送方式',
                                      kind=FreightTypeModel)

    try:
        from plugins.supplier.models.supplier_model import SupplierModel
    except ImportError:

        class SupplierModel(BasicModel):
            pass

    supplier = Fields.CategoryProperty(verbose_name=u'供應商', kind=SupplierModel)

    @classmethod
    def get_or_create(cls, user, supplier=None, supplier_key=None):
        if supplier is not None and supplier_key is None:
            supplier_key = supplier.key
        cart = cls.query(cls.user == user.key,
                         cls.supplier == supplier_key).get()
        if cart is None:
            cart = cls()
            cart.user = user.key
            if supplier_key:
                cart.supplier = supplier_key
            cart.put()
        return cart

    def get_shopping_cart_item(self, product, spec, item_order_type):
        from shopping_cart_item_model import ShoppingCartItemModel
        return ShoppingCartItemModel.get_or_create(self, self.user, product,
                                                   spec, item_order_type)

    @property
    def items(self):
        from shopping_cart_item_model import ShoppingCartItemModel
        return ShoppingCartItemModel.query(
            ShoppingCartItemModel.cart == self.key).fetch()

    def clean(self):
        if len(self.items) == 0:
            self.key.delete()

    def calc_size_weight_price_and_put(self, items=None):
        if items is None:
            items = self.items
        total_volume = 0.0
        total_size = 0.0
        total_price = 0.0
        total_weight = 0.0
        total_volumetric_weight = 0.0
        total_cost_for_items = 0.0
        for cart_item in items:
            total_size += cart_item.quantity * (
                cart_item.size_1 + cart_item.size_2 + cart_item.size_3)
            total_volume += cart_item.quantity * cart_item.size_1 * cart_item.size_2 * cart_item.size_3
            total_price += cart_item.quantity * cart_item.price
            total_weight += cart_item.quantity * cart_item.weight
            total_volumetric_weight += cart_item.quantity * cart_item.volumetric_weight(
            )
            total_cost_for_items += cart_item.quantity * cart_item.cost
        self.total_volume = total_volume
        self.total_size = total_size
        self.total_price = total_price
        self.total_weight = total_weight
        self.total_volumetric_weight = total_volumetric_weight
        self.cost_for_items = total_cost_for_items
        self.put()