Merge branch 'main' of git.kaiyuancloud.cn:yumoqing/accounting
This commit is contained in:
commit
45a8359aca
@ -5,7 +5,7 @@ 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
|
||||
from appPublic.log import debug, exception
|
||||
from sqlor.dbpools import DBPools
|
||||
from appPublic.timeUtils import curDateString
|
||||
# from .argsconvert import ArgsConvert
|
||||
@ -25,17 +25,13 @@ async def get_accounting_config(sor):
|
||||
return None
|
||||
|
||||
class Accounting:
|
||||
/*
|
||||
"""
|
||||
需要caller功能:
|
||||
caller中要有分录中的变量
|
||||
get_accounting_orgid(leg) 获得记账机构
|
||||
get_account(leg,accounting_orgid) 获得记账账号(通过科目,机构类型,账务机构确定一个唯一的账号)
|
||||
*/
|
||||
def __init__(self, caller,
|
||||
accounting_orgid,
|
||||
customerid,
|
||||
resellerid=None
|
||||
):
|
||||
"""
|
||||
def __init__(self, caller):
|
||||
self.caller = caller
|
||||
self.curdate = caller.curdate
|
||||
self.realtimesettled = False
|
||||
@ -43,16 +39,14 @@ class Accounting:
|
||||
self.timestamp = caller.timestamp
|
||||
self.billid = caller.billid
|
||||
self.action = caller.action
|
||||
self.billid = getID()
|
||||
self.summary = f'{self.caller.orderid}:{self.caller.billid}'
|
||||
self.providerid = caller.providerid
|
||||
self.productid = caller.productid
|
||||
self.accounting_orgid = accounting_orgid
|
||||
self.resellerid = resellerid
|
||||
self.customerid = customerid
|
||||
self.resellerid = caller.resellerid
|
||||
self.customerid = caller.customerid
|
||||
self.own_salemode = None
|
||||
self.reseller_salemode = None
|
||||
self.variable = self.caller.varable
|
||||
self.variable = caller.variable
|
||||
|
||||
async def setup_accounting_legs(self):
|
||||
global accounting_config
|
||||
@ -68,14 +62,18 @@ class Accounting:
|
||||
else:
|
||||
l['acc_dir'] = l['accounting_dir']
|
||||
ac = ArgsConvert('${', '}$')
|
||||
debug(f'{l["id"]},{l["amt_pattern"]=}')
|
||||
try:
|
||||
amtstr = ac.convert(l['amt_pattern'],
|
||||
self.variable.copy()
|
||||
)
|
||||
l['amount'] = eval(amtstr)
|
||||
debug(f'{l["amt_pattern"]=}, {amtstr=}, {self.variable=}')
|
||||
if isinstance(amtstr, str):
|
||||
l['amount'] = eval(amtstr)
|
||||
else:
|
||||
l['amount'] = amtstr
|
||||
|
||||
except Exception as e:
|
||||
print(l['amt_pattern'], l['id'], self.variable)
|
||||
exception(f'{e=}, {l['amt_pattern']}, {self.variable=}')
|
||||
raise e
|
||||
|
||||
if l['amount'] is None:
|
||||
@ -87,9 +85,9 @@ class Accounting:
|
||||
credit_balance = 0.0
|
||||
for l in legs:
|
||||
if l['acc_dir'] == DEBT:
|
||||
debt_balance += legs['amount']
|
||||
debt_balance += l['amount']
|
||||
else:
|
||||
credit_balance += legs['amount']
|
||||
credit_balance += l['amount']
|
||||
if abs(credit_balance - debt_balance) >= 0.01:
|
||||
e = Exception('accounting legs not balance')
|
||||
exception(f'{legs=}, {e=}')
|
||||
@ -102,14 +100,18 @@ class Accounting:
|
||||
debug(f'do_accounting() ...{self.accounting_legs=}')
|
||||
self.check_accounting_balance(self.accounting_legs)
|
||||
for leg in self.accounting_legs:
|
||||
accounting_orgid = await self.caller.get_accounting_orgid(sor, leg.accounting_orgtype)
|
||||
orgid = await self.caller.get_accounting_orgid(sor, leg.orgtype)
|
||||
accounting_orgid = await self.caller.get_orgid_by_trans_role(sor, leg.accounting_orgtype)
|
||||
orgid = await self.caller.get_orgid_by_trans_role(sor, leg.orgtype)
|
||||
org1id = None if leg.org1type is None else \
|
||||
await self.caller.get_account_orgid(sor, leg.org1type)
|
||||
await self.caller.get_orgid_by_trans_role(sor, leg.org1type)
|
||||
acc = await get_account(sor, accounting_orgid, orgid, leg.subjectid, org1id=org1id)
|
||||
if acc is None:
|
||||
debug('can not get accountid {accounting_orgid=}, {leg=}')
|
||||
raise AccountIdNone(self.accounting_orgid, orgid, leg['subjectname'])
|
||||
debug(f'can not get accountid {accounting_orgid=}, {orgid=},{leg.subjectid=}, {org1id=}')
|
||||
raise AccountIdNone(accounting_orgid, orgid, leg['subjectid'])
|
||||
leg['_accounting_orgid'] = accounting_orgid
|
||||
leg['_orgid'] = orgid
|
||||
leg['_org1id'] = org1id
|
||||
leg['acc'] = acc
|
||||
await self.leg_accounting(sor, acc.id, leg)
|
||||
|
||||
async def write_settle_log(self):
|
||||
@ -197,9 +199,9 @@ where accountid=${accid}$
|
||||
# summary = self.summary
|
||||
ns = {
|
||||
'id':getID(),
|
||||
'accounting_orgid' : self.accounting_orgid,
|
||||
'accounting_orgid' : leg['accounting_orgid'],
|
||||
'billid' : self.billid,
|
||||
'description' : self.specstr,
|
||||
'description' : self.summary,
|
||||
'participantid' : leg['orgid'],
|
||||
'participanttype' : leg['orgtype'],
|
||||
'subjectname' : leg['subjectname'],
|
||||
@ -214,7 +216,7 @@ where accountid=${accid}$
|
||||
'acc_date':self.curdte,
|
||||
'acc_timestamp':self.timestamp,
|
||||
'acc_dir':leg['acc_dir'],
|
||||
'summary':leg['summary'],
|
||||
'summary':self.summary,
|
||||
'amount':leg['amount'],
|
||||
'billid':self.billid
|
||||
}
|
||||
@ -225,7 +227,7 @@ where accountid=${accid}$
|
||||
'acc_date':self.curdate,
|
||||
'acc_timestamp':self.timestamp,
|
||||
'acc_dir':leg['acc_dir'],
|
||||
'summary':leg['summary'],
|
||||
'summary':self.summary,
|
||||
'amount':leg['amount'],
|
||||
'balance':leg['new_balance'],
|
||||
'acclogid':logid
|
||||
|
@ -1,13 +1,14 @@
|
||||
from appPublic.uniqueID import getID
|
||||
from appPublic.dictObject import DictObject
|
||||
from sqlor.dbpools import DBPools
|
||||
from ahserver.serverenv import get_serverenv
|
||||
from appPublic.argsConvert import ArgsConvert
|
||||
import datetime
|
||||
from .const import *
|
||||
from .accountingnode import get_offer_orgs, get_parent_orgid
|
||||
from .excep import *
|
||||
from .getaccount import getAccountByName
|
||||
from .accounting_config import get_accounting_config, AccountingOrgs
|
||||
from .businessdate import get_business_date
|
||||
from .accounting_config import get_accounting_config, Accounting
|
||||
# from .settle import SettleAccounting
|
||||
|
||||
async def write_bill(sor, customerid, userid, orderid, business_op, amount):
|
||||
@ -18,6 +19,7 @@ async def write_bill(sor, customerid, userid, orderid, business_op, amount):
|
||||
bill.orderid = orderid
|
||||
bill.business_op = business_op
|
||||
bill.amount = amount
|
||||
get_business_date = get_serverenv('get_business_date')
|
||||
bill.bill_date = await get_business_date(sor)
|
||||
bill_state = '0'
|
||||
await sor.C('bill', bill.copy())
|
||||
|
@ -1,4 +1,6 @@
|
||||
from appPublic.log import debug, exception
|
||||
from sqlor.dbpools import DBPools
|
||||
from ahserver.serverenv import ServerEnv, get_serverenv
|
||||
from .const import *
|
||||
from accounting.accountingnode import get_parent_orgid
|
||||
|
||||
@ -13,12 +15,41 @@ async def get_account(sor, accounting_orgid, orgid, subjectid, org1id=None):
|
||||
accounting_orgid = ${accounting_orgid}$ and
|
||||
orgid = ${orgid}$ and
|
||||
""" + ss
|
||||
ns = {
|
||||
"accounting_orgid":accounting_orgid,
|
||||
"orgid":orgid,
|
||||
"org1id":org1id,
|
||||
"subjectid":subjectid
|
||||
}
|
||||
recs = await sor.sqlExe(sql, {
|
||||
"accounting_orgid":accounting_orgid,
|
||||
"orgid":orgid,
|
||||
"org1id":org1id,
|
||||
"subjectid":subjectid
|
||||
});
|
||||
})
|
||||
if len(recs) == 0:
|
||||
debug(f'{sql=}, {ns=}')
|
||||
return None
|
||||
return recs[0]
|
||||
|
||||
async def get_account_by_subjectname(sor, accounting_orgid, orgid, subjectname, org1id=None):
|
||||
ss = "a.org1id is NULL"
|
||||
if org1id:
|
||||
ss = "a.org1id = ${org1id}$"
|
||||
|
||||
sql = """select * from account a, subject b
|
||||
where
|
||||
a.subjectid = b.id and
|
||||
b.name = ${subjectname}$ and
|
||||
a.accounting_orgid = ${accounting_orgid}$ and
|
||||
a.orgid = ${orgid}$ and
|
||||
""" + ss
|
||||
recs = await sor.sqlExe(sql, {
|
||||
"accounting_orgid":accounting_orgid,
|
||||
"orgid":orgid,
|
||||
"org1id":org1id,
|
||||
"subjectname":subjectname
|
||||
});
|
||||
if len(recs) == 0:
|
||||
return None
|
||||
for rec in recs:
|
||||
@ -26,31 +57,6 @@ async def get_account(sor, accounting_orgid, orgid, subjectid, org1id=None):
|
||||
return rec['id']
|
||||
return None
|
||||
|
||||
async def get_account_by_subjectname(sor, accounting_orgid, orgid, subjectname, org1id=None):
|
||||
ss = "a.org1id is NULL"
|
||||
if org1id:
|
||||
ss = "a.org1id = ${org1id}$"
|
||||
|
||||
sql = """select * from account a, subject b
|
||||
where
|
||||
a.subjectid = b.id and
|
||||
b.name = ${subjectname}$ and
|
||||
a.accounting_orgid = ${accounting_orgid}$ and
|
||||
a.orgid = ${orgid}$ and
|
||||
""" + ss
|
||||
recs = await sor.sqlExe(sql, {
|
||||
"accounting_orgid":accounting_orgid,
|
||||
"orgid":orgid,
|
||||
"org1id":org1id,
|
||||
"subjectname":subjectname
|
||||
});
|
||||
if len(recs) == 0:
|
||||
return None
|
||||
for rec in recs:
|
||||
if a.org1id == org1id:
|
||||
return rec['id']
|
||||
return None
|
||||
|
||||
async def getAccountByName(sor, accounting_orgid, orgid, name, org1id):
|
||||
sql = """select a.* from account a, subject b
|
||||
where a.subjectid = b.id and
|
||||
@ -65,33 +71,28 @@ where a.subjectid = b.id and
|
||||
if len(recs) == 0:
|
||||
return None
|
||||
for rec in recs:
|
||||
if a.org1id == org1id:
|
||||
if rec.org1id == org1id:
|
||||
return rec['id']
|
||||
return None
|
||||
|
||||
async def getTransPayMode():
|
||||
pass
|
||||
|
||||
async def getParentOrganization(sor, childid):
|
||||
sql="select a.* from organization a, organization b where b.parentid=a.id and b.id = ${childid}$"
|
||||
ns = {
|
||||
"childid":childid
|
||||
}
|
||||
recs = await sor.sqlExe(sql, ns)
|
||||
if len(recs) == 0:
|
||||
return None
|
||||
return recs[0]
|
||||
|
||||
async def getCustomerBalance(sor, customerid):
|
||||
name = '业务账'
|
||||
orgid = await get_parent_orgid(sor, customerid)
|
||||
name = '客户资金账户'
|
||||
get_owner_orgid = get_serverenv('get_owner_orgid')
|
||||
if get_owner_orgid is None:
|
||||
debug('get_owner_orgid function is not a serverenv function')
|
||||
return None
|
||||
debug(f'{get_owner_orgid=}')
|
||||
orgid = await get_owner_orgid(sor, customerid)
|
||||
if orgid is None:
|
||||
print(f"{customerid=}'s parent organization not found")
|
||||
debug(f"{customerid=}'s parent organization not found")
|
||||
return None
|
||||
|
||||
balance = await getAccountBalance(sor, orgid, customerid, name)
|
||||
balance = await getAccountBalance(sor, orgid, customerid, name, None)
|
||||
if balance is None:
|
||||
print(f'accid is None, {orgid=}, {customerid=}, {name=}')
|
||||
debug(f'accid is None, {orgid=}, {customerid=}, {name=}')
|
||||
return None
|
||||
return balance
|
||||
|
||||
@ -100,14 +101,35 @@ async def getAccountBalance(sor, accounting_orgid, orgid, subjectname, org1id):
|
||||
orgid,
|
||||
subjectname,org1id)
|
||||
if accid is None:
|
||||
print(f'accid is None, {accounting_orgid=}, {orgid=}, {subjectname=}')
|
||||
debug(f'accid is None, {accounting_orgid=}, {orgid=}, {subjectname=}')
|
||||
return None
|
||||
return await getAccountBalanceByAccid(sor, accid)
|
||||
|
||||
async def get_account_total_amount(sor, accid, accounting_dir, from_date, to_date):
|
||||
sql = """select sun(amount) as amount from acc_detail
|
||||
where accountid =${accountid}$
|
||||
and acc_date >= ${from_date}$
|
||||
and acc_date < ${to_date}$
|
||||
and acc_dir = ${accounting_dir}$
|
||||
"""
|
||||
ns = {
|
||||
'accountid':accid,
|
||||
'accounting_dir':accounting_dir,
|
||||
'from_date':from_date,
|
||||
'to_date':to_date
|
||||
}
|
||||
recs = await sor.sqlExe(sql, ns.copy())
|
||||
if len(recs)==0:
|
||||
e = Exception(f'get_account_total_amount() error, {ns=}')
|
||||
exception('{e=}')
|
||||
raise e
|
||||
return recs[0].amount
|
||||
|
||||
|
||||
async def getAccountBalanceByAccid(sor, accid):
|
||||
balances = await sor.sqlExe("""select * from acc_balance where accountid=${accid}$ order by acc_date desc""", {'accid':accid})
|
||||
if len(balances) == 0:
|
||||
print(f'acc_balance is None, {accid=}')
|
||||
debug(f'acc_balance is None, {accid=}')
|
||||
return 0
|
||||
return balances[0]['balance']
|
||||
|
||||
|
@ -1,18 +1,21 @@
|
||||
from appPublic.registerfunction import RegisterFunction
|
||||
from appPublic.dictOBject import DictObject
|
||||
from appPublic.dictObject import DictObject
|
||||
from appPublic.log import debug, exception, error
|
||||
from ahserver.serverenv import ServerEnv
|
||||
from accounting.accounting_config import AccountingOrgs
|
||||
from accounting.accounting_config import Accounting
|
||||
from accounting.bill import write_bill
|
||||
from accounting.openaccount import openOwnerAccounts, openProviderAccounts, openResellerAccounts, openCustomerAccounts
|
||||
from accounting.getaccount import getAccountBalance, getCustomerBalance, getAccountByName, get_account_total_amount
|
||||
|
||||
def load_accounting():
|
||||
g = ServerEnv()
|
||||
g.recharge_accounting = recharge_accounting
|
||||
g.pay_accounting = pay_accounting
|
||||
g.settle_accounting = settle_accounting
|
||||
g.open_customer_account = open_customer_account
|
||||
g.open_reseller_account = open_reseller_account
|
||||
g.open_provider_account = open_provider_account
|
||||
g.open_owner_account = open_owner_account
|
||||
g.get_customer_balance = get_customer_balance
|
||||
g.Accounting = Accounting
|
||||
g.write_bill = write_bill
|
||||
g.openOwnerAccounts = openOwnerAccounts
|
||||
g.openProviderAccounts = openProviderAccounts
|
||||
g.openResellerAccounts = openResellerAccounts
|
||||
g.openCustomerAccounts = openCustomerAccounts
|
||||
g.getAccountBalance = getAccountBalance
|
||||
g.getCustomerBalance = getCustomerBalance
|
||||
g.getAccountByName = getAccountByName
|
||||
g.get_account_total_amount = get_account_total_amount
|
||||
|
@ -4,8 +4,15 @@ from appPublic.uniqueID import getID
|
||||
from appPublic.registerfunction import RegisterFunction, rfexe
|
||||
from appPublic.log import debug, exception
|
||||
from datetime import datetime
|
||||
from accounting.getaccount import get_account
|
||||
|
||||
async def openAccount(sor, accounting_orgid, orgid, account_config, org1id=None):
|
||||
acc = await get_account(sor, accounting_orgid, orgid,
|
||||
account_config['subjectid'], org1id=org1id)
|
||||
if acc:
|
||||
debug(f'{acc=} opened')
|
||||
return
|
||||
|
||||
ns = {
|
||||
'id':getID(),
|
||||
'accounting_orgid':accounting_orgid,
|
||||
@ -18,7 +25,7 @@ async def openAccount(sor, accounting_orgid, orgid, account_config, org1id=None)
|
||||
ns['org1id'] = org1id;
|
||||
debug(f'openAccount(), {ns=}')
|
||||
await sor.C('account', ns.copy())
|
||||
print(ns, 'opened')
|
||||
debug(f'{ns=} opened')
|
||||
|
||||
async def openPartyAccounts(sor, accounting_orgid, orgid, party_type, org1id=None, party1_type=None):
|
||||
addon_cond = " and a.party1type is NULL "
|
||||
@ -27,7 +34,7 @@ async def openPartyAccounts(sor, accounting_orgid, orgid, party_type, org1id=Non
|
||||
addon_cond = " and a.party1type = ${party1type}$ "
|
||||
ns['party1type'] = party1_type
|
||||
|
||||
sql = """select a.*, b.id as subjectid, b.balance_side from account_config a, subject b
|
||||
sql = """select a.*, b.id as subjectid, b.name as subjectname,b.balance_side from account_config a, subject b
|
||||
where a.subjectid = b.id """ \
|
||||
+ addon_cond + """
|
||||
and a.partytype=${partytype}$ """
|
||||
@ -38,24 +45,18 @@ where a.subjectid = b.id """ \
|
||||
debug(f'{r=}')
|
||||
await openAccount(sor, accounting_orgid, orgid, r, org1id=org1id)
|
||||
|
||||
async def _openPartyAccounts(accounting_orgid, orgid, party_type):
|
||||
db = DBPools()
|
||||
dbname = await rfexe('get_module_dbname', 'accounting')
|
||||
async with db.sqlorContext(dbname) as sor:
|
||||
await openPartyAccounts(sor, accounting_orgid, orgid, party_type)
|
||||
|
||||
async def openResellerAccounts(sor, accounting_orgid, orgid):
|
||||
return await _openPartyAccounts(accounting_orgid, orgid, PARTY_RESELLER)
|
||||
return await openPartyAccounts(sor, accounting_orgid, orgid, PARTY_RESELLER)
|
||||
|
||||
async def openCustomerAccounts(sor, accounting_orgid, orgid):
|
||||
return await _openPartyAccounts(accounting_orgid, orgid, PARTY_CUSTOMER)
|
||||
return await openPartyAccounts(sor, accounting_orgid, orgid, PARTY_CUSTOMER)
|
||||
|
||||
async def openOwnerAccounts(sor, accounting_orgid):
|
||||
orgid = accounting_orgid
|
||||
return await _openPartyAccounts(accounting_orgid, orgid, PARTY_OWNER)
|
||||
return await openPartyAccounts(sor, accounting_orgid, orgid, PARTY_OWNER)
|
||||
|
||||
async def openProviderAccounts(sor, accounting_orgid, orgid):
|
||||
return await _openPartyAccounts(accounting_orgid, orgid, PARTY_PROVIDER)
|
||||
return await openPartyAccounts(sor, accounting_orgid, orgid, PARTY_PROVIDER)
|
||||
|
||||
async def openAllCustomerAccounts(sor, accounting_orgid):
|
||||
rf = RegisterFunction()
|
||||
@ -91,13 +92,10 @@ async def openAllProviderAccounts(sor, accounting_orgid):
|
||||
await openProviderAccounts(sor, accounting_orgid, r['id'])
|
||||
|
||||
async def openRetailRelationshipAccounts(sor, accounting_orgid, providerid, resellerid):
|
||||
db = DBPools()
|
||||
dbname = await rfexe('get_module_dbname', 'accounting')
|
||||
async with db.sqlorContext(dbname) as sor:
|
||||
await openPartyAccounts(sor, accounting_orgid, providerid, PARTY_PROVIDER,
|
||||
org1id=resellerid,
|
||||
party1_type=PARTY_RESELLER)
|
||||
await openPartyAccounts(sor, accounting_orgid, resellerid, PARTY_RESELLER,
|
||||
org1id=providerid,
|
||||
party1_type=PARTY_PROVIDER)
|
||||
await openPartyAccounts(sor, accounting_orgid, providerid, PARTY_PROVIDER,
|
||||
org1id=resellerid,
|
||||
party1_type=PARTY_RESELLER)
|
||||
await openPartyAccounts(sor, accounting_orgid, resellerid, PARTY_RESELLER,
|
||||
org1id=providerid,
|
||||
party1_type=PARTY_PROVIDER)
|
||||
|
||||
|
@ -1,7 +1,4 @@
|
||||
{
|
||||
"models_dir": "${HOME}$/py/accounting/models",
|
||||
"output_dir": "${HOME}$/py/sage/wwwroot/accounting_config",
|
||||
"dbname": "sage",
|
||||
"tblname": "accounting_config",
|
||||
"title":"账务设置",
|
||||
"params": {
|
||||
|
3
json/build.sh
Executable file
3
json/build.sh
Executable file
@ -0,0 +1,3 @@
|
||||
#!/usr/bin/bash
|
||||
|
||||
xls2ui -m ../models -o ../wwwroot accounting *.json
|
8
script/roleperm.sh
Executable file
8
script/roleperm.sh
Executable file
@ -0,0 +1,8 @@
|
||||
#!/usr/bin/bash
|
||||
|
||||
python ~/py/rbac/script/roleperm.py sage accounting owner superuser account_config accounting_config subject
|
||||
python ~/py/rbac/script/roleperm.py sage accounting reseller operator account acc_detail acc_balance accounting_log bill bill_detail ledger
|
||||
python ~/py/rbac/script/roleperm.py sage accounting reseller sale account acc_detail acc_balance accounting_log bill bill_detail ledger
|
||||
python ~/py/rbac/script/roleperm.py sage accounting reseller accountant account acc_detail acc_balance accounting_log bill bill_detail ledger
|
||||
python ~/py/rbac/script/roleperm.py sage accounting customer customer account acc_detail acc_balance accounting_log bill bill_detail ledger
|
||||
|
Loading…
Reference in New Issue
Block a user