def patch(self, user_id, activity_id): """ 修改报名信息 """ try: activity = Activity.get(id=activity_id) except Activity.DoesNotExist: raise ApiException(404, "活动不存在") self.joined_this_activity(activity_id, user_id) # 校验提交的参数是否合法, 1. 自定义参数; 2. 必填参数是否发生修改 fields = {} fields.update(self.handle_extra_fields(activity=activity)) fields.update(self.handler_required_fields(activity)) if not fields: raise ApiException(400, "填写需要修改的属性和值") ActivityMember.update(**fields)\ .where(ActivityMember.activity == activity_id, ActivityMember.user == user_id)\ .execute() self.set_status(204)
def test_online_pay_activity(self): url = self.JOIN_ACTIVITY.format(activity_id=self.activity.id) body = {"payment": "wxpay", "nickname": "Nick name"} self.auth_user = User.create(name='join activity') response = self.fetch(url, method='POST', body=json.dumps(body), params={'team_id': self.team.id}) self.assertEqual(200, response.code, response.body) order = TeamOrder.get_or_none(user=self.auth_user, activity_id=self.activity.id) self.assertIsNotNone(order, "加入活动时订单 `TeamOrder` 未创建") result = json.loads(response.body.decode()) expect = { "status": "ok", "state": ActivityMember.ActivityMemberState.wait_confirm.value, "payment_state": TeamOrder.OrderState.WAIT_BUYER_PAY.value, "order_no": order.order_no } self.assertDictEqual(expect, result, result) member = ActivityMember.get_or_none(activity=self.activity, user=self.auth_user) self.assertIsNotNone(member, "加入活动后 `ActivityMember` 未添加记录")
def get(self, activity_id, member_id): activity = Activity.get_or_404(id=activity_id) self.has_read_permission(activity) member = ActivityMember.get_or_404(id=member_id) self.write(InsecureActivityMemberSerializer(member).data)
def cancel_activity(activity_id, cancel_reason=""): """取消活动 1. 取消活动后需要通知用户活动取消,已付款用户将退款 2. 已结算活动不能取消 """ activity = Activity.get_or_404(id=activity_id) if activity.state == Activity.ActivityState.finished: raise ArgumentError(400, "已结束活动不能取消") members = ActivityMember.select().where( ActivityMember.activity == activity_id) with app.db.transaction() as txn: for member in members: member.refund("活动取消") # 修改场次状态为取消 Activity.update(state=Activity.ActivityState.cancelled, cancelled=datetime.now(), cancel_reason=cancel_reason, online_paid_amount=Decimal(0), credit_paid_amount=Decimal(0), cash_paid_amount=Decimal(0), free_times_amount=Decimal(0)).where( Activity.id == activity.id).execute()
def joined_this_activity(self, activity_id, user_id): """用户是否参加了对应活动""" try: member = ActivityMember.get(activity=activity_id, user=user_id) except ActivityMember.DoesNotExist: raise ApiException(400, "未参加该活动") return member
def test_patch_activity_profile(self): url = self.ACTIVITY_PROFILE.format(user_id=self.user.id, activity_id=self.activity.id) body = {"nickname": "new nick"} self.auth_user = self.user response = self.fetch(url, method="PATCH", body=json.dumps(body)) self.assertEqual(204, response.code, response.body) updated = ActivityMember.get(activity=self.activity.id, user=self.user) self.assertEqual("new nick", updated.nickname)
def test_activity_member_detail(self): member = ActivityMember.get(activity=self.activity, user=self.user) url = self.MEMBER_DETAIL.format(activity_id=self.activity.id, member_id=member.id) self.auth_user = self.creator response = self.fetch(url) self.assertEqual(200, response.code, response.body.decode()) self.auth_user = User.create(name="permission deny") response = self.fetch(url) self.assertEqual(403, response.code, response.body.decode())
def get(self, activity_id): activity = Activity.get(id=activity_id) query = ActivityMember.select()\ .where(ActivityMember.activity == activity) query = self.filter_query(query) page = self.paginate_query(query) data = self.get_paginated_data( page=page, alias="members", serializer=self.get_serializer(activity) ) self.write(data)
def get(self, activity_id): activity = Activity.get_or_404(id=activity_id) members = ActivityMember.select( ActivityMember, TeamOrder, User ).join( User, on=(ActivityMember.user == User.id).alias("user") ).switch( ActivityMember ).join( TeamOrder, join_type=JOIN_LEFT_OUTER, on=(TeamOrder.id == ActivityMember.order_id).alias("order") ).where( ActivityMember.activity == activity ) activity.total_amount = ActivityMember.select( fn.SUM(ActivityMember.total_fee) ).where( ActivityMember.payment_state << (TeamOrder.OrderState.TRADE_BUYER_PAID, TeamOrder.OrderState.TRADE_FINISHED), ActivityMember.activity == activity ).scalar() or 0 members = self.paginate_query(members) activity.members_count = ActivityMember.select( fn.SUM(ActivityMember.users_count) ).where( ActivityMember.state == ActivityMember.ActivityMemberState.confirmed, ActivityMember.activity == activity ).scalar() or 0 self.render("activity/members.html", activity=activity, members=members)
def initial_data(self): self.team_owner = User.create(name='test_activity') self.team = Team.create(name='club_test_activity', owner_id=self.team_owner.id) self.user = self.creator = User.create(name='activity_creator') self.activity = Activity.create(team=self.team, creator=self.creator, price='10', vip_price='8', leader=self.creator, title='just a test', description='description', need_nickname=True, join_end="3000-12-30 22:59:59", max_members=10, start_time='3000-01-01 00:00:01', end_time='3000-12-31 23:59:59') self.activity_2 = Activity.create(team=self.team, creator=self.creator, price='10', vip_price='8', leader=self.creator, title='just a test', description='description', need_nickname=True, join_end="3000-12-30 22:59:59", max_members=10, start_time='3000-01-01 00:00:01', end_time='3000-12-31 23:59:59') self.activity_member = ActivityMember.create( activity=self.activity, user=self.user, total_fee='0.01', nickname="leave activities", payment_method=TeamOrder.OrderPaymentMethod.WXPAY.value, payment_state=TeamOrder.OrderState.TRADE_BUYER_PAID, ) TeamMemberService.new_order(team=self.team, activity_id=self.activity.id, user=self.user, order_type=TeamOrder.OrderType.ACTIVITY, payment_method='wxpay', total_fee=self.activity.price, payment_fee=self.activity.price, title='TestLeave') TeamOrder.update(state=TeamOrder.OrderState.TRADE_BUYER_PAID)\ .where(TeamOrder.activity_id == self.activity.id, TeamOrder.user == self.user)\ .execute()
def test_cash_pay(self): activity = Activity.create(team=self.team, creator=self.creator, price='10', vip_price='8', leader=self.creator, payment_type=Activity.PaymentType.CASH_PAY, title='no online pay', description='on need online pay', start_time='3000-01-01 00:00:01', end_time='3000-12-31 23:59:59', join_end="4000-01-01 22:59:59", max_members=10) url = self.JOIN_ACTIVITY.format(activity_id=activity.id) body = { "payment": TeamOrder.OrderPaymentMethod.WXPAY.value, "nickname": "Nick name" } self.auth_user = User.create(name='no need online pay') response = self.fetch(url, method='POST', body=json.dumps(body), params={'team_id': self.team.id}) result = json.loads(response.body.decode()) expect = { "status": "ok", "state": ActivityMember.ActivityMemberState.confirmed.value, "payment_state": TeamOrder.OrderState.WAIT_BUYER_PAY.value, "order_no": "" } self.assertDictEqual(expect, result, result) self.assertEqual(200, response.code, response.body) with self.assertRaises(TeamOrder.DoesNotExist): TeamOrder.get( user=self.auth_user, activity_id=activity.id, ) member = ActivityMember.get(activity=activity, user=self.auth_user) # 现在支付, 直接确认 self.assertEqual(ActivityMember.ActivityMemberState.confirmed.value, member.state, member.state)
def initial_data(self): self.team_owner = User.create(name='test_activity') self.team = Team.create(name='club_test_activity', owner_id=self.team_owner.id) self.user = self.creator = User.create(name='activity_creator') self.activity = Activity.create(team=self.team, creator=self.creator, price='10', vip_price='8', leader=self.creator, title='just a test', description='description', need_nickname=True, max_members=10, start_time='3000-01-01 00:00:01', end_time='3000-12-31 23:59:59') self.activity_member = ActivityMember.create(activity=self.activity, user=self.user, total_fee='0.01', nickname="my activities")
def get(self): orders = ActivityMember.select( ActivityMember, TeamOrder, User ).join( TeamOrder, on=(TeamOrder.id == ActivityMember.order_id).alias("order") ).switch( ActivityMember ).join( User, on=(ActivityMember.user == User.id).alias("user") ).where( TeamOrder.team == self.current_team, TeamOrder.refund_state > TeamOrder.OrderRefundState.NO_REFUND ).order_by( TeamOrder.refunded_time.desc() ) orders = self.paginate_query(orders) self.render("activity/refunded_orders.html", orders=orders )
def test_cash_free_activity(self): """ 参加免费活动不需要支付 线下支付活动的 ActivityMember.state 应该为 `确认` confirmed """ activity = self.create_free_activity( payment_type=Activity.PaymentType.CASH_PAY.value) url = self.JOIN_ACTIVITY.format(activity_id=activity.id) body = { "payment": TeamOrder.OrderPaymentMethod.WXPAY.value, "nickname": "Nick name" } self.auth_user = User.create(name='free activity') response = self.fetch(url, method='POST', body=json.dumps(body), params={'team_id': self.team.id}) self.assertEqual(200, response.code, response.body) result = json.loads(response.body.decode()) expect = { "status": "ok", "state": ActivityMember.ActivityMemberState.confirmed.value, "payment_state": TeamOrder.OrderState.TRADE_BUYER_PAID.value, "order_no": "" } self.assertDictEqual(expect, result, result) with self.assertRaises(TeamOrder.DoesNotExist): TeamOrder.get(user=self.auth_user, activity_id=activity.id) member = ActivityMember.get(activity=activity, user=self.auth_user) self.assertEqual(ActivityMember.ActivityMemberState.confirmed.value, member.state, member.state)
def initial_data(self): self.leader = User.create(name="imleader") self.team = Team.create(name="test_finish_activity", owner_id=self.leader.id) self.activity = Activity.create( team=self.team, creator=self.leader, leader=self.leader, title="test_finish_activity", description="test_stoped_activity", price=Decimal(15), max_members=30, start_time=datetime.datetime.now() - datetime.timedelta(hours=2), end_time=datetime.datetime.now() - datetime.timedelta(hours=1), payment_type=0, repeat_type="weekly", state=Activity.ActivityState.opening) self.online_paid_amount = 0 for i in range(0, 5): user = User.create(name="test_%s" % i) order = TeamOrder.create( team=self.team, user=user, order_type=0, activity_id=self.activity.id, title="test_finish", order_no=TeamOrder.get_new_order_no(), credit_fee=0, total_fee=self.activity.price, payment_fee=self.activity.price, payment_method="wxpay", state=TeamOrder.OrderState.TRADE_BUYER_PAID, paid=self.activity.start_time, created=self.activity.start_time, finished=self.activity.start_time) ActivityMember.create( team=self.team, activity=self.activity, user=user, price=self.activity.price, users_count=1, total_fee=self.activity.price, payment_state=order.state, payment_method="wxpay", order_id=order.id, order_no=order.order_no, state=ActivityMember.ActivityMemberState.confirmed, free_times=0, ) self.online_paid_amount += self.activity.price for i in range(0, 3): user = User.create(name="test2_%s" % i) order = TeamOrder.create(team=self.team, user=user, order_type=0, activity_id=self.activity.id, title="test_finish", order_no=TeamOrder.get_new_order_no(), credit_fee=0, total_fee=self.activity.price, payment_fee=self.activity.price, payment_method="wxpay", state=TeamOrder.OrderState.WAIT_BUYER_PAY, created=self.activity.start_time, finished=self.activity.start_time) ActivityMember.create( team=self.team, activity=self.activity, user=user, price=self.activity.price, users_count=1, total_fee=self.activity.price, payment_state=order.state, payment_method="wxpay", order_id=order.id, order_no=order.order_no, state=ActivityMember.ActivityMemberState.wait_confirm, free_times=0, )
def finish_activity(activity_id): """结算活动场次 1. 将用户在线支付费用转到俱乐部账户 2. 标记场次和订单状态为完成 3. 记录俱乐部账户变化 """ activity = Activity.get_or_404(id=activity_id) if activity.end_time > datetime.now(): raise Exception("活动场次未结束") if activity.state == Activity.ActivityState.cancelled: raise Exception("活动场次已取消") if activity.state == Activity.ActivityState.finished: raise Exception("活动场次已结算") # 计算在线支付完成交易的总额 online_paid_amount = TeamOrder.select(fn.SUM(TeamOrder.payment_fee)).where( TeamOrder.activity_id == activity_id, TeamOrder.state >= TeamOrder.OrderState.TRADE_BUYER_PAID.value, TeamOrder.refund_state == TeamOrder.OrderRefundState.NO_REFUND, TeamOrder.payment_method << TeamOrder.ONLINE_PAYMENT_METHODS).scalar() or 0 # 计算余额支付完成交易的总额 credit_paid_amount = TeamOrder.select(fn.SUM(TeamOrder.credit_fee)).where( TeamOrder.activity_id == activity_id, TeamOrder.state >= TeamOrder.OrderState.TRADE_BUYER_PAID.value).scalar() or 0 # 使用次数 free_times_amount = ActivityMember.select(fn.SUM( ActivityMember.free_times)).where( ActivityMember.state == ActivityMember.ActivityMemberState.confirmed).scalar() or 0 # online_paid_amount= DecimalField(default=Decimal(0), verbose_name="在线支付收入") # credit_paid_amount= DecimalField(default=Decimal(0), verbose_name="余额支付收入") # cash_paid_amount= DecimalField(default=Decimal(0), verbose_name="现金支付收入") # free_times_amount = IntegerField(default=0, verbose_name="次卡支付数量") with app.db.transaction() as txn: team = Team.select().where( Team.id == activity.team.id).for_update().get() # 将收入打到俱乐部账上 Team.update( credit=Team.credit + online_paid_amount, total_receipts=Team.total_receipts + online_paid_amount, updated=datetime.now()).where(Team.id == team.id).execute() # 将订单修改状态为已完成 TeamOrder.update( state=TeamOrder.OrderState.TRADE_FINISHED.value, finished=datetime.now()).where( TeamOrder.activity_id == activity_id, TeamOrder.state == TeamOrder.OrderState.TRADE_BUYER_PAID.value, TeamOrder.refund_state == TeamOrder.OrderRefundState.NO_REFUND.value).execute() # 修改场次状态为已结算 Activity.update(state=Activity.ActivityState.finished, finished=datetime.now(), online_paid_amount=online_paid_amount, credit_paid_amount=credit_paid_amount, free_times_amount=free_times_amount).where( Activity.id == activity_id).execute() # 记录俱乐部账户变更 TeamAccountLog.create(team_id=team.id, credit_change=online_paid_amount, change_type=0, credit_before=team.credit, credit_after=team.credit + online_paid_amount, note="活动结算:%s(%s)" % (activity.title, activity.start_time), activity_id=activity_id, operator_id=0) # 生成下期活动 gen_next_activity(activity_id)