From a78eae866443c24787a69f94273b0139abcd6f92 Mon Sep 17 00:00:00 2001 From: yumoqing Date: Mon, 5 Jan 2026 17:39:55 +0800 Subject: [PATCH] bugfix --- accounting/accounting_config.py | 33 ++++++++++----- accounting/getaccount.py | 69 +++----------------------------- models/acc_balance.xlsx | Bin 14912 -> 14913 bytes models/account.xlsx | Bin 16315 -> 16354 bytes 4 files changed, 29 insertions(+), 73 deletions(-) diff --git a/accounting/accounting_config.py b/accounting/accounting_config.py index 2e08a62..5c7e69a 100644 --- a/accounting/accounting_config.py +++ b/accounting/accounting_config.py @@ -49,7 +49,7 @@ class Accounting: async def setup_all_accounting_legs(self): self.accounting_legs = [] debug(f'{self.callers=}') - for caller in self.callers: + for i, caller in ienumerate(self.callers): self.caller = caller self.curdate = caller.curdate self.realtimesettled = False @@ -64,18 +64,20 @@ class Accounting: self.own_salemode = None self.reseller_salemode = None self.variable = caller.variable - await self.setup_accounting_legs() + await self.setup_accounting_legs(i) legs = sorted( self.accounting_legs, key=lambda x: ( x.get('accounting_orgid','0'), - x.get('accid', '0'), + x.get('orgid'), + x.get('subjectid'), 0 if x.get('acc_dir', '0') == x.get('balance_at', '0') else 1 ) ) self.accounting_legs = legs + self.get_legs_account() - async def setup_accounting_legs(self): + async def setup_accounting_legs(self, pos): sor = self.sor action = self.action.split('_')[0] acfg = await get_accounting_config(self.sor) @@ -84,6 +86,7 @@ class Accounting: debug(f'{legs=}') rev = self.action.endswith('_REVERSE') for l in legs: + l['position'] = pos if rev: l['acc_dir'] = DEBT if l['accounting_dir'] == CREDIT else CREDIT else: @@ -110,17 +113,27 @@ class Accounting: orgid = await self.caller.get_orgid_by_trans_role(sor, l, l.orgtype) org1id = None if l.org1type is None else \ await self.caller.get_orgid_by_trans_role(sor, l, 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=}, {l=}, {self.customerid=},{self.resellerid=},{self.providerid=}') - raise AccountIdNone(accounting_orgid, orgid, l['subjectid']) l['accounting_orgid'] = accounting_orgid l['orgid'] = orgid l['org1id'] = org1id + self.accounting_legs += legs + + def get_legs_account(self): + sor = self.sor + oldk = '' + acc = None + for l in self.accounting_legs: + k = f'{l.accounting_orgid}|{l.orgid}|{l.subjectid}|{l.org1id=org1id}' + if oldk != k: + acc = await get_account(sor, l.accounting_orgid, l.orgid, + l.subjectid, l.org1id=org1id, update=True) + if acc is None: + debug(f'can not get accountid {accounting_orgid=}, {orgid=},{l.subjectid=}, {org1id=}, {l=}, {self.customerid=},{self.resellerid=},{self.providerid=}') + raise AccountIdNone(accounting_orgid, orgid, l['subjectid']) + oldk = k l['accid'] = acc.id l['balance_at'] = acc.balance_at l['acc'] = acc - self.accounting_legs += legs def check_accounting_balance(self, legs): debt_balance = 0.0 @@ -136,7 +149,7 @@ class Accounting: else: acc_balance += l['amount'] if acc_balance < 0.000000: - e = AccountOverDraw(curacc, acc['balance'], leg['amount']) + e = AccountOverDraw(curacc, l['acc'].balance, leg['amount']) exception(f'{e},{legs=}') raise e l['new_balance'] = acc_balance diff --git a/accounting/getaccount.py b/accounting/getaccount.py index 14b4d7e..1bae40a 100644 --- a/accounting/getaccount.py +++ b/accounting/getaccount.py @@ -13,9 +13,7 @@ async def get_account(sor, accounting_orgid, orgid, subjectid, org1id=None, upda sql = """select a.*, -case when b.balance is null then 0.00 else b.balance end as balance -from account a left join acc_balance b - on a.id = b.accountid +from account a where a.subjectid = ${subjectid}$ and a.accounting_orgid = ${accounting_orgid}$ and @@ -38,48 +36,14 @@ where 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: - 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 - a.accounting_orgid = ${accounting_orgid}$ and - a.orgid = ${orgid}$ and - b.name = ${name}$""" + sql = """select a.* from subject a where a.name = ${name}$""" recs = await sor.sqlExe(sql, { - "accounting_orgid":accounting_orgid, - "orgid":orgid, "name":name }); if len(recs) == 0: return None - for rec in recs: - if rec.org1id == org1id: - return rec['id'] - return None + return get_account(sor, accounting_orgid, orgid, recs[0].id, org1id=org1id) async def getTransPayMode(): pass @@ -103,13 +67,13 @@ async def getCustomerBalance(sor, customerid): return balance async def getAccountBalance(sor, accounting_orgid, orgid, subjectname, org1id): - accid = await getAccountByName(sor, accounting_orgid, + acc = await getAccountByName(sor, accounting_orgid, orgid, subjectname,org1id) if accid is None: debug(f'accid is None, {accounting_orgid=}, {orgid=}, {subjectname=}') return None - return await getAccountBalanceByAccid(sor, accid) + return acc.balance async def get_account_total_amount(sor, accid, accounting_dir, from_date, to_date): sql = """select sun(amount) as amount from acc_detail @@ -133,30 +97,9 @@ where accountid =${accountid}$ async def getAccountBalanceByAccid(sor, accid): - balances = await sor.sqlExe("""select * from acc_balance where accountid=${accid}$ order by acc_date desc""", {'accid':accid}) + balances = await sor.sqlExe("""select * from account where id=${accid}$""", {'accid':accid}) if len(balances) == 0: debug(f'acc_balance is None, {accid=}') return 0 return balances[0]['balance'] -async def get_account_info(sor, accid): - sql = ''' -select b.orgname as accounting_org, -case when a.accounting_orgid = a.orgid then '本机构' - when c.org_type in ('0', '1') then '分销商' - when c.org_type = '2' then '供应商' - else '客户' end as acctype, -c.orgname, -d.name -from account a, organization b, organization c, subject d -where a.accounting_orgid = b.id - and a.orgid = c.id - and a.subjectid = d.id - and a.id = ${accid}$''' - recs = await sor.sqlExe(sql, {'accid':accid}) - if len(recs) == 0: - - return None - r = recs[0] - r['balance'] = await getAccountBalanceByAccid(sor, accid) - return r diff --git a/models/acc_balance.xlsx b/models/acc_balance.xlsx index 8b4cd3a2a39c6821556da17346c383d1caa6cfe4..52b46e545cc0578f7bc2ce0bc197aed3fa3f5054 100644 GIT binary patch delta 1966 zcmV;f2T}OIbis76MF|DfEP8HUlS&C3e_d~zJQTj4wEuv(r^bYj1eH!930kFgs=BOw zcU3vy6sra^WAdSC|9!_0(lmKBWnGjQY#%>7=bYypa`|afaAQSf%|scQ_`)^~TBagn z<#S|yn@0;Wh=QqnMs+1A$?BX^RdD3kwvP(JO0z=<1BaGjKU~?LSfAf%BBkn`2&GE*Yl}opcRSRbNP8YqZD(kr ztG%4>BupUpW3H$yiJ}uxDv;Wa`oGGm#h&B>L~PvC9}SZfY6m0)?!ZXWe~>KdJEC%< zkvuZdw;KFI+u{eRwuq#uXi5d8i3*WXUZVpIl2gI|g$hZkgMh&Cj$C(t90cGf!(M53 zN*Zu~J-vZwe;~3231(J2bAvb@ z4uWyw{{m;EAEtsdD&M75e?v#63pqU5x+R-_2isx8vR4{E?cK-H*Q24|`=uS$4eWu@ zb^R&;JvBCutjxq39$=4r@M_!7@yHp%eBEw8vP|WX>DWVU)2)4`>^TR{7*=7Cq>8QR zoGf5PJK<=ik@<$8-dxeT&5ZTxp#`a+3SZ;z7%f%zxieulkylFD< z0z93}yhKY)zqP`RTt-~Jvl$Ihdzuo}Ko#o(Zs(yMlilimaoH{Gvi7Dj!~3arWq0~d zhF_udIX%-jc{tN>^5u4Zd#3HpZ2t6^oM}A1zaM{}&;IL=p#KdJf*eA-=`)G?KNeTN z0h8ed6tm6@#~ccsck8>m1ONah43ohn8I!mv8v(78)F~(?7jRzLrl5S9Py&s#rE1m% z{r2@?azlv^qA7*84HWbhJiT4Mf47q&DmZ^|Z{^lN6AlmuS_Jg(Yt{OJX5=L}Biv@& zPNX$0B34SP@Y+EsF>?O2Zmbh4jdkyNCM4NAJX5@`hBV#!Stg^Tv))!=iez^1d|v*H z&6toQ>Ae1nFg#-pUR2z`BPxBHC4N1!(j)BZjj()##n0vDTU8eHchVmdoOv9QNy260 zaB}>i%SEYhhhtU5K~>O?eE!H&%9e|+fxau)`IDFgv3dp#G5{vwl>D;RJWCPxF3qv4 z$NNvQBXz$TyLe^oCgPq@m|$YxVPaw-gL;8G(D?fOHU0=cJ1ZEX4L15XjR#K;lRhgQ z0SJ>^D;|F-+LK!!tQj)(@`Etzg*XpFKK-{O?faverqG4;T zyurE9)2_n}*RC7uW^78=-(Rb~P)4nWM{^tCX`g?o(zOU4038c8!27dYJN+!3Zoiz5 zIYYTB=5~~;V=klIG3Ij0ok%?v=1fSI=0Zq2e^x{5bN^QCAJDn~E$e@Qt76V1Yyfr| zXYwaVA_f6;4q`Se30exZjU_2N5aQ>7lEpw9F%Y035FZU%SRl3q74e5PAZL<_l>rTv z*^*3nw9v|ytx6U9EnAg3okqbu#}6FlPGZ8~f3J>56q9JUGx4JBL^Yz4Iuq51O6pux zBPyxQT9i+)s2Bec-XJXM#XIE8noab8d%4nFQBRI4u zZf|nYFkvjbSkr*@3S1OO+A-10(a!sZVeG^XYVMNY&_OJXt+@}Q-QtFeJ>LRO37O&= zJeS;a+yUceAfhu;iUHYt+NuXgfuVvLw10P)CKUg8J=og)xzH;kXRZ9P37yVy$80H1 z;^00wH5l8rP1;ExBjl&}ef9L(SB;hKZY2N}xfD!T;NI9`-?lj(&E4%P?))m8xl|zU zkHty}Yn&;4^jwxoK(ujSbNt&FxP6Ti9Ap%Nu~UtU@-}&RTrW|P5}L(i8q;)5XDN(M z86h8Cj;sAH=;@(8r}>wdPGdr2lC8;%Wf{xT5%B^j`rOx_qxc4sOE%aA)hv2$UXv&{ zQUSt~dpAV^EtA1FMFN);ld%*PlN~rJ0iTmdI7I@N9+R;i7L%noDgmXF&^S5)tCI^k zD;u46>$|%I001Wp000;O000000000000000iIY(|ss&A%B?VQIIyweYHUIzs0Ewrd A-2eap delta 1957 zcmV;W2U_^Sbij15MF|CAvq6bmlS&C3fA4RbJP`gqY5xQAcWO)sC8%_2LeMI;Q`Ked zyHAw^PO)k*GbTSY?SJ1HLYgM8rmTw+gYEOfb9c`jx%jj$gtcU<=CX_sIdhQ3%2Z~& ze2&n!Sz-sssx>V$DrCtbv|%;+bouea#Y(D|xs)#!0F-rva;>Wn<2ub*LF+SFf3XsF z7E%>d!&E)vx>Ag0bJUP83Wi)Pc*%)&YFu47bVC(2n1y7Z% zoUq~9D~+Gd_G6pt!O-vhG7g&t_Q2Vy zeieY3TI)w%W^xrFH}GBXYSYij$PHk=YPTPGrgN}y0)MymnepcwI1^ZfMVe~9WHUO4 z72||!m`3Og!?G1xmXI6Tq4Irgl*J!|jKI%lHVvo)33Gat5k z>^)AYNbi(oF0G3rDBF>-U~7F->-Gv2!y&TcVK8p?Y+Tu%{*&QX zD1E_BG)^8)G@N|7o!y>jdo!IqJtij_U)|qdeVyP074G@MLLc8fRiTghmm%jm% z;RY15&?Jr<5%hT?2hru=6J|31amG8e{-W!YTP>t$C6n?p>N=SC99fVn^zJHFojJ z+D*hgqAw`5zre1y!X1x&SLCB~7mSDYIE}RER`X9-=UV`%=$u6?Tu|c|IG3cc?7@k+ex-aq< z0096000030|9n*K4uUWYd=;`67#o6U28jbdUV|7Cf2jeYuWyTnt+o0O?ymIO-EiZj z@29q#y4nr5XEIdEsARl%*Abq7wxz1w8NnT(Q>8|Df7GedkJ{<;hx0LKDA&Z?nsRN- zm6Y4Z+=g-o(vO)r5|X(&5z;Q7)iC-pzZK^PbeX?k^Z((Rm@^q$fSuQw{VW!#IR8pH%l+UoJ z7yl97AS~*|JLL_+M6bi|=moRJEDi?+L~8kTRI}MLGXVvrWpjkKlMyu(f9+N~6d!NS zxgY0Tk}Z#Q6?}oQQmY)1C`JJ&u7y;)9BntNaDf8rm=dhg3UYJ;iH&gdsGtVre=H^u!9QLHrnY}B^vc9pOLuB~r*qsXTkt^~-A5}&W81b- zoAxn$euCfEPp^H|P^#`$98i%7PPqZ*v?&g4o8iga-L7KRt^Jux3F7`#tR*+v>e270E#~M_2($Q0h3HN*acy;L5WuS{ zH!1-ulfpMe0hN;oI6wlO8k4&k8k1x=Dgl*~k2paAqm$7%IsvJZ3^^+svNA)Yy#xRN rCky}p7ytkO0000000000004)RQaP#xL~8kTRFeTZItEcT00000?YpP% diff --git a/models/account.xlsx b/models/account.xlsx index 17aee0550979e978cf126ee8e484108ae54baf22..40e912c49b63c81832dd404b6b6feafebdd42685 100644 GIT binary patch delta 3443 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