# -*- coding: utf-8 -*-
"""
利息计算脚本(复核终稿版)
本版相对《利息计算-交接终稿.py》的修改:
1. 每项正式计算参数改为"值/核定状态/依据"三联可填写记录:缺值、核定状态非
"已核定"、依据空白,三者任一命中即停算——仅填值不视为已核。核定状态与依据
系可填写的工作记录,便于追溯,不构成法律授权证明;脚本不设签字或审批环节。
2. 第七节"正式计算中止/已执行"按本轮实际停算条件动态输出,不再写死。
3. 测算截止日或起诉日落在三笔借款之后、2024-09-02 5,000元付款日之前时:不扣减
该款、不倒算付款日前后利息,并如实注明;测算截止日早于LPR备选起算日的检查
改为仅约束方案二与LPR演示组合(组合六),不再阻断其余演示组合。
4. 配套三稿为"复核终稿"批文件;清单"【待核定】。待定。"重复标注已去重
(清单第3、4项)。
设计原则(沿用前版):
· 参数读取实际文书:本金、起息日等自同目录起诉状匹配并回显。
· 日期顺序违例(截止日早于起息日等)一律停算,绝不出负数。
· 演示算例按显式假设计算:月1%、年10%仅系候选理解示例(非穷尽、非唯一口径);
抵息/抵本并列;分配口径未定的组合不出数;组合六的105,000元基数仅系演示假设。
· 运行结果按序另存,不覆盖。
用法:python3 利息计算-复核终稿.py
依赖:仅Python标准库。
"""
import os
import re
import sys
from datetime import date
from decimal import Decimal, ROUND_HALF_UP
# ───────── 参数区(默认全部未核;每项=值/核定状态/依据 三联可填写记录) ─────────
# 填写示例(承办律师核定后逐项填定):
# 起诉日 = 参数(值=date(2026, 11, 2), 状态="已核定",
# 依据="承办律师2026-XX-XX核定立案日,工作记录见卷内备注")
# 规则:状态仅接受字面"已核定"放行;缺值、状态非"已核定"、依据空白任一命中即停算;
# 仅填值(状态/依据留默认)不视为已核。
付款日5000 = date(2024, 9, 2) # 5,000元付款日(证据四),窗口规则参照点(非可核参数)
def 参数(值=None, 状态="未核", 依据=""):
return {"值": 值, "状态": 状态, "依据": 依据}
计息本金表 = 参数(状态="已核定", 依据="测试假设:起诉状自动读取三笔本金及起息日,副本视为已核定(非真实核定)") # 三笔本金及起息日:脚本自起诉状自动读取,读取后仍须承办律师核定
计息方案 = 参数(值="方案一", 状态="已核定", 依据="测试假设:采方案一(非真实核定)") # 待核定:"方案一"(主张约定利息)或"方案二"(LPR备选)——起诉状诉请二
起诉日 = 参数(值=date(2026, 11, 2), 状态="已核定", 依据="测试假设:暂定起诉日(非真实核定)") # 待核定:填 date(2026, 11, 2) 这类
利率口径 = 参数(值="月1%", 状态="已核定", 依据="测试假设:按月1%读法(非真实核定)") # 方案一待核定:"月1%"或"年10%"——清单第4项(两读法仅为候选示例,非穷尽)
抵充口径 = 参数(值="抵息", 状态="已核定", 依据="测试假设:5,000元抵息(非真实核定)") # 待核定:"抵息"或"抵本"——清单第3项
# (方案一"抵本"还须核定5,000元在三笔本金间的分配,未定则利息仍中止;
# 方案二下本金基数受其影响)
三千元性质 = 参数(值="茶叶货款", 状态="已核定", 依据="测试假设:3,000元系茶叶货款(非真实核定)") # 待核定:"茶叶货款"或"还款"——清单第8项
# (任一方案下"还款"还须核定抵减口径,未定则中止)
本金基数 = 参数(值=Decimal("110000"), 状态="已核定", 依据="测试假设:抵息口径110,000元(非真实核定)") # 待核定:诉请一本金,如 Decimal("110000") 或 Decimal("105000")
# ——取决于抵充口径、3,000元性质等;本脚本不代推
展期效力 = 参数() # 方案二待核定:值填"成立"或"不成立"——清单第17项
LPR起算日 = 参数(值=date(2025, 7, 1)) # 候选值暂按展期届满次日,仍须核定——清单第5项、第17项
LPR年利率 = 参数() # 方案二待核定:起诉日适用的一年期LPR(本脚本不联网代查),如 Decimal("0.034")
测算截止日 = 参数(状态="演示用", 依据="未填=取运行日(仅演示用,不是起诉日)") # 演示用,不入正式门槛
LPR演示值 = 参数(值=Decimal("0.030"), 状态="演示用",
依据="沿用原第5轮脚本3.0%,未经核定、不联网更新") # 演示用,不入正式门槛
# ──────────────────────────────────────────────────────────────
BASE = os.path.dirname(os.path.abspath(__file__))
诉状名 = "起诉状-复核终稿.txt"
证据名 = "证据目录-复核终稿.txt"
清单名 = "待核清单-复核终稿.txt"
序号 = 1
while os.path.exists(os.path.join(BASE, f"利息计算结果-复核终稿_运行{序号}.txt")):
序号 += 1
结果名 = f"利息计算结果-复核终稿_运行{序号}.txt"
行 = []
def 输出(s=""):
行.append(s)
print(s)
def 读文本(p):
with open(p, "r", encoding="utf-8") as f:
return f.read()
def 紧(t):
return re.sub(r"\s+", "", t)
D2 = Decimal("0.01")
def 舍(x):
return x.quantize(D2, rounding=ROUND_HALF_UP)
def 天数(起, 止):
d = (止 - 起).days
if d < 0:
raise ValueError(f"日期顺序错误:截止 {止.isoformat()} 早于起算 {起.isoformat()}(停算,不出负数)")
return d
def 计息(本金, 起, 止, 日利率):
d = 天数(起, 止)
return d, 舍(本金 * 日利率 * d)
def 中(日):
return f"{日.isoformat()}({日.year}年{日.month}月{日.day}日)"
def 打明细(截止, 名义利率, 式样, 缩进=" "):
日利率 = 名义利率 / 30 if 式样 == "月" else 名义利率 / 365
除数 = "30" if 式样 == "月" else "365"
总 = Decimal("0")
for 序, (本金, 起, 说明) in enumerate(借款, 1):
d, i = 计息(本金, 起, 截止, 日利率)
总 += i
输出(f"{缩进}第{序}笔 本金{本金:,.0f}元({说明})")
输出(f"{缩进} 起止:{中(起)} 至 {中(截止)},算头不算尾共 {d} 天")
输出(f"{缩进} 算式:{本金:,.0f} × {名义利率:%} ÷ {除数} × {d} = {i:,.2f} 元")
return 总
def 截至已生息(止, 日利率):
return sum(计息(p, d, 止, 日利率)[1] for p, d, _ in 借款)
# ── 三联门槛:缺值/核定状态非"已核定"/依据空白,任一命中即停算 ──
演示用参数 = ("测算截止日", "LPR演示值") # 不设正式计算门槛(非正式计算参数)
def 门槛命中(p):
命中 = []
if p["值"] is None:
命中.append("缺值")
if p["状态"] != "已核定":
命中.append(f"核定状态为“{p['状态']}”(非“已核定”,仅填值不视为已核)")
if not str(p["依据"]).strip():
命中.append("依据空白")
return 命中
def 显状态(p):
return p["状态"] if str(p["状态"]).strip() else "(空白)"
def 显依据(p):
return p["依据"] if str(p["依据"]).strip() else "(空白)"
# ════════════════════════ 主流程 ════════════════════════
缺失 = [n for n in (诉状名, 证据名, 清单名) if not os.path.exists(os.path.join(BASE, n))]
if 缺失:
输出("【错误】以下输入文件缺失,拒绝在无依据下计算:")
for n in 缺失:
输出(f" - {n}")
with open(os.path.join(BASE, 结果名), "w", encoding="utf-8") as f:
f.write("\n".join(行) + "\n")
sys.exit(1)
诉状原文 = 读文本(os.path.join(BASE, 诉状名))
证据原文 = 读文本(os.path.join(BASE, 证据名))
清单原文 = 读文本(os.path.join(BASE, 清单名))
诉紧, 证紧, 清紧 = 紧(诉状原文), 紧(证据原文), 紧(清单原文)
截止 = date.today()
截止注 = "未填,取运行日(仅演示用)"
if isinstance(测算截止日["值"], date):
截止 = 测算截止日["值"]
截止注 = "参数区填写(仅演示用)"
elif 测算截止日["值"] is not None:
截止注 = "参数区所填非date类型,已忽略,取运行日(仅演示用)"
输出("利息计算报告(复核终稿版脚本自动生成)")
输出(f"运行日期:{date.today().isoformat()}")
输出(f"参数来源:本目录《{诉状名}》(计算参数);《{证据名}》《{清单名}》(全量核对)。")
输出("原则:缺值、核定状态非“已核定”、依据空白,任一命中即停算(仅填值不视为已核);"
"日期顺序违例停算;测算截止日早于5,000元付款日(2024-09-02)时不扣减、不倒算该款;"
"每个参数的核定状态与依据可核对;演示算例按显式假设、不设唯一口径;结果按序另存、不覆盖。")
输出()
# ── 一、文书参数读取、回显与核定状态 ──
输出(f"一、从《{诉状名}》读取的参数(自动匹配)")
借款 = []
本金项 = re.findall(r"以([\d,]+)元为基数自(\d{4})年(\d{1,2})月(\d{1,2})日起", 诉紧)
解析通过 = True
if len(本金项) != 3:
输出(f" ✗ 方案一本金项匹配到 {len(本金项)} 笔(应为3笔),本金参数不进入计算。")
解析通过 = False
else:
期望 = [("80,000", 2024, 3, 8), ("10,000", 2024, 3, 10), ("20,000", 2024, 3, 12)]
说明表 = {
"80,000": "银行转账2024-03-08,证据二",
"10,000": "现金交付2024-03-10(当事人陈述,证据七补强),证据一",
"20,000": "茶行账户转公司账户2024-03-12,证据五",
}
for 金额串, y, m, d in 本金项:
借款.append((Decimal(金额串.replace(",", "")), date(int(y), int(m), int(d)),
说明表.get(金额串, 金额串)))
for (金额串, y, m, d), (e金额, ey, em, ed) in zip(本金项, 期望):
ok = (金额串 == e金额 and (int(y), int(m), int(d)) == (ey, em, ed))
输出(f" {'✓' if ok else '✗'} 以{金额串}元为基数自{y}年{m}月{d}日起"
+ ("" if ok else f"(与预期 {e金额}元/{ey}-{em}-{ed} 不符)"))
if not ok:
解析通过 = False
if 解析通过 and 借款:
计息本金表["值"] = list(借款)
def 格式值(名称, p):
v = p["值"]
if v is None:
return "未填"
if 名称 == "本金三笔及起息日":
return ";".join(f"{a:,.0f}元@{b.isoformat()}" for a, b, _ in v)
if 名称 == "本金基数":
return f"{v:,.0f}元"
if 名称 in ("LPR年利率", "LPR演示值"):
return f"{v:%}"
if isinstance(v, date):
return v.isoformat() + ("(候选暂按)" if 名称 == "LPR起算日" else "")
return str(v)
输出(" 参数核定状态与来源一览(值/核定状态/依据为可填写工作记录;正式计算要求"
"状态为“已核定”且依据非空白,仅填值不视为已核):")
参数行 = [
("本金三笔及起息日", 计息本金表, f"《{诉状名}》诉请二(自动匹配,读取后仍须核定)"),
("计息方案", 计息方案, "参数区(承办律师核定)"),
("起诉日", 起诉日, "参数区(承办律师核定)"),
("利率口径", 利率口径, "参数区(清单第4项待定)"),
("抵充口径", 抵充口径, "参数区(清单第3项待定)"),
("3,000元性质", 三千元性质, "参数区(清单第8项待定)"),
("本金基数", 本金基数, "参数区(清单第3项两口径,不代推)"),
("展期效力", 展期效力, "参数区(清单第17项待定)"),
("LPR起算日", LPR起算日, "参数区(清单第5项、第17项;候选值暂按展期届满次日)"),
("LPR年利率", LPR年利率, "参数区(不联网代查)"),
("测算截止日", 测算截止日, f"{截止注}|当前取值 {截止.isoformat()}"),
("LPR演示值", LPR演示值, "沿用原第5轮脚本——演示用"),
]
for 名称, p, 源 in 参数行:
if 名称 in 演示用参数:
门槛预检 = "不入门槛(演示用)"
else:
n项 = len(门槛命中(p))
门槛预检 = "通过" if n项 == 0 else f"命中{n项}项(见第四节)"
输出(f" {名称}|值:{格式值(名称, p)}|核定状态:{显状态(p)}|依据:{显依据(p)}"
f"|门槛预检:{门槛预检}|来源:{源}")
输出(" · 核定状态与依据系可填写的工作记录,便于追溯,不构成法律授权证明;脚本不设签字或审批环节。")
输出()
# ── 二、互引检查(按实际文件名) ──
输出("二、互引检查(按实际文件名)")
定义项 = set(int(m) for m in re.findall(r"(?m)^(\d{1,2})\.", 清单原文))
互引全过 = True
引用集 = set()
for 来源, 紧t in (("起诉状", 诉紧), ("证据目录", 证紧), ("待核清单", 清紧)):
for name in re.findall(r"《([^》]+)》", 紧t):
引用集.add((来源, name))
for 来源, name in sorted(引用集):
if not re.search(r"\.(txt|py)$", name):
输出(f" · {来源}引用《{name}》——非文件引用(法律或文书名),不作文件核对")
continue
存在 = os.path.exists(os.path.join(BASE, name))
互引全过 = 互引全过 and 存在
输出(f" {'✓' if 存在 else '✗'} {来源}引用《{name}》" + ("" if 存在 else "——本目录无此文件"))
for 来源, 紧t in (("起诉状", 诉紧), ("证据目录", 证紧), ("待核清单", 清紧)):
for n in sorted(set(int(x) for x in re.findall(r"第(\d{1,2})项", 紧t))):
ok = n in 定义项
互引全过 = 互引全过 and ok
输出(f" {'✓' if ok else '✗'} {来源}引用清单第{n}项" + ("" if ok else "——清单中无此编号"))
输出()
# ── 三、证据状态、转写来源与文稿口径核对 ──
输出("三、证据状态、转写来源与文稿口径核对")
已收数 = len(re.findall(r"【已收", 证紧))
待补数 = len(re.findall(r"【待补", 证紧))
输出(f" {'✓' if 已收数 >= 5 else '✗'} 证据目录'已收'标注 {已收数} 处(应≥5)")
输出(f" {'✓' if 待补数 >= 6 else '✗'} 证据目录'待补'标注 {待补数} 处(应≥6)")
在卷图 = ["IMG_20261012_借条.jpg", "IMG_20240308_142240.jpg", "微信聊天长截图_栋哥.png",
"Screenshot_20251011_204501.jpg", "Screenshot_20251011_204530.jpg",
"IMG_20251011_203312.jpg"]
for f in 在卷图:
ok = f in 证紧
输出(f" {'✓' if ok else '✗'} 在卷图片名已载入证据目录:{f}")
来源核对 = [
("00:28–00:36", 清紧, "清单第8项:3,000元'拿不准'转写时间点已载"),
("非第三人转述", 清紧, "清单第8项:已核实系原告当场自述、非转述"),
("应该是茶叶钱", 清紧, "清单第8项并记原告'应该是茶叶钱'的事后判断(两处并存)"),
("00:57–01:03", 清紧, "清单第12项:证人出庭意愿转述之转写时间点已载"),
("可以帮我说话,但是不想去法院", 清紧, "清单第12项引转写原话"),
("00:57–01:03", 证紧, "证据七备注③载转述时间点"),
("可以帮我说话,但是不想去法院", 证紧, "证据七备注③引转写原话"),
("原告转述", 证紧, "证据七载明该节系原告转述(来源已核实)"),
("通话转写-原第2轮.txt", 清紧, "清单第18项载转写原件文件名"),
("未播放音频", 清紧, "清单注明本轮未播放音频"),
("不等于所转述内容的确认", 清紧, "清单第12项:转写记载存在≠所转述内容确认"),
("不等于所转述内容的确认", 证紧, "证据七③:转写记载存在≠所转述内容确认"),
("未校音", 清紧, "清单载明本轮未播放音频、未校音"),
("历史记录", 清紧, "回听校对注明系转写自带的历史记录、非本轮"),
("均系原告主张", 清紧, "清单第3项:总额与现金交付标注为原告主张"),
("不预设其内容", 清紧, "清单第13项:语音内容不预设"),
("同样未经证实", 清紧, "清单第12项:'拍胸脯'句注明未经证实"),
("原告主张为110,000元", 证紧, "证据一:借款总额标注原告主张"),
("原告主张其已交付", 诉紧, "起诉状:总额交付写作原告主张"),
("截图所见:显示时长48秒", 诉紧, "起诉状:语音只写截图所见48秒"),
]
for 片, 文, 说明 in 来源核对:
ok = 片 in 文
输出(f" {'✓' if ok else '✗'} {说明}")
撤回核对 = [
("证人现表示不愿出庭", 证紧, "证据目录不再写无出处的证人意愿定论"),
("来源不明", 清紧, "此前'来源不明'误判结论应已移除(转写原件已核实出处)"),
("转写文件未随卷", 清紧, "转写原件已提供,旧表述应已移除"),
("转述属实", 清紧, "'转述属实'不得用于确认所转述内容"),
("转述属实", 证紧, "'转述属实'不得用于确认所转述内容"),
("统一口径", 清紧, "'统一口径'已改为'核实事实并保留拿不准'"),
("按交易习惯有", 清紧, "'按交易习惯'的解释框架已交承办律师核定"),
("符合\u201c法定代表人", 清紧, "追加共同被告的法律构成认定已交承办律师"),
("内容未保存", 诉紧, "语音内容不作推测性表述"),
("被告仅回复一条48秒语音", 诉紧, "语音表述只写截图所见"),
]
撤回干净 = True
for 片, 文, 说明 in 撤回核对:
ok = 片 not in 文
撤回干净 = 撤回干净 and ok
输出(f" {'✓' if ok else '✗'} 已无'{片}'——{说明}")
输出()
# ── 四、正式计算:停算条件检查 ──
输出("四、正式计算")
未核 = []
def 收门槛(p, 名称):
命中 = 门槛命中(p)
if 命中:
未核.append(f"{名称}——" + ";".join(命中))
收门槛(计息本金表, "本金三笔及起息日(起诉状已自动读取,仍须核定)")
收门槛(计息方案, "计息方案(方案一/方案二)——起诉状诉请二,待承办律师核定")
收门槛(起诉日, "起诉日——起诉状'暂计至起诉之日',待核定")
方案 = 计息方案["值"]
值域 = []
if 方案 is not None and 方案 not in ("方案一", "方案二"):
值域.append(f"计息方案:值“{方案}”不在支持范围(方案一/方案二)")
起诉 = 起诉日["值"]
if 起诉 is not None and not isinstance(起诉, date):
值域.append("起诉日:值须为 date(年,月,日) 类型")
for 名称, p, 范围 in (("利率口径", 利率口径, ("月1%", "年10%")),
("抵充口径", 抵充口径, ("抵息", "抵本")),
("三千元性质", 三千元性质, ("茶叶货款", "还款")),
("展期效力", 展期效力, ("成立", "不成立"))):
if p["值"] is not None and p["值"] not in 范围:
值域.append(f"{名称}:值“{p['值']}”不在支持范围({'/'.join(范围)})")
if 本金基数["值"] is not None and (not isinstance(本金基数["值"], Decimal) or 本金基数["值"] <= 0):
值域.append("本金基数:值须为正的 Decimal,如 Decimal(\"110000\")")
if LPR起算日["值"] is not None and not isinstance(LPR起算日["值"], date):
值域.append("LPR起算日:值须为 date(年,月,日) 类型")
if LPR年利率["值"] is not None and (not isinstance(LPR年利率["值"], Decimal)
or not (0 < LPR年利率["值"] < 1)):
值域.append("LPR年利率:值须为 0–1 之间的 Decimal,如 Decimal(\"0.034\")")
if 方案 == "方案一":
收门槛(利率口径, "'一分'利率口径(月1%/年10%,仅为候选示例)——清单第4项,待定")
收门槛(抵充口径, "5,000元抵充口径(抵息/抵本)——清单第3项,待定")
if 抵充口径["值"] == "抵本":
未核.append("5,000元抵本时在三笔本金间的分配口径——材料未指明,须另行核定")
收门槛(三千元性质, "3,000元(2024-12-31)性质——清单第8项,待定")
if 三千元性质["值"] == "还款":
未核.append("3,000元认定还款后的抵减口径(抵息/抵本及分配)——须另行核定")
收门槛(本金基数, "诉请一本金基数——起诉状留【待核定】,本脚本不代推110,000元")
elif 方案 == "方案二":
收门槛(展期效力, "展期效力(成立/不成立)——清单第17项,LPR起算日以其为前提")
收门槛(LPR起算日, "LPR起算日(候选暂按展期届满次日,仍须核定)——清单第5项、第17项")
收门槛(LPR年利率, "起诉日适用的一年期LPR数值——待核定(本脚本不联网代查)")
收门槛(抵充口径, "5,000元抵充口径——方案二本金基数受其影响(清单第3项),未核不得默认105,000元")
收门槛(三千元性质, "3,000元性质——影响方案二本金基数(清单第8项),未核不得默认")
if 三千元性质["值"] == "还款":
未核.append("3,000元认定还款后的抵减口径——须另行核定")
收门槛(本金基数, "方案二本金基数——起诉状诉请一留【待核定】,本脚本不代推105,000元或其他数值")
未核.extend(值域)
# 日期顺序检查:起诉日早于起息日、方案二起诉日早于LPR起算日、截止日早于起息日——停算;
# 截止日早于LPR备选起算日不再全局阻断,仅约束方案二(此处)与LPR演示组合(第五节组合六)。
日期违例 = []
if isinstance(起诉, date):
for _, 起, _ in 借款:
if 起诉 < 起:
日期违例.append(f"起诉日 {起诉.isoformat()} 早于起息日 {起.isoformat()}")
lpr起暂 = LPR起算日["值"]
if 方案 == "方案二" and isinstance(lpr起暂, date) and 起诉 < lpr起暂:
日期违例.append(f"方案二:起诉日 {起诉.isoformat()} 早于LPR起算日 {lpr起暂.isoformat()}")
for _, 起, _ in 借款:
if 截止 < 起:
日期违例.append(f"测算截止日 {截止.isoformat()} 早于起息日 {起.isoformat()}")
for v in 日期违例:
未核.append("日期顺序错误(停算):" + v)
if 未核:
输出(f" 【中止】本轮实际状态:停算条件命中 {len(未核)} 项,正式计算不产出任何可填入诉请的金额:")
for i, s in enumerate(未核, 1):
输出(f" {i}. {s}")
输出(" 承办律师在参数区逐项填定值、核定状态“已核定”与依据(三者缺一仍停算),并消除日期"
"违例后重跑(结果另存为新文件),本节给出正式结果。")
else:
输出(" 【执行】参数区各项值、核定状态与依据齐备且日期顺序无误,正式计算如下:")
try:
if 方案 == "方案一" and 抵充口径["值"] == "抵息" and 三千元性质["值"] == "茶叶货款":
毛利 = 打明细(起诉, Decimal("0.01") if 利率口径["值"] == "月1%" else Decimal("0.10"),
"月" if 利率口径["值"] == "月1%" else "年", 缩进=" ")
if 起诉 >= 付款日5000:
净利 = 毛利 - Decimal("5000")
输出(f" 利息合计:{毛利:,.2f} 元;抵5,000元后净利息:{净利:,.2f} 元")
输出(f" 诉请填列:本金 {本金基数['值']:,.0f} 元+利息暂计 {净利:,.2f} 元"
f"={本金基数['值'] + 净利:,.2f} 元(截至 {中(起诉)})")
else:
输出(f" 起诉日 {起诉.isoformat()} 早于5,000元付款日 {付款日5000.isoformat()}:"
"该款于起诉日尚未支付,不扣减、不倒算,利息取全额:")
输出(f" 诉请填列:本金 {本金基数['值']:,.0f} 元+利息暂计 {毛利:,.2f} 元"
f"={本金基数['值'] + 毛利:,.2f} 元(截至 {中(起诉)})")
elif 方案 == "方案二":
lpr起 = LPR起算日["值"]
d = 天数(lpr起, 起诉)
i = 舍(本金基数["值"] * LPR年利率["值"] / 365 * d)
输出(f" 诉请填列:本金 {本金基数['值']:,.0f} 元+逾期利息 {i:,.2f} 元"
f"({中(lpr起)} 起按 LPR {LPR年利率['值']:%},共 {d} 天)")
else:
输出(" 该核定组合的自动计算路径未实现(如抵本分配、3,000元抵减),"
"请按核定口径人工复算或扩展本脚本。")
except ValueError as e:
输出(f" 【停算】{e}")
输出()
# ── 五、演示算例(非诉请金额) ──
截止在付款日前 = 截止 < 付款日5000
演示值显示 = f"{LPR演示值['值']:%}" if isinstance(LPR演示值["值"], Decimal) else "未填"
输出(f"五、演示算例(非诉请金额,不得填入文书;截止日 {中(截止)}——{截止注})")
输出(" 前置声明:")
输出(" · '一分'的月1%、年10%两种读法仅系候选理解示例(清单第4项待定),非穷尽、")
输出(" 非唯一口径;脚本不视其为唯一选项。")
输出(" · 抵息/抵本两口径并列,无默认(清单第3项);3,000元茶叶款/还款并列(第8项)。")
输出(" · 分配口径未定的组合一律不出数;抵本组合仅给'界限值'参考并标注非结果。")
输出(f" · 窗口规则:测算截止日{'早于' if 截止在付款日前 else '不早于'}5,000元付款日"
f"({付款日5000.isoformat()})——"
+ ("该款于截止日尚未支付:涉及组合不扣减该款、不倒算付款日前后数据。"
if 截止在付款日前 else "各组合按该款已支付处理。"))
输出(" · 通用假设④:截止日非起诉日;⑦:算头不算尾,各笔四舍五入至分后加总;")
输出(" 月1%按÷30、年10%按÷365折算(折算口径未统一,均为假设);")
输出(f" LPR演示值沿用原第5轮脚本所列 {演示值显示}(未经核定,不联网更新)。")
输出(" · 组合六的基数105,000元仅系沿用原第5轮脚本的演示假设——该基数取决于抵充等")
输出(" 未核口径,正式计算不采用、不代推。")
if not 解析通过:
输出(" 【停算】文书本金参数与预期不符(见第一节✗行),演示算例不出任何数字"
"(避免以未核对参数演算)。")
elif not 借款:
输出(" 【停算】文书本金参数未读取成功(见第一节),演示算例不出任何数字。")
elif 日期违例:
输出(" 【停算】存在日期顺序错误(见第四节末尾各项),演示算例不出任何数字。")
else:
lpr起 = LPR起算日["值"]
输出()
输出(" 组合一(月1%×抵息×3,000按茶叶款)——假设①②③④⑦齐备,可算:")
毛利A = 打明细(截止, Decimal("0.01"), "月")
if 截止在付款日前:
输出(f" 5,000元付款日 {付款日5000.isoformat()} 晚于测算截止日 {截止.isoformat()}:"
"该款尚未支付,本组合不扣减、不倒算,净利息=利息合计。")
输出(f" 利息合计:{毛利A:,.2f} 元(不扣减);本金+利息={Decimal('110000') + 毛利A:,.2f} 元"
"(演示合计,本金110,000元亦系演示假设)")
else:
净利A = 毛利A - Decimal("5000")
输出(f" 利息合计:{毛利A:,.2f} 元;抵息后净利息:{净利A:,.2f} 元;"
f"本金+净利息={Decimal('110000') + 净利A:,.2f} 元(演示合计,本金110,000元亦系演示假设)")
截至抵充日 = 截至已生息(付款日5000, Decimal("0.01") / 30)
输出(f" (算术注:截至{中(付款日5000)}已生息 {截至抵充日:,.2f} 元 ≥ 5,000 元,"
"抵充时点不影响本组合合计。)")
输出()
输出(" 组合二(月1%×抵息×3,000按还款)——【不出数】:3,000元抵减口径(抵息/抵本及分配)")
输出(" 未核定;核定后重算。")
输出()
输出(" 组合三(月1%×抵本)——【不出利息数】:5,000元在三笔本金间的扣减分配未核定。")
输出(f" 界限值参考(非结果):抵充前利息合计 {毛利A:,.2f} 元,任何抵本结果应低于此值。")
输出()
输出(" 组合四(年10%×抵息×3,000按茶叶款)——假设④⑤⑦,可算:")
毛利C = 打明细(截止, Decimal("0.10"), "年")
if 截止在付款日前:
输出(f" 利息合计:{毛利C:,.2f} 元(5,000元付款日在截止日之后,不扣减、不倒算)")
else:
输出(f" 利息合计:{毛利C:,.2f} 元;抵息后净利息:{毛利C - Decimal('5000'):,.2f} 元")
输出()
输出(" 组合五(年10%×抵本)——【不出利息数】:分配口径未核定;"
f"界限值参考(非结果):{毛利C:,.2f} 元。")
输出()
if not isinstance(lpr起, date):
输出(" 组合六(LPR备选,以展期效力核定为前提)——【不出数】:LPR起算日未填或非date类型。")
elif 截止 < lpr起:
输出(f" 组合六(LPR备选,以展期效力核定为前提)——【不出数】:测算截止日 {截止.isoformat()} "
f"早于LPR备选起算日 {lpr起.isoformat()},该组合不出数(其余组合不受影响)。")
elif not isinstance(LPR演示值["值"], Decimal):
输出(" 组合六(LPR备选,以展期效力核定为前提)——【不出数】:LPR演示值未填或非Decimal。")
else:
输出(" 组合六(LPR备选,以展期效力核定为前提)——假设④⑥⑦+基数演示假设,演示值可算:")
dD = 天数(lpr起, 截止)
iD = 舍(Decimal("105000") * LPR演示值["值"] / 365 * dD)
输出(f" 算式:105,000 × {LPR演示值['值']:%} ÷ 365 × {dD} = {iD:,.2f} 元"
f"({中(lpr起)} 起算;基数105,000元系演示假设,见前置声明)")
输出()
截止在年末前 = 截止 < date(2024, 12, 31)
if 截止在年末前:
输出(" 附注:参考日 2024-12-31 晚于测算截止日,不出该参考数据(不倒算);"
"以上任一组合若另涉3,000元被认定为还款,均需另行抵减重算。")
else:
截至年末 = 截至已生息(date(2024, 12, 31), Decimal("0.01") / 30)
输出(" 附注:以上任一组合若另涉3,000元被认定为还款,均需另行抵减重算;"
f"参考数据:截至{中(date(2024, 12, 31))}已生息 {截至年末:,.2f} 元(月利率1%口径)。")
输出()
# ── 六、三份文稿一致性抽查 ──
输出("六、三份文稿一致性抽查")
一致性 = [
("6214****3317", 诉紧, "起诉状载8万元收款账号尾号"),
("6214****3317", 证紧, "证据目录证据二载同一账号尾号"),
("2024年9月2日", 诉紧, "起诉状载5,000元还款日"),
("2024年9月2日", 证紧, "证据目录证据四载同一还款日"),
("19时32分", 证紧, "证据四载5,000元收款时刻"),
("22时47分", 诉紧, "起诉状载3,000元发起时刻"),
("22时47分", 证紧, "证据目录载同一发起时刻"),
("22时50分", 诉紧, "起诉状载3,000元收款时刻"),
("22时50分", 证紧, "证据目录载同一收款时刻"),
("2024年3月12日", 诉紧, "起诉状载2万元交付日"),
("2024年3月12日9时47分", 证紧, "证据五载同一日及时刻"),
("110,000元/105,000元", 清紧, "清单第3项列明两口径本金"),
("能否认定为自认", 证紧, "证据三第5项保留自认待定"),
("能否认定为自认", 清紧, "清单第12项与两稿口径一致"),
("的自认,待定", 诉紧, "起诉状对账段保留自认待定"),
("个体工商户", 诉紧, "起诉状主体类型待核"),
("个体工商户", 清紧, "清单第1项主体类型待核"),
("手指遮挡", 清紧, "清单第2项手指遮挡表述"),
("原告转述", 清紧, "清单第2项文三路系原告转述"),
("拿不准他啥意思", 清紧, "清单第8项保留原告原话"),
("好像有一笔,又好像没有", 清紧, "清单第11项保留原告原话"),
("好像有一笔,又好像没有", 诉紧, "起诉状保留原告原话"),
("拍胸脯说出了事他兜着", 清紧, "清单第12项保留咨询记录原话(原告陈述)"),
]
一致全过 = True
for 片, 文, 说明 in 一致性:
ok = 片 in 文
一致全过 = 一致全过 and ok
输出(f" {'✓' if ok else '✗'} {说明}")
输出()
# ── 七、口径与结果保存说明(按本轮实际状态输出) ──
输出("七、口径与结果保存说明")
if 未核:
输出(f" 1. 正式计算本轮中止(实际状态):停算条件命中 {len(未核)} 项——缺值/核定状态非"
"“已核定”/依据空白/日期顺序违例,逐项见第四节。参数区逐项填定值、核定状态"
"“已核定”与依据(三者缺一仍停算)后重跑(结果按序另存为新文件),本节随实际状态更新。")
else:
输出(" 1. 正式计算本轮已执行(实际状态):参数区各项值、核定状态与依据齐备且无日期顺序"
"违例,正式结果见第四节;重跑请在参数区更新并按序另存新结果文件。")
输出(" 2. 测算截止日或起诉日落在三笔借款后、5,000元付款日(2024-09-02)前时,不扣减该款、"
f"不倒算(本轮演示口径:{'已触发' if 截止在付款日前 else '未触发'},见第五节窗口规则行)。")
输出(" 3. 演示算例的假设见第五节前置声明与各组合标注;月1%/年10%非唯一口径;")
输出(" 组合六基数105,000元仅系演示假设。")
输出(" 4. 天数=两日期之差(算头不算尾);月÷30、年÷365两套折算并存,均为假设;")
输出(" 截止早于起算一律停算(天数函数含负值硬拦);截止早于LPR备选起算日仅约束")
输出(" 方案二与组合六,不再阻断其余演示组合。")
输出(f" 5. 本脚本只做算术与核对,不构成法律判断;待定事项以《{清单名}》")
输出(" 及承办律师决定为准。")
输出(f" 6. 本报告按序另存为《{结果名}》,未覆盖任何既有文件。")
输出()
状态行 = "正式计算:中止(存在未核参数/依据空白/日期违例)" if 未核 else "正式计算:已执行"
互引状态 = "互引检查:全部通过" if 互引全过 else "互引检查:存在未通过项"
一致状态 = "一致性抽查:全部通过" if 一致全过 else "一致性抽查:存在未通过项"
撤回状态 = "撤回检查:干净" if 撤回干净 else "撤回检查:存在残留"
输出(f"—— 报告完(生成:{date.today().isoformat()};{状态行};{互引状态};{一致状态};"
f"{撤回状态})——")
with open(os.path.join(BASE, 结果名), "w", encoding="utf-8") as f:
f.write("\n".join(行) + "\n")
if not (解析通过 and 互引全过 and 一致全过 and 撤回干净):
print("\n[存在未通过项,请核对上方 ✗ 行后修正文稿或脚本,再重跑]")
sys.exit(1)
print(f"\n[已按序另存 {os.path.join(BASE, 结果名)},未覆盖任何既有文件]")