class RecruitingCycle(db.Document): url = db.StringField(max_length=70)
class ControlData(db.EmbeddedDocument): controlTopic = db.StringField() controlStatus = db.FloatField()
class Wifi(db.Document): ssid = db.StringField() password = db.StringField() meta = {'max_documents': 1, 'max_size': 200}
class Role(db.Document, RoleMixin): name = db.StringField(max_length=255)
class Controls(db.Document): groupName = db.StringField() rooms = db.ListField(db.EmbeddedDocumentField(Rooms)) meta = {'collection': 'controls', 'queryset_class': BaseQuerySet}
class Role(db.Document): pkid = db.IntField(required=True) name = db.StringField(required=True, max_length=100) index = db.StringField(required=True) permissions = db.DictField(required=True) default = db.BooleanField(required=True, default=False) enable = db.BooleanField(required=True, default=True) createtime = db.DateTimeField(required=True, default=arrow.utcnow().datetime) meta = { 'db_alias': 'account', 'collection': 'role', 'allow_inheritance': True } def __init__(self, **kwargs): super(Role, self).__init__(**kwargs) if self.permissions is None: self.permissions = Permission().to_json() def save(self): if self.pkid is None: self.pkid = Counter.get_id('role') super(Role, self).save() def to_json(self): return { "pkid": self.pkid, "name": self.name, "index": self.index, "permissions": self.permissions, } def get_pkid(self): return str(self.pkid) @staticmethod def insert_roles(): permissions = Permission().to_json() roles = dict() roles['User'] = dict( permissions=permissions, index='account', default=True, enable=True, ) permissions['content_audit'] = True permissions['content_manage'] = True roles['Manager'] = dict( permissions=permissions, index='admin', default=False, enable=True, ) permissions['account_manage'] = True permissions['administer'] = True roles['Administrator'] = dict( permissions=permissions, index='admin', default=False, enable=True, ) for k, v in roles.items(): role = Role.objects(name=k).first() if role is None: role = Role(name=k) role.permissions = v['permissions'] role.index = v['index'] role.default = v['default'] role.enable = v['enable'] role.save() def add_permission(self, perm): if not self.has_permission(perm): self.permissions[perm] = True def remove_permission(self, perm): if self.has_permission(perm): self.permissions[perm] = False def reset_permissions(self): self.permissions = Permission().to_json() def has_permission(self, perm): return self.permissions[perm] def __repr__(self): return '<Role %r>' % self.name
class Note(db.Document): title = db.StringField(required=True, max_length=120) content = db.StringField() last_updated = db.DateTimeField(default=datetime.datetime.now()) user = db.ReferenceField(User)
class Category(db.Document): category = db.StringField(required=True, Unique=True, max_length=10)
class Payment(db.Document): """""" meta = { 'db_alias': 'db_order', 'indexes': ['order', 'ptype', '-created_at'], } created_at = db.DateTimeField(default=datetime.datetime.utcnow(), required=True) order = db.ReferenceField('Order') logistic = db.ReferenceField('Logistic') other_reason = db.StringField() ptype = db.StringField(required=True, choices=PAYMENT_TYPE) status = db.StringField(max_length=256, required=True, choices=PAYMENT_STATUS, default=PAYMENT_STATUS.UNPAID) # transaction reference number from alipay/bank ref_number = db.StringField(max_length=128) paid_amount = db.FloatField() foreign_amount = db.FloatField() currency = db.StringField() buyer_id = db.StringField(max_length=50) trader = db.StringField(choices=PAYMENT_TRADERS) trade_type = db.StringField(choices=TRADE_TYPE) trade_status = db.StringField() trader_msg = db.StringField() extra = db.StringField() modified = db.DateTimeField() redirect_url = db.StringField() @property def is_paid(self): return self.status == PAYMENT_STATUS.PAID @property def amount(self): if self.ptype == PAYMENT_TYPE.WITHOUT_TAX: return self.order.final if self.ptype == PAYMENT_TYPE.WITH_TAX: return self.order.final + self.order_tax def mark_paid(self, data): if self.is_paid: return self.update(set__status=PAYMENT_STATUS.PAID) kwargs = {'set__' + key: value for key, value in data.items()} self.update(**kwargs) self.reload() paid_amount = float(data.get('paid_amount', 0)) if self.ptype == PAYMENT_TYPE.WITHOUT_TAX: self.order.update_payment(self.ptype, paid_amount, self.trader) def to_json(self): return dict(id=self.id, ref_num=self.ref_number, status=self.status, type=self.type, amount=self.amount)
class Table(db.Document): number = db.StringField() owner = db.ReferenceField(User) url = db.StringField() empty = True
class Requests(db.Document): tableid = db.ReferenceField(Table) table_number = db.StringField() time = db.DateTimeField() wait_minutes = db.DateTimeField() owner = db.ReferenceField(User)
class Todo(db.Document): content = db.StringField() time = db.DateTimeField(default=datetime.datetime.now()) status = db.IntField(default=0)
class Users(db.Document): username = db.StringField(required=True, unique=True) password = db.StringField(required=True) email = db.EmailField(required=True)
class Capital(db.Document): ''' coin str 货币代码 name str 货币名称 marketcap str 市值(美元) price float 当前时间价格(美元) vol24 float 24小时成交额(美元) supply float 流通总量 date str 交易日期 ctime datetime 数据采集时间 ''' _id = db.StringField() coin = db.StringField(required=True) name = db.StringField(required=True) marketcap = db.StringField(required=True) price = db.FloatField(required=True, default=0) vol24 = db.FloatField(required=True, default=0) supply = db.FloatField(required=True, default=0) time = db.DateTimeField(required=True) ctime = db.DateTimeField(required=True, default=arrow.utcnow().datetime) utime = db.DateTimeField(required=True, default=arrow.utcnow().datetime) meta = {'db_alias': 'market', 'collection': 'capital', 'strict': False} def to_json(self, key=True): if key: return { "coin": self.coin.upper(), "name": self.name, "marketcap": self.marketcap, "price": self.price, "vol24": self.vol24, "supply": self.supply, "time": self.time, "ctime": arrow.get(self.ctime).float_timestamp, } else: return [ arrow.get(self.time).float_timestamp, self.name, self.marketcap, self.price, self.vol24, self.supply, ] def __repr__(self): return '<Trade name:\'%s\', marketcap:\'%s\'>' % (self.name, self.marketcap) @staticmethod def get_within(coin=None, date=None, start_time=None, end_time=None, key=True): ''' 获取时间区间内的数据 :param coin: :param date: :param start_time: :param end_time: :param key: :return: ''' query = Capital.objects if coin: query = query.filter(coin=coin) if date: query = query.filter(date=date) if freq: query = query.filter(freq=freq) if start_time: start_time = arrow.get(start_time).datetime query = query.filter(time__gte=start_time) if end_time: end_time = arrow.get(end_time).datetime query = query.filter(time__lt=end_time) data_list = query.order_by("time").all() result = [] if data_list: for data in data_list: result.append(data.to_json(key)) return result @staticmethod def insert_data(data): if 'coin' not in data or 'marketcap' not in data or 'time' not in data: raise Exception('params missed') # 检测,防止重复插入 capital = Capital.objects(coin=data['coin'], marketcap=data['marketcap'], time=data['time']).first() if not capital: return Capital(**data).save() else: # 只更新当天的,过去的数据不用改变,所以不用更新 new_time = arrow.get(data['time']).datetime old_time = arrow.get(capital.time).datetime if new_time == old_time: update_data = dict() if 'marketcap' in data and data[ 'marketcap'] != capital.marketcap: update_data['marketcap'] = data['marketcap'] if 'price' in data and data['price'] != capital.price: update_data['price'] = data['price'] if 'vol24' in data and data['vol24'] != capital.vol24: update_data['vol24'] = data['vol24'] if 'supply' in data and data['supply'] != capital.supply: update_data['supply'] = data['supply'] if update_data: print('Capital update:', capital._id, update_data) update_data['utime'] = arrow.utcnow().datetime Capital.objects(_id=capital._id).update_one(**update_data) return True
class Tip(db.Document): """ Represents the definition of a tip in the repository. Fields: tip_name Name of the tip. Required. takes a string. description Brief description of the tip. Required. takes a string difficulty Level of difficulty for the tip. Required. takes a string: 'beginner', 'intermediate', or 'advanced' media_type Type of supplemental media. Required. takes a string: 'No Supplemental Media', 'Video', or 'Audio media_url Audio component. Optional. takes a string. video_id ID of a youtube video, used to embed. Optional. takes a string. submitter Name of the submitter. Required. takes a string equipment Names of equipment that might relate to this tip. Optional. takes a list of strings ingredients Names of ingredients that might relate to this tip. Optional. takes a list of strings techniques Names of techniques that might relate to this tip. Optional. takes a list of strings instructions Main text of the tip. takes a string tags List of the categories it falls into takes a list of strings (method, ingredient, equipment) """ query_class = TipQuery tip_name = db.StringField(required=True) description = db.StringField(required=True) difficulty = db.StringField(required=True) media_type = db.StringField(required=True) media_url = db.StringField(required=False) video_id = db.StringField(required=False) submitter = db.StringField(required=False) equipment = db.ListField(db.StringField(required=False), required=False) ingredients = db.ListField(db.StringField(required=False), required=False) techniques = db.ListField(db.StringField(required=False), required=False) instructions = db.ListField(db.StringField(required=False), required=False) tags = db.ListField(db.StringField(required=False), required=False) def get_id(self): return str(self.mongo_id)
class Order(db.Document): """""" meta = { 'db_alias': 'db_order', 'ordering': ['-created_at'], 'indexes': [ 'customer_id', 'status', 'address', 'amount', 'final', 'order_type', 'is_paid', 'is_payment_abnormal', 'refund_entries' ], } created_at = db.DateTimeField(default=datetime.datetime.utcnow, required=True) order_type = db.StringField(choices=ORDER_TYPE, default=ORDER_TYPE.COMMODITY) # one day expired_in = db.IntField(default=1440) # in minutes payment_expired_in = db.IntField(default=1440) short_id = db.SequenceField(required=True, unique=True) is_vip = db.BooleanField(default=False) status = db.StringField(max_length=256, required=True, choices=ORDER_STATUS, default=ORDER_STATUS.PAYMENT_PENDING) status_modified = db.DateTimeField() source = db.StringField(choices=ORDER_SOURCES) is_rewards_given = db.BooleanField(default=False) # order detail amount_usd = db.FloatField(default=0) amount = db.FloatField(default=0) discount = db.ListField(db.DictField()) # 优惠卷兑换码 coupon_codes = db.ListField(db.StringField()) coin = db.IntField() lucky_money = db.IntField() cash = db.IntField() final = db.FloatField(required=True) # 库存 logistic_provider = db.StringField() # 预估退税 estimated_tax = db.FloatField(default=0) real_tax = db.FloatField(default=-1) paid_tax = db.FloatField(default=-1) # for internal usage # 汇率 forex = db.FloatField() real_shipping = db.FloatField() cn_shipping = db.FloatField(default=0) address = db.ReferenceField('Address') customer_id = db.ObjectIdField(required=True) is_new_customer = db.BooleanField(default=False) entries = db.ListField( db.ReferenceField('OrderEntry', reverse_delete_rule=mongoengine.PULL)) extra = db.StringField() logistics = db.ListField(db.ReferenceField('Logistic')) # 库存 closed_logistics = db.ListField(db.ReferenceField('Logistic')) is_paid = db.BooleanField(default=False) # 是否支付 is_payment_abnormal = db.BooleanField(default=False) # 是否支付异常 paid_date = db.DateTimeField() # 支付时间 pay_tax_deadline = db.DateTimeField() # 支付税截至时间 refund_entries = db.ListField( db.ReferenceField('OrderEntry', reverse_delete_rule=mongoengine.PULL)) refund_amount = db.FloatField(default=0) is_test = db.BooleanField(default=False) fields_to_log = { 'status', 'amount', 'coin', 'final', 'estimated_tax', 'real_tax', 'paid_tax', 'real_shipping', 'is_paid', } # 处理中的状态 PROCESSING_STATUS = [ORDER_STATUS.PAYMENT_RECEIVED, ORDER_STATUS.SHIPPING] # 异常状态 ABNORMAL_STATUS = [ ORDER_STATUS.CANCELLED, ORDER_STATUS.ABNORMAL, ORDER_STATUS.ORDER_DELETE, ORDER_STATUS.EXPIRED, ORDER_STATUS.REFUNDED ] def __unicode__(self): return '%s' % self.sid def __str__(self): return '{}'.format(self.id) @classmethod def get_order_or_404(cls, order_id, check_user=True): try: order = cls.objects(id=order_id).first_or_404() except mongoengine.ValidationError: try: short_id = int(order_id) except (ValueError, TypeError): abort(404) order = cls.objects(short_id=short_id).first_or_404() if check_user and str(order.customer_id) != str(current_user.id): abort(404) return order @queryset_manager def commodities(doc_cls, queryset): return queryset.filter(order_type=ORDER_TYPE.COMMODITY, status__nin=doc_cls.ABNORMAL_STATUS) @queryset_manager def transfer(doc_cls, queryset): return queryset.filter(order_type=ORDER_TYPE.TRANSFER, status__nin=doc_cls.ABNORMAL_STATUS) @queryset_manager def processing(doc_cls, queryset): return queryset.filter(status__in=doc_cls.PROCESSING_STATUS) @queryset_manager def payment_pending(doc_cls, queryset): return queryset.filter(status=ORDER_STATUS.PAYMENT_PENDING) @queryset_manager def abnormal(doc_cls, queryset): return queryset.filter( Q(status__in=doc_cls.ABNORMAL_STATUS) | Q(refund_entries__0__exists=True) & Q(status__in=doc_cls.PROCESSING_STATUS + [ORDER_STATUS.RECEIVED])) @queryset_manager def received(doc_cls, queryset): return queryset.filter(status=ORDER_STATUS.RECEIVED) @queryset_manager def is_processing(self): return self.status in self.PROCESSING_STATUS @queryset_manager def is_payment_pending(self): return self.status == ORDER_STATUS.PAYMENT_PENDING @queryset_manager def is_abnormal(self): if self.status in self.ABNORMAL_STATUS: return True if self.status in self.PROCESSING_STATUS or self.status == ORDER_STATUS.RECEIVED: return len(self.refund_entries) > 0 return False def has_refund_entries(self): if self.status in (self.PROCESSING_STATUS + [ORDER_STATUS.RECEIVED, ORDER_STATUS.REFUNDED]): return len(self.refund_entries) > 0 return False @property def tax(self): if self.real_tax == -1: return self.estimated_tax else: return self.real_tax @property def shipping(self): return self.cn_shipping @property def estimated_weight(self): return sum( float(entry.item_snapshot.weight) * entry.quantity for entry in self.entries) @property def pay_tax_remain_days(self): if self.pay_tax_deadline: time_remain = self.pay_tax_deadline.date() - datetime.date.today() if time_remain.days > 0: return time_remain.days @property def latest_logistic(self): attr = LogisticDetail.attr_by_log_status.get(self.status) if not attr: return None return max(self.logistics, key=lambda l: getattr(l.detail, attr)) @classmethod def create_transfer(cls, customer_id, entries, logistic_provider, coupon_codes, coin=0, cash=0, address=None, **kwargs): order = cls(customer_id=customer_id, entries=entries, logistic_provider=logistic_provider, coupon_codes=coupon_codes, coin=coin, cash=cash, **kwargs) if not order.forex: order.forex = ForexRate.get() order.update_amount() order.reload() if address: order.set_address(address) order_created.send('system', order=order) return order @classmethod def create_from_skus(cls, customer_id, skus, logistic_provider, coupon_codes, coin=0, cash=0, address=None, **kwargs): entries = [] for s in skus: availability = check_availability_and_update_stock( s['item_id'], s['sku'], s['quantity']) if not availability: return s spec = ItemSpec.objects(sku=s['sku']).first() item = Item.objects(item_id=['item_id']).first() entry = OrderEntry(spec=spec, item=item, quantity=s['quantity']).save() entries.append(entry) order = cls(customer_id=customer_id, entries=entries, logistic_provider=logistic_provider, coupon_codes=coupon_codes, coin=coin, cash=cash, **kwargs) if not order.forex: order.forex = ForexRate.get() order.update_amount() order.reload() # 简介 for e in order.entries: e.create_snapshot() if address: order.set_address(address) order_created.send('system', order=order) return order @classmethod def create(cls, customer_id, entries, logistic_provider, coupon_codes, coin=0, cash=0, address=None, **kwargs): order_entries = [] for entry in entries: availability = check_availability_and_update_stock( entry.item_snapshot.item_id, entry.item_spec_snapshot.sku, entry.quantity) if not availability: return entry if isinstance(entry, (CartEntry, OrderEntry)): e = deepcopy(entry) e.__class__ = OrderEntry e.id = None order_entries.append(e.save()) order = cls(customer_id=customer_id, entries=order_entries, logistic_provider=logistic_provider, coupon_codes=coupon_codes, coin=coin, cash=cash, **kwargs) if not order.forex: order.forex = ForexRate.get() order.update_amount() order.reload() for e in order.entries: e.create_snapshot() if address: order.set_address(address) order_created.send('system', order=order) return order @property def item_changed(self): res = False for e in self.entries: res = res and e.item_changed if res: return res return res def __get__(self, *args, **kwargs): order = super(Order, self).__get__(*args, **kwargs) if (not order.is_paid) and order.item_changed: order.update_entry() return order def update_entry(self): if self.is_paid: return map(lambda e: e.update_snapshot(), self.entries) self.update_amount() def set_address(self, addr): if not isinstance(addr, Address): addr = Address.objects(id=addr).first() if not addr: return False addr_snapshot = deepcopy(addr) addr_snapshot.id = None addr_snapshot.order_id = self.id addr_snapshot.save() if self.address: self.address.delete(w=1) self.address = addr_snapshot self.save() return True @property def customer(self): return User.objects(id=self.customer_id).first() def create_payment(self, ptype, trader): ptype = ptype.upper() self.update_entry() self.reload() if self.order_type != ORDER_TYPE.TRANSFER: is_available = self.check_entries_avaliable() if not is_available or self.status in [ 'CANCELLED', 'ABNORMAL', 'ORDER_DELETED', 'EXPIRED' ]: return None new_payment = Payment(order=self, ptype=ptype, trader=trader).save() return new_payment def get_payment(self, ptype): ptype = ptype.upper() payments = Payment.objects(order=self, ptype=ptype).order_by('-created_at') paid_payments = payments.filter(status=PAYMENT_STATUS.PAID) if paid_payments: return paid_payments.first() else: return payments.first() @property def goods_payment(self): return self.get_payment(PAYMENT_TYPE.WITHOUT_TAX) @property def tax_payment(self): return self.get_payment(PAYMENT_TYPE.WITH_TAX) @property def refunds(self): return Refund.objects(order=self) def check_entries_avaliable(self): availability = all( map(lambda e: e.is_available or e.item_spec_snapshot.stock != -1, self.entries)) if not availability: self.status = ORDER_STATUS.EXPIRED self.save() return availability def set_paid(self): if self.is_paid: return self.is_new_customer = not bool( Order.objects(custom_id=self.customer_id, is_paid=True)) self.is_paid = True self.status = ORDER_STATUS.PAYMENT_RECEIVED self.paid_date = datetime.datetime.utcnow() self.save() payment_received(self) def update_payment(self, paid_type, paid_amount, trader): if paid_type == PAYMENT_TYPE.WITHOUT_TAX and not self.is_paid and self.status in [ ORDER_STATUS.PAYMENT_PENDING, ORDER_STATUS.W ]: if paid_amount == self.final and trader == PAYMENT_TRADERS.PAYPAL: self.set_paid() elif paid_amount == float('%.2f' % (self.final * self.forex) ) and trader == PAYMENT_TRADERS.WEIXIN: self.set_paid() else: current_app.logger.error( 'error at updating payment. trader: {}; ptype: {}; amount: {} order id: {}' .format(trader, paid_type, paid_amount, self.id)) self.is_payment_abnormal = True else: current_app.logger.error( 'error at updating payment. trader: {}; ptype: {}; amount: {}; order id: {}' .format(trader, paid_type, paid_amount, self.id)) self.is_payment_abnormal = True self.save() @property def coin_trades(self): return Trade.objects(reason_id=str(self.id)) def update_logistic_status(self): if self.logistics: log_status = map(lambda m: m.detail.status, self.logistics) new_status = min(log_status, key=lambda l: LOG_STATUS.index(1)) self._change_status(new_status) def _change_status(self, new_status): if self.status == new_status: return self.status = new_status self.status_modified = datetime.datetime.utcnow() self.save() if new_status in LOG_STATUS: notification_order(self, new_status) order_logistic_status_changed.send('Order.Logistic.Status.Changed', order=self, new_status=new_status) else: order_status_changed.send('order_status_changed', order=self, new_status=new_status) def delete_order(self): for l in self.logistics: l.delete(w=1) for entry in self.entries: entry.delete(w=1) if self.goods_payment: self.goods_payment.delete(w=1) self.delete(w=1) def cancel_order(self, reason, status=None): """ :param reason: :param status: :return: """ for l in self.logistics: l.close(reason) self.extra = reason self.save() if not status: status = ORDER_STATUS.ABNORMAL self._change_status(status) for entry in self.entries: try: if entry.spec.stock != -1: entry.spec.update(inc__stock=entry.quantity, set__availability=True) entry.item.update(set__availability=True, set__status='MOD') except AttributeError: pass def update_amount(self): for e in self.entries: e.update_amount() cal_order_price_and_apply(self) self.estimated_tax = cal_order_tax(self) self.save() @property def sid(self): return self.short_id def to_json(self, include_logistic=False, replace_entries_to_refunded=False): if not self.is_paid: self.update_amount() self.reload() entries_json = [] if replace_entries_to_refunded and self.has_refund_entries(): for e in self.refund_entries: entries_json.append(e.to_json()) else: for e in self.entries: entries_json.append(e.to_json()) refund_entries_json = [] for e in self.refund_entries: refund_entries_json.append(e.to_json()) result = dict( id=str(self.id), short_id=str(self.sid), status=self.status, customer_id=str(self.customer_id), amount=self.amount, cn_shipping=self.cn_shipping, coin=self.coin, lucky_money=self.lucky_money, discount=self.discount, final=self.final, estimated_tax=self.estimated_tax, payment_status='PAID' if self.is_paid else 'UNPAID', payment_ref_number=[ p.ref_number for p in Payment.objects(order=self) ], created_at=format_date(self.created_at), entries=entries_json, refund_entries=refund_entries_json, refund_amount=self.refund_amount, real_tax=self.real_tax, ) if self.address: result.update({'address': self.address.to_json()}) if include_logistic: result.update(logistics=[l.to_json() for l in self.logistics]) return result def to_grouped_json(self): """ :return: """ res = dict( estimated_weight=self.estimated_weight, amount=self.amount, cn_shipping=self.cn_shipping, coin=self.coin, lucky_money=self.lucky_money, discount=self.discount, final=self.final, extimated_tax=self.extimated_tax, ) res['sid'] = self.id res['status'] = self.status if self.address: res.update(dict(address=self.address.to_json())) return res
class Kline(db.Document): ''' ex: str 交易所 contract: str 交易对 open: float 开盘价 high: float 最高价 low: float 最低价 close: float 收盘价 volume: float 成交量 count: int 成交笔数(默认不展示,有些交易所没有此项数据,若需要请在fields里添加) amount: float 成交额 (默认不展示,需在fields里添加上,有些交易所没有此项数据) freq: str 行情频率 time: datetime 行情时间 ''' _id = db.StringField() ex = db.StringField(required=True) contract = db.StringField(required=True) open = db.FloatField(required=True) high = db.FloatField(required=True) low = db.FloatField(required=True) close = db.FloatField(required=True) volume = db.FloatField(required=True) count = db.FloatField(required=True, default=0) amount = db.FloatField(required=True, default=0) freq = db.StringField(required=True) time = db.DateTimeField(required=True) ctime = db.DateTimeField(required=True, default=arrow.utcnow().datetime) utime = db.DateTimeField(required=True, default=arrow.utcnow().datetime) meta = {'db_alias': 'market', 'collection': 'kline', 'strict': False} def to_json(self, key=True): if key: return { "ex": self.ex.upper(), "contract": self.contract.upper(), "open": self.open, "high": self.high, "low": self.low, "close": self.close, "volume": self.volume, "freq": self.freq, "time": arrow.get(self.time).float_timestamp, "ctime": arrow.get(self.ctime).float_timestamp, } else: return [ arrow.get(self.time).float_timestamp, self.open, self.high, self.low, self.close, self.volume, ] def __repr__(self): return '<Kline ex:\'%s\', contract:\'%s\'>' % (self.ex, self.contract) @staticmethod def get_within(ex=None, contract=None, freq=None, start_time=None, end_time=None, limit=None, order=None, key=True): ''' 获取时间区间内的数据 :param ex: :param contract: :param freq: :param start_time: :param end_time: :param limit: :param key: :return: ''' if contract not in ALL_CONTRACTS: raise Exception('error contract') query = Kline.objects if ex: query = query.filter(ex=ex) if contract: query = query.filter(contract=contract) if freq: query = query.filter(freq=freq) if start_time: start_time = arrow.get(start_time).datetime query = query.filter(time__gte=start_time) if end_time: end_time = arrow.get(end_time).datetime query = query.filter(time__lt=end_time) if order: query = query.order_by(order) data_list = query.all() if limit: data_list = data_list[:limit] result = [] if data_list: for data in data_list: result.append(data.to_json(key)) return result @staticmethod def insert_data(data, update_when_exist=True, update_fields=['open', 'high', 'low', 'close', 'volume']): ''' 新增数据 :param data: :return: ''' if 'ex' not in data or 'contract' not in data or 'freq' not in data or 'time' not in data: raise Exception('params missed') if data['contract'] not in ALL_CONTRACTS: raise Exception('error contract') # 检测,防止重复插入 kline = Kline.objects(ex=data['ex'], contract=data['contract'], freq=data['freq'], time=data['time']).first() if not kline: return Kline(**data).save() else: if not update_when_exist: return False # 只更新当天的,过去的数据不用改变,所以不用更新 new_time = arrow.get(data['time']).datetime old_time = arrow.get(kline.time).datetime if new_time == old_time: update_data = dict() if 'open' in data and data[ 'open'] != kline.open and 'open' in update_fields: update_data['open'] = data['open'] if 'high' in data and data[ 'high'] != kline.high and 'high' in update_fields: update_data['high'] = data['high'] if 'low' in data and data[ 'low'] != kline.low and 'low' in update_fields: update_data['low'] = data['low'] if 'close' in data and data[ 'close'] != kline.close and 'close' in update_fields: update_data['close'] = data['close'] if 'volume' in data and data[ 'volume'] != kline.volume and 'volume' in update_fields: update_data['volume'] = data['volume'] if update_data: print('kline update:', data['ex'], data['contract'], data['freq'], data['time'], update_data) update_data['utime'] = arrow.utcnow().datetime Kline.objects(_id=kline._id).update_one(**update_data) return True
class Events(db.EmbeddedDocument): time = db.LongField() desc = db.StringField()
class User(db.Document): """A user model. The :class:`User` object is only created once the user logs in for the first time and confirms the details of their account. :ivar date_created: :class:`mongoengine.fields.DateTimeField` - The date that this user was created. :ivar date_modified: :class:`mongoengine.fields.DateTimeField` - The date the this user was last modified. :ivar gplus_id: :class:`mongoengine.fields.StringField` - The Google+ ID for this user. It's what we use in the Google+ authentication. :ivar name: :class:`mongoengine.fields.StringField` - The user's name. :ivar slug: :class:`mongoengine.fields.StringField` - A URL slug their internal profile page. :ivar email: :class:`mongoengine.fields.EmailField` - The user's email address. :ivar roles: :class:`mongoengine.fields.ListField` of :class:`mongoengine.fields.StringField` - A list of roles that the user has. :ivar privileges: :class:`mongoengine.fields.DictField` - A dictionary of privileges that the user has. Often determined soley by their ``user_type``. :ivar image_url: :class:`mongoengine.fields.URLField` - The URL of the profile picture for the user's profile picture. :ivar image: :class:`mongoengine.fields.ReferenceField` - The local image for the user's profile picture. :ivar user_type: :class:`mongoengine.fields.StringField` - The type of the user. Can either be ``"fake_user"``, ``"editor"``, ``"publisher"``, or ``"admin"``. The selection of user type determines their ``privileges``. :ivar last_logon: :class:`mongoengine.fields.DateTimeField` - The date of this user's last logon. """ date_created = db.DateTimeField(required=True, default=now) date_modified = db.DateTimeField(required=True, default=now) gplus_id = db.StringField(required=True, unique=True) name = db.StringField(required=True, max_length=510) slug = db.StringField(required=True, max_length=510, unique=True, regex=SLUG_REGEX) email = db.EmailField(required=True, unique=True) roles = db.ListField(db.StringField(db_field="role"), default=list) privileges = db.DictField(required=True, default={}) image_url = db.URLField() image = db.ReferenceField('Image') user_type = db.StringField(default='editor', regex=USER_TYPE_REGEX) last_logon = db.DateTimeField() # MongoEngine ORM metadata meta = {'allow_inheritance': True, 'indexes': ['email', 'gplus_id']} def can(self, privilege): """Returns True if the user has ``privilege``. :returns: True if the user has ``privilege`` :rtype: bool """ return self.privileges.get(privilege) def get_profile_picture(self, size=50): """Returns the url to the profile picture for the user. TODO: This method needs major fixing. What's going on with that URL? :param int size: The size of the image to pass, if the size can be changed. :returns: The URL of the image. :rtype: str """ if self.image: return self.image.url() if not self.image_url: # Import app in the function body to avoid importing `None` when # the module is first loaded. from app import app return url_for('static', filename=app.config['DEFAULT_PROFILE_PICTURE']) if "googleusercontent.com" in self.image_url: return self.image_url + str(size) return self.image_url def register_login(self): """Update the model as having logged in.""" self.last_logon = now() def clean(self): """Called by Mongoengine on every ``.save()`` to the object. Update date_modified and apply privileges shorthand notation. :raises: :class:`wtforms.validators.ValidationError` """ self.date_modified = now() # Update self.privileges with one of the USER_TYPES dictionaries self.privileges.update(USER_TYPES[self.user_type]) # Update the slug for the user (used in URLs) new_slug = self.name.lower().replace(' ', '-') new_slug = re.sub(r"\'|\.|\_|", "", new_slug) if User.objects(slug=new_slug).count() > 0: i = 2 new_slug = new_slug + "-{}".format(i) while User.objects(slug=new_slug).count() > 0: i += 1 new_slug = re.sub(r"-([0-9])*$", "-{}".format(i), new_slug) self.slug = new_slug if self.image_url and "googleusercontent.com" in self.image_url: self.image_url = re.sub(r"sz=([0-9]*)$", "sz=", self.image_url) def id_str(self): """The id of this object, as a string. :returns: The id :rtype: str """ return str(self.id) def role(self): """Returns the role of the user, in plain English. It is either ``"Admin"``, ``"Publisher"``, ``"Editor"``, or ``"Fake User"``. :returns: The role. :rtype: str """ if self.can('admin'): return "Admin" if self.can('publish'): return "Publisher" if self.can('edit'): return "Editor" return "Fake User" def __repr__(self): """The representation of this user. :returns: The user's details. :rtype: str """ return ('User(id=%r, name=%r, email=%r, roles=%r, privileges=%r, ' 'gplus_id=%r, date_created=%r)' % (self.id, self.name, self.email, self.roles, self.privileges, self.gplus_id, self.date_created)) def __unicode__(self): """This user, as a unicode string. :returns: The user encoded as a string. :rtype: str """ if self.can('admin'): return '%r <%r> (Admin)' % (self.name, self.email) if self.can('publish'): return '%r <%r> (Publisher)' % (self.name, self.email) if self.can('edit'): return '%r <%r> (Editor)' % (self.name, self.email) else: return '%r <%r> (Fake User)' % (self.name, self.email)
class DynamicRow(db.Document): timeStamp = db.StringField() motor = db.EmbeddedDocumentField(Motor) dataReceived = db.EmbeddedDocumentField(DataReceived) meta = {'collection': 'DynamicRow'}
class User(db.Document): email = db.EmailField(unique=True) password = db.StringField(default=True) active = db.BooleanField(default=True) isAdmin = db.BooleanField(default=False) timestamp = db.DateTimeField(default=datetime.datetime.now())
class Weather(db.Document): anaemometer = db.StringField() pyranometer = db.StringField() site = db.IntField() timeStamp = db.IntField()
class Rooms(db.EmbeddedDocument): name = db.StringField() controls = db.ListField(db.EmbeddedDocumentField(Control))
class Motor(db.EmbeddedDocument): trackingResolution = db.IntField() status = db.StringField() cumulativeHours = db.IntField() current = db.FloatField() inclinometerAngle = db.FloatField()
class AccessGroup(db.DynamicDocument): type = db.StringField(max_length=10) name = db.StringField(max_length=80, unique=True) UIDs = db.ListField(db.StringField(), default=[]) meta = {'collection': 'access_group'}
class Led(db.EmbeddedDocument): power = db.StringField() comm = db.StringField() motor = db.StringField() mode = db.StringField() master = db.StringField()
class Mode(db.Document): name = db.StringField() controlData = db.EmbeddedDocumentListField(ControlData)
class Transactions(db.Document): sourceAccount = db.StringField() destinationAccount = db.StringField() value = db.IntField() createdDate = db.DateTimeField(default=datetime.now)
class Todo(db.Document): content = db.StringField(required=True, max_length=20) time = db.DateTimeField(default=datetime.datetime.now()) status = db.IntField(default=0)
class User(UserMixin, db.Document): user_id = db.IntField(required=True) user_name = db.StringField(required=True, max_length=100) email = db.StringField(max_length=200) password_hash = db.StringField(requied=True) timezone = db.StringField(requied=True, max_length=6) user_info = db.DictField(requied=True) role_id = db.IntField(required=True) confirmed = db.BooleanField(required=True, default=False) must_change_password = db.BooleanField(required=True, default=False) banned = db.BooleanField(required=True, default=False) suspended = db.BooleanField(required=True, default=False) created_time = db.DateTimeField(required=True, default=arrow.utcnow().datetime) updated_time = db.DateTimeField(required=True, default=arrow.utcnow().datetime) meta = { 'db_alias': 'account', 'collection': 'user', 'allow_inheritance': True } def __init__(self, **kwargs): super(User, self).__init__(**kwargs) def save(self): if not self.user_id: self.user_id = Counter.get_id('user') if not self.user_info: self.user_info = default_user_info super(User, self).save() def to_json(self): return { "user_id": self.user_id, "user_name": self.user_name, "email": self.email, "timezone": self.timezone, "role_id": self.role_id, "confirmed": self.confirmed, "must_change_password": self.must_change_password, "banned": self.banned, "suspended": self.suspended, "created_time": self.created_time, "updated_time": self.updated_time, } @property def role(self): return Role.objects(pkid=self.role_id, enable=True).first() def full_name(self): return '%s %s' % (self.user_info['first_name'], self.user_info['last_name']) def can(self, permission): return self.role is not None and self.role.permissions[ permission] == True def is_admin(self): return self.can('administer') def is_active(self): return True @property def is_authenticated(self): return True def is_confirmed(self): return self.confirmed def is_must_change_password(self): return self.must_change_password def is_banned(self): return self.banned def is_suspended(self): return self.suspended def get_id(self): return str(self.user_id) @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): """Generate a confirmation token to email a new user.""" s = Serializer(current_app.config['SECRET_KEY'], expiration) return s.dumps({'confirm': self.user_id}) def generate_email_change_token(self, new_email, expiration=3600): """Generate an email change token to email an existing user.""" s = Serializer(current_app.config['SECRET_KEY'], expiration) return s.dumps({'change_email': self.user_id, 'new_email': new_email}) def generate_password_reset_token(self, expiration=3600): """ Generate a password reset change token to email to an existing user. """ s = Serializer(current_app.config['SECRET_KEY'], expiration) return s.dumps({'reset': self.user_id}) def confirm_account(self, token): """Verify that the provided token is for this user's id.""" s = Serializer(current_app.config['SECRET_KEY']) try: data = s.loads(token) except (BadSignature, SignatureExpired): return False if data.get('confirm') != self.user_id: return False self.confirmed = True self.save() return True def change_email(self, token): """Verify the new email for this user.""" s = Serializer(current_app.config['SECRET_KEY']) try: data = s.loads(token) except (BadSignature, SignatureExpired): return False if data.get('change_email') != self.user_id: return False new_email = data.get('new_email') if new_email is None: return False if self.objects(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): """Verify the new password for this user.""" 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 = new_password self.save() return True def __repr__(self): return '<User \'%s %s\'>' % (self.user_id, self.user_name)