def test_balance(self): url = reverse('merchant-balance') response = self.client.get(url, Token=self.token) resp_json = response.json() self.assertEqual( resp_json, dict( wechat_balance=1000, wechat_withdrawable_balance=500.05, alipay_balance=2000, alipay_withdrawable_balance=1000.05, wechat_nickname=self.merchant_admin.wechat_nickname, alipay_user_name=self.merchant_admin.alipay_user_name, )) with self.not_change_account(): # 更改可提现余额为0.99 self.account.withdrawable_balance = set_amount(0.99) self.account.alipay_withdrawable_balance = set_amount(0.99) self.account.save() # 检查可提现金额显示为0.99(前端显示为0) response = self.client.get(url, Token=self.token) resp_json = response.json() self.assertEqual( resp_json, dict( wechat_balance=1000, wechat_withdrawable_balance=0.99, alipay_balance=2000, alipay_withdrawable_balance=0.99, wechat_nickname=self.merchant_admin.wechat_nickname, alipay_user_name=self.merchant_admin.alipay_user_name, ))
def setUpTestData(cls): cls.factory = PayunionFactory() # 商户分类 cls.merchant_category = None for p in range(4): parent = cls.factory.create_merchant_category( name='parent{}'.format(p)) for c in range(4): cls.merchant_category = cls.factory.create_merchant_category( parent=parent, name='{}_child{}'.format(parent.name, c)) # 商户街道 for p in range(4): parent = cls.factory.create_area(name='市{}'.format(p)) for c in range(4): child = cls.factory.create_area(parent=parent, name='{}_区{}'.format( parent.name, c)) for cc in range(4): cls.area = cls.factory.create_area( parent=child, name='{}_区{}_街道{}'.format(parent.name, c, cc)) cls.account = cls.factory.create_account( balance=set_amount(1000.00), withdrawable_balance=set_amount('500.05'), alipay_balance=set_amount(2000), alipay_withdrawable_balance=set_amount('1000.05'), real_name='张三', bank_card_number='1234567890123', bank_name='中国招商银行成都玉林路支行') cls.merchant = cls.factory.create_merchant( name='就是这个公司', status=MERCHANT_STATUS['USING'], account=cls.account, area=cls.area, category=cls.merchant_category, avatar_url='https://merchant_avatar.jpg', photo_url='https://merchant_photo.jpg', id_card_back_url=True, id_card_front_url=True, day_begin_minute=8 * 60, # 商户订单日结时间设置为08:00 ) cls.merchant_admin = cls.factory.create_merchant_admin( merchant_admin_type=MERCHANT_ADMIN_TYPES['ADMIN'], work_merchant=cls.merchant, wechat_nickname='张微信', alipay_user_name='张付宝', voice_on=True) cls.merchant_cashier = cls.factory.create_merchant_admin( merchant_admin_type=MERCHANT_ADMIN_TYPES['CASHIER'], work_merchant=cls.merchant) # 创建token并缓存, 绕过登录 super(TestMerchantViewSet, cls).setUpTestData()
def setUpTestData(cls): cls.factory = PayunionFactory() cls.account = cls.factory.create_account( balance=set_amount(1000.00), withdrawable_balance=set_amount('500.05'), alipay_balance=set_amount(2000), alipay_withdrawable_balance=set_amount(0.99), bank_card_number='1234567890123' ) cls.merchant = cls.factory.create_merchant( name='就是这个公司', account=cls.account, day_begin_minute=8 * 60, # 商户订单日结时间设置为08:00 ) cls.merchant_admin = cls.factory.create_merchant_admin( status=SYSTEM_USER_STATUS['USING'], work_merchant=cls.merchant, merchant_admin_type=MERCHANT_ADMIN_TYPES['ADMIN'] ) cls.manager = MerchantManager(cls.merchant) # create cashiers cls.normal_cashier_a = cls.factory.create_merchant_admin( status=SYSTEM_USER_STATUS['USING'], work_merchant=cls.merchant, merchant_admin_type=MERCHANT_ADMIN_TYPES['CASHIER'] ) cls.normal_cashier_b = cls.factory.create_merchant_admin( status=SYSTEM_USER_STATUS['USING'], work_merchant=cls.merchant, merchant_admin_type=MERCHANT_ADMIN_TYPES['CASHIER'] ) cls.other_merchant_cashier = cls.factory.create_merchant_admin( status=SYSTEM_USER_STATUS['USING'], merchant_admin_type=MERCHANT_ADMIN_TYPES['CASHIER'] ) cls.disabled_cashier = cls.factory.create_merchant_admin( status=SYSTEM_USER_STATUS['DISABLED'], work_merchant=cls.merchant, merchant_admin_type=MERCHANT_ADMIN_TYPES['CASHIER'] )
def test_account_wechat_withdraw_balance(self): # 能正确查询到商户账户微信可提现余额 self.assertEqual(self.manager.account_wechat_withdraw_balance, 500.05) # 修改余额为0.01后不足微信最小可提现余额, 可提现余额逻辑显示为0.01(前端显示为0) with self.not_change_account(): self.account.withdrawable_balance = set_amount('0.01') self.account.save() self.assertEqual(self.manager.account_wechat_withdraw_balance, 0.01)
def create_marketer(cls, user): account = cls.factory.create_account( balance=set_amount(10), withdrawable_balance=set_amount('0.50'), alipay_balance=set_amount('15006.50'), alipay_withdrawable_balance=set_amount('15006.50'), real_name=user['name']) cls.marketer = cls.factory.create_marketer( wechat_openid=user['openid'], wechat_unionid=user['unionid'], inviter_type=MARKETER_TYPES[user['type']], status=SYSTEM_USER_STATUS['USING'], name=user['name'], phone='13333333333', id_card_front_url=cls.C.id_card_front_url, id_card_back_url=cls.C.id_card_back_url, account=account, )
def test_alipay_wechat_withdraw_balance(self): # 不足支付宝最小可提现余额, 可提现余额逻辑显示为0 self.assertEqual(self.manager.account_alipay_withdraw_balance, 0.99) # 修改余额为100.3后能正确查询到 with self.not_change_account(): self.account.alipay_withdrawable_balance = set_amount('100.3') self.account.save() self.assertEqual(self.manager.account_alipay_withdraw_balance, 100.3)
def _create_coupon_rule(self): self.coupon_rule = self.factory.create_coupon_rule( merchant=self.merchant, discount=set_amount(100.1), min_charge=set_amount(300), ) for day in (Config.day_1, Config.day_2, Config.day_3, Config.day_4): for i in range(20): coupon = self.factory.create_coupon( rule=self.coupon_rule, status=(COUPON_STATUS['NOT_USED'], COUPON_STATUS['USED'])[i % 2]) payment = self.factory.create_payment( order_price=set_amount(300), coupon=coupon, status=PAYMENT_STATUS['FINISHED'], datetime=day) self.factory.create_transaction(content_object=payment, amount=payment.order_price - self.coupon_rule.discount)
def _create_different_type_coupon_rules(self): # 指定日期区间 self.factory.create_coupon_rule( merchant=self.merchant, discount=set_amount(100), min_charge=set_amount(300), valid_strategy=VALID_STRATEGY['DATE_RANGE'], start_date=Config.jan, end_date=Config.feb, ) # 指定有效天数 self.factory.create_coupon_rule( number=10, merchant=self.merchant, discount=set_amount(1000), min_charge=set_amount(3000), valid_strategy=VALID_STRATEGY['EXPIRATION'], expiration_days=90, )
def alipay_withdraw(self, amount): """支付宝提现 amount为0时不进行任何操作""" if amount != 0: try: alipay_payment.withdraw(self.obj, set_amount(amount)) except BalanceInsufficient: return MerchantError.withdrawable_balance_not_sufficient except (ApiRequestError, ApiReturnedError): return MerchantError.withdraw_api_error return None
def validate(self, attrs): now = timezone.now() # update CouponRule, only has param 'stock' if 'discount' not in attrs: return attrs # create CouponRule attrs['discount'] = set_amount(attrs['discount']) attrs['min_charge'] = set_amount(attrs['min_charge']) # 最低消费 > 优惠减免 if not float(attrs['discount']) < float(attrs['min_charge']): self.fail(MerchantError.min_charge_must_greater_than_discount['error_code']) # 指定日期区间时 if attrs['valid_strategy'] == VALID_STRATEGY['DATE_RANGE']: # 必须传入参数start_date与end_date if attrs.get('start_date') is None or attrs.get('end_date') is None: self.fail(MerchantError.must_have_param_start_date_and_end_date['error_code']) # 开始日期 <= 结束日期 if not attrs['start_date'] <= attrs['end_date']: self.fail(MerchantError.end_date_must_greater_than_start_date['error_code']) # 时间段:开始时间可选择1年内 if attrs['start_date'] > now.date().replace(year=now.year + 1): self.fail(MerchantError.start_date_must_be_in_1_year['error_code']) # 时间段:结束时间按开始时间起计算的1年内 if attrs['end_date'] > attrs['start_date'].replace(year=now.year + 1): self.fail(MerchantError.start_date_must_be_in_1_year_from_start_date['error_code']) # 指定有效天数时 if attrs['valid_strategy'] == VALID_STRATEGY['EXPIRATION']: if attrs.get('expiration_days') is None: self.fail(MerchantError.must_have_param_expiration_days['error_code']) return attrs
def create_coupon_rule( self, number=Config.default_number, merchant=None, discount=None, min_charge=None, valid_strategy=None, start_date=None, end_date=None, expiration_days=None, stock=None, photo_url=None, note=None, datetime=None, update_datetime=None, ): for _ in range(number): e = CouponRule.objects.create( merchant=self.create_merchant() if merchant is None else merchant, discount=set_amount(choice(Config.discount)) if discount is None else discount, min_charge=set_amount(choice(Config.min_charge)) if min_charge is None else min_charge, valid_strategy=self.random_choice(VALID_STRATEGY) if valid_strategy is None else valid_strategy, start_date=fake.date_time_this_year(before_now=True) if start_date is None else start_date, end_date=fake.future_datetime(end_date="+90d", tzinfo=None) if end_date is None else end_date, expiration_days=randint(30, 90) if expiration_days is None else expiration_days, stock=randint(0, 100) if stock is None else stock, photo_url=choice(Config.image_urls) if photo_url is None else photo_url, note=fake.text(max_nb_chars=300, ext_word_list=None) if note is None else note, ) if datetime: e.datetime = fake.date_time_this_year(before_now=True) if datetime is True else datetime if update_datetime: e.update_datetime = fake.date_time_this_year( before_now=True) if update_datetime is True else update_datetime e.save() return e
def validate(self, attrs): channel = attrs.get('channel') amount = attrs.get('amount') if channel == PAY_CHANNELS.WECHAT and WECHAT_MAX_WITHDRAW_AMOUNT < amount: self.fail(MerchantError.exceeding_the_wechat_maximum_withdrawal_balance['error_code']) # 可提现余额不足 if (channel == PAY_CHANNELS.WECHAT and self.instance.withdrawable_balance < set_amount( amount)) \ or ( channel == PAY_CHANNELS.ALIPAY and self.instance.alipay_withdrawable_balance < set_amount( amount)): self.fail(MerchantError.withdrawable_balance_not_sufficient['error_code']) return attrs
def wechat_withdraw( self, amount, client_ip, app_id=dynasettings.SUBSCRIPTION_ACCOUNT_APP_ID_MERCHANT): """微信提现 amount为0时不进行任何操作""" if amount != 0: try: wechat_payment.withdraw(self.obj, set_amount(amount), client_ip, app_id) except BalanceInsufficient: return MerchantError.withdrawable_balance_not_sufficient except (ApiRequestError, ApiReturnedError): return MerchantError.withdraw_api_error return None
def test_serialize_relative_payment(self): for day in (Config.day_1, Config.day_2, Config.day_3, Config.day_4): payment = self.factory.create_payment( coupon=self.factory.create_coupon(rule=self.coupon_rule), order_price=set_amount(300), datetime=day) self.factory.create_transaction(content_object=payment, amount=payment.order_price - self.coupon_rule.discount) payments = self.manager.relative_payment()[:20] # page data = self.manager.serialize_relative_payment(payments) for e in data: day = e['month'] payments = e['cur_page_transactions'] self.assertTrue(re.match('2018-0[1-4]-01', day)) self.assertIn(payments[0]['title'], ('微信支付', '支付宝支付')) self.assertEqual(payments[0]['desc'], '[满300减100.1优惠券]') self.assertTrue( re.match('0[1-4]-01 00:00', payments[0]['datetime'])) self.assertEqual(payments[0]['amount'], 300 - 100.1) self.assertIn(payments[0]['status'], ('', '已退款', '退款中'))
def set_account_balance(account_instance, amount, channel): """ 为instance设置金额 :param account_instance: Account实例 :param amount: 设置的金额 :param channel: 相关渠道 :return: account对象 """ assert isinstance(account_instance, Account) amount = set_amount(amount) if channel == config.PAY_CHANNELS.ALIPAY: account_instance.alipay_balance = amount account_instance.alipay_withdrawable_balance = amount elif channel == config.PAY_CHANNELS.WECHAT: account_instance.balance = amount account_instance.withdrawable_balance = amount else: assert channel in (config.PAY_CHANNELS.WECHAT, config.PAY_CHANNELS.ALIPAY) account_instance.save() return account_instance
def test_merchant_statistics(self): first_day = timezone.now().replace(year=2018, month=1, day=1, hour=9) second_day = timezone.now().replace(year=2018, month=1, day=2, hour=9) # 1. 创建一笔退款订单 refund_payment = self.factory.create_payment( datetime=second_day, merchant=self.merchant, order_price=set_amount(100), status=PAYMENT_STATUS.REFUND ) # 退款订单 self.factory.create_transaction( transaction_type=TRANSACTION_TYPE.MERCHANT_RECEIVE, datetime=second_day, account=self.account, amount=set_amount(100), content_object=refund_payment ) self.factory.create_transaction( transaction_type=TRANSACTION_TYPE.MERCHANT_REFUND, datetime=second_day, account=self.account, amount=-set_amount(100), content_object=self.factory.create_refund( datetime=second_day, status=REFUND_STATUS.FINISHED, payment=refund_payment) ) # 2. 两天分别创建一笔未支付订单, 一笔优惠订单, 一笔普通订单, 一笔引流收益 for datetime_ in (first_day, second_day): # 未支付订单 self.factory.create_payment( datetime=datetime_, status=PAYMENT_STATUS.UNPAID, merchant=self.merchant, order_price=set_amount(100), ) # 优惠券订单 coupon = self.factory.create_coupon( discount=set_amount(10), min_charge=set_amount(100), status=COUPON_STATUS.USED, use_datetime=datetime_, ) use_coupon_payment = self.factory.create_payment( datetime=datetime_, status=PAYMENT_STATUS.FINISHED, merchant=self.merchant, order_price=set_amount(110), coupon=coupon, platform_share=set_amount(3), originator_share=set_amount(1), inviter_share=set_amount(1) ) self.factory.create_transaction( transaction_type=TRANSACTION_TYPE.MERCHANT_RECEIVE, datetime=datetime_, account=self.account, amount=set_amount(95), content_object=use_coupon_payment, ) # 普通订单 not_use_coupon_payment = self.factory.create_payment( datetime=datetime_, status=PAYMENT_STATUS.FINISHED, merchant=self.merchant, order_price=set_amount(100), platform_share=set_amount(0), originator_share=set_amount(0), inviter_share=set_amount(0) ) self.factory.create_transaction( transaction_type=TRANSACTION_TYPE.MERCHANT_RECEIVE, datetime=datetime_, account=self.account, amount=set_amount(100), content_object=not_use_coupon_payment, ) # 引流收益 self.factory.create_transaction( transaction_type=TRANSACTION_TYPE.MERCHANT_SHARE, datetime=datetime_, account=self.account, amount=set_amount(1), ) # 3. 检查第二日 second_day_begin = second_day.replace(hour=0, minute=0, second=0, microsecond=0) result = self.manager.merchant_business_report( datetime_start=second_day_begin, datetime_end=second_day_begin + timedelta(days=1) ) self.assertEqual(result, {'turnover': 200, 'originator_expenditure': 5, 'originator_earning': 1, 'payment': {'use_coupon': 1, 'not_use_coupon': 2}}) # 4. 检查第一日 first_day_begin = first_day.replace(hour=0, minute=0, second=0, microsecond=0) result = self.manager.merchant_business_report( datetime_start=first_day_begin, datetime_end=first_day_begin + timedelta(days=1) ) self.assertEqual(result, {'turnover': 200, 'originator_expenditure': 5, 'originator_earning': 1, 'payment': {'use_coupon': 1, 'not_use_coupon': 1}})
def test_business_report(self): first_day = timezone.now().replace(year=2018, month=1, day=1, hour=9) second_day = timezone.now().replace(year=2018, month=1, day=2, hour=9) # 1. 创建一笔退款订单 refund_payment = self.factory.create_payment( datetime=second_day, merchant=self.merchant, order_price=set_amount(100), status=PAYMENT_STATUS.REFUND) # 退款订单 self.factory.create_transaction( transaction_type=TRANSACTION_TYPE.MERCHANT_RECEIVE, datetime=second_day, account=self.account, amount=set_amount(100), content_object=refund_payment) self.factory.create_transaction( transaction_type=TRANSACTION_TYPE.MERCHANT_REFUND, datetime=second_day, account=self.account, amount=-set_amount(100), content_object=self.factory.create_refund( datetime=second_day, status=REFUND_STATUS.FINISHED, payment=refund_payment)) # 2. 两天分别创建一笔未支付订单, 一笔优惠订单, 一笔普通订单, 一笔引流收益 for datetime_ in (first_day, second_day): # 未支付订单 self.factory.create_payment( datetime=datetime_, status=PAYMENT_STATUS.UNPAID, merchant=self.merchant, order_price=set_amount(100), ) # 优惠券订单 coupon = self.factory.create_coupon( discount=set_amount(10), min_charge=set_amount(100), status=COUPON_STATUS.USED, use_datetime=datetime_, ) use_coupon_payment = self.factory.create_payment( datetime=datetime_, status=PAYMENT_STATUS.FINISHED, merchant=self.merchant, order_price=set_amount(110), coupon=coupon, platform_share=set_amount(3), originator_share=set_amount(1), inviter_share=set_amount(1)) self.factory.create_transaction( transaction_type=TRANSACTION_TYPE.MERCHANT_RECEIVE, datetime=datetime_, account=self.account, amount=set_amount(95), content_object=use_coupon_payment, ) # 普通订单 not_use_coupon_payment = self.factory.create_payment( datetime=datetime_, status=PAYMENT_STATUS.FINISHED, merchant=self.merchant, order_price=set_amount(100), platform_share=set_amount(0), originator_share=set_amount(0), inviter_share=set_amount(0)) self.factory.create_transaction( transaction_type=TRANSACTION_TYPE.MERCHANT_RECEIVE, datetime=datetime_, account=self.account, amount=set_amount(100), content_object=not_use_coupon_payment, ) # 引流收益 self.factory.create_transaction( transaction_type=TRANSACTION_TYPE.MERCHANT_SHARE, datetime=datetime_, account=self.account, amount=set_amount(1), ) url = reverse('merchant-business_report') # 第一日数据 response = self.client.get( url, dict(start_date=first_day.strftime('%Y-%m-%d'), end_date=first_day.strftime('%Y-%m-%d')), Token=self.token, format='json') result = response.json() self.assertEqual( result, { 'turnover': 200, 'originator_expenditure': 5, 'originator_earning': 1, 'payment': { 'use_coupon': 1, 'not_use_coupon': 1 } }) # 第二日数据 response = self.client.get( url, dict(start_date=second_day.strftime('%Y-%m-%d'), end_date=second_day.strftime('%Y-%m-%d')), Token=self.token, format='json') result = response.json() self.assertEqual( result, { 'turnover': 200, 'originator_expenditure': 5, 'originator_earning': 1, 'payment': { 'use_coupon': 1, 'not_use_coupon': 2 } }) # 第1-10日数据 response = self.client.get( url, dict(start_date=first_day.strftime('%Y-%m-%d'), end_date=(first_day + timedelta(days=9)).strftime('%Y-%m-%d')), Token=self.token, format='json') result = response.json() self.assertEqual( result, { 'turnover': 400, 'originator_expenditure': 10, 'originator_earning': 2, 'payment': { 'use_coupon': 2, 'not_use_coupon': 3 } })
def _create_transactions(self): # 1月2月3月4月5月 一个月对应创建一条 提现/普通订单/优惠券订单/分成/结算transaction # 提现 self.withdraw = self.factory.create_withdraw( withdraw_type=WITHDRAW_TYPE.ALIPAY, account=self.account, amount=set_amount(Config.withdraw), datetime=Config.jan, status=WITHDRAW_STATUS['PROCESSING'] ) self.withdraw_transaction = self.factory.create_transaction( content_object=self.withdraw, account=self.account, datetime=Config.jan, amount=set_amount(Config.withdraw), transaction_type=TRANSACTION_TYPE['MERCHANT_WITHDRAW']) # 普通订单 self.payment_without_coupon = self.factory.create_payment( merchant=self.merchant, datetime=Config.feb, pay_channel=PAY_CHANNELS['WECHAT'], note='这是一个普通订单', status=PAYMENT_STATUS['REFUND'], order_price=set_amount(Config.receive), ) self.payment_without_coupon_transaction = self.factory.create_transaction( content_object=self.payment_without_coupon, account=self.account, datetime=Config.feb, amount=set_amount(Config.receive), transaction_type=TRANSACTION_TYPE['MERCHANT_RECEIVE']) # 优惠券订单 coupon = self.factory.create_coupon( rule=self.factory.create_coupon_rule(discount=set_amount(100), min_charge=set_amount(300))) self.payment_with_coupon = self.factory.create_payment( merchant=self.merchant, datetime=Config.mar, pay_channel=PAY_CHANNELS['ALIPAY'], note='这是一个优惠券订单', status=PAYMENT_STATUS['FROZEN'], coupon=coupon, order_price=set_amount(200.1), platform_share=set_amount(33), inviter_share=set_amount(33), originator_share=set_amount(34), ) self.payment_with_coupon_transaction = self.factory.create_transaction( content_object=self.payment_with_coupon, account=self.account, datetime=Config.mar, amount=set_amount(Config.receive), transaction_type=TRANSACTION_TYPE['MERCHANT_RECEIVE'], ) # 引流收益订单 share_merchant = self.factory.create_merchant(name='引流到达的商户') coupon = self.factory.create_coupon( rule=self.factory.create_coupon_rule(discount=set_amount(100), min_charge=set_amount(300))) self.share_payment = self.factory.create_payment( coupon=coupon, datetime=Config.apr, status=PAYMENT_STATUS['FINISHED'], merchant=share_merchant, order_price=set_amount(200.1), platform_share=set_amount(33), inviter_share=set_amount(33), originator_share=set_amount(34), ) self.share_transaction = self.factory.create_transaction( content_object=self.share_payment, account=self.account, datetime=Config.apr + timedelta(hours=2), amount=set_amount(Config.share), transaction_type=TRANSACTION_TYPE['MERCHANT_SHARE']) # 企业商户结算 self.settlement = self.factory.create_settlement( status=SETTLEMENT_STATUS.FINISHED, account=self.account, datetime=Config.may, finished_datetime=Config.may + timedelta(hours=1), wechat_amount=set_amount(-Config.wechat_settlement), alipay_amount=set_amount(-Config.alipay_settlement), ) self.settlement_transaction = self.factory.create_transaction( content_object=self.settlement, account=self.account, datetime=Config.may, amount=set_amount(Config.withdraw / 2), transaction_type=TRANSACTION_TYPE['MERCHANT_WECHAT_SETTLEMENT']) self.factory.create_transaction( content_object=self.settlement, account=self.account, datetime=Config.may, amount=set_amount(Config.withdraw / 2), transaction_type=TRANSACTION_TYPE['MERCHANT_ALIPAY_SETTLEMENT'])
def test_create(self): # 指定日期范围 url = reverse('coupon-list') coupon_rule_json = dict(discount=100, min_charge='300', valid_strategy=VALID_STRATEGY['DATE_RANGE'], start_date='2018-01-01', end_date='2018-01-01', stock=100, photo_url='a url', note='a note') response = self.client.post(url, data=coupon_rule_json, Token=self.token, format='json') # auth by token self.assertEqual(response.status_code, status.HTTP_201_CREATED) resp_json = response.json() # 检查response expect = copy.copy(coupon_rule_json) expect.update( dict( discount=coupon_rule_json['discount'], min_charge=int(coupon_rule_json['min_charge']), expiration_days=None, )) self.assertEqual(resp_json, expect) # 检查创建的coupon_rule coupon_rule = CouponRule.objects.filter( merchant=self.merchant, stock=coupon_rule_json['stock']).first() self.assertEqual(coupon_rule.discount, set_amount(coupon_rule_json['discount'])) self.assertEqual(coupon_rule.min_charge, set_amount(coupon_rule_json['min_charge'])) self.assertEqual(coupon_rule.valid_strategy, coupon_rule_json['valid_strategy']) self.assertEqual(str(coupon_rule.start_date), coupon_rule_json['start_date']) self.assertEqual(str(coupon_rule.end_date), coupon_rule_json['end_date']) self.assertEqual(coupon_rule.expiration_days, None) self.assertEqual(coupon_rule.stock, coupon_rule_json['stock']) self.assertEqual(coupon_rule.photo_url, coupon_rule_json['photo_url']) self.assertEqual(coupon_rule.note, coupon_rule_json['note']) # 参数格式不正确 减免金额小于最低消费 data = copy.copy(coupon_rule_json) data.update(dict( discount=101, min_charge=100, )) response = self.client.post(url, data=data, Token=self.token, format='json') # auth by token resp_json = response.json() self.assertEqual( resp_json, NonFieldError(MerchantError.min_charge_must_greater_than_discount)) # 参数格式不正确 无start_date 或 end_date data = copy.copy(coupon_rule_json) del data['start_date'] response = self.client.post(url, data=data, Token=self.token, format='json') # auth by token resp_json = response.json() self.assertEqual( resp_json, NonFieldError( MerchantError.must_have_param_start_date_and_end_date)) # 参数格式不正确 需 start_date <= end_date data = copy.copy(coupon_rule_json) data.update(dict( start_date='2018-03-01', end_date='2018-01-01', )) response = self.client.post(url, data=data, Token=self.token, format='json') # auth by token resp_json = response.json() self.assertEqual( resp_json, NonFieldError(MerchantError.end_date_must_greater_than_start_date)) # 指定有效天数 coupon_rule_json = dict(discount=100, min_charge='300', valid_strategy=VALID_STRATEGY['EXPIRATION'], expiration_days=90, stock=200, photo_url='another url', note='another note') response = self.client.post(url, data=coupon_rule_json, Token=self.token, format='json') # auth by token resp_json = response.json() # 检查response expect = copy.copy(coupon_rule_json) expect.update( dict( discount=coupon_rule_json['discount'], min_charge=float(coupon_rule_json['min_charge']), start_date=None, end_date=None, )) self.assertEqual(resp_json, expect) # 检查创建的coupon_rule coupon_rule = CouponRule.objects.filter( merchant=self.merchant, stock=coupon_rule_json['stock']).first() self.assertEqual(coupon_rule.valid_strategy, coupon_rule_json['valid_strategy']) self.assertEqual(coupon_rule.start_date, None) self.assertEqual(coupon_rule.end_date, None) self.assertEqual(coupon_rule.expiration_days, coupon_rule_json['expiration_days']) # 参数格式不正确 指定有效天数时无expiration_days data = copy.copy(coupon_rule_json) del data['expiration_days'] response = self.client.post(url, data=data, Token=self.token, format='json') # auth by token resp_json = response.json() self.assertEqual( resp_json, NonFieldError(MerchantError.must_have_param_expiration_days)) # 有效天数不正确需>0 data = copy.copy(coupon_rule_json) data['expiration_days'] = 0 response = self.client.post(url, data=data, Token=self.token, format='json') # auth by token resp_json = response.json() self.assertEqual(resp_json, { 'expiration_days': ['请确保该值大于或者等于 1。'], 'error_code': 'min_value' }) # 参数格式不正确 满减金额与最低消费必须为整数 # 指定有效天数 coupon_rule_json = dict(discount=100, min_charge='300.01', valid_strategy=VALID_STRATEGY['EXPIRATION'], expiration_days=90, stock=200, photo_url='another url', note='another note') response = self.client.post(url, data=coupon_rule_json, Token=self.token, format='json') # auth by token resp_json = response.json() self.assertEqual(resp_json, { 'min_charge': ['请确保总计不超过 0 个小数位。'], 'error_code': 'max_decimal_places' })
def test_statistics(self): yesterday = timezone.now().replace(hour=1) today = timezone.now().replace(hour=9) # 1. 今日创建一笔退款订单 refund_payment = self.factory.create_payment( datetime=today, merchant=self.merchant, order_price=set_amount(100), status=PAYMENT_STATUS.REFUND) # 退款订单 self.factory.create_transaction( transaction_type=TRANSACTION_TYPE.MERCHANT_RECEIVE, datetime=today, account=self.account, amount=set_amount(100), content_object=refund_payment) self.factory.create_transaction( transaction_type=TRANSACTION_TYPE.MERCHANT_REFUND, datetime=today, account=self.account, amount=-set_amount(100), content_object=self.factory.create_refund( datetime=today, status=REFUND_STATUS.FINISHED, payment=refund_payment)) # 2. 昨日今日分别创建一笔未支付订单, 一笔优惠订单, 一笔普通订单, 一笔引流收益 for datetime_ in (yesterday, today): # 未支付订单 self.factory.create_payment( datetime=datetime_, status=PAYMENT_STATUS.UNPAID, merchant=self.merchant, order_price=set_amount(100), ) # 优惠券订单 coupon = self.factory.create_coupon( discount=set_amount(10), min_charge=set_amount(100), status=COUPON_STATUS.USED, use_datetime=datetime_, ) use_coupon_payment = self.factory.create_payment( datetime=datetime_, status=PAYMENT_STATUS.FINISHED, merchant=self.merchant, order_price=set_amount(110), coupon=coupon, platform_share=set_amount(3), originator_share=set_amount(1), inviter_share=set_amount(1)) self.factory.create_transaction( transaction_type=TRANSACTION_TYPE.MERCHANT_RECEIVE, datetime=datetime_, account=self.account, amount=set_amount(95), content_object=use_coupon_payment, ) # 普通订单 not_use_coupon_payment = self.factory.create_payment( datetime=datetime_, status=PAYMENT_STATUS.FINISHED, merchant=self.merchant, order_price=set_amount(100), platform_share=set_amount(0), originator_share=set_amount(0), inviter_share=set_amount(0)) self.factory.create_transaction( transaction_type=TRANSACTION_TYPE.MERCHANT_RECEIVE, datetime=datetime_, account=self.account, amount=set_amount(100), content_object=not_use_coupon_payment, ) # 引流收益 self.factory.create_transaction( transaction_type=TRANSACTION_TYPE.MERCHANT_SHARE, datetime=datetime_, account=self.account, amount=set_amount(1), ) url = reverse('merchant-statistics') response = self.client.get(url, Token=self.token) statistics = response.json() self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual( statistics, { 'name': '就是这个公司', 'status': self.merchant.status, 'avatar_url': self.merchant.avatar_url, 'wechat_balance': 1000, 'alipay_balance': 2000, 'turnover': 200, 'originator_expenditure': 5, 'originator_earning': 1, 'payment': { 'use_coupon': 1, 'not_use_coupon': 2 } }) # 订单数要计算退款订单
def _create_transactions(self): # 1月2月3月5月, 每月分别创建2条 营业额/提现/分成transaction share_merchant = self.factory.create_merchant(name='引流到达的商户') for time in (Config.jan, Config.feb, Config.mar, Config.may): for i in range(2): # 提现 withdraw = self.factory.create_withdraw( withdraw_type=WITHDRAW_TYPE.ALIPAY if i % 2 else WITHDRAW_TYPE.WECHAT, account=self.account, amount=set_amount(-Config.withdraw), datetime=time) self.factory.create_transaction( content_object=withdraw, account=self.account, datetime=time, amount=set_amount(Config.withdraw), transaction_type=TRANSACTION_TYPE['MERCHANT_WITHDRAW']) # 企业商户结算 settlement = self.factory.create_settlement( status=SETTLEMENT_STATUS.FINISHED, account=self.account, finished_datetime=time, wechat_amount=set_amount(-Config.wechat_settlement), alipay_amount=set_amount(-Config.alipay_settlement), ) self.factory.create_transaction( content_object=settlement, account=self.account, datetime=time, amount=set_amount(Config.withdraw / 2), transaction_type=TRANSACTION_TYPE[ 'MERCHANT_WECHAT_SETTLEMENT']) self.factory.create_transaction( content_object=settlement, account=self.account, datetime=time, amount=set_amount(Config.withdraw / 2), transaction_type=TRANSACTION_TYPE[ 'MERCHANT_ALIPAY_SETTLEMENT']) coupon_rule = self.factory.create_coupon_rule( discount=set_amount(100), min_charge=set_amount(300)) # 支付成功 coupon = self.factory.create_coupon(rule=coupon_rule) payment = self.factory.create_payment( merchant=self.merchant, datetime=time, coupon=coupon, status=PAYMENT_STATUS['FINISHED']) self.factory.create_transaction( content_object=payment, account=self.account, datetime=time, amount=set_amount(Config.receive), transaction_type=TRANSACTION_TYPE['MERCHANT_RECEIVE']) # 退款 coupon = self.factory.create_coupon(rule=coupon_rule) payment = self.factory.create_payment( merchant=self.merchant, datetime=time, coupon=coupon, status=PAYMENT_STATUS['REFUND']) self.factory.create_transaction( content_object=payment, account=self.account, datetime=time, amount=set_amount(Config.receive), transaction_type=TRANSACTION_TYPE['MERCHANT_RECEIVE']) self.factory.create_transaction( content_object=payment, account=self.account, datetime=time, amount=set_amount(-Config.receive), transaction_type=TRANSACTION_TYPE['MERCHANT_REFUND']) # 引流分成 coupon_rule = self.factory.create_coupon_rule( merchant=self.merchant) share = self.factory.create_payment( coupon=self.factory.create_coupon( rule=coupon_rule, originator_merchant=self.merchant), datetime=time, merchant=share_merchant) self.factory.create_transaction( content_object=share, account=self.account, datetime=time, amount=set_amount(Config.share), transaction_type=TRANSACTION_TYPE['MERCHANT_SHARE'])
def create_merchant(cls, user): # 商户account account = cls.factory.create_account( balance=set_amount(10), withdrawable_balance=set_amount('0.50'), alipay_balance=set_amount('15006.50'), alipay_withdrawable_balance=set_amount('15006.50'), real_name=user['name']) # 付款二维码, 使用唯一可测试的code payment_qr_code = cls.factory.create_payment_qrcode(uuid='129d3209ad9f87771719df50347492d9') \ if 'qr_code_uuid' in user else None # 商户 merchant = cls.factory.create_merchant( name=f"一家咖啡店({user['name']}店)", status=MERCHANT_STATUS['USING'], location_lat=30.533743, location_lon=104.068197, account=account, area=cls.area, category=cls.merchant_category, inviter=cls.marketer, avatar_url=cls.C.avatar_url, photo_url=cls.C.photo_url, id_card_back_url=cls.C.id_card_back_url, id_card_front_url=cls.C.id_card_front_url, payment_qr_code=payment_qr_code) cls.factory.create_merchant_admin( wechat_openid=user['openid'], wechat_unionid=user['unionid'], merchant_admin_type=MERCHANT_ADMIN_TYPES['ADMIN'], work_merchant=merchant, wechat_nickname=user['name']) # 创建投放完成的优惠券 coupon_rule = cls.factory.create_coupon_rule(merchant=merchant, stock=0) share_merchant = cls.factory.create_merchant( name='通过发优惠券引流客户到达的商户', area=cls.area, category=cls.merchant_category, inviter=cls.marketer, ) grant_coupon_merchant = cls.factory.create_merchant( name='发优惠券的商户', area=cls.area, category=cls.merchant_category, inviter=cls.marketer, ) cls.factory.create_coupon(number=1, rule=coupon_rule, status=COUPON_STATUS['NOT_USED'], originator_merchant=grant_coupon_merchant, use_datetime=timezone.now()) cls.factory.create_coupon(number=2, rule=coupon_rule, status=COUPON_STATUS['USED'], originator_merchant=grant_coupon_merchant, use_datetime=timezone.now()) cls.factory.create_coupon(number=4, rule=coupon_rule, status=COUPON_STATUS['DESTROYED'], originator_merchant=grant_coupon_merchant, use_datetime=timezone.now()) cls.factory.create_coupon(number=8, rule=coupon_rule, status=COUPON_STATUS['USED'], originator_merchant=grant_coupon_merchant, use_datetime=timezone.now().replace( hour=7, minute=59, second=59, microsecond=0)) for day in range(10): withdraw = cls.factory.create_withdraw(account=account, amount=set_amount( cls.C.withdraw)) cls.factory.create_transaction( content_object=withdraw, account=account, datetime=withdraw.datetime, transaction_type=TRANSACTION_TYPE['MERCHANT_WITHDRAW']) withdraw = cls.factory.create_withdraw( withdraw_type=WITHDRAW_TYPE.ALIPAY, account=account, amount=set_amount(cls.C.withdraw)) cls.factory.create_transaction( content_object=withdraw, account=account, amount=-withdraw.amount, datetime=withdraw.datetime, transaction_type=TRANSACTION_TYPE['MERCHANT_WITHDRAW']) coupon_rule = cls.factory.create_coupon_rule( merchant=merchant, datetime=timezone.now(), end_date=timezone.now().replace(year=2019)) coupon = cls.factory.create_coupon( rule=coupon_rule, originator_merchant=grant_coupon_merchant, obtain_datetime=timezone.now() - timedelta(days=day), use_datetime=timezone.now() - timedelta(days=day), ) payment = cls.factory.create_payment( merchant=merchant, coupon=coupon, datetime=timezone.now() - timedelta(days=day), ) cls.factory.create_transaction( content_object=payment, account=account, datetime=payment.datetime, transaction_type=TRANSACTION_TYPE['MERCHANT_RECEIVE']) without_coupon_payment = cls.factory.create_payment( merchant=merchant, datetime=timezone.now() - timedelta(days=day), ) cls.factory.create_transaction( content_object=without_coupon_payment, account=account, datetime=without_coupon_payment.datetime, transaction_type=TRANSACTION_TYPE['MERCHANT_RECEIVE']) share = cls.factory.create_payment( coupon=cls.factory.create_coupon( rule=coupon_rule, originator_merchant=grant_coupon_merchant), datetime=timezone.now() - timedelta(days=day), merchant=share_merchant) cls.factory.create_transaction( content_object=share, account=account, datetime=share.datetime, transaction_type=TRANSACTION_TYPE['MERCHANT_SHARE'])
def banlance(min_balance=1, max_balance=10000000): return set_amount(randint(min_balance, max_balance))
def setUpTestData(cls): cls.factory = PayunionFactory() cls.coupon_rule = cls.factory.create_coupon_rule( discount=set_amount(100.1), min_charge=set_amount(300)) cls.manager = CouponRuleManager(cls.coupon_rule)
def test_merchant_earning_list_by_day(self): first_day = timezone.now().replace(year=2018, month=1, day=1, hour=9) second_day = timezone.now().replace(year=2018, month=1, day=2, hour=9) third_day = timezone.now().replace(year=2018, month=1, day=4, hour=9) first_day_begin = first_day.replace(hour=0, minute=0, second=0, microsecond=0) # 1. 创建一笔退款订单 refund_payment = self.factory.create_payment( datetime=second_day, merchant=self.merchant, order_price=set_amount(100), status=PAYMENT_STATUS.REFUND ) # 退款订单 self.factory.create_transaction( transaction_type=TRANSACTION_TYPE.MERCHANT_RECEIVE, datetime=second_day, account=self.account, amount=set_amount(100), content_object=refund_payment ) self.factory.create_transaction( transaction_type=TRANSACTION_TYPE.MERCHANT_REFUND, datetime=second_day, account=self.account, amount=-set_amount(100), content_object=self.factory.create_refund( datetime=second_day, status=REFUND_STATUS.FINISHED, payment=refund_payment) ) # 2. 三天分别创建一笔未支付订单, 一笔优惠订单, 一笔普通订单, 一笔引流收益 for datetime_ in (first_day, second_day, third_day): # 未支付订单 self.factory.create_payment( datetime=datetime_, status=PAYMENT_STATUS.UNPAID, merchant=self.merchant, order_price=set_amount(100), ) # 优惠券订单 coupon = self.factory.create_coupon( discount=set_amount(10), min_charge=set_amount(100), status=COUPON_STATUS.USED, use_datetime=datetime_, ) use_coupon_payment = self.factory.create_payment( datetime=datetime_, status=PAYMENT_STATUS.FINISHED, merchant=self.merchant, order_price=set_amount(110), coupon=coupon, platform_share=set_amount(3), originator_share=set_amount(1), inviter_share=set_amount(1) ) self.factory.create_transaction( transaction_type=TRANSACTION_TYPE.MERCHANT_RECEIVE, datetime=datetime_, account=self.account, amount=set_amount(95), content_object=use_coupon_payment, ) # 普通订单 not_use_coupon_payment = self.factory.create_payment( datetime=datetime_, status=PAYMENT_STATUS.FINISHED, merchant=self.merchant, order_price=set_amount(100), platform_share=set_amount(0), originator_share=set_amount(0), inviter_share=set_amount(0) ) self.factory.create_transaction( transaction_type=TRANSACTION_TYPE.MERCHANT_RECEIVE, datetime=datetime_, account=self.account, amount=set_amount(100), content_object=not_use_coupon_payment, ) # 引流收益 self.factory.create_transaction( transaction_type=TRANSACTION_TYPE.MERCHANT_SHARE, datetime=datetime_, account=self.account, amount=set_amount(1), ) result = self.manager.merchant_earning_list_by_day( date_start=first_day_begin.date() - timedelta(days=1), date_end=first_day_begin.date() + timedelta(days=5) ) self.assertEqual( result, [{'date': '2017-12-31', 'amount': 0}, {'date': '2018-01-01', 'amount': 195 + 1}, {'date': '2018-01-02', 'amount': 195 + 1}, {'date': '2018-01-03', 'amount': 0}, {'date': '2018-01-04', 'amount': 195 + 1}, {'date': '2018-01-05', 'amount': 0}, {'date': '2018-01-06', 'amount': 0}] )
def test_update(self): self._create_coupon_rule() # 修改优惠券库存 for stock in (0, 1, 300, 301): coupon_rule = self.coupon_rule old_update_datetime = coupon_rule.update_datetime url = reverse('coupon-detail', kwargs=dict(pk=self.coupon_rule.id)) response = self.client.put(url, data=dict(stock=stock), Token=self.token, format='json') # auth by token detail = response.json() self.assertEqual( detail, dict( discount=get_amount(self.coupon_rule.discount), min_charge=get_amount(self.coupon_rule.min_charge), valid_strategy=self.coupon_rule.valid_strategy, start_date=self.coupon_rule.start_date.strftime( '%Y-%m-%d'), end_date=self.coupon_rule.end_date.strftime('%Y-%m-%d'), expiration_days=self.coupon_rule.expiration_days, stock=stock, photo_url=self.coupon_rule.photo_url, note=self.coupon_rule.note, )) # 检查修改库存的coupon_rule coupon_rule.refresh_from_db() self.assertEqual(coupon_rule.discount, set_amount(detail['discount'])) self.assertEqual(coupon_rule.min_charge, set_amount(detail['min_charge'])) self.assertEqual(coupon_rule.valid_strategy, detail['valid_strategy']) self.assertEqual(str(coupon_rule.start_date), detail['start_date']) self.assertEqual(str(coupon_rule.end_date), detail['end_date']) self.assertNotEqual(coupon_rule.update_datetime, old_update_datetime) # 不存在的优惠券 url = reverse('coupon-detail', kwargs=dict(pk='id_not_exist')) response = self.client.put(url, Token=self.token, format='json') # auth by token resp_json = response.json() self.assertEqual(resp_json, { 'detail': '未找到。', 'error_code': 'not_found' }) # 非商户创建的优惠券 another_coupon_rule = self.factory.create_coupon_rule() url = reverse('coupon-detail', kwargs=dict(pk=another_coupon_rule.id)) response = self.client.put(url, Token=self.token, format='json') # auth by token resp_json = response.json() self.assertEqual(resp_json, { 'detail': '未找到。', 'error_code': 'not_found' })
def test_list_earning(self): the_day_before_yesterday = timezone.now() - timedelta(days=2) yesterday = timezone.now() - timedelta(days=1) # 1. 昨日创建一笔退款订单 refund_payment = self.factory.create_payment( datetime=yesterday, merchant=self.merchant, order_price=set_amount(100), status=PAYMENT_STATUS.REFUND) # 退款订单 self.factory.create_transaction( transaction_type=TRANSACTION_TYPE.MERCHANT_RECEIVE, datetime=yesterday, account=self.account, amount=set_amount(100), content_object=refund_payment) self.factory.create_transaction( transaction_type=TRANSACTION_TYPE.MERCHANT_REFUND, datetime=yesterday, account=self.account, amount=-set_amount(100), content_object=self.factory.create_refund( datetime=yesterday, status=REFUND_STATUS.FINISHED, payment=refund_payment)) # 2. 前天昨天分别创建一笔未支付订单, 一笔优惠订单, 一笔普通订单, 一笔引流收益 for datetime_ in (the_day_before_yesterday, yesterday): # 未支付订单 self.factory.create_payment( datetime=datetime_, status=PAYMENT_STATUS.UNPAID, merchant=self.merchant, order_price=set_amount(100), ) # 优惠券订单 coupon = self.factory.create_coupon( discount=set_amount(10), min_charge=set_amount(100), status=COUPON_STATUS.USED, use_datetime=datetime_, ) use_coupon_payment = self.factory.create_payment( datetime=datetime_, status=PAYMENT_STATUS.FINISHED, merchant=self.merchant, order_price=set_amount(110), coupon=coupon, platform_share=set_amount(3), originator_share=set_amount(1), inviter_share=set_amount(1)) self.factory.create_transaction( transaction_type=TRANSACTION_TYPE.MERCHANT_RECEIVE, datetime=datetime_, account=self.account, amount=set_amount(95), content_object=use_coupon_payment, ) # 普通订单 not_use_coupon_payment = self.factory.create_payment( datetime=datetime_, status=PAYMENT_STATUS.FINISHED, merchant=self.merchant, order_price=set_amount(100), platform_share=set_amount(0), originator_share=set_amount(0), inviter_share=set_amount(0)) self.factory.create_transaction( transaction_type=TRANSACTION_TYPE.MERCHANT_RECEIVE, datetime=datetime_, account=self.account, amount=set_amount(100), content_object=not_use_coupon_payment, ) # 引流收益 self.factory.create_transaction( transaction_type=TRANSACTION_TYPE.MERCHANT_SHARE, datetime=datetime_, account=self.account, amount=set_amount(1), ) url = reverse('merchant-list_earning') start_date = timezone.now().date().replace(year=timezone.now().year - 1, day=1) response = self.client.get(url, dict(start_date=start_date), Token=self.token) statistics = response.json() for earning in statistics: date, amount = earning['date'], earning['amount'] if date in (the_day_before_yesterday.strftime('%Y-%m-%d'), yesterday.strftime('%Y-%m-%d')): self.assertEqual(amount, 95 + 100 + 1) else: self.assertEqual(amount, 0)
def test_set_amount(self): self.assertEqual(set_amount(0), 0) self.assertEqual(set_amount(0.01), 1) self.assertEqual(set_amount(300), 30000) self.assertEqual(set_amount(300.3), 30030) self.assertEqual(set_amount(300.33), 30033) self.assertEqual(set_amount('0'), 0) self.assertEqual(set_amount('0.01'), 1) self.assertEqual(set_amount('300'), 30000) self.assertEqual(set_amount('300.00'), 30000) self.assertEqual(set_amount('300.3'), 30030) self.assertEqual(set_amount('300.30'), 30030) self.assertEqual(set_amount('300.33'), 30033)
def test_transaction_list(self): url = reverse('transaction-list') # 1月2月3月5月, 每月分别创建2条 营业额/提现/分成transaction share_merchant = self.factory.create_merchant(name='引流到达的商户') for time in (Config.jan, Config.feb, Config.mar, Config.may): for i in range(2): # 提现 withdraw = self.factory.create_withdraw( withdraw_type=WITHDRAW_TYPE.ALIPAY if i % 2 else WITHDRAW_TYPE.WECHAT, account=self.account, amount=set_amount(-Config.withdraw), datetime=time) self.factory.create_transaction( content_object=withdraw, account=self.account, datetime=time, amount=set_amount(Config.withdraw), transaction_type=TRANSACTION_TYPE['MERCHANT_WITHDRAW']) coupon_rule = self.factory.create_coupon_rule(discount=set_amount(100), min_charge=set_amount(300)) # 支付成功 coupon = self.factory.create_coupon(rule=coupon_rule) payment = self.factory.create_payment( merchant=self.merchant, datetime=time, coupon=coupon, status=PAYMENT_STATUS['FINISHED'] ) self.factory.create_transaction( content_object=payment, account=self.account, datetime=time, amount=set_amount(Config.receive), transaction_type=TRANSACTION_TYPE['MERCHANT_RECEIVE']) # 退款 coupon = self.factory.create_coupon(rule=coupon_rule) payment = self.factory.create_payment( merchant=self.merchant, datetime=time, coupon=coupon, status=PAYMENT_STATUS['REFUND'] ) self.factory.create_transaction( content_object=payment, account=self.account, datetime=time, amount=set_amount(Config.receive), transaction_type=TRANSACTION_TYPE['MERCHANT_RECEIVE']) self.factory.create_transaction( content_object=payment, account=self.account, datetime=time, amount=set_amount(-Config.receive), transaction_type=TRANSACTION_TYPE['MERCHANT_REFUND']) # 引流分成 coupon_rule = self.factory.create_coupon_rule(merchant=self.merchant) share = self.factory.create_payment( coupon=self.factory.create_coupon(rule=coupon_rule, originator_merchant=self.merchant), datetime=time, merchant=share_merchant) self.factory.create_transaction( content_object=share, account=self.account, datetime=time, amount=set_amount(Config.share), transaction_type=TRANSACTION_TYPE['MERCHANT_SHARE']) # 企业商户结算 settlement = self.factory.create_settlement( status=SETTLEMENT_STATUS.FINISHED, account=self.account, finished_datetime=time, wechat_amount=set_amount(-Config.wechat_settlement), alipay_amount=set_amount(-Config.alipay_settlement), ) self.factory.create_transaction( content_object=settlement, account=self.account, datetime=time, amount=set_amount(Config.withdraw / 2), transaction_type=TRANSACTION_TYPE['MERCHANT_WECHAT_SETTLEMENT']) self.factory.create_transaction( content_object=settlement, account=self.account, datetime=time, amount=set_amount(Config.withdraw / 2), transaction_type=TRANSACTION_TYPE['MERCHANT_ALIPAY_SETTLEMENT']) # 第一页 response = self.client.get(url, dict(page=1), Token=self.token) first_page_resp_json = response.json() for month_data in first_page_resp_json['results']: if month_data['month'] == '2018/04': self.assertEqual(month_data['cur_page_transactions'], []) self.assertEqual(month_data['turnover'], 0) self.assertEqual(month_data['originator_earning'], 0) self.assertEqual(month_data['withdraw'], 0) else: # 获取的是该月总额 self.assertEqual(month_data['turnover'], Config.receive * 2) self.assertEqual(month_data['originator_earning'], float(Config.share * 2)) self.assertEqual(month_data['withdraw'], -float(Config.withdraw * 2)) # 检查每笔订单详细展示 for transaction in month_data['cur_page_transactions']: self.assertIsInstance(transaction['id'], int) self.assertIn(transaction['title'], ( '余额提现 - 到支付宝余额', '余额提现 - 到微信零钱', '微信支付', '支付宝支付', '微信支付 - 优惠账单', '支付宝支付 - 优惠账单', '引流到达的商户', '账单结算', )) self.assertIn(transaction['desc'], ('[其他]', '[普通]', '[满300减100优惠券]')) self.assertTrue(re.match('0[1-5]-01 00:00', transaction['datetime'])) self.assertIn(transaction['status'], ('已完成', '已退款', '退款中', '退款失败', '处理中', '已失败', '已结算', '结算中', '')) self.assertIn(transaction['transaction_type'], ('normal', 'discount', 'withdraw', 'original_earning')) # 第二页 response = self.client.get(url, dict(page=2, type='all'), Token=self.token) resp_json = response.json() self.assertEqual(len(resp_json['results']), 2) # 有两个月数据 month_data = resp_json['results'][0] self.assertEqual(month_data['turnover'], float(Config.receive * 2)) self.assertEqual(month_data['originator_earning'], float(Config.share * 2)) self.assertEqual(month_data['withdraw'], -float(Config.withdraw * 2)) for transaction in month_data['cur_page_transactions']: self.assertIsInstance(transaction['id'], int) self.assertIn(transaction['title'], ( '余额提现 - 到支付宝余额', '余额提现 - 到微信零钱', '微信支付', '支付宝支付', '微信支付 - 优惠账单', '支付宝支付 - 优惠账单', '引流到达的商户', '账单结算', )) self.assertIn(transaction['desc'], ('[其他]', '[普通]', '[满300减100优惠券]')) self.assertTrue(re.match('0[1-5]-01 00:00', transaction['datetime'])) self.assertIn(transaction['status'], ('已完成', '已退款', '退款中', '退款失败', '处理中', '已失败', '已结算', '结算中', '')) self.assertIn(transaction['transaction_type'], ('normal', 'discount', 'withdraw', 'original_earning')) # 第一页 营业额 response = self.client.get(url, dict(page=1, type='turnover'), Token=self.token) resp_json = response.json() for month_data in resp_json['results']: if month_data['month'] == '2018/04': self.assertEqual(month_data['cur_page_transactions'], []) self.assertEqual(month_data['turnover'], 0) self.assertEqual(month_data['originator_earning'], 0) self.assertEqual(month_data['withdraw'], 0) else: # 每月2笔营业额 self.assertEqual(len(month_data['cur_page_transactions']), 4) # 获取的是该月总额 self.assertEqual(month_data['turnover'], float(Config.receive * 2)) self.assertEqual(month_data['originator_earning'], float(Config.share * 2)) self.assertEqual(month_data['withdraw'], -float(Config.withdraw * 2)) # 检查每笔订单详细展示 for transaction in month_data['cur_page_transactions']: self.assertIsInstance(transaction['id'], int) self.assertIn(transaction['title'], ( '微信支付', '支付宝支付', '微信支付 - 优惠账单', '支付宝支付 - 优惠账单' )) self.assertEqual(transaction['desc'], '[满300减100优惠券]') self.assertTrue(re.match('0[1-5]-01 00:00', transaction['datetime'])) self.assertIsInstance(transaction['amount'], float) self.assertIn(transaction['status'], ('已退款', '退款中', '退款失败', '')) self.assertIn(transaction['transaction_type'], ('normal', 'discount')) # 第一页 引流收益 response = self.client.get(url, dict(page=1, type='originator_earning'), Token=self.token) resp_json = response.json() for month_data in resp_json['results']: if month_data['month'] == '2018/04': self.assertEqual(month_data['cur_page_transactions'], []) self.assertEqual(month_data['turnover'], 0) self.assertEqual(month_data['originator_earning'], 0) self.assertEqual(month_data['withdraw'], 0) else: # 每月2笔引流收益 self.assertEqual(len(month_data['cur_page_transactions']), 2) # 获取的是该月总额 self.assertEqual(month_data['turnover'], float(Config.receive * 2)) self.assertEqual(month_data['originator_earning'], float(Config.share * 2)) self.assertEqual(month_data['withdraw'], -float(Config.withdraw * 2)) # 检查每笔订单详细展示 for transaction in month_data['cur_page_transactions']: self.assertIsInstance(transaction['id'], int) self.assertEqual(transaction['title'], '引流到达的商户') self.assertEqual(transaction['desc'], '[其他]') self.assertTrue(re.match('0[1-5]-01 00:00', transaction['datetime'])) self.assertEqual(transaction['amount'], 1.01) self.assertIn(transaction['status'], ('已退款', '退款中', '退款失败', '')) self.assertEqual(transaction['transaction_type'], 'original_earning') # 第一页 提现 response = self.client.get(url, dict(page=1, type='withdraw'), Token=self.token) resp_json = response.json() for month_data in resp_json['results']: if month_data['month'] == '2018/04': self.assertEqual(month_data['cur_page_transactions'], []) self.assertEqual(month_data['turnover'], 0) self.assertEqual(month_data['originator_earning'], 0) self.assertEqual(month_data['withdraw'], 0) else: # 每月2笔提现账单 self.assertEqual(len(month_data['cur_page_transactions']), 2) # 获取的是该月总额 self.assertEqual(month_data['turnover'], float(Config.receive * 2)) self.assertEqual(month_data['originator_earning'], float(Config.share * 2)) self.assertEqual(month_data['withdraw'], -float(Config.withdraw * 2)) # 检查每笔订单详细展示 for transaction in month_data['cur_page_transactions']: self.assertIsInstance(transaction['id'], int) self.assertIn(transaction['title'], ('余额提现 - 到支付宝余额', '余额提现 - 到微信零钱')) self.assertEqual(transaction['desc'], '[其他]') self.assertTrue(re.match('0[1-5]-01 00:00', transaction['datetime'])) self.assertEqual(transaction['amount'], -Config.withdraw) self.assertIn(transaction['status'], ('已完成', '处理中', '已失败', '')) self.assertEqual(transaction['transaction_type'], 'withdraw') # 第一页 结算账单 response = self.client.get(url, dict(page=1, type='settlement'), Token=self.token) resp_json = response.json() for month_data in resp_json['results']: if month_data['month'] == '2018/04': self.assertEqual(month_data['cur_page_transactions'], []) self.assertEqual(month_data['turnover'], 0) self.assertEqual(month_data['originator_earning'], 0) self.assertEqual(month_data['withdraw'], 0) else: # 每月2笔结算账单 self.assertEqual(len(month_data['cur_page_transactions']), 2) # 获取的是该月总额 self.assertEqual(month_data['turnover'], float(Config.receive * 2)) self.assertEqual(month_data['originator_earning'], float(Config.share * 2)) self.assertEqual(month_data['withdraw'], -float(Config.withdraw * 2)) # 检查每笔订单详细展示 for transaction in month_data['cur_page_transactions']: self.assertIsInstance(transaction['id'], int) self.assertIn(transaction['title'], ('账单结算',)) self.assertEqual(transaction['desc'], '[其他]') self.assertTrue(re.match('0[1235]-01 00:00', transaction['datetime'])) self.assertEqual(transaction['amount'], -Config.withdraw) self.assertIn(transaction['status'], ('已结算',)) self.assertEqual(transaction['transaction_type'], 'withdraw') # 无数据页 response = self.client.get(url, dict(page=3), Token=self.token) resp_json = response.json() self.assertEqual(resp_json['detail'], '无效页面。') self.assertEqual(resp_json['error_code'], 'not_found') # 请求不带page参数, 应返回第一页数据 response = self.client.get(url, Token=self.token) resp_json = response.json() self.assertEqual(resp_json, first_page_resp_json) # 请求参数错误 response = self.client.get(url, dict(page=1, type='wrong_type'), Token=self.token) resp_json = response.json() self.assertEqual(resp_json, NonFieldError(MerchantError.unsupported_transaction_type))