diff --git a/accounting/alipay_recharge.py b/accounting/alipay_recharge.py deleted file mode 100644 index 76d277a..0000000 --- a/accounting/alipay_recharge.py +++ /dev/null @@ -1,55 +0,0 @@ - -from datetime import datetime -from appPublic.uniqueID import getID -from sqlor.dbpools import DBPools -from appPublic.timeUtils import curDateString -from appPublic.argsConvert import ArgsConvert -from .accounting_config import get_accounting_config, AccountingOrgs -from .const import * -from .accountingnode import get_accounting_nodes -from .excep import * -from .getaccount import getAccountByName -from .businessdate import get_business_date -from .recharge import RechargeAccounting - -class AlipayAccountingOrgs(AccountingOrgs): - def __init__(self, caller, - accounting_orgid, - customerid, - resellerid=None): - - super(AlipayAccountingOrgs, self). __init__(caller, - accounting_orgid, - customerid, - resellerid=resellerid) - self.variable['手续费'] = self.caller.fee_amt - - async def get_act_specstr(self): - return ACTNAME_RECHARGE_ALIPAY - -class AlipayRechargeAccounting(RechargeAccounting): - def __init__(self, recharge_log): - super(AlipayRechargeAccounting, self).__init__(recharge_log) - self.fee_amt = recharge_log['fee_amt'] - - async def accounting(self, sor): - self.sor = sor - bz_date = await get_business_date(sor=sor) - if bz_date != self.curdate: - raise AccountingDateNotInBusinessDate(self.curdate, bz_date) - - nodes = await get_accounting_nodes(sor, self.customerid) - lst = len(nodes) - 1 - self.accountingOrgs = [] - for i, n in enumerate(nodes): - if i < lst: - ao = AlipayAccountingOrgs(self, nodes[i], self.customerid, - resellerid=nodes[i+1]) - else: - ao = AlipayAccountingOrgs(self, nodes[i], self.customerid) - self.accountingOrgs.append(ao) - await self.write_bill(sor) - [await ao.do_accounting(sor) for ao in self.accountingOrgs ] - print(f'recharge ok for {self.bill}, {nodes=}') - return True - diff --git a/accounting/bizaccount.py b/accounting/bizaccount.py deleted file mode 100644 index 69154ea..0000000 --- a/accounting/bizaccount.py +++ /dev/null @@ -1,262 +0,0 @@ -import asyncio -import re -from .const import * -from .accountingnode import get_parent_orgid -from .excep import * -from .getaccount import get_account, getAccountByName -from appPublic.uniqueID import getID -from appPublic.log import debug, exception -from sqlor.dbpools import DBPools -from appPublic.timeUtils import curDateString -# from .argsconvert import ArgsConvert -from appPublic.argsConvert import ArgsConvert -from datetime import datetime - -accounting_config = None - -async def get_accounting_config(sor): - global accounting_config - if accounting_config: - return accounting_config - recs = await sor.R('accounting_config', {}) - if len(recs) > 0: - accounting_config = recs - return accounting_config - return None - -class BizAccounting: - """ - def __init__(self, curdate, accountset): - accountset:with accounting attribute and a sub accountsets - accountset: - action:with action can find the accounting_config - participal: found the account to be accounting - async def prepare(sor): - find all the accounting_legs - merge multiple accounting for one account to one - check if account overdraw - sort accounting_legs by account id - - async def do_accounting(sor) - wrtie bill, billdetail - writ accounting_log - write acc_detail - write acc_balance - """ - def __init__(self, curdate, biz_order, accountset, amount_threahold=0.0001): - self.accounting_config = None - self.curdate = curdate - self.biz_order = biz_order - self.accountset = accountset - self.amount_threahold = amount_threahold - self.timestamp = timestampstr() - - async def do_accounting(self, sor): - legs = self.get_accounting_legs(sor) - legs = [l for l in legs if l['amount'] >= self.amount_threahold] - self.check_accounting_balance(legs) - bill = await write_bill(sor, self.biz_order.customerid, - self.biz_order.userid, - self.biz_order.id, - self.biz_order.business_op, - self.biz_order.amount) - await self.write_billdetail(sor) - self.merge_legs(legs) - self.accounting_legs = legs - for leg in legs: - await self.leg_accounting(sor, leg) - - async def get_orgid_by_trans_role(self, role, accountset): - return accountset.get(role) - - async def get_accounting_legs(self, sor): - leg = self.get_accountset_legs(sor, self.accountset) - if self.accountset.subsets: - for aset in self.accountset.subsets: - legs1 = self.get_accountset_legs(sor, aset) - leg += legs1 - return legs - - async def get_accountset_legs(self, sor, accountset): - global accounting_config - action = accountset.action.split('_')[0] - await get_accounting_config(sor) - legs = [r.copy() for r in accounting_config - if r.action == action ] - debug(f'{legs=}') - rev = accountset.action.endswith('_REVERSE') - for l in legs: - if rev: - l['acc_dir'] = DEBT if l['accounting_dir'] == CREDIT else CREDIT - else: - l['acc_dir'] = l['accounting_dir'] - ac = ArgsConvert('${', '}$') - try: - amtstr = ac.convert(l['amt_pattern'], - accountset.copy() - ) - debug(f'{l["amt_pattern"]=}, {amtstr=}, {accountset=}') - if isinstance(amtstr, str): - l['amount'] = eval(amtstr) - else: - l['amount'] = amtstr - - except Exception as e: - exception(f"{e=}, {l['amt_pattern']}, {accountset=}") - raise e - - if l['amount'] is None: - debug(f'amount is None:{l["amt_pattern"]}, {accountset=}') - raise AccountingAmountIsNone(self.caller.billid) - accounting_orgid = await self.get_orgid_by_trans_role(l.accounting_orgtype) - orgid = await self.get_orgid_by_trans_role(l.orgtype) - org1id = None if l.org1type is None else \ - await self.get_orgid_by_trans_role(l.org1type) - acc = await get_account(sor, accounting_orgid, orgid, l.subjectid, org1id=org1id) - if acc is None: - debug(f'can not get accountid {accounting_orgid=}, {orgid=},{l.subjectid=}, {org1id=}') - raise AccountIdNone(accounting_orgid, orgid, l['subjectid']) - l['_accounting_orgid'] = accounting_orgid - l['_orgid'] = orgid - l['_org1id'] = org1id - l['acc'] = acc - legs = sorted(legs, key=lambda x: x['acc']) - return legs - - def merge_two_legs(self, l1, l2): - if l1['acc_dir'] == l2['acc_dir']: - l = l1 - l['amount'] = l1['amount'] + l2['amount'] - return l - l = l1 if l1['amount'] > l2['amount'] else l2 - l['amount'] = abs(l1['amount'] - l2['amount']) - return l - - def merge_legs(self, legs): - mlegs = [] - cnt = len(legs) - cleg = None - for i, leg in enumerate(legs): - if leg['acc'].id == cleg['acc'].id: - cleg = self.merge_two_legs(cleg, leg) - else: - mlegs.append(cleg) - cleg = leg - mleg.append(cleg) - return mleg - - def check_accounting_balance(self, legs): - debt_balance = 0.0 - credit_balance = 0.0 - for l in legs: - if l['acc_dir'] == DEBT: - debt_balance += l['amount'] - else: - credit_balance += l['amount'] - if abs(credit_balance - debt_balance) >= self.threahold: - e = Exception('accounting legs not balance') - exception(f'{legs=}, {e=}') - raise e - - async def write_billdetail(self, sor, legs): - for leg in legs: - ns = { - 'id':getID(), - 'accounting_orgid' : leg['accounting_orgid'], - 'billid' : self.billid, - 'description' : self.summary, - 'participantid' : leg['orgid'], - 'participanttype' : leg['orgtype'], - 'subjectname' : leg['subjectname'], - 'accounting_dir': leg['accounting_dir'], - 'amount' : leg['amount'] - } - await sor.C('bill_detail', ns) - - async def overdraw_check(self, sor, accid, leg, tryAgain=True): - if accid is None: - raise AccountIdNone() - - sql0 = "select max(acc_date) as acc_date from acc_balance where accountid=${accid}$" - recs = await sor.sqlExe(sql0, {'accid':accid}) - acc_date = recs[0]['acc_date'] - bal = {} - if acc_date is not None: - if acc_date > self.curdate: - raise FutureAccountingExist(accid, self.curdate, acc_date) - ns={'accid':accid, 'acc_date':acc_date} - r = await sor.sqlExe("""select * from acc_balance -where accountid=${accid}$ - and acc_date = ${acc_date}$""", ns.copy()) - if len(r) > 0: - bal = r[0] - - accs = await sor.R('account', {'id':accid}) - if len(accs) == 0: - raise AccountNoFound(accid) - - acc = accs[0] - acc['acc_date'] = self.curdate - acc['balance'] = bal.get('balance', 0) - - if acc.get('balance') is None: - acc['balance'] = 0 - if acc['balance_at'] == DEBT and leg['acc_dir'] == CREDIT \ - or acc['balance_at'] == CREDIT and leg['acc_dir'] == DEBT: - if int(acc['balance']*10000) - int(leg['amount']*10000) < 0: - if tryAgain: - await asyncio.sleep(1.5); - return await self.overdraw_check(sor, accid, leg, tryAgain=False) - else: - print(f"{acc['balance_at']=}, {leg=}") - raise AccountOverDraw(accid, acc['balance'], leg['amount']) - leg['new_balance'] = acc['balance'] - leg['amount'] - else: - leg['new_balance'] = acc['balance'] + leg['amount'] - - async def leg_accounting(self, sor, leg): - accid = leg['acc'].id - await self.overdraw_check(sor, accid, leg) - # write acc_balance - sql = """select * from acc_balance -where accountid=${accid}$ - and acc_date = ${curdate}$""" - recs = await sor.sqlExe(sql, {'accid':accid, 'curdate':self.curdate}) - if len(recs) == 0: - ns = { - 'id':getID(), - 'accountid':accid, - 'acc_date':self.curdate, - 'balance':leg['new_balance'] - } - await sor.C('acc_balance', ns.copy()) - else: - ns = recs[0] - ns['balance'] = leg['new_balance'] - await sor.U('acc_balance', ns.copy()) - - # summary = self.summary - logid = getID() - ns = { - 'id':logid, - 'accountid':accid, - 'acc_date':self.curdte, - 'acc_timestamp':self.timestamp, - 'acc_dir':leg['acc_dir'], - 'summary':self.summary, - 'amount':leg['amount'], - 'billid':self.billid - } - await sor.C('accounting_log', ns.copy()) - ns = { - 'id':getID(), - 'accountid':accid, - 'acc_date':self.curdate, - 'acc_timestamp':self.timestamp, - 'acc_dir':leg['acc_dir'], - 'summary':self.summary, - 'amount':leg['amount'], - 'balance':leg['new_balance'], - 'acclogid':logid - } - await sor.C('acc_detail', ns.copy())