# -*- coding: utf-8 -*- #!/usr/bin/env python """ 手工对账 """ import os import sys import click from typing import Union, TYPE_CHECKING from apps.web.core.payment import PaymentGateway from apps.web.dealer.define import DEALER_INCOME_TYPE from apps.web.user.transaction import post_pay if TYPE_CHECKING: from apps.web.core.payment.wechat import WechatPaymentGateway from apps.web.core.payment.ali import AliPayGateway PROJECT_ROOT = os.path.join(os.path.abspath(os.path.split(os.path.realpath(__file__))[0] + "/.."), '..') sys.path.insert(0, PROJECT_ROOT) from script.base import init_env, get_logger logger = get_logger(__name__) init_env(interactive=True) from apilib.monetary import RMB from apilib.utils_datetime import to_datetime, yesterday_format_str from apps.web.common.models import WithdrawRecord from apps.web.dealer.models import Dealer from apps.web.dealer.proxy import DealerIncomeProxy from apps.web.user.models import RechargeRecord @click.group() def cli(): """ 同步mongoDB :return: """ click.echo(u"欢迎进入自动对账脚本") def check_dealer_balance(dealer, income_type = DEALER_INCOME_TYPE.DEVICE_INCOME, source_key = None): proxies = DealerIncomeProxy.objects(dealerIds = dealer.id) acc_income = RMB(0) for proxy in proxies: acc_income += RMB(proxy.actualAmountMap[str(dealer.id)]) dealer_actual_balance = dealer.sub_balance(income_type, source_key) for record in WithdrawRecord.get_succeeded_records(ownerId = str(dealer.id)): dealer_actual_balance += RMB(record.amount) return acc_income == dealer_actual_balance, acc_income, dealer_actual_balance, abs( dealer_actual_balance - acc_income) def check_dealer_balance_by_interval(dealer, income_type, source_key): """ records = WithdrawRecord.get_succeeded_records(ownerId=str(dealer.id)) Stage 0 interval <- [ records[-1], now] : balance == DealerIncomeProxy.sum_by_dealer(time >= last WithdrawRecord's date, dealerId) Stage 1 interval <- [ records[-2], records[-1]) records[-2].dealerBalance == DealerIncomeProxy.sum_by_dealer( time in interval, dealerId) Stage 2 ... :param dealer: :return: """ dealer_id = dealer.id records = list(WithdrawRecord.get_succeeded_records(ownerId=str(dealer_id))) def sum_by_dealer(**query): return DealerIncomeProxy.sum_by_dealer(dealerId=dealer_id, **query) if not records: assert dealer.sub_balance(income_type = income_type, source_key = source_key) == sum_by_dealer() return else: last_record = records.pop() endTime = last_record.postTime assert dealer.sub_balance(income_type = income_type, source_key = source_key) == sum_by_dealer( dateTimeAdded__gt = last_record.postTime) while len(records): record = records.pop() # type: WithdrawRecord assert record.balance == sum_by_dealer(dateTimeAdded__gt = record.postTime, dateTimeAdded__lt = endTime) endTime = record.postTime def generate_dealer_income_intervals(dealer): pass @cli.command() def check_dealer_balances(): dealers = Dealer.objects() total = dealers.count() count = 0 for dealer in dealers: match, balance, order_income, _ = check_dealer_balance(dealer) if not match: count += 1 click.echo('mismatch!, dealer(phone=%s, id=%s), acc_recharge_record_income=%s, dealer_actual_balance=%s' % (dealer.username, str(dealer.id), order_income, balance)) click.echo('there are %d mismatch records, total %d, normal %d' % (count, total, total - count ) ) def fixed_upay_record(record, gateway_dict): click.echo('check unpay record. record = {}'.format(record)) if record.payGatewayKey in gateway_dict: payment_gateway = gateway_dict[ '{}-{}-{}'.format(record.gateway, record.payAppType, record.payGatewayKey)] else: payment_gateway = PaymentGateway.from_gateway_key( record.gateway, record.payGatewayKey, record.payAppType) # type: Union[WechatPaymentGateway, AliPayGateway, SaobeiPaymentGateway] gateway_dict[ '{}-{}-{}'.format(record.gateway, record.payAppType, record.payGatewayKey)] = payment_gateway status, trade_no = payment_gateway.api_trade_query(out_trade_no = record.orderNo) if status in [PaymentGateway.TradeStatus.Finished, PaymentGateway.TradeStatus.Success]: click.echo('record really paid. something is error. record = {}'.format(str(record.id))) modified = record.succeed(wxOrderNo = trade_no) if not modified: click.echo('record has done. record = {}'.format(str(record.id))) post_pay(recharge_record = record, accounting = True) @cli.command() @click.option('-d','--dealer_id', prompt=u'please input dealer id') @click.option('-t','--check_time', prompt=u'please input check date. for example: 2019-09-04') def fixed_upay_record_by_dealer(dealer_id, check_time): if not check_time: check_time = yesterday_format_str() start_time = to_datetime('{} 00:00:00'.format(check_time)) end_time = to_datetime('{} 23:59:59'.format(check_time)) records = RechargeRecord.objects(ownerId = dealer_id, result = RechargeRecord.PayResult.UNPAY, dateTimeAdded__gte = start_time, dateTimeAdded__lte = end_time) gateway_dict = {} for record in records: # type: RechargeRecord try: fixed_upay_record(record, gateway_dict) except Exception as e: click.echo('exception = {}'.format(str(e))) @cli.command() @click.option('-r', '--order_no', prompt = u'please input order no') def fixed_upay_record_by_order(order_no): record = RechargeRecord.objects(orderNo = order_no).first() try: fixed_upay_record(record = record, gateway_dict = {}) except Exception as e: click.echo('exception = {}'.format(str(e))) if __name__ == '__main__': # cli(sys.argv[1:]) cli()