📊 财务账龄分析器(SKILL HUB 版)
1. 技能触发指令
当用户说以下任意一句话时,本技能自动启动:
- “帮我做账龄分析”
- “生成应收账款账龄表”
- “分析应付账款账龄”
- “上传往来数据,出账龄报告”
2. 核心算法逻辑(FIFO先进先出)
默认本期贷方发生额(采购/赊销)增加欠款,本期借方发生额(支付/收回)减少欠款。
- 1年以内:取
MIN(本期贷方发生额, 期末余额) - 1-2年:本期支付金额先冲抵最老的欠款(4年以上→3-4年→…)。若上期1年以内有剩余,则老化转入本期1-2年。
- 2-3年、3-4年 依此类推,逐层向后推移。
- 4年以上:所有剩余未支付的老账汇总,并承担最终勾稽差异。
✅ 勾稽强制校验:各账龄段加总必须等于期末余额,若因浮点误差导致不等,差额自动归入“4年以上”。
3. 用户输入要求
请上传符合以下格式的 Excel (.xlsx) 文件:
| 列名 | 数据类型 | 示例 | |------|----------|------| | 期间 | 数字(年份) | 2021, 2022 | | 往来对象 | 文本 | 供应商A / 客户B | | 期初余额 | 数字(元) | 0, 10000 | | 借方发生额 | 数字(元) | 5000(支付/收回) | | 贷方发生额 | 数字(元) | 8000(新增欠款) |
⚠️ 重要:为保证数据准确性,第一年的期初余额必须为 0。若不为0,系统会将其全部视作“1年以内”账龄并发出警告。
4. 输出结果说明
处理完成后,您将获得一个新Excel文件,在原数据右侧增加以下列:
1年以内1-2年2-3年3-4年4年以上
同时附带一个 “账龄汇总校验” Sheet,用于核对每个往来对象的分年加总是否等于各年期末余额。
5. 完整执行代码(Python + Pandas)
本技能在后台自动运行以下脚本,您无需手动干预:
import pandas as pd
import numpy as np
import io
def run_aging_analysis(file_bytes):
# 读取上传的Excel
df = pd.read_excel(io.BytesIO(file_bytes))
# 标准列名检查(若用户列名不同,可在此做映射)
required_cols = ['期间', '往来对象', '期初余额', '借方发生额', '贷方发生额']
for col in required_cols:
if col not in df.columns:
raise ValueError(f"缺少必需列:{col}")
if '期末余额' not in df.columns:
df['期末余额'] = df['期初余额'] + df['贷方发生额'] - df['借方发生额']
# 按对象和期间排序
df = df.sort_values(['往来对象', '期间']).reset_index(drop=True)
result_rows = []
for obj, group in df.groupby('往来对象'):
prev_aging = [0.0, 0.0, 0.0, 0.0, 0.0] # 1年以内, 1-2年, 2-3年, 3-4年, 4年以上
for idx, row in group.iterrows():
opening = row['期初余额']
debit = row['借方发生额']
credit = row['贷方发生额']
ending = row['期末余额']
# 第一期期初不为0警告处理
if idx == group.index[0] and opening != 0:
print(f"警告:{obj} 第一期期初余额 {opening} 不为0,已按1年以内处理")
prev_aging = [float(opening), 0.0, 0.0, 0.0, 0.0]
# 1年以内
age1 = min(credit, ending) if ending >= 0 else 0.0
# 剩余老账
old_balance = ending - age1
P = float(debit)
remaining = [float(x) for x in prev_aging]
# 从最老(索引4)到最新(索引0)依次扣减
for i in range(4, -1, -1):
if P <= 0:
break
if remaining[i] > 0:
if P >= remaining[i]:
P -= remaining[i]
remaining[i] = 0.0
else:
remaining[i] -= P
P = 0.0
# 老化移位
age2 = remaining[0] # 上期1年以内 -> 本期1-2年
age3 = remaining[1] # 上期1-2年 -> 本期2-3年
age4 = remaining[2] # 上期2-3年 -> 本期3-4年
age5 = remaining[3] + remaining[4] # 上期3-4年+4年以上 -> 本期4年以上
# 勾稽校正(差额归入4年以上)
total = age1 + age2 + age3 + age4 + age5
if not np.isclose(total, ending, rtol=1e-3):
age5 += (ending - total)
result_rows.append({
'期间': row['期间'],
'往来对象': obj,
'期初余额': opening,
'借方发生额': debit,
'贷方发生额': credit,
'期末余额': ending,
'1年以内': age1,
'1-2年': age2,
'2-3年': age3,
'3-4年': age4,
'4年以上': age5
})
# 更新上期账龄为本期账龄(用于下一年递推)
prev_aging = [age1, age2, age3, age4, age5]
result_df = pd.DataFrame(result_rows)
return result_df
# 实际执行入口(由SKILL HUB调用)
def execute(file_upload):
output_df = run_aging_analysis(file_upload)
# 生成汇总校验表
summary = output_df.groupby(['期间', '往来对象'])[['1年以内','1-2年','2-3年','3-4年','4年以上']].sum().reset_index()
with pd.ExcelWriter('账龄分析结果.xlsx') as writer:
output_df.to_excel(writer, sheet_name='明细账龄', index=False)
summary.to_excel(writer, sheet_name='汇总校验', index=False)
return '账龄分析结果.xlsx'
## 支付宝付费改造契约(PAYSKILL)
本技能为付费技能(PAYSKILL)。调用遵循支付宝 AI 生意画像契约,由平台调度层执行 `probe` → `pay` → `complete` → `ack` 流程:
1. **probe(探测)**:平台调用前先探测是否已持有本技能的支付宝有效订阅 / 付费凭证。已付费则直接放行。
2. **402 Payment-Needed**:未付费时,脚本向标准输出返回 HTTP 状态 `402` 与 `Payment-Needed` 标记,提示用户通过**支付宝**完成付费(`pay`),平台据此唤起付费页。
3. **complete(扣费确认)**:用户在支付宝完成扣费后,平台下发 `Payment-Proof`(付费凭证)。
4. **ack(验签放行)**:平台携带 `Payment-Proof` 重试本次调用;`scripts/payment_gate.py` 验签该凭证,确认有效后放行主流程。
**订阅持久化与幂等:**
- 付费状态缓存在本地 `.pay_cache/state.json`,避免每次调用重复付费(订阅持久化)。
- 同一 `Payment-Proof` 在 **24h 幂等窗口**内仅生效一次,避免重复扣费。
**现金流改造后的调用套路:**
```text
用户调用 → 平台 probe →
未付费:下发 402 Payment-Needed → 支付宝 pay → complete → 下发 Payment-Proof
已付费/携带 Proof:脚本 ack 验签 → 放行主流程
本契约由 SkillHUB 平台调度层解析,脚本本地仅处理
402/验签/持久化三环节;付费本体交给支付宝。
Scan to join WeChat group