class MatchOrder(AutoIncrementBase): sell_user_id = db.Column(db.String(36), db.ForeignKey('user.id'), nullable=False) # 卖方用户 buy_user_id = db.Column(db.String(36), db.ForeignKey('user.id'), nullable=False) # 买方用户 sell_order_id = db.Column(db.Integer, db.ForeignKey('order.id'), nullable=False) # 卖方订单 buy_order_id = db.Column(db.Integer, db.ForeignKey('order.id'), nullable=False) # 买方订单 sell_number = db.Column(db.String(16), unique=True, nullable=False) buy_number = db.Column(db.String(16), unique=True, nullable=False) payment_amount = db.Column(db.Numeric(24, 8), default=0, nullable=False) # 对应支付方式,支付金额 人民币 payment_amount_usdt = db.Column(db.Numeric(24, 8), default=0, nullable=False) # 对应支付方式,支付数量 USDT proof_img = db.Column(db.Text, default='[]') # 转账凭证 current_price = db.Column(db.Numeric(24, 8), nullable=False) # 当前价格 payment_id = db.Column(db.String(36), db.ForeignKey('payment.id')) # 卖方收款方式 sell_user = db.relationship(User, foreign_keys=[sell_user_id]) buy_user = db.relationship(User, foreign_keys=[buy_user_id]) sell_order = db.relationship('Order', foreign_keys=[sell_order_id]) buy_order = db.relationship('Order', foreign_keys=[buy_order_id]) payment = db.relationship(Payment, foreign_keys=[payment_id])
class OrderOld(AutoIncrementBase): user_id = db.Column(db.String(36), db.ForeignKey('user.id'), nullable=False) # 卖方用户 match_user_id = db.Column(db.String(36), db.ForeignKey('user.id')) # 买方用户 # side = db.Column(db.SmallInteger, nullable=False) # 1 买单 2 卖单 number = db.Column(db.String(16), default=generate_timestamp_id, unique=True, nullable=False) # price = db.Column(db.Numeric(24, 8), nullable=False) # 单价 amount = db.Column(db.Numeric(24, 8), nullable=False) # 售卖数量 hold_amount = db.Column(db.Numeric(24, 8), nullable=False) # 冻结数量 fee = db.Column(db.Numeric(24, 8), nullable=False) # 手续费 status = db.Column(db.SmallInteger, default=g_order_old_status.PENDING, nullable=False) # 订单状态参见 g_order_status payment_amount = db.Column(db.Numeric(24, 8), default=0, nullable=False) # 对应支付方式,支付数量 match_at = db.Column(db.DateTime) proof_img = db.Column(db.Text, default='[]') # 转账凭证 current_price = db.Column(db.Numeric(24, 8), nullable=False) # 冻结数量 payment_id = db.Column(db.String(36), db.ForeignKey('payment.id')) # 卖方收款方式 details = db.Column(db.String(255), default='', nullable=True) # 备注 user = db.relationship(User, foreign_keys=[user_id]) match_user = db.relationship(User, foreign_keys=[match_user_id]) payment = db.relationship(Payment, foreign_keys=[payment_id])
class Board(db.Model, TimestampMixin): id = db.Column(db.Integer, primary_key=True, nullable=False) title = db.Column(db.String(200), nullable=False) description = db.Column(db.String(200), nullable=True) status = db.Column(ChoiceType(BoardStatus, impl=db.Integer()), default=BoardStatus.NORMAL) user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False) user = db.relationship("User") posts = db.relationship("Post", backref="board", lazy='dynamic') @hybrid_property def is_deleted(self): return self.status == BoardStatus.DELETED def delete(self): self.status = BoardStatus.DELETED def is_owner(self, user: User): return self.user_id == user.id def __repr__(self): return "<Board title: %s, description: %s, status: %s," \ " created_at: %s, updated_at: %s>"\ % (self.title, self.description, self.status, self.created_at, self.updated_at)
class Account(db.Model): __tablename__ = "accounts" id = db.Column(db.Integer(), primary_key=1) name = db.Column(db.String(255), unique=1, nullable=0) text = db.Column(db.String(255), unique=1, nullable=0) info = db.Column(db.String(255), unique=0, nullable=1) auth = db.Column(db.String(255), unique=0, nullable=1) feed = db.relationship("Feed", cascade="all,delete", backref="account", uselist=0) articles = db.relationship("Article", cascade="all,delete", backref="account", lazy="dynamic") def __init__(self, name="", text="", info="", auth=""): self.name = name self.text = text self.info = info self.auth = auth def __repr__(self): return self.text def to_json(self): account = dict() account["id"] = self.id account["name"] = self.name account["text"] = self.text account["info"] = self.info account["auth"] = self.auth return account
class ConfirmOrder(AutoIncrementBase): sell_user_id = db.Column(db.String(36), db.ForeignKey('user.id'), nullable=False) # 卖方用户 buy_user_id = db.Column(db.String(36), db.ForeignKey('user.id'), nullable=False) # 买方用户 amount = db.Column(db.Numeric(24, 8), nullable=False) # 数量 status = db.Column(db.SmallInteger, default=g_confirm_order_status.UNPROCESSED ) # 状态参见 g_confirm_order_status sell_user = db.relationship(User, foreign_keys=[sell_user_id]) buy_user = db.relationship(User, foreign_keys=[buy_user_id])
class RecommendScheduleTask(ScheduleTaskBase): user_id = db.Column(db.String(36), db.ForeignKey('user.id'), nullable=False, unique=True) user = db.relationship(User)
class SellOrder(AutoIncrementBase): user_id = db.Column(db.String(36), db.ForeignKey('user.id'), nullable=False) # 用户 side = db.Column(db.SmallInteger, default=2, nullable=False) # 单类型 参见 g_order_side number = db.Column(db.String(16), default=generate_timestamp_id, unique=True, nullable=False) amount = db.Column(db.Numeric(24, 8), nullable=False) # 数量 status = db.Column( db.SmallInteger, default=g_sell_order_status.UNPROCESSED) # 状态参见 g_sell_order_status details = db.Column(db.String(255), default='{}', nullable=True) # 失败备注 user = db.relationship(User, foreign_keys=[user_id]) @staticmethod def order_create(user, amount): if user.transaction_level != g_user_transaction_level.ULTIMATE: order = SellOrder.query.filter( SellOrder.user_id == user.id, SellOrder.status == g_sell_order_status.UNPROCESSED).first() if order is not None: return False, dict( code=1006, message={'user': '******'}) order = SellOrder(user_id=user.id, amount=amount) return True, order
class Payment(UuidBase): user_id = db.Column(db.String(36), db.ForeignKey('user.id'), nullable=False) type = db.Column(db.SmallInteger, nullable=False) # 收款类型 g_payment_type name = db.Column(db.String(64)) # 姓名 bank = db.Column(db.String(128)) # 开户行 card_number = db.Column(db.String(64)) # 卡号 wechat = db.Column(db.String(64)) # 微信 wechat_image = db.Column(db.String(512), default='') # 微信二维码 alipay = db.Column(db.String(64)) # 支付宝 alipay_image = db.Column(db.String(512), default='') # 支付宝二维码 address = db.Column(db.String(64)) # usdt 地址 remark = db.Column(db.String(64), default='') # 备注 invalid = db.Column(db.SmallInteger, default=0) # 收款方式是否有效 0 有效 1 无效 # relationship user = db.relationship('User', foreign_keys=[user_id]) @staticmethod def get_payment(user_id, type): return Payment.query.filter_by(user_id=user_id, type=type, invalid=0).first() @staticmethod def get_all_payment(user_id): return Payment.query.filter_by(user_id=user_id, invalid=0).all()
class LoginInfo(UuidBase): user_id = db.Column(db.String(36), db.ForeignKey('user.id'), nullable=False) client_ip = db.Column(db.String(50), nullable=False) # 登录IP # relationship user = db.relationship(User)
class AssetsBalanceRecord(AutoIncrementBase): user_id = db.Column(db.String(36), db.ForeignKey('user.id'), nullable=False) current_amount = db.Column(db.Numeric(24, 8), nullable=False) # 当前量 delta_amount = db.Column(db.Numeric(24, 8), nullable=False) # 变化量 assets_type = db.Column(db.SmallInteger, nullable=False) # 钱包类型 g_assets_type record_type = db.Column(db.Integer, nullable=False) # 记录类型 g_assets_record_type details = db.Column(db.Text, nullable=False) # 详情 user = db.relationship('User', foreign_keys=[user_id])
class CommentGroup(db.Model): id = db.Column(db.Integer, primary_key=True) post_id = db.Column(db.ForeignKey('post.id'), nullable=False) created_at = db.Column(db.DateTime, default=datetime.utcnow(), nullable=False) comments = db.relationship('Comment', backref='comment_group', lazy='dynamic') def __repr__(self): return '<CommentGroup id: %d> ' % self.id def get_comment_in_group(self, comment_id): return self.comments.filter(Comment.id == comment_id).first() def add_comment(self, user, comment): try: comment.user_id = user.id self.post.increase_comment_count() self.comments.append(comment) db.session.commit() except Exception as e: db.session.rollback() raise e else: return comment def add_layer_comment(self, user: User, comment: Comment, parent_comment: Comment): try: self._update_comment_step(parent_comment) # add comment comment.user_id = user.id comment.step = parent_comment.step + 1 comment.depth = parent_comment.depth + 1 self.post.increase_comment_count() self.comments.append(comment) db.session.commit() except Exception as e: db.session.rollback() raise e else: return comment def _update_comment_step(self, parent_comment: Comment): # update step self.comments \ .filter(Comment.step > parent_comment.step) \ .update({Comment.step: Comment.step + 1})
class Role(db.Model, CRUD): __tablename__ = 'role' id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(250), nullable=True, unique=True) description = db.Column(db.String(250)) user = db.relationship('User', backref='role', lazy='dynamic') def __repr__(self): return '<Role %s>' % self.name
class Wallet(UuidBase): user_id = db.Column(db.String(36), db.ForeignKey('user.id'), nullable=False) currency_id = db.Column(db.String(50), nullable=False) # 货币代码 address = db.Column(db.String(100), unique=True, nullable=False) # 区块链币地址 address_qr_code = db.Column(db.String(512)) # 地址二维码 URL __table_args__ = (db.UniqueConstraint('user_id', 'currency_id'), ) # relationship user = db.relationship(User) @staticmethod def generate_wallet(user_id, currency_list): api = cryptopay_api() url = '{}/member/create_wallet'.format( current_app.config['CRYPTOPAY_BASE_URL']) data = {'currency_list': currency_list} try: wallet_list = api.post(url, data) for w in wallet_list['objects']: address_qr_code = '%s/currency_address_qr_code/%s' % ( current_app.config['CRYPTOPAY_BASE_URL'], w['address']) wallet = Wallet(user_id=user_id, currency_id=w['currency_id'], address=w['address'], address_qr_code=address_qr_code) db.session.add(wallet) db.session.commit() except CryptoPayApiError as e: abort(e.http_status_code, code=e.code, message=e.message) @staticmethod def query_wallet(wallet_list): address_list = [] for wallet in wallet_list: address_list.append(wallet.address) api = cryptopay_api() url = '{}/member/query_wallet'.format( current_app.config['CRYPTOPAY_BASE_URL']) data = {'address_list': ','.join(address_list)} try: address_balance_dict = {} query_wallet_list = api.post(url, data) for query_wallet in query_wallet_list['objects']: address_balance_dict[ query_wallet['address']] = query_wallet['balance'] for wallet in wallet_list: wallet.balance = address_balance_dict.get(wallet.address, '0') except CryptoPayApiError as e: abort(e.http_status_code, code=e.code, message=e.message)
class Comment(db.Model, TimestampMixin): id = db.Column(db.Integer, primary_key=True, nullable=False) content = db.Column(db.Text, nullable=False) status = db.Column(ChoiceType(CommentStatus, impl=db.Integer()), default=CommentStatus.NORMAL) user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False) user = db.relationship("User") comment_group_id = db.Column(db.Integer, db.ForeignKey('comment_group.id'), nullable=False) parent_id = db.Column(db.Integer, db.ForeignKey('comment.id'), nullable=True) depth = db.Column(db.Integer, nullable=False, default=0) step = db.Column(db.Integer, nullable=False, default=0) edited_count = db.Column(db.Integer, default=0) def delete(self): self.comment_group.post.decrease_comment_count() self.status = CommentStatus.DELETED db.session.commit() @hybrid_property def is_deleted(self): return self.status == CommentStatus.DELETED def is_owner(self, user: User): return self.user_id == user.id def update(self, data): self.content = data self.edited_count = Comment.edited_count + 1 db.session.commit() def __repr__(self): return "<Comment content: %s, status: %s" \ " created_at: %s, updated_at: %s>"\ % (self.content, self.status, self.created_at, self.updated_at)
class User(db.Model, UserMixin): __tablename__ = "user" id = db.Column(db.Integer(), primary_key=1) email = db.Column(db.String(255), unique=1) active = db.Column(db.Boolean()) password = db.Column(db.String(255)) # confirmed_at = db.Column(db.DateTime()) roles = db.relationship("Role", secondary=roles_users, backref=db.backref("users", lazy="dynamic")) def __init__(self, email="", active=1, password="", roles=None): self.roles = roles self.email = email self.active = active self.password = password def __repr__(self): return self.email def to_json(self): user = dict() user["id"] = self.id user["roles"] = self.roles user["email"] = self.email user["active"] = self.active return user
class TransferOrder(OrderBase): user_id = db.Column(db.String(36), db.ForeignKey('user.id'), nullable=False) type = db.Column(db.SmallInteger, default=2) # 1 内部转账 2 商家付款 currency_id = db.Column(db.String(50), nullable=False) # 货币代码 amount = db.Column(db.Numeric(24, 8), nullable=False) # 金额 fee = db.Column(db.Numeric(24, 8), nullable=False, default=0) # 手续费 status = db.Column(db.SmallInteger, default=1, nullable=False) # 1 确认中 2 成功 4 失败 message = db.Column(db.String(140)) user = db.relationship('User', foreign_keys=[user_id], remote_side="User.id") @staticmethod def create_transaction_order(order_number, address, amount, fee, type=2): api = cryptopay_api() url = '{}/member/create_transaction_order'.format( current_app.config['CRYPTOPAY_BASE_URL']) data = { 'number': order_number, 'address': address, 'amount': str(amount), 'fee': str(fee), 'extra': json.dumps({'type': type}) } try: return api.post(url, data) except CryptoPayApiError as e: abort(e.http_status_code, code=e.code, message=e.message) @staticmethod def pay_order(order_number): api = cryptopay_api() url = '{}/member/pay_order'.format( current_app.config['CRYPTOPAY_BASE_URL']) data = {'number': order_number} try: return api.post(url, data) except CryptoPayApiError as e: abort(e.http_status_code, code=e.code, message=e.message)
class AdminUser(AdminUserBase): parent_id = db.Column(db.String(36), db.ForeignKey('admin_user.id')) # relationship parent = db.relationship('AdminUser', foreign_keys=[parent_id], remote_side="AdminUser.id") @staticmethod def initialize(): root_admin = AdminUser.query.get(AdminUserBase.ROOT_ID) if root_admin is None: root_admin = AdminUser(id=AdminUserBase.ROOT_ID, uid='admin', role=1) root_admin.set_password('888888') root_admin.generate_auth_token() db.session.add(root_admin) db.session.commit()
class BookModel(db.Model): __tablename__ = 'book_model' id = db.Column(db.Integer, primary_key=True, autoincrement=True) title = db.Column(db.String(255), nullable=False) description = db.Column(db.String(255), nullable=False) image = db.Column(db.String(255)) author_id = db.Column(db.Integer, db.ForeignKey('author_model.id'), nullable=False) author = db.relationship( "AuthorModel", backref="books", primaryjoin="AuthorModel.id == BookModel.author_id") def save_to_db(self): db.session.add(self) db.session.commit() def __repr__(self): return '<Book %r>' % self.title
class User(db.Model, UserMixin): id = db.Column(db.Integer, primary_key = True) email = db.Column(db.String(64), unique = True) password = db.Column(db.String(255)) active = db.Column(db.Boolean()) roles = db.relationship('Role', secondary=roles_users, backref=db.backref('users', lazy='dynamic')) def is_authenticated(self): return True def is_active(self): return True def is_anonymous(self): return False def get_id(self): return unicode(self.id) def __repr__(self): return '<User %r>' % (self.name)
class Solution(db.Model): __tablename__ = "solution" solution_id = Column("solution_id", Integer, primary_key=True, autoincrement=True) challenge_number = Column("challenge_number", Integer, ForeignKey("challenge.challenge_number")) solution_array = db.Column("solution_array", Text) challenge = db.relationship( "Challenge", primaryjoin="Challenge.challenge_number == Solution.challenge_number", backref="challenge", ) def json(self): return { "solution_id": self.solution_id, "challenge_number": self.challenge_number, "solution_array": self.solution_array, } def __repr__(self): return f"<Solution {self.solution_id} for {self.challenge_number}>"
class Assets(UuidBase): user_id = db.Column(db.String(36), db.ForeignKey('user.id'), nullable=False) total_balance = db.Column(db.Numeric(24, 8), default=0, nullable=False) # 总资产钱包 冻结 community_balance = db.Column(db.Numeric(24, 8), default=0, nullable=False) # 社区钱包 用于交易 community_today_balance = db.Column(db.Numeric(24, 8), default=0, nullable=False) # 社区钱包 今日买入的冻结值 用于交易 transaction_balance = db.Column(db.Numeric(24, 8), default=0, nullable=False) # 交易钱包 用于冻结释放 grand_total_balance = db.Column(db.Numeric(24, 8), default=0, nullable=False) # 累计总资产钱包 # relationship user = db.relationship('User', foreign_keys=[user_id]) @staticmethod def get_assets(user_id): return Assets.query.filter_by(user_id=user_id).first() def update_grand_total_balance(self, delta_amount): delta_amount = decimal.Decimal(delta_amount) if delta_amount > 0: Assets.query.filter( Assets.id == self.id, Assets.grand_total_balance >= -delta_amount).update( dict(grand_total_balance=Assets.grand_total_balance + delta_amount)) return True return False def update_total_balance(self, delta_amount, record_type, details): delta_amount = decimal.Decimal(delta_amount) rows_changed = Assets.query.filter( Assets.id == self.id, Assets.total_balance >= -delta_amount).update( dict(total_balance=Assets.total_balance + delta_amount)) if rows_changed == 1: option = Setting.get_json('general_option') transaction_allow_amount = option['transaction_allow_amount'] if self.total_balance >= transaction_allow_amount: self.user.allow_transaction = 1 self.update_grand_total_balance(delta_amount) record = AssetsBalanceRecord(user_id=self.user_id, current_amount=self.total_balance, delta_amount=delta_amount, assets_type=g_assets_type.TOTAL, record_type=record_type, details=json.dumps(details)) db.session.add(record) db.session.flush() return True return False def update_community_balance(self, delta_amount, record_type, details): delta_amount = decimal.Decimal(delta_amount) rows_changed = Assets.query.filter( Assets.id == self.id, Assets.community_balance >= -delta_amount).update( dict(community_balance=Assets.community_balance + delta_amount)) if rows_changed == 1: record = AssetsBalanceRecord(user_id=self.user_id, current_amount=self.community_balance + self.community_today_balance, delta_amount=delta_amount, assets_type=g_assets_type.COMMUNITY, record_type=record_type, details=json.dumps(details)) db.session.add(record) db.session.flush() return True return False def update_community_today_balance(self, delta_amount, record_type, details): delta_amount = decimal.Decimal(delta_amount) rows_changed = Assets.query.filter( Assets.id == self.id, Assets.community_today_balance >= -delta_amount).update( dict(community_today_balance=Assets.community_today_balance + delta_amount)) if rows_changed == 1: record = AssetsBalanceRecord(user_id=self.user_id, current_amount=self.community_today_balance + self.community_balance, delta_amount=delta_amount, assets_type=g_assets_type.COMMUNITY, record_type=record_type, details=json.dumps(details)) db.session.add(record) db.session.flush() return True return False def update_transaction_balance(self, delta_amount, record_type, details): delta_amount = decimal.Decimal(delta_amount) rows_changed = Assets.query.filter( Assets.id == self.id, Assets.transaction_balance >= -delta_amount).update( dict(transaction_balance=Assets.transaction_balance + delta_amount)) if rows_changed == 1: record = AssetsBalanceRecord(user_id=self.user_id, current_amount=self.transaction_balance, delta_amount=delta_amount, assets_type=g_assets_type.TRANSACTION, record_type=record_type, details=json.dumps(details)) db.session.add(record) db.session.flush() return True return False @property def community_frozen_balance(self): from app.model.order import g_order_side from app.model.order import Order, g_order_status amount = db.session.query(db.func.sum(Order.amount)).filter( Order.user_id == self.user_id, Order.side == g_order_side.SELL, Order.status.op('&')(g_order_status.CONFIRMED | g_order_status.CANCELLED) == 0).first()[0] return amount if amount else 0
class Order(AutoIncrementBase): match_order_id = db.Column(db.Integer, db.ForeignKey('match_order.id'), nullable=True) # 匹配订单 user_id = db.Column(db.String(36), db.ForeignKey('user.id'), nullable=False) # 用户 side = db.Column(db.SmallInteger, nullable=False) # 单类型 参见 g_order_side number = db.Column(db.String(16), nullable=False) amount = db.Column(db.Numeric(24, 8), nullable=False) # 数量 status = db.Column(db.SmallInteger, default=g_order_status.PENDING, nullable=False) # 订单状态参见 g_order_status priority = db.Column(db.SmallInteger, default=0) # 订单优先级 数值越大优先级越高 user = db.relationship(User, foreign_keys=[user_id]) match_order = db.relationship(MatchOrder, foreign_keys=[match_order_id]) __table_args__ = (db.UniqueConstraint('side', 'number'),) @staticmethod def confirm_order(match_order): rows_changed = Order.query.filter_by( user_id=match_order.sell_user_id, side=g_order_side.SELL, number=match_order.sell_number, status=g_order_status.PAID).update(dict(status=g_order_status.CONFIRMED)) if not rows_changed: return False, dict(code=1001, message={'order_number': 'order does not exist'}) rows_changed = Order.query.filter_by( user_id=match_order.buy_user_id, side=g_order_side.BUY, number=match_order.buy_number, status=g_order_status.PAID).update(dict(status=g_order_status.CONFIRMED)) if not rows_changed: return False, dict(code=1001, message={'order_number': 'order does not exist'}) confirm_order = ConfirmOrder(sell_user_id=match_order.sell_user_id, buy_user_id=match_order.buy_user_id, amount=match_order.sell_order.amount) return True, confirm_order @staticmethod def generate_order_process(): option = Setting.get_json('general_option') sell_people = option['sell_people'] buy_people = option['buy_people'] sell_count = option['sell_count'] buy_count = option['buy_count'] str_time = datetime.datetime.now().strftime('%Y-%m-%d') order_list = SellOrder.query.filter(SellOrder.status == g_sell_order_status.UNPROCESSED).all() buy_list = BuyOrder.query.filter(BuyOrder.status == g_buy_order_status.UNPROCESSED).all() order_list.extend(buy_list) order_list = sorted(order_list, key=lambda e: e.created_at) for item in order_list: logging.info('Order side:{}, id:{}'.format(item.side, item.id)) if item.side == g_order_side.SELL: if item.user.transaction_level != g_user_transaction_level.ULTIMATE: order = Order.query.filter(Order.user_id == item.user_id, Order.side == g_order_side.BUY, Order.status == g_order_status.CONFIRMED).first() if not order: # 提示语"该用户从未购买过" error_details = dict(code=1001, message={'user': '******'}) item.details = json.dumps(error_details) item.status = g_sell_order_status.FAILED db.session.commit() continue order_people = db.session.query(Order.user_id).filter( Order.created_at >= str_time, Order.side == g_order_side.SELL, Order.status != g_order_status.CANCELLED).count() order_people = order_people if order_people else 0 if order_people >= sell_people: # 提示语"当日入场单量已满" error_details = dict(code=1003, message={'count': 'count >= {}'.format(sell_people)}) item.details = json.dumps(error_details) item.status = g_sell_order_status.FAILED db.session.commit() continue count = db.session.query(db.func.count(SellOrder.id)).filter( db.func.date_format(SellOrder.created_at, '%Y-%m-%d') == str_time, SellOrder.user_id == item.user_id, SellOrder.status == g_sell_order_status.PROCESSED).first()[0] count = count if count else 0 if count >= sell_count: # 提示语"今天卖出的单数已满" error_details = dict(code=1006, message={'user': '******'.format(sell_count)}) item.details = json.dumps(error_details) item.status = g_sell_order_status.FAILED db.session.commit() continue detail = {'message': '挂单冻结'} assets = Assets.get_assets(item.user_id) if not assets.update_community_balance(-item.amount, g_assets_record_type.SELL, detail): # 提示语"余额不足" if assets.community_today_balance > 0: error_details = dict(code=1007, message={ 'order': 'please tomorrow to sell, today buy balance:{}'.format( assets.community_today_balance)}) else: error_details = dict(code=1008, message={'balance': 'current balance < {}'.format(item.amount)}) item.details = json.dumps(error_details) item.status = g_sell_order_status.FAILED db.session.commit() continue item.status = g_sell_order_status.PROCESSED else: order_people = db.session.query(Order.user_id).filter( Order.created_at >= str_time, Order.side == g_order_side.BUY, Order.status != g_order_status.CANCELLED).count() order_people = order_people if order_people else 0 if order_people >= buy_people: # 提示语"当日入场单量已满" error_details = dict(code=1003, message={'count': 'count >= {}'.format(buy_people)}) item.details = json.dumps(error_details) item.status = g_sell_order_status.FAILED db.session.commit() continue # 用于计算今天买入的单数 count = db.session.query(db.func.count(BuyOrder.id)).filter( db.func.date_format(BuyOrder.created_at, '%Y-%m-%d') == str_time, BuyOrder.user_id == item.user_id, BuyOrder.status == g_buy_order_status.PROCESSED).first()[0] count = count if count else 0 if count >= buy_count: # 提示语"今天买入的单数已满" error_details = dict(code=1006, message={'user': '******'.format(buy_count)}) item.details = json.dumps(error_details) item.status = g_sell_order_status.FAILED db.session.commit() continue item.status = g_buy_order_status.PROCESSED order = Order(created_at=item.created_at, user_id=item.user_id, side=item.side, amount=item.amount, number=item.number) db.session.add(order) db.session.commit() @staticmethod def match_order_process(): option = Setting.get_json('general_option') # match_order_cnt = option['match_order_cnt'] dollar2rmb = decimal.Decimal(option['dollar2rmb']) task = MatchOrderTask.query.filter(MatchOrderTask.status == g_match_order_task_status.UNPROCESSED).first() if task is None: return change = MatchOrderTask.query.filter(MatchOrderTask.status == g_match_order_task_status.UNPROCESSED).update( dict(status=g_match_order_task_status.PROCESSED)) if not change: return sell_list = Order.query.filter( Order.side == g_order_side.SELL, Order.status == g_order_status.PENDING) sell_list = sell_list.order_by(Order.priority.desc(), Order.created_at.asc()) i = 0 for item in sell_list: if i >= task.order_cnt: break buy_order = Order.query.filter( Order.side == g_order_side.BUY, Order.user_id != item.user_id, Order.status == g_order_status.PENDING).order_by(Order.priority.desc(), Order.created_at.asc()).first() if buy_order is None: continue change = Order.query.filter(Order.id == item.id, Order.status == g_order_status.PENDING).update( dict(status=g_order_status.MATCH)) if not change: continue change = Order.query.filter(Order.id == buy_order.id, Order.status == g_order_status.PENDING).update( dict(status=g_order_status.MATCH)) if not change: item.status = g_order_status.PENDING db.session.commit() continue usd_price = CryptoCurrency.query.filter(CryptoCurrency.currency_code == 'USDT').first().usd_price dollar = Currency.get_price() * item.amount usdt = dollar / usd_price order = MatchOrder(sell_user_id=item.user_id, buy_user_id=buy_order.user_id, sell_order_id=item.id, buy_order_id=buy_order.id, sell_number=item.number, buy_number=buy_order.number, payment_amount=dollar * dollar2rmb, payment_amount_usdt=usdt, current_price=Currency.get_price()) db.session.add(order) db.session.flush() item.match_order_id = order.id buy_order.match_order_id = order.id db.session.commit() try: if order.buy_user.order_mobile: clnt = YunpianClient('fcf725316cbb8ff1438c90ff76c6cebe') param = {YC.MOBILE: '+' + order.buy_user.order_mobile.replace(' ', ''), YC.TEXT: "【乐宝】您的订单{}已匹配成功,请尽快安排处理。".format('')} clnt.sms().single_send(param) except: pass i += 1 db.session.commit() @staticmethod def confirm_order_process(): order_list = ConfirmOrder.query.filter(ConfirmOrder.status == g_confirm_order_status.UNPROCESSED).all() for order in order_list: change = ConfirmOrder.query.filter( ConfirmOrder.id == order.id, ConfirmOrder.status == g_confirm_order_status.UNPROCESSED).update( dict(status=g_confirm_order_status.PROCESSED)) if not change: continue detail = {'message': '挂单交易'} assets = Assets.get_assets(order.buy_user_id) assets.update_community_today_balance(order.amount, g_assets_record_type.BUY, detail) # 用于计算一个买卖周期 order.buy_user.buy_order_cnt += 1 if order.sell_user.buy_order_cnt > 0: order.sell_user.buy_order_cnt -= 1 option = Setting.get_json('general_option') buy_sell_free_amount = option['buy_sell_free_amount'] buy_sell_rate = decimal.Decimal(option['buy_sell_rate']) fee = order.amount * buy_sell_rate amount = buy_sell_free_amount - fee detail = { 'message': '成功买卖各一单,释放数量:{}, 单数量:{}, 扣除手续费:{}'.format( buy_sell_free_amount, order.amount, fee) } assets = Assets.get_assets(order.sell_user_id) if assets.update_total_balance(-buy_sell_free_amount, g_assets_record_type.BUY_SELL_FREE, detail): assets.update_transaction_balance(amount, g_assets_record_type.BUY_SELL_FREE, detail) sell_user = order.sell_user sell_user.update_today_have_transaction() sell_user.update_transaction_free() currency = Currency.get_currency() currency.update_transaction_cnt() db.session.commit() @staticmethod def check_order_process(): option = Setting.get_json('general_option') change_time = int(option['order_status_change_time']) # 接单后不打款 q = db.session.query(Order).filter(Order.id == MatchOrder.sell_order_id, MatchOrder.created_at < datetime.datetime.now() - datetime.timedelta(hours=change_time), Order.status == g_order_status.MATCH).all() for order in q: match_order = order.match_order if match_order is None: continue rows_changed = Order.query.filter( Order.side == g_order_side.SELL, Order.number == match_order.sell_number, Order.status == g_order_status.MATCH).update(dict(status=g_order_status.CANCELLED)) if not rows_changed: continue detail = {'message': "超时不打款,卖单号:{},买单号:{},买方手机:{}".format(match_order.sell_number, match_order.buy_number, match_order.buy_user.mobile)} rows_changed = Order.query.filter( Order.side == g_order_side.BUY, Order.number == match_order.buy_number, Order.status == g_order_status.MATCH).update(dict(status=g_order_status.CANCELLED)) if rows_changed: assets = Assets.get_assets(order.user_id) assets.update_community_balance(order.amount, g_assets_record_type.SELL, detail) else: order.status = g_order_status.MATCH db.session.commit()
class User(UserBase): VIRTUAL_ID = '00000000-0000-0000-0000-000000000000' name = db.Column(db.String(64)) # 姓名 avatar = db.Column(db.String(512)) # 头像 URL order_mobile = db.Column(db.String(16)) nickname = db.Column(db.String(64)) # 昵称 gender = db.Column(db.SmallInteger, default=0) # 性别: 0 未填 1 男 2 女 sponsor_id = db.Column(db.String(36), db.ForeignKey('user.id')) # 推荐人 active = db.Column(db.SmallInteger, default=0) # 是否激活: 0 未激活 1 激活 left_id = db.Column(db.Integer, default=0) # 用于推荐网络图子节点的查询 right_id = db.Column(db.Integer, default=0) wechat = db.Column(db.String(64)) # 微信 state = db.Column(db.Integer, default=0) # 资料和测评状态,参见 g_user_state_type allow_transaction = db.Column(db.Integer, default=0) # 允许交易 0 不允许 1 允许 transaction_level = db.Column( db.Integer, default=0) # 交易级别 参见 g_user_transaction_level buy_order_cnt = db.Column(db.Integer, default=0) # 买进的单数 continuous_buy_cnt = db.Column(db.Integer, default=0) # 持续购买天数 today_have_transaction = db.Column(db.SmallInteger, default=0) # 今天是否拥有一次买卖交易 0 没有 1 有 team_qualified_cnt = db.Column(db.Integer, default=0) # 团队合格用户人数 is_community_node = db.Column(db.SmallInteger, default=0) # 是否为社区节点 0 不是 1 是 # relationship sponsor = db.relationship('User', foreign_keys=[sponsor_id], remote_side="User.id") assets = db.relationship('Assets', uselist=False) def is_virtual(self): return self.id == User.VIRTUAL_ID def is_active(self): return self.active == 1 def activate(self): from app.model.schedule_task import RegisterScheduleTask self.active = 1 task = RegisterScheduleTask(user_id=self.id) db.session.add(task) from app.model.assets import Assets assets = Assets(user_id=self.id) db.session.add(assets) db.session.flush() # 保证顺序 def update_state(self, state): from app.model.schedule_task import RecommendScheduleTask rows_changed = User.query.filter(User.id == self.id, User.state != state).update( dict(state=state)) if rows_changed: if state == g_user_state_type.EVALUATION: task = RecommendScheduleTask.query.filter( RecommendScheduleTask.user_id == self.id).first() if task is None: task = RecommendScheduleTask(user_id=self.id) db.session.add(task) db.session.flush() # 保证顺序 def update_left_right_id(self): if self.left_id or self.right_id: return False parent = User.query.get(self.sponsor_id) new_user_left = parent.right_id User.query.filter(User.left_id > new_user_left).update( dict(left_id=User.left_id + 2)) User.query.filter(User.right_id >= new_user_left).update( dict(right_id=User.right_id + 2)) self.left_id = new_user_left self.right_id = new_user_left + 1 db.session.flush() return True def update_team_qualified_cnt(self): sponsor = self.sponsor # 自己也算 User.query.filter(User.id == self.id).update( dict(team_qualified_cnt=User.team_qualified_cnt + 1)) while sponsor: User.query.filter(User.id == sponsor.id).update( dict(team_qualified_cnt=User.team_qualified_cnt + 1)) sponsor = sponsor.sponsor def update_recommend_reward(self): option = Setting.get_json('general_option') recommend_reward_amount = [ decimal.Decimal(x) for x in option['recommend_reward_amount'] ] evaluation_reward_amount = decimal.Decimal( option['evaluation_reward_amount']) # 先赠送本用户 usd_price = Currency.get_price() if usd_price == 0: abort(400, code=1002, message={'usd_price': 'usd_price is invaild'}) # amount = evaluation_reward_amount / usd_price amount = 1000 assets = Assets.get_assets(self.id) details = {'message': u'完成评测奖励'} assets.update_total_balance(amount, g_assets_record_type.EVALUATION, details) # 再赠送每一代推荐 layer = 0 layer_max = len(recommend_reward_amount) sponsor = self.sponsor while sponsor and layer < layer_max: details = { 'message': '被推荐人:{}, 第几代:{}'.format(self.uid, layer + 1) } if sponsor.state == g_user_state_type.EVALUATION: assets = Assets.get_assets(sponsor.id) assets.update_total_balance(recommend_reward_amount[layer], g_assets_record_type.SPONSOR, details) layer += 1 sponsor = sponsor.sponsor def update_transaction_free(self): option = Setting.get_json('general_option') transaction_free_generation = option['transaction_free_generation'] transaction_free_amount = option['transaction_free_amount'] community_free_generation = option['community_free_generation'] community_free_amount = option['community_free_amount'] # 加速释放每一代 layer = 0 sponsor = self.sponsor while sponsor and layer < community_free_generation: if sponsor.is_community_node == 0 and layer < transaction_free_generation: amount = transaction_free_amount elif sponsor.is_community_node == 1: amount = community_free_amount else: amount = 0 if amount != 0: details = { 'message': '交易加速释放,交易完成者:{}, 第几代:{}'.format(self.uid, layer + 1) } assets = Assets.get_assets(sponsor.id) # amount = min(assets.total_balance, amount) if assets.update_total_balance( -amount, g_assets_record_type.ACCELERATE_FREE, details): assets.update_transaction_balance( amount, g_assets_record_type.ACCELERATE_FREE, details) layer += 1 sponsor = sponsor.sponsor # def update_buy_order_cnt(self, delta_amount): # rows_changed = User.query.filter( # User.id == self.id, # User.buy_order_cnt >= -delta_amount).update( # dict(buy_order_cnt=User.buy_order_cnt + delta_amount)) # if rows_changed == 1: # return True # return False @staticmethod def update_continuous_buy_cnt(): rows_changed = User.query.filter( User.today_have_transaction == 1).update( dict(continuous_buy_cnt=User.continuous_buy_cnt + 1)) if rows_changed: User.query.filter(User.today_have_transaction == 0).update( dict(continuous_buy_cnt=0)) User.query.update(dict(today_have_transaction=0)) return True return False def update_today_have_transaction(self): rows_changed = User.query.filter(User.id == self.id).update( dict(today_have_transaction=1)) if rows_changed: return True return False @property def cal_team_count(self): count = db.session.query(db.func.count(User.id)).filter( User.left_id > self.left_id, User.locked != 2, User.right_id < self.right_id).first()[0] if count is None: count = 0 return count def update_is_community_node(self): rows_changed = User.query.filter(User.id == self.id).update( dict(is_community_node=1)) if rows_changed: return True return False @property def node_profit(self): amount = db.session.query(db.func.sum( AssetsBalanceRecord.delta_amount)).filter( AssetsBalanceRecord.user_id == self.id, AssetsBalanceRecord.record_type == g_assets_record_type.DIVIDEND).first()[0] return amount if amount else 0 @staticmethod def initialize(): virtual_user = User.query.get(User.VIRTUAL_ID) if virtual_user is None: # 生成虚拟用户 virtual_user = User( id=User.VIRTUAL_ID, mobile='13288888888', left_id=1, right_id=2, active=1, transaction_level=g_user_transaction_level.ULTIMATE) virtual_user.set_password('8RBcdxlofE8F') virtual_user.set_security_password('8RBcdxlofE8F') virtual_user.uid = 'root' db.session.add(virtual_user) db.session.flush() virtual_user.activate() virtual_user.update_state(g_user_state_type.COMPLETED_DATA) db.session.commit()
class CheckOrderStatusTask(ScheduleTaskBase): order_id = db.Column(db.Integer, db.ForeignKey('order.id'), nullable=False) # relationship order = db.relationship(Order)