"""R05独立标准库复算。所有金额为构造值,输出到本文件同目录。""" from calendar import monthrange from datetime import date from decimal import Decimal, ROUND_HALF_UP from pathlib import Path from collections import defaultdict import json D=Decimal CENT=D('0.01') LIMIT=D('1000000000000') def money(x): n=D(str(x)) if not n.is_finite() or abs(n)>LIMIT: raise ValueError('金额越限') return n.quantize(CENT,rounding=ROUND_HALF_UP) def add_months(origin,months,anchor=None): origin=date.fromisoformat(origin) if isinstance(origin,str) else origin total=origin.year*12+origin.month-1+months y,m=divmod(total,12);m+=1 return date(y,m,min(anchor or origin.day,monthrange(y,m)[1])) def cert(name,start,principal,months,rates,mode='stop',cycles=1,bank='教学甲行',person='甲',interest_override=None): return dict(name=name,start=start,principal=str(principal),months=months,rates=[str(v) for v in rates],mode=mode,cycles=cycles,bank=bank,person=person,interest_override=interest_override) def events(items): assert len(items)<=60 out=[] initial_total=money(sum((money(c['principal']) for c in items),D(0))) for c in items: p=money(c['principal']);origin=date.fromisoformat(c['start']) for i in range(c['cycles']): end=add_months(origin,c['months']*(i+1)) assert end<=add_months(origin,120) rate=D(c['rates'][min(i,len(c['rates'])-1)]) interest=money(p*rate*D(c['months'])/12) source='声明单利估算' if c['interest_override'] is not None and i==0: interest=money(c['interest_override']);source='构造已确认合同覆盖' gross=money(p+interest) renew=i