Files
caiwuzongzhang/src/bank_importer/templates.py
T
腾讯WorkBuddy 763a940683 B-39: 数据库持久化与不可变导入
- 版本化 SQLite 迁移(向前/回滚)与连接助手。
- 导入管线:上传文件按 SHA-256 内容哈希不可变保存,文件/行/批次
  幂等;重复上传返回 duplicate 并复用已有批次,不产生第二份事实。
- 每条规范化源行反查文件、工作表、原始行号与模板版本。
- 解析失败保留 exception/failed 批次与诊断,不产生已确认交易。
- 决策记录见 docs/decisions/002-persistence.md。
2026-08-16 01:48:53 +08:00

180 lines
6.0 KiB
Python

from __future__ import annotations
from dataclasses import dataclass
import unicodedata
@dataclass(frozen=True)
class BankTemplate:
template_id: str
bank_name: str
columns: dict[str, tuple[str, ...]]
required: tuple[str, ...]
version: int = 1
def normalize_header(value: object) -> str:
if value is None:
return ""
text = unicodedata.normalize("NFKC", str(value)).strip().casefold()
return "".join(text.split())
def _aliases(*values: str) -> tuple[str, ...]:
return tuple(normalize_header(value) for value in values)
TEMPLATES: tuple[BankTemplate, ...] = (
BankTemplate(
template_id="citic-account-detail-v1",
bank_name="中信银行",
columns={
"transaction_date": _aliases("交易日期"),
"transaction_time": _aliases("交易时间"),
"counterparty_account": _aliases("对方账号"),
"counterparty_name": _aliases("对方账户名称"),
"counterparty_bank": _aliases("对方账号开户网点名称"),
"expense": _aliases("借方发生额"),
"income": _aliases("贷方发生额"),
"balance": _aliases("账户余额"),
"summary": _aliases("摘要"),
"purpose": _aliases("附言"),
"currency": _aliases("币种"),
"own_account": _aliases("交易账号"),
"reference": _aliases("柜员交易号", "发起方流水号"),
},
required=(
"transaction_date",
"transaction_time",
"counterparty_account",
"expense",
"income",
"balance",
),
),
BankTemplate(
template_id="abc-account-detail-v1",
bank_name="中国农业银行",
columns={
"transaction_at": _aliases("交易时间"),
"income": _aliases("收入金额"),
"expense": _aliases("支出金额"),
"balance": _aliases("账户余额"),
"counterparty_account": _aliases("对方账号"),
"counterparty_name": _aliases("对方户名"),
"counterparty_bank": _aliases("对方开户行"),
"summary": _aliases("摘要"),
},
required=(
"transaction_at",
"income",
"expense",
"balance",
"counterparty_account",
"counterparty_name",
"summary",
),
),
BankTemplate(
template_id="icbc-history-detail-v1",
bank_name="中国工商银行",
columns={
"reference": _aliases("凭证号"),
"own_account": _aliases("本方账号"),
"counterparty_account": _aliases("对方账号"),
"transaction_at": _aliases("交易时间"),
"expense": _aliases("借方发生额"),
"income": _aliases("贷方发生额"),
"summary": _aliases("摘要"),
"purpose": _aliases("用途"),
"counterparty_name": _aliases("对方单位名称"),
"balance": _aliases("余额"),
},
required=(
"reference",
"own_account",
"transaction_at",
"expense",
"income",
"counterparty_name",
"balance",
),
),
BankTemplate(
template_id="ccb-account-detail-v1",
bank_name="中国建设银行",
columns={
"own_account": _aliases("客户账号"),
"own_name": _aliases("账户名称"),
"transaction_at": _aliases("交易时间"),
"expense": _aliases("借方发生额(支取)"),
"income": _aliases("贷方发生额(收入)"),
"balance": _aliases("余额"),
"currency": _aliases("币种"),
"counterparty_name": _aliases("对方户名"),
"counterparty_account": _aliases("对方账号"),
"counterparty_bank": _aliases("对方开户机构"),
"summary": _aliases("摘要"),
"purpose": _aliases("备注"),
},
required=(
"own_account",
"transaction_at",
"expense",
"income",
"balance",
"counterparty_account",
),
),
BankTemplate(
template_id="henan-rural-history-v1",
bank_name="河南农商银行",
columns={
"transaction_at": _aliases("交易时间"),
"reference": _aliases("交易流水号"),
"income": _aliases("收入"),
"expense": _aliases("支出"),
"balance": _aliases("账户余额"),
"summary": _aliases("交易类型"),
"counterparty_account": _aliases("对方帐号"),
"counterparty_name": _aliases("对方户名"),
"counterparty_bank": _aliases("交易网点"),
"purpose": _aliases("备注"),
},
required=(
"transaction_at",
"reference",
"income",
"expense",
"balance",
"counterparty_account",
"counterparty_name",
),
),
BankTemplate(
template_id="bank-of-zhengzhou-detail-v1",
bank_name="郑州银行",
columns={
"transaction_at": _aliases("交易时间"),
"income": _aliases("收入金额(元)"),
"expense": _aliases("支出金额(元)"),
"balance": _aliases("账户余额(元)"),
"counterparty_name": _aliases("对方户名"),
"counterparty_account": _aliases("对方账号"),
"counterparty_bank": _aliases("对方账户开户行"),
"purpose": _aliases("用途"),
"summary": _aliases("摘要"),
"currency": _aliases("币种"),
"reference": _aliases("交易流水号"),
},
required=(
"transaction_at",
"income",
"expense",
"balance",
"counterparty_account",
"reference",
),
),
)