Preserve August hydrogen revision and September audit evidence; calculate interrupted vehicle history across all prior months. Record remaining carry-policy and layout-baseline discrepancies.
70 lines
6.5 KiB
Python
70 lines
6.5 KiB
Python
"""Read-only audit. No business workbook or calculation state is modified."""
|
|
from pathlib import Path
|
|
from collections import Counter,defaultdict
|
|
from decimal import Decimal,ROUND_HALF_UP
|
|
import json,hashlib,calendar
|
|
import openpyxl
|
|
P=Path(__file__).resolve().parent;S=P.parent;H=S.parent/'hydrogen-history-20260916'
|
|
load=lambda p:json.loads(p.read_text())
|
|
d=load(S/'september_calculation.json');aug=load(H/'august_calculation.json');paid=load(H/'historical_paid.json')
|
|
money=lambda v:float(Decimal(str(v)).quantize(Decimal('.01'),rounding=ROUND_HALF_UP))
|
|
key=lambda x:(x['plate'],x['sales'])
|
|
groups={key(g):g for g in d['groups']};prior={key(g):g for g in aug['groups']}
|
|
hist={(x['month'],x['plate'],x['sales']):x for x in d['historical_months']}
|
|
settled={(r['assessment_month'],r['plate'],r['owner']) for r in paid}
|
|
settled.update((l['assessment_month'],*key(l)) for l in aug['ledger'] if l['gross_amount']>0)
|
|
carry_paid=Counter((r['plate'],r['owner']) for r in paid if r['category']=='结转')
|
|
carry_paid.update(key(l) for l in aug['ledger'] if l['category']=='结转' and l['amount']>0)
|
|
ledger={(l['plate'],l['sales'],l['category']):l for l in d['ledger']}
|
|
assert len(ledger)==len(d['ledger'])
|
|
expected={};details=[];carry_basis=[];balance_inconsistent=[];status_inconsistent=[];used_inconsistent=[];cross_owner=[]
|
|
for k,g in groups.items():
|
|
rows=[r for r in d['records'] if (r['车牌号'],r['销售经理'])==k]
|
|
hist_t=sum(x['target'] for h,x in hist.items() if h[1:]==k)
|
|
hist_a=sum(x['actual'] for h,x in hist.items() if h[1:]==k)
|
|
full_t=money(hist_t+g['target']);full_a=money(hist_a+g['actual']);cq=full_a>=full_t and full_t>0
|
|
assert abs(full_t-g['cum_target'])<.02 and abs(full_a-g['cum_actual'])<.02,k
|
|
prev=prior.get(k,{})
|
|
locked=prev.get('carry_left',0)
|
|
if locked>=1:expected[(*k,'结转')]=money(g['reward'])
|
|
else:
|
|
current=sum(Decimal(str(r['月奖励']))*Decimal(str(r['考核天数']))/30 for r in rows if r['实际行驶里程(km)']>=r['应考核里程(km)'])
|
|
if current:expected[(*k,'当月')]=money(current)
|
|
if cq and not g['virtual']:
|
|
for m in range(1,9):
|
|
old=hist.get((m,*k))
|
|
if old and (m,*k) not in settled:expected[(*k,f'补发{m}月')]=money(Decimal(str(old['reward']))*Decimal(str(old['days']))/calendar.monthrange(2026,m)[1])
|
|
if not any(r['实际行驶里程(km)']>=r['应考核里程(km)'] for r in rows) and locked<1:
|
|
expected[(*k,'累计补发9月')]=money(Decimal(str(g['reward']))*Decimal(str(g['days']))/30)
|
|
used_actual=carry_paid[k]+int(locked>=1)
|
|
if used_actual!=g['used_carry']:used_inconsistent.append(dict(plate=k[0],sales=k[1],ledger_used=used_actual,stored_used=g['used_carry']))
|
|
recomputed_prior=max(0,int(max(0,hist_a-hist_t)//g['monthly_target'])-carry_paid[k])
|
|
recomputed_balance=max(0,int(max(0,full_a-full_t)//g['monthly_target'])-used_actual)
|
|
evidence=dict(plate=k[0],sales=k[1],aug_cumulative_target=money(hist_t),aug_cumulative_actual=money(hist_a),monthly_target=g['monthly_target'],carry_paid_jan_aug=carry_paid[k],aug_saved_balance=locked,aug_formula_balance=recomputed_prior,sep_saved_balance=g['carry_left'],sep_formula_balance=recomputed_balance,sep_payment=g['total'],virtual=g['virtual'])
|
|
if recomputed_prior!=locked:carry_basis.append(evidence)
|
|
if recomputed_balance!=g['carry_left']:balance_inconsistent.append(evidence)
|
|
if cq!=g['cum_qualified']:status_inconsistent.append(dict(plate=k[0],sales=k[1],target=full_t,actual=full_a,stored=g['cum_qualified'],calculated=cq,virtual=g['virtual']))
|
|
if g['virtual']:
|
|
other=[l for l in d['ledger'] if l['plate']==k[0] and l['sales']!=k[1]]
|
|
if other:cross_owner.append(dict(plate=k[0],carry_owner=k[1],carry_amount=ledger.get((*k,'结转'),{}).get('amount',0),current_payments=[{f:l[f] for f in ['sales','category','amount']} for l in other]))
|
|
for l in d['ledger']:
|
|
if key(l)==k and l['assessment_month']<9:
|
|
assert (l['assessment_month'],*k) not in settled
|
|
details.append({**{f:l[f] for f in ['plate','sales','category','amount']},'aug_cumulative_target':prev.get('cum_target'),'aug_cumulative_actual':prev.get('cum_actual'),'sep_cumulative_target':full_t,'sep_cumulative_actual':full_a,'historically_unpaid':True})
|
|
missing=[dict(plate=k[0],sales=k[1],category=k[2],expected=v,actual=ledger.get(k,{}).get('amount',0)) for k,v in expected.items() if abs(v-ledger.get(k,{}).get('amount',0))>.001]
|
|
extra=[dict(plate=k[0],sales=k[1],category=k[2],actual=l['amount'],expected=expected.get(k,0)) for k,l in ledger.items() if abs(l['amount']-expected.get(k,0))>.001]
|
|
source_checks={}
|
|
for tag,x in d['sources'].items():source_checks[tag]=hashlib.sha256(Path(x['path']).read_bytes()).hexdigest()==x['sha256']
|
|
fp=S/'里程任务考核_2026年9月_含缺口核算.xlsx';wb=openpyxl.load_workbook(fp,data_only=True,read_only=True)
|
|
xrows=list(wb['9月奖金发放记录'].values)
|
|
excel_ledger={(r[0],r[1],r[4]):r[9] for r in xrows[1:] if r[0] and r[0]!='合计' and isinstance(r[9],(int,float))}
|
|
assert excel_ledger=={k:l['amount'] for k,l in ledger.items()}
|
|
errors=[(s.title,c.coordinate,c.value) for s in wb for row in s for c in row if c.data_type=='e'];wb.close()
|
|
assert not errors
|
|
by_cat={c:money(sum(l['amount'] for l in d['ledger'] if l['category']==c)) for c in d['categories']}
|
|
virtual_pay=[l for l in d['ledger'] if l['virtual']]
|
|
gap_pay=[l for l in d['ledger'] if l['gap_days']>0 or l['history_gap_days']>0]
|
|
wholly=[r for r in d['records'] if r['缺口天数']==r['考核天数']]
|
|
out=dict(amount=d['summary']['amount'],ledger_items=len(ledger),expected_amount_under_locked_aug_carry=money(sum(expected.values())),missing_payments=missing,extra_payments=extra,categories=by_cat,historical_backpay=details,prior_carry_basis_differences=carry_basis,next_balance_differences=balance_inconsistent,cumulative_status_inconsistencies=status_inconsistent,used_count_differences=used_inconsistent,cross_owner_payments=cross_owner,virtual_count=len(virtual_pay),virtual_amount=money(sum(l['amount'] for l in virtual_pay)),gap_payment_count=len(gap_pay),gap_payment_amount=money(sum(l['amount'] for l in gap_pay)),wholly_missing=[{f:r[f] for f in ['车牌号','销售经理','考核天数']} for r in wholly],source_hash_checks=source_checks,excel_ledger_matches=True,formula_errors=errors,workbook_sha256=hashlib.sha256(fp.read_bytes()).hexdigest())
|
|
(P/'audit_results.json').write_text(json.dumps(out,ensure_ascii=False,indent=2));print(json.dumps({k:v for k,v in out.items() if k not in ['next_balance_differences','cumulative_status_inconsistencies','source_hash_checks','historical_backpay']},ensure_ascii=False,indent=2));print('NEXT_BALANCES',len(balance_inconsistent),'STATUS',len(status_inconsistent))
|