def get(self, match_id): keyword = self.get_argument("kw", "") match = Match.get_or_404(id=match_id) query = MatchMember.query_all_members(match_id) group_query = MatchGroup.select() \ .where(MatchGroup.match_id == match_id) self.logger.debug(group_query.sql()) groups = [] for group in group_query: groups.append({"name": group.name}) group_name = self.get_argument("group_name", "") if group_name: query = query.where(MatchGroup.name == group_name) if keyword: if is_mobile(keyword): query = query.where(MatchMember.mobile == keyword) else: query = query.where(MatchMember.name.contains(keyword)) members = self.paginate_query(query) sum_fee = MatchMember.select( fn.SUM(MatchMember.total_fee).alias("sum")).where( MatchMember.match_id == match_id).scalar() self.render("match/match_members_list.html", sum_fee=sum_fee, match=match, groups=groups, members=members, pagination=members.pagination)
def post(self, match_id, status_id): match = Match.get_or_404(id=match_id) status = MatchStatus.get_or_404(id=status_id) delete_photo_keys = self.get_argument("delete-photo-keys", "") form = MatchStatusForm(self.arguments) if not form.validate(): self.render("match/statuses_edit.html", match=match, status=status, form=form) else: if delete_photo_keys: delete_photo_keys_list = delete_photo_keys.split(",") else: delete_photo_keys_list = [] if "photos" in self.request.files: photo_keys_list = self.upload_photos(match_id) else: photo_keys_list = [] new_photos_set = set(status.photos) ^ set(delete_photo_keys_list) new_photos_set = new_photos_set.union(set(photo_keys_list)) form.populate_obj(status) status.photos = list(new_photos_set) status.save() self.redirect(self.reverse_url("admin_match_statuses", match_id))
def get(self, match_id): match = Match.get_or_404(id=match_id) query = MatchMember.select(MatchMember, MatchGroup).join( MatchGroup, join_type=JOIN_LEFT_OUTER, on=(MatchMember.group_id == MatchGroup.id).alias("group")).where( MatchMember.match_id == match.id).order_by( MatchMember.id.desc()) group_query = MatchGroup.select() \ .where(MatchGroup.match_id == match_id) self.logger.debug(group_query.sql()) groups = [] for group in group_query: groups.append({"name": group.name}) group_name = self.get_argument("group_name", "") if group_name: query = query.where(MatchGroup.name == group_name) members = self.paginate_query(query) sum_fee = MatchMember.select( fn.SUM(MatchMember.total_fee).alias("sum")).where( MatchMember.match_id == match_id).scalar() self.render("match/match_members_list.html", sum_fee=sum_fee, groups=groups, match=match, members=members, pagination=members.pagination)
def get(self, round_id): match_round = MatchRound.get_or_404(id=round_id) match = Match.get_or_404(id=match_round.match_id) query = MatchMember.select().where( MatchMember.match_id == match.id, MatchMember.state == MatchMember.MatchMemberState.normal) members = [] for member in query: members.append({"id": member.id, "name": member.name}) query = MatchAgainst.select().where( MatchAgainst.round_id == match_round.id).order_by( MatchAgainst.id.asc()) againsts = [] for against in query: againsts.append(against.info) match_options = MatchOption.select().where( MatchOption.match_id == match.id) self.render("match/round_againsts.html", match=match, match_round=match_round, members=members, againsts=againsts, match_options=match_options)
def post(self, match_id): match = Match.get_or_404(id=match_id) form = CreateCoverForm(self.arguments) if form.validate(): cover = MatchCover(match_id=match.id) form.populate_obj(cover) if "coverfile" in self.request.files: to_bucket = self.settings['qiniu_avatar_bucket'] to_key = "match:cover:%s%s" % (match_id, time.time()) to_key = hashlib.md5(to_key.encode()).hexdigest() cover_key = self.upload_file( "coverfile", to_bucket=to_bucket, to_key=to_key, ) cover.cover_key = cover_key cover.save() self.redirect(self.reverse_url("admin_match_detail", match_id)) return self.render("match/add_cover.html", form=form, match=match)
def post(self, match_id: int): """ 提交退塞请求, http_form: reason: 退赛原因, insists: 强制退出, 强制退出比赛无退款 :param match_id: int, Match.id """ form = self.validated_arguments insists = form.pop("insists", False) match = Match.get_or_404(id=match_id) if not insists: self.can_leave(match, self.current_user.id) member = self.has_joined_match(match, user_id=self.current_user.id) notify_url = urljoin(self.request.full_url(), self.reverse_url("rest_matches_refund_callback")) try: MatchService.leave(user_id=self.current_user.id, match=match, notify_url=notify_url, insists=insists) except MatchException as e: logging.error(e) msg = "退出赛事失败, 原因: `{0}`".format(str(e)) raise ApiException(422, msg) self.set_status(204, "退出赛事成功") self.finish()
def _settlement_application(self, match_id): # 提交结算申请 match = Match.get_or_404(id=match_id) if not match.can_apply_settlement(): self.write_error(403, "此活动不能手动结算") else: MatchService.settlement_application(self.current_user, match) self.write_success()
def get(self, match_id): match = Match.get_or_404(id=match_id) match_round = MatchRound(match_id=match_id) form = CreateRoundForm(obj=match_round) self.render("match/round_create.html", form=form, match=match)
def get(self, round_id): match_round = MatchRound.get_or_404(id=round_id) match = Match.get_or_404(id=match_round.match_id) form = EditRoundForm(obj=match_round) self.render("match/round_edit.html", form=form, match=match)
def get(self, match_id): match = Match.get_or_404(id=match_id) cover = MatchCover(match_id=match_id) form = CreateCoverForm(obj=cover) self.render("match/add_cover.html", form=form, match=match)
def get(self, match_id, state): match = Match.get_or_404(id=match_id) if state == "normal": # 查询正常参赛成员 members = MatchMember\ .query_all_members(match_id)\ .where(MatchMember.state == MatchMember.MatchMemberState.normal) else: members = MatchMember.query_all_members(match_id) # 排除文件和图片项 option_info_list = [ option_info for option_info in match.option_info_list if not (option_info.is_photo() or option_info.is_file() or option_info.is_avatar() or option_info.is_idcard_photo()) ] option_name_list = [ option_info.option_name for option_info in option_info_list ] option_name_list.extend(["报名时间", "状态"]) file_name = "{match_name}成员列表.xlsx"\ .format(match_name=match.title) # temp_file_name = str(uuid.uuid4()) o = io.BytesIO() with Workbook(o) as workbook: worksheet = workbook.add_worksheet() row, col = 0, 0 worksheet.write_row(row, col, option_name_list) for member in members: row, col = row + 1, 0 assert isinstance(member, MatchMember) for option_info in option_info_list: option_value = option_info.get_option_value(member) # 处理布尔值显示 if option_info.is_leader_check() or option_info.is_boolean( ): option_value = "是" if option_value else "否" if option_info.is_gender(): option_value = member.display_gender() worksheet.write(row, col, option_value) col += 1 worksheet.write(row, col, member.created.strftime('%Y.%m.%d')) worksheet.write(row, col + 1, member.state_name) data = o.getvalue() o.close() self.set_header("Content-Type", "application/octet-stream") self.set_header("Content-Disposition", "attachment; filename={0}".format(file_name)) self.add_header("Content-Length", len(data)) self.set_header("Content-Transfer-Encoding", "binary") self.write(data)
def get(self, match_id, status_id): match = Match.get_or_404(id=match_id) status = MatchStatus.get_or_404(id=status_id) form = MatchStatusForm(obj=status) self.render("match/statuses_edit.html", match=match, status=status, form=form)
def get(self, match_id): match = Match.get_or_404(id=match_id) query = MatchStatus.select( MatchStatus, ).where(MatchStatus.match_id == match.id).order_by( MatchStatus.created.desc()) statuses = self.paginate_query(query) self.render("match/statuses.html", statuses=statuses, match=match)
def get(self, match_id): match = Match.get_or_404(id=match_id) # 获取赛事分组信息 groups = MatchGroup.select().where( MatchGroup.match_id == match.id).order_by( MatchGroup.sort_num.desc()) # 获取报名表自定义选项 custom_options = MatchOption.select().where( MatchOption.match_id == match.id).order_by( MatchOption.sort_num.desc()) rounds = MatchRound.select(MatchRound, ).where( MatchRound.match_id == match.id).order_by(MatchRound.created.asc(), MatchRound.id.asc()) covers = MatchCover.select().where( MatchCover.match_id == match.id).order_by(MatchCover.id.desc()) # 获取对阵图 RightMember = MatchMember.alias() against_query = MatchAgainst.select( MatchAgainst, MatchMember, RightMember).join( MatchMember, on=(MatchAgainst.left_member_id == MatchMember.id ).alias("left_member")).switch(MatchAgainst).join( RightMember, join_type=JOIN_LEFT_OUTER, on=(MatchAgainst.right_member_id == RightMember.id ).alias("right_member")).where( MatchAgainst.match_id == match_id).order_by( MatchAgainst.start_time.asc()) againsts = {} for against in against_query: if against.round_id not in againsts: againsts[against.round_id] = [] againsts[against.round_id].append(against) # 如果已经结束 获取是否已经提交了结算申请 is_application_exist =\ SettlementApplication.is_application_exist(match_id) self.render("match/detail.html", match=match, rounds=rounds, groups=groups, custom_options=custom_options, covers=covers, againsts=againsts, is_application_exist=is_application_exist)
def post(self, round_id): match_round = MatchRound.get_or_404(id=round_id) match = Match.get_or_404(id=match_round.match_id) form = EditRoundForm(self.arguments) if form.validate(): form.populate_obj(match_round) match_round.save() self.redirect(self.reverse_url("admin_match_detail", match.id)) return self.render("match/round_edit.html", form=form, match=match)
def get(self, match_id): match = Match.get_or_404(id=match_id) qr = MatchService.get_preview_qrcode(match.id) o = io.BytesIO() qr.save(o, format="JPEG") qr_obj = o.getvalue() o.close() self.set_header('Expires', '0') self.set_header('Cache-Control', 'must-revalidate, post-check=0, pre-check=0') self.set_header('Content-type', 'image/jpg') self.set_header('Content-length', len(qr_obj)) self.write(qr_obj)
def post(self, match_id): match = Match.get_or_404(id=match_id) form = CreateRoundForm(self.arguments) match_round = MatchRound(match_id=match.id) if form.validate(): form.populate_obj(match_round) match_round.save() service.match.MatchService.add_match_status_notify(match) self.redirect(self.reverse_url("admin_match_detail", match_id)) return self.render("match/round_create.html", form=form, match=match)
def get(self, match_id): """ 获取赛事轮次列表 """ match = Match.get_or_404(id=match_id) query = MatchRound.select().where( MatchRound.match_id == match.id).order_by( MatchRound.start_time.asc()) rounds = [] for match_round in query: rounds.append(match_round.info) RightMember = MatchMember.alias() against_query = MatchAgainst.select( MatchAgainst, MatchMember, RightMember).join( MatchMember, on=(MatchAgainst.left_member_id == MatchMember.id ).alias("left_member")).switch(MatchAgainst).join( RightMember, join_type=JOIN_LEFT_OUTER, on=(MatchAgainst.right_member_id == RightMember.id ).alias("right_member")).where( MatchAgainst.match_id == match_id).order_by( MatchAgainst.start_time.asc()) againsts = {} for against in against_query: if against.round_id not in againsts: againsts[against.round_id] = [] against_info = against.info against_info['left_member'] = against.left_member.mini_info if against.right_member: against_info['right_member'] = against.right_member.mini_info againsts[against.round_id].append(against_info) for i in range(0, len(rounds)): round_id = rounds[i]['id'] rounds[i]['against_mapping'] = againsts.get(round_id, []) self.write({"rounds": rounds})
def post(self, match_id): match = Match.get_or_404(id=match_id) form = MatchStatusForm(self.arguments) if not form.validate(): self.render("match/statuses_add.html", match=match, form=form) else: status = MatchStatus(match_id=match_id) form.populate_obj(status) if "photos" in self.request.files: photo_keys_list = self.upload_photos(match_id) else: photo_keys_list = [] status.photos = photo_keys_list status.save() self.redirect(self.reverse_url("admin_match_statuses", match_id))
def get(self, match_id): """ 获取赛事成员列表 :match_id: 赛事ID :returns: TODO """ match = Match.get_or_404(id=match_id) query = MatchService.members(match=match) filtered = self.filter_query(query) page = self.paginate_query(filtered) uids = self.get_parteam_uid(page) parteam_users = self.get_parteam_users(uids) if uids else {} data = self.render_page_info(page) data["members"] = self.serializing_members(page, parteam_users) self.write(data)
def get(self, match_id): """获取赛事信息 :match_id: 赛事ID :returns: 赛事信息 """ match = Match.get_or_404(id=match_id) # 获取自定义选项 query = MatchOption.select().where( MatchOption.match_id == match.id).order_by( MatchOption.sort_num.desc()) options = [] for option in query: options.append(option.info) self.write({"options": match.fields, "custom_options": options})
def get(self, match_id): match = Match.get_or_404(id=match_id) match.sport_id = Sport.get_or_none(id=match.sport_id) match.group_type = str(match.group_type) team = Team.get_or_404(id=match.team_id) form = EditMatchFrom(obj=match, team=team) # 获取赛事分组信息 query = MatchGroup.select().where( MatchGroup.match_id == match.id).order_by( MatchGroup.sort_num.desc()) groups = [] for group in query: group = group.info group['max'] = group['max_members'] groups.append(group) # 获取报名表自定义选项 query = MatchOption.select().where( MatchOption.match_id == match.id).order_by( MatchOption.sort_num.desc()) custom_options = [] for option in query: option = option.info if 'choices' in option: option['choices'] = "|".join(option['choices']) custom_options.append(option) self.render("match/edit.html", form=form, match=match, cities=ChinaCity.get_cities(), group_type=match.group_type, groups=groups, custom_options=custom_options, options=match.fields)
def _unban(self, member_id): """ unban 成员,并恢复到 ban 时原状态 """ member = MatchMember.get_or_404(id=member_id) match = Match.get_or_404(id=member.match_id) if member.state != MatchMember.MatchMemberState.banned: self.write_success() else: # 判断是不是人数已满等 以确定是否可以恢复 res = match.can_join() if res["can"]: MatchMember.update(state=member.state_before_ban).where( MatchMember.id == member_id).execute() Match.update_members_count(member.match_id) self.write_success() else: self.set_status(403) self.write({"reason": res["reason"]})
def post(self, match_id): action = self.get_argument("action") match = Match.get_or_404(id=match_id) if action == "pass": Match.update( state=Match.MatchState.opening, updated=datetime.now()).where( Match.id == match.id, Match.state << [Match.MatchState.wait_review, Match.MatchState.in_review ]).execute() elif action == "reject": Match.update( state=Match.MatchState.rejected, reject_time=datetime.now(), reject_reason=self.get_argument("reject_reason", "")).where( Match.id == match.id, Match.state << [Match.MatchState.wait_review, Match.MatchState.in_review ]).execute() self.write_success()
def post(self, match_id): """ 报名赛事 :match_id: 赛事ID :returns: """ match = Match.get_or_404(id=match_id) # 检查赛事是否可以报名 result = match.can_join() self.has_joined(match, user_id=self.current_user.id) if not result['can']: raise ApiException(403, result['reason'], log_message="报名失败:{0}, {1}".format( match_id, result['reason'])) team = Team.get_or_404(id=match.team_id) # 分组比赛模式 group = None if match.group_type == 1: group_id = self.get_argument("group_id") group = MatchGroup.get_or_none(id=group_id, match_id=match_id) if group is None: raise ApiException(404, "赛事分组不存在") # 分组是否已报满 if group.max_members <= group.members_count: raise ApiException(403, "赛事分组已报满") total_fee = group.price else: total_fee = match.price name = self.get_argument("name") mobile = self.get_argument("mobile") if not name: raise ApiException(400, "请填写名称") if not mobile: raise ApiException(400, "请填写手机号码") elif not is_mobile(mobile): raise ApiException(400, "手机号码格式有误") # TODO: 上线前移除 # member = MatchMember.get_or_none(match_id=match.id, # user_id=self.current_user.id) # if member is not None: # raise ApiException(403, "你已报名此赛事,无需重复报名") extra_attrs = self.parse_options(match_id) with self.db.transaction() as txn: # 零元赛事无需支付不生成订单 order = None if total_fee > 0: order = TeamOrder.create( order_no=TeamOrder.get_new_order_no(), team=team, user=team.owner_id, title=match.title, order_type=TeamOrder.OrderType.MATCH, payment_fee=total_fee, total_fee=total_fee, activity_id=match.id, state=TeamOrder.OrderState.WAIT_BUYER_PAY) other_attrs = {} if "avatar" in match.fields: other_attrs['avatar_key'] = self.upload_photo("avatar", "头像") if "idcard_photo" in match.fields: other_attrs['idcard_front'] = self.upload_photo( "idcard_front", "证件照片正面") other_attrs['idcard_back'] = self.upload_photo( "idcard_back", "证件照片背面") gender = self.get_argument("gender", "") if gender in ("0", "1"): gender = ("f", "m")[int(gender)] else: gender = "n" if order and order.state == TeamOrder.OrderState.WAIT_BUYER_PAY: member_state = MatchMember.MatchMemberState.wait_pay else: member_state = MatchMember.MatchMemberState.normal team.add_member(self.current_user.id, nick=name, state=TeamMember.TeamMemberState.normal) member = MatchMember.create( match_id=match.id, group_id=group.id if group else 0, member_type=match.join_type, user_id=self.current_user.id, name=name, mobile=mobile, gender=gender, age=self.get_argument("age", "0"), is_leader=self.get_argument("is_leader", False), realname=self.get_argument("realname", ""), idcard_number=self.get_argument("idcard_number", ""), extra_attrs=extra_attrs, order_id=order.id if order else 0, total_fee=total_fee, state=member_state, **other_attrs) # 如果需要付费则生成支付订单 if total_fee > 0: if match.refund_expire: refund_expire = match.refund_expire.strftime( "%Y%m%d%H%M%S") else: refund_expire = datetime.now().strftime("%Y%m%d%H%M%S") resp = self.parteam_request( "/match/openapi/createOrderInfo.do", post_args={ "orderValue": match.id, "eachFee": int(total_fee * 100), "num": 1, "totalFee": int(total_fee * 100), "subject": match.title, "userId": self.current_user.id, "notifyUrl": urljoin( self.request.full_url(), self.reverse_url('rest_match_join_notify', match.id)), "version": 1, "expDatetime": refund_expire, "tradeType": "APP" if self.device_type.lower() in ("ios", "android") else "WEB", }) if "orderNo" not in resp: txn.rollback() raise ApiException( 400, "创建订单失败", log_message="match order fail:{0}".format(resp)) MatchMember.update(pt_order_no=resp['orderNo']).where( MatchMember.id == member.id).execute() # 统计赛事人数 Match.update_members_count(match.id) if group: MatchGroup.update_members_count(group.id) member = MatchMember.get_or_404(id=member.id) member_info = member.info member_info['order'] = { "orderNo": member.pt_order_no, "orderValue": match.id, "eachFee": int(total_fee * 100), "num": 1, "totalFee": int(total_fee * 100), "subject": match.title, "userId": self.current_user.id, } self.write(member_info)
def post(self, match_id): match = Match.get_or_404(id=match_id) MatchService.cancel(match, self.current_user) self.write_success()
def get(self, match_id): match = Match.get_or_404(id=match_id) form = MatchStatusForm() self.render("match/statuses_add.html", match=match, form=form)
def post(self, round_id): match_round = MatchRound.get_or_404(id=round_id) match = Match.get_or_404(id=match_round.match_id) againsts = {} for key in self.request.arguments: if key.startswith("ag-"): value = self.get_argument(key) parts = key.split("-") idx = int(parts[-1]) if idx not in againsts: againsts[idx] = { "left": 0, "right": 0, "address": "", "start_time": "", "left_score": 0, "right_score": 0 } if parts[1] in ("left", "right", "left_score", "right_score"): value = intval(value) elif parts[1] in ("start_time", ) and value == "": raise ArgumentError(400, "请填写对战时间") elif parts[1] in ("address", ) and value == "": raise ArgumentError(400, "请填写对战地址") againsts[idx][parts[1]] = value # 清除旧的 MatchAgainst.delete().where( MatchAgainst.round_id == match_round.id).execute() againsts = [againsts[idx] for idx in againsts if againsts[idx]['left']] start_time = None end_time = None for against in againsts: if against['left_score'] > against['left_score']: win_member_id = against['left'] elif against['left_score'] < against['left_score']: win_member_id = against['right'] elif against['left_score'] == against['left_score']: win_member_id = 0 MatchAgainst.create(match_id=match.id, round_id=match_round.id, left_member_id=intval(against['left']), right_member_id=intval(against['right']), address=against['address'], left_score=intval(against['left_score']) or "0", right_score=intval(against['right_score']) or "0", win_member_id=win_member_id, start_time=against['start_time'] if against['start_time'] else None) if not start_time or against['start_time'] < start_time: start_time = against['start_time'] if not end_time or against['start_time'] > end_time: end_time = against['start_time'] if match.type == 0: MatchRound.update(start_time=start_time, end_time=end_time).where( MatchRound.id == match_round.id).execute() self.write_success()
def post(self, match_id): match = Match.get_or_404(id=match_id) team = Team.get_or_404(id=match.team_id) form = EditMatchFrom(self.arguments, team=team) groups = self.parse_groups() options = self.parse_options() custom_options = self.parse_custom_options() # 验证分组设置 groups_validated = self.validate_groups(form, groups) if form.validate() and groups_validated: with (self.db.transaction()): form.populate_obj(match) # 计算赛事总人数限制 if intval(match.group_type) == 1: match.price = min(map(lambda x: float(x['price']), groups)) if groups else 0 match.max_members = reduce(lambda x, y: x + y, map(lambda x: x['max'], groups)) if groups else 0 if "coverfile" in self.request.files: to_bucket = self.settings['qiniu_avatar_bucket'] to_key = "match:%s%s" % (self.current_user.id, time.time()) to_key = hashlib.md5(to_key.encode()).hexdigest() cover_key = self.upload_file( "coverfile", to_bucket=to_bucket, to_key=to_key, ) match.cover_key = cover_key match.user_id = self.current_user.id match.fields = options if not match.join_end: match.join_end = match.start_time match.save() if intval(match_id) > 0: group_ids = [ group['id'] for group in groups if group['id'] > 0 ] if len(group_ids) > 0: MatchGroup.delete().where( MatchGroup.match_id == intval(match_id), MatchGroup.id.not_in(group_ids)).execute() else: MatchGroup.delete().where( MatchGroup.match_id == intval(match_id)).execute() # 保存分组 for group in groups: if group['id'] > 0: MatchGroup.update( name=group['name'], price=group['price'], max_members=group['max']).where( MatchGroup.id == group['id']).execute() else: MatchGroup.create(match_id=match.id, name=group['name'], price=group['price'], max_members=group['max']) if intval(match_id) > 0: custom_option_ids = [ custom_option['id'] for custom_option in custom_options if custom_option['id'] > 0 ] if len(custom_option_ids) > 0: MatchOption.delete().where( MatchOption.match_id == intval(match_id), MatchOption.id.not_in( custom_option_ids)).execute() else: MatchOption.delete().where(MatchOption.match_id == intval(match_id)).execute() # 保存自定义选项 for custom_option in custom_options: if custom_option['id'] > 0: MatchOption.update( title=custom_option['title'], field_type=custom_option['field_type'], required=custom_option['required'], choices=custom_option['choices'], ).where( MatchOption.id == custom_option['id']).execute() else: MatchOption.create( match_id=match.id, title=custom_option['title'], field_type=custom_option['field_type'], required=custom_option['required'], choices=custom_option['choices'], ) # MatchService.add_match_start_notify(match) self.redirect(self.reverse_url("admin_match_detail", match.id)) return province = self.get_argument("province", None) if province: form.city.choices = ChinaCity.get_cities(province) self.validate_groups(form, groups) self.render("match/edit.html", form=form, match=match, cities=ChinaCity.get_cities(), groups=groups, group_type=self.get_argument("group_type", "0"), options=options, custom_options=custom_options)