class Tag(db.Document): meta = {'db_alias': 'inventory_db'} en = db.StringField() cn = db.StringField() kind = db.StringField(required=True, choices=TAG_TYPES, default=TAG_TYPES.CATEGORY) def __unicode__(self): return '%s' % self.en @classmethod def get_tags(cls): return [dict(en=tag.en, cn=tag.cn) for tag in Tag.objects.all()] @classmethod def get_tag_or_create(cls, en, cn=None): if not Tag.objects(en=en): Tag(en=en, cn=cn, kind=TAG_TYPES.CATEGORY).save() @classmethod def update_cn(cls, en, cn): Tag.objects(en=en).update(set__cn=cn) def to_json(self): return dict(id=str(self.id), en=self.en, cn=self.cn, kind=self.kind)
class UserAccount(db.EmbeddedDocument): ''' The UserAccount class contains user personal informations and account settings ''' created_at = db.DateTimeField(default=datetime.datetime.utcnow, required=True) # login related email = db.EmailField(required=True, unique=True) mobile_number = db.StringField() is_email_verified = db.BooleanField(default=False) _password = db.StringField(max_length=255) activation_key = db.StringField(max_length=255) activate_key_expire_date = db.DateTimeField() # =============================================== # password @property def password(self): return self._password @password.setter def password(self, password): self._password = bcrypt.generate_password_hash(password).decode( 'utf-8') print(self._password) def check_password(self, password): if self.password is None: return False return bcrypt.check_password_hash(self.password, password) def to_json(self): return dict(created_at=str(self.created_at), email=self.email)
class Item(db.Document): content = db.StringField(required=True) created_date = db.DateTimeField() completed = db.BooleanField(default=False) completed_date = db.DateTimeField() created_by = db.ReferenceField('User', required=True) notes = db.ListField(db.StringField()) priority = db.IntField() def __repr__(self): return "<Item: {} Content: {}>".format(str(self.id), self.content) def to_json(self): return { 'id': str(self.id), 'content': self.content, 'completed': self.completed, 'completed_at': self.completed_date.strftime("%Y-%m-%d %H:%M:%S") if self.completed else "", 'created_by': self.created_by.name, 'notes': self.notes, 'priority': self.priority }
class User(db.Document): username = db.StringField(required=True) email = db.StringField(required=True) password = db.StringField(required=True) role = db.StringField(default='normal') todolists = db.ListField() @property def id(self): return str(self._id) def to_dict(self): return { 'name': self.name, 'email': self.email, 'role': self.role } def is_authenticated(self): return True def is_active(self): return True def is_anonymous(self): return False def get_id(self): return str(self.id) def verify_password(self, password): return check_password_hash(self.password, password)
class Category(db.Document): meta = { 'db_alias': 'inventory_db' } en = db.StringField(required=True, unique=True) cn = db.StringField() level = db.IntField(required=True) logo = db.StringField() def __unicode__(self): return '%s' % self.en @classmethod def get_category_or_create(cls, sub, lv): category = cls.objects(en=sub, level=lv).first() if not category: category = cls(en=sub, level=lv).save() return category @classmethod def update_cn(cls, en, cn): cls.objects(en=en).update(set__cn=cn) def to_json(self): return dict( en=self.en, cn=self.cn, level=self.level, logo=self.logo)
class ChannelProvider(db.Document): meta = { 'db_alias': 'order_db' } name = db.StringField() display_name = db.StringField() description = db.StringField() service_intro = db.DictField() country = db.StringField() is_active = db.BooleanField(default=False) shipping = db.FloatField(required=True) is_recommended = db.BooleanField(default=False) def __repr__(self): return '<ChannelProvider {}>'.format(self.name) @classmethod def get_shipping(cls, channel_name, country): if not channel_name: channel_name = 'default' provider = cls.objects(name=channel_name, country=country).first() return provider.shipping @queryset_manager def active(doc_cls, queryset): return queryset.filter(is_active=True) def to_json(self): return dict( name = self.name, display_name = self.display_name, service_intro = self.service_intro, desc = self.description)
class ChangeLog(db.EmbeddedDocument): ''' log all user actions of change for a board ''' user = db.StringField() date = db.DateTimeField(required=True, default=datetime.utcnow) action = db.StringField() item = db.StringField() info = db.StringField()
class Data(db.Document): meta = { 'db_alias': 'data_db', } sku = db.IntField(required=True, unique=True) item_id = db.IntField() title = db.StringField() primary_image = db.StringField() item_available = db.BooleanField()
class Express(db.Document): meta = {'indexes': ['name']} name = db.StringField(unique=True) cn_name = db.StringField() logo_url = db.StringField() desc = db.StringField() def to_json(self): return dict(key=self.name, name=self.cn_name, logo=self.logo_url, desc=self.desc)
class Cart(db.Document): meta = { 'db_alias': 'cart_db', 'indexes': ['user_id', 'session_key'] } entries = db.EmbeddedDocumentListField('CartEntry') user_id = db.StringField() session_key = db.StringField() def __repr__(self): return '<Cart: {}>'.format(self.id)
class OrderExtra(db.Document): meta = { 'indexes': [ 'order', 'paid_date', 'device_id', 'client', 'version', 'client_channel' ] } order = db.ReferenceField('Order', unique=True) paid_date = db.DateTimeField() client = db.StringField() version = db.StringField() device_id = db.StringField() client_channel = db.StringField()
class Address(db.Document): created_at = db.DateTimeField(default=datetime.utcnow) # address detail country = db.StringField(required=True) state = db.StringField(required=True) city = db.StringField() street1 = db.StringField() street2 = db.StringField() postcode = db.StringField() # receiver infomation receiver = db.StringField(required=True) mobile_number = db.StringField() def __unicode__(self): return '%s' % str(self.id) @property def fields(self): return [ 'country', 'state', 'city', 'street1', 'street2', 'postcode', 'receiver', 'mobile_number' ] def to_json(self): result = {f: getattr(self, f) for f in self.fields} result.update({'id': str(self.id)}) return result
class Partner(db.Document): name = db.StringField(unique=True) auth = db.StringField() _password = db.StringField() description = db.StringField() @property def password(self): return self._password @password.setter def password(self, password): self._password = bcrypt.generate_password_hash(password).decode('utf-8') self.save() @classmethod def create(cls, name, password, description): partner = cls( name=name, auth=hashlib.sha1(name).hexdigest(), description=description ) partner.password = password partner.save() def check_password(self, password): if self.password is None: return False return bcrypt.check_password_hash(self.password, password) def __str__(self): return self.name @classmethod def authorization(cls, auth, password): partner = cls.objects(auth=auth.lower()).first() if partner: authenticated = partner.check_password(password) else: authenticated = False return partner, authenticated def get_shipping(self, weight): provider = LogisticProvider.objects.get( name=self.name) shipping = provider.get_shipping(weight) return shipping
class Cart(db.Document): meta = { 'db_alias': 'cart_db', 'indexes': ['user_id'] } entries = db.ListField(db.ReferenceField('CartEntry')) logistic_free = db.FloatField() total_price = db.FloatField() user_id = db.StringField() def __repr__(self): return '<Cart: {}>'.format(self.id) @classmethod def get_cart_or_create(cls, user_id): try: cart = cls.objects.get(user_id=user_id) except: cart = cls(user_id=user_id).save() return cart def total_price(self): total_price = 0 for i in self.entries: total_price += i.price self.total_price = total_price return total_price
class BackendPermission(db.Document): meta = { 'indexes': ['name'], } name = db.StringField(required=True, unique=True) roles = db.ListField(db.ReferenceField('Role'))
class PostComment(db.Document): meta = { 'db_alias': 'content_db', 'indexes': ['user_id', 'content', 'post', 'created_at'], 'ordering': ['created_at'] } content = db.StringField(required=True) user_id = db.ObjectIdField() post = db.ReferenceField('Post') created_at = db.DateTimeField(default=datetime.utcnow, required=True) @property def user(self): from application import models as Models return Models.User.objects(id=self.user_id).first() def to_json(self): user = self.user return dict(id=str(self.id), content=self.content, user=dict(id=str(user.id), name=user.name, avatar_url=user.avatar_url, avatar_thumb=user.avatar_thumb), created_at=self.created_at.strftime("%Y-%m-%dT%H:%M:%S Z"))
class TodoList(db.Document): title = db.StringField() created_at = db.DateTimeField(default=datetime.now()) creator = db.ReferenceField('User') todos = db.ListField(default=[]) @property def id(self): return str(self._id) @property def todo_count(self): return len(self.todos) @property def finished_count(self): return len(list(filter(lambda x: x.is_finished, self.todos))) @property def open_count(self): return len(list(filter(lambda x: not x.is_finished, self.todos))) def to_dict(self): return { 'title': self.title, 'create_at': self.created_at, 'creator': self.creator.username, 'todo_count': self.todo_count, 'finished_count': self.finished_count, 'open_count': self.open_count }
class Role(db.Document): name = db.StringField(max_length=80, unique=True) description = db.StringField(max_length=255) def __unicode__(self): return self.name def __eq__(self, other): return (self.name == other or self.name == getattr(other, 'name', None)) def __ne__(self, other): return not self.__eq__(other) def __hash__(self): return hash(self.name)
class LogisticLog(db.Document): meta = { 'db_alias': 'log_db', 'allow_inheritance': True, 'indexes': ['logistic_id', 'timestamp'], 'ordering': ['-timestamp'], } log_type = db.StringField() logistic_id = db.ObjectIdField(required=True) timestamp = db.DateTimeField(default=datetime.utcnow) user_id = db.StringField(required=False) info = db.DictField() @classmethod def create(cls, log, data, user_id='system'): return cls(logistic_id=log.id, info=data, user_id=user_id).save()
class Todo(db.Document): desc = db.StringField() create_at = db.DateTimeField(default=datetime.now()) finished_at = db.DateTimeField(default=None) # todo的完成时间 is_finished = db.BooleanField(default=False) # todo状态:1. finished, 2. open creator = db.ReferenceField('User') todolist = db.ReferenceField('TodoList') @property def id(self): return str(self._id) @property def status(self): return 'finished' if self.is_finished else 'open' def finished(self): self.finished_at = datetime.now() self.is_finished = True self.save() def reopen(self): self.finished_at = None self.is_finished = False self.save() def to_dict(self): return { 'description': self.desc, 'creator': self.creator.username, 'create_at': self.create_at, 'finished_at': self.finished_at, 'status': self.status }
class OrderEntry(BaseEntry): meta = { 'db_alias': 'order_db', } _item_snapshot = db.ReferenceField( 'ItemSnapshot') # store the info of the item when an order is produced _item_spec_snapshot = db.ReferenceField('ItemSpecSnapshot') remark = db.StringField() shipping_info = db.DictField() @property def item_snapshot(self): return self._item_snapshot or self.item @property def item_spec_snapshot(self): return self._item_spec_snapshot or self.spec @property def item_changed(self): if self.item_spec_snapshot and self.item_snapshot: return self.item_snapshot.is_changed or self.item_spec_snapshot.is_changed else: return False def create_snapshot(self, item=None, spec=None): if not spec: spec = self.spec if not item: item = self.spec.item from application import models as Models if not self._item_snapshot: item_snapshot = Models.ItemSnapshot.create(item) self._item_snapshot = item_snapshot self._item_snapshot.price = item.price self._item_snapshot.save() if not self._item_spec_snapshot: item_spec_snapshot = Models.ItemSpecSnapshot.create( spec, item_snapshot) self._item_spec_snapshot = item_spec_snapshot self._item_spec_snapshot.price = spec.price self._item_spec_snapshot.save() self.save() return self._item_snapshot, self._item_spec_snapshot def update_snapshot(self): if not (self._item_spec_snapshot and self._item_snapshot): return self.create_snapshot() self.item_snapshot.update_to_head() self.item_spec_snapshot.update_to_head() return self.save()
class ItemSpec(db.Document): meta = { 'db_alias': 'inventory_db', 'indexes': [ 'item_id', 'web_sku', 'sku', 'price', 'original_price', 'availability', 'attributes', 'created_at', 'stock' ], 'ordering': ['price'] } item_id = db.IntField(required=True) sku = db.SequenceField(required=True, unique=True, primary_key=True) web_sku = db.StringField(required=True) images = db.ListField(db.StringField(required=True)) original_price = db.FloatField(required=True, min_value=0) price = db.FloatField(required=True, min_value=0) china_price = db.FloatField(min_value=0, default=0) availability = db.BooleanField(default=True, required=True) stock = db.IntField(default=-1) # spec.attributes: {color: 'Blue', size: 'M'} attributes = db.DictField() shipping_info = db.DictField() created_at = db.DateTimeField(default=datetime.utcnow, required=True) modified = db.DateTimeField() url = db.StringField() extra = db.DictField(default={}) @property def item(self): return Item.objects(item_id=self.item_id).first() def __unicode__(self): return '%s' % self.sku def update_spec(self, new_spec): for k, v in new_spec.items(): setattr(self, k, v) self.save()
class Role(db.Document): name = db.StringField(unique=True) permission = db.IntField() def __repr__(self): return '{}-{}'.format(self.name, self.permission) __str__ = __repr__
class GuestRecord(db.Document, FavorAction): ''' Visit records for guests user ''' meta = {'indexes': ['session_key']} session_key = db.StringField(required=True) device_tokens = db.ListField(db.StringField()) # favor related (item_ids) num_favors = db.IntField(default=0, min_value=0) favor_items = db.ListField(db.IntField()) @classmethod def by_key(cls, key): cls.objects(session_key=key).update_one(set__session_key=key, upsert=True) return cls.objects.get(session_key=key)
class LogisticProvider(db.Document, WeightPrice): meta = { 'db_alias': 'order_db' } name = db.StringField() display_name = db.StringField() description = db.StringField() service_intro = db.DictField() logo = db.StringField() country = db.StringField() is_active = db.BooleanField(default=False) rule_desc = db.StringField() init_price = db.FloatField(required=True) init_weight = db.IntField(required=True) continued_price = db.FloatField(required=True) continued_weight = db.IntField(required=True) init_coin = db.IntField(default=0) features = db.ListField(db.StringField()) promotion = db.StringField(default='') limited_weight = db.IntField(required=True) limited_category = db.ListField(db.StringField()) is_recommended = db.BooleanField(default=False) rating = db.DecimalField(precision=1) rating_users = db.IntField() def __repr__(self): return '<LogisticProvider {}>'.format(self.name) # TODO: memoize here @classmethod def get_provider_shipping(cls, logistic_name, country, weight): if not logistic_name: logistic_name = 'default' provider = cls.objects(name=logistic_name, country=country).first() return provider.get_shipping(weight) @queryset_manager def active(doc_cls, queryset): return queryset.filter(is_active=True) def to_json(self): return dict( name = self.name, display_name = self.display_name, service_intro = self.service_intro, desc = self.description)
class PostFeedback(db.Document): meta = { 'db_alias': 'content_db', 'indexes': ['user_id', 'post', 'subject', 'created_at'], 'ordering': ['created_at'] } user_id = db.ObjectIdField() post = db.ReferenceField('Post') subject = db.StringField() status = db.StringField(default=ACTIVITY_STATUS.PENDING, choices=ACTIVITY_STATUS) created_at = db.DateTimeField(default=datetime.utcnow, required=True) @property def user(self): from application import models as Models return Models.User.objects(id=self.user_id).first()
class Coupon(db.Document): meta = { 'strict': False, 'db_alias': 'order_db', 'indexes': ['code', 'apply', 'expire_date', 'description'] } scope = db.StringField(required=True, choices=COUPON_SCOPE, default=COUPON_SCOPE.ORDER) coupon_type = db.StringField(default=COUPON_TYPES.NORMAL, required=True, choices=COUPON_TYPES) value = db.FloatField() description = db.StringField() effective_date = db.DateTimeField(default=datetime.utcnow) expire_date = db.DateTimeField(default=datetime(2019, 12, 31)) code = db.StringField(unique=True) # by which means this coupon can be applied: by coupon code, by display_id apply = db.StringField(required=True, default=COUPON_APPLY.BY_DISPLAY_ID, choices=COUPON_APPLY) required_amount = db.FloatField(default=0) required_final = db.FloatField(default=0) require_new_order = db.BooleanField(default=False) once_per_user = db.BooleanField(default=False) # note for internal usage note = db.StringField() coupon_category = db.StringField(choices=['PROMOTION', 'STAFF', 'NEW_USER'], default='PROMOTION') @property def is_expired(self): if not self.expire_date: return False return (datetime.utcnow() >= self.expire_date) def to_json(self): return dict( coupon_type=self.coupon_type, value=self.value, code=self.code, effective_date=format_date(self.effective_date, '%Y-%m-%d'), expire_date=format_date(self.expire_date, '%Y-%m-%d'), is_expired=self.is_expired, description=self.description) def is_effective(self): return self.effective_date <= datetime.utcnow() < self.expire_date def can_apply(self, order): res = bool( (self.required_final <= order.final) and (self.required_amount <= order.amount) and not (self.require_new_order and order.customer.orders) and not (self.once_per_user and order.customer.used_coupon(self.code)) ) return res
class Statistics(db.Document): meta = { 'db_alias': 'inventory_db', 'indexes': ['tag', 'sub_category', 'main_category', 'brand'], } main_category = db.StringField() sub_category = db.StringField() brand = db.StringField() tag = db.StringField() sex_tag = db.StringField() count = db.IntField(required=True, default=1) @classmethod def create(cls, main, sub, brand, tags, sex_tag): if not tags: tags = [None] for tag in tags: try: stats = cls.objects.get(main_category=main, sub_category=sub, brand=brand, tag=tag, sex_tag=sex_tag) stats.count += 1 stats.save() except: stats = cls(main_category=main, sub_category=sub, brand=brand, tag=tag, sex_tag=sex_tag) stats.save() def to_json(self): return dict(main=self.main_category, sub=self.sub_category, brand=self.brand, tag=self.tag, sex_tag=self.sex_tag, count=self.count)
class PostActivity(db.Document): meta = { 'db_alias': 'content_db', 'indexes': ['user_id', 'to_user_id', 'post', 'created_at', 'action'], 'ordering': ['-created_at'] } user_id = db.ObjectIdField() post = db.ReferenceField('Post') action = db.StringField(choices=NOTI_TYPE) created_at = db.DateTimeField(default=datetime.utcnow, required=True) to_user_id = db.ObjectIdField() info = db.StringField(default="") @property def user(self): from application import models as Models return Models.User.objects(id=self.user_id).first() @property def to_user(self): from application import models as Models return Models.User.objects(id=self.to_user_id).first() def to_json(self): user = self.user return dict( id=str(self.id), user=dict(id=str(user.id), name=user.name, avatar_url=user.avatar_url, avatar_thumb=user.avatar_thumb), ) @classmethod def create(cls, user, to_user, post, action, info=''): noti = cls(user_id=user, to_user_id=to_user, action=action, info=info, post=post).save() return noti
class TransferOrderCode(db.Document): order_id = db.ObjectIdField() code = db.StringField() @classmethod def set_order(cls, order_id): import random code = random.randint(100000, 999999) cls.objects(order_id=order_id).update_one(set__order_id=order_id, set__code=code, upsert=True)