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
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)
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()