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 Likes(db.Model, TimestampMixin): def __init__(self, post_id, user_id): self.post_id = post_id self.user_id = user_id id = db.Column(db.Integer, primary_key=True) post_id = db.Column(db.Integer, db.ForeignKey('post.id'), nullable=False) user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
class Article(Base): __tablename__ = "article" ArticleUrl = db.Column(db.String(255), unique=True, primary_key=True) ArticleTitle = db.Column(db.String(255)) ArticleAuthor = db.Column(db.Integer, db.ForeignKey("user.id", use_alter=True), nullable=False) Content = db.Column(db.TEXT) Language = db.Column(db.String(10), db.ForeignKey("language.Lang", use_alter=True), nullable=False)
class Comment(Base): __tablename__ = "comment" FromArticle = db.Column(db.Integer, db.ForeignKey("article.id", use_alter=True), nullable=False) Author = db.Column(db.Integer, db.ForeignKey("user.id", use_alter=True), nullable=False) CommentString = db.Column(db.TEXT) CommentTime = db.Column(db.DateTime()) CommentPush = db.Column(db.String(5)) Language = db.Column(db.String(10), db.ForeignKey("language.Lang", use_alter=True), nullable=False)
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 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 Feed(db.Model): __tablename__ = "feeds" id = db.Column(db.Integer(), primary_key=1) url = db.Column(db.String(255), unique=1) account_id = db.Column(db.Integer(), db.ForeignKey("accounts.id")) def __init__(self, url="", account=None): self.url = url self.account = account def __repr__(self): return self.account.text + u"的订阅地址" def to_json(self): feed = dict() feed["id"] = self.id feed["url"] = self.url feed["account"] = self.account return feed
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 Keywords(Base): # which kind of endorsement __tablename__ = "keywords" CommentID = db.Column(db.Integer, db.ForeignKey("comment.id", use_alter=True), nullable=False) Phase = db.Column(db.TEXT)
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 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 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 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 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 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, CRUD): __tablename__ = 'user' id = db.Column(db.Integer, primary_key=True) email = db.Column(db.String(250), nullable=False, unique=True) password = db.Column(db.String(250), nullable=False) firstname = db.Column(db.String(250)) lastname = db.Column(db.String(250)) role = db.Column(db.String(250), db.ForeignKey('role.name')) active = db.Column(db.Integer, nullable=False) create = db.Column(db.TIMESTAMP, server_default=db.func.current_timestamp(), nullable=False) def is_active(self): return True def get_id(self): return self.email def is_authenticated(self): return self.authenticated def is_anonymous(self): return def __init__(self, email, password, firstname, lastname, role, active): self.email = email self.password = password self.firstname = firstname self.lastname = lastname self.role = role self.active = active def __repr__(self): return '<User %s>' % self.email
class EmotionScore(Base): __tablename__ = "emotionScore" CommentID = db.Column(db.Integer, db.ForeignKey("comment.id", use_alter=True), nullable=False) Score = db.Column(db.Float())
# -*- coding: utf-8 -*- from datetime import datetime from flask.ext.security import SQLAlchemyUserDatastore, UserMixin, RoleMixin from app.model import db # Define models required for Flask-Security roles_users = db.Table('roles_users', db.Column('user_id', db.Integer(), db.ForeignKey('user.id')), db.Column('role_id', db.Integer(), db.ForeignKey('role.id'))) class Role(db.Model, RoleMixin): id = db.Column(db.Integer(), primary_key=True) name = db.Column(db.String(80), unique=True) description = db.Column(db.String(255)) 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
class Article(db.Model): __tablename__ = "articles" id = db.Column(db.Integer(), primary_key=1) title = db.Column(db.String(255), unique=1) cover = db.Column(db.String(255)) digest = db.Column(db.String(255)) content = db.Column(db.Text()) read_num = db.Column(db.Integer()) post_date = db.Column(db.Date()) account_id = db.Column(db.Integer(), db.ForeignKey("accounts.id")) def __init__(self, title="", cover="", digest="", content="", read_num=0, post_date="", account=None): self.title = title self.cover = cover self.digest = digest self.content = content self.account = account self.read_num = read_num self.post_date = post_date def __repr__(self): return self.title def to_json(self): article = dict() article["id"] = self.id article["title"] = self.title article["cover"] = self.cover article["digest"] = self.digest article["content"] = self.content article["account"] = self.account article["read_num"] = self.read_num article["post_date"] = self.post_date return article
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 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