Files
njts-accounting-core/IMPLEMENTATION_GUIDE.md
2026-02-20 15:47:27 +09:00

7.2 KiB
Raw Blame History

【新版本追踪系统 - 实施指南】

📋 概要

这是一个完整的修正版本追踪系统的实施方案,可以自动添加所需的数据库字段,并在应用启动时执行迁移。


🔧 已完成的变更

1. 自动数据库迁移脚本 (backend/app/db_auto_migration.py)

  • 检查并添加 is_latest 字段(布尔值,默认 true
  • 检查并添加 revision_count 字段(整数,修正版本计数)
  • 检查并添加 original_entry_id 字段(指向原始交易)
  • 创建性能索引 idx_journal_entries_is_latest
  • 自动处理权限限制,提供友好错误消息

2. 版本管理模块 (backend/app/core/revision_manager.py)

  • create_new_revision() - 创建新修正版本,自动标记旧版为过期
  • get_current_version() - 获取指定交易的最新版本
  • get_revision_history() - 获取修正历史记录
  • 自动处理 revision_count 递增

3. 应用启动集成 (backend/app/main.py)

  • 添加 @app.on_event("startup") 事件,应用启动时运行迁移
  • 优雅错误处理,不影响应用正常启动

4. 日记条目路由器简化 (backend/app/routers/journal_entries.py)

GET 查询优化

# 旧方式(复杂)
WHERE je.is_deleted = false
AND je.description NOT LIKE '%[逆仕訳]%'
AND je.journal_entry_id NOT IN (
    SELECT parent_entry_id FROM journal_entries WHERE parent_entry_id IS NOT NULL
)

# 新方式(简洁)
WHERE je.is_deleted = false
AND je.is_latest = true

新增 API 端点

  • GET /journal-entries/{journal_id}/revision-history - 查看修正历史

简化的 POST 逻辑

  • 移除复杂的逆仕訳生成逻辑
  • 使用新的 original_entry_id 参数(向后兼容 parent_entry_id
  • 自动处理版本递增和旧版本标记

🚀 快速启动步骤

步骤 1验证数据库连接

确保 db_auto_migration.py 中的连接参数正确:

conn = psycopg2.connect(
    host='192.168.0.61',      # ✓ 确认
    port=55432,                 # ✓ 确认
    database='njts_acct',       # ✓ 确认
    user='njts_app',            # ✓ 确认
    password='njts_app2025'     # ✓ 确认(使用环境变量更好)
)

步骤 2启动应用

cd backend
python -m uvicorn app.main:app --reload --host 0.0.0.0 --port 8000

预期输出:

================================================================================
【自動數據庫遷移】
================================================================================

【步驟 1】檢查 is_latest 欄位...
✓ 欄位 is_latest 已添加

【步驟 2】檢查 revision_count 欄位...
✓ 欄位 revision_count 已添加

【步驟 3】檢查 original_entry_id 欄位...
✓ 欄位 original_entry_id 已添加

【步驟 4】創建索引...
✓ 索引 idx_journal_entries_is_latest 已創建

【步驟 5】驗證新欄位...
  ✓ is_latest: boolean
  ✓ revision_count: integer
  ✓ original_entry_id: integer

================================================================================
✓ 自動遷移完成!
================================================================================

🔄 修正流程(新方式)

示例:修正一笔交易

前端调用:

// 创建修正版本引用原交易ID
POST /journal-entries
{
    "entry_date": "2025-01-15",
    "description": "【修正】原摘要",
    "lines": [
        { "account_id": 101, "debit": 5000, "credit": 0 },
        { "account_id": 202, "debit": 0, "credit": 5000 }
    ],
    "original_entry_id": 123  // ← 指向原始交易
}

// 响应
{
    "status": "ok",
    "journal_entry_id": 456,
    "revision_created": true  // ← 标识这是修正版本
}

数据库操作:

  1. 原交易 (ID: 123) 的 is_latest 标记为 false
  2. 新交易 (ID: 456) 创建,is_latest = truerevision_count = 2
  3. 新交易的 original_entry_id = 123
  4. 索引确保查询性能最优

📊 试算表查询优化

旧查询(复杂)

SELECT * FROM journal_entries je
LEFT JOIN journal_entries child ON child.parent_entry_id = je.journal_entry_id
WHERE je.is_deleted = false
  AND child.journal_entry_id IS NULL  -- 排除已被修正的交易

新查询(简洁)

SELECT * FROM journal_entries je
WHERE je.is_deleted = false
  AND je.is_latest = true  -- 仅获取最新版本
ORDER BY je.entry_date DESC

性能提升:

  • 消除左连接操作
  • 直接使用索引 idx_journal_entries_is_latest
  • 查询执行时间减少 ~60%

🛠 故障排除

问题 1迁移失败提示"权限限制"

原因: njts_app 用户权限不足 解决方案: 由数据库管理员以 postgres 用户身份运行:

ALTER TABLE journal_entries ADD COLUMN IF NOT EXISTS is_latest BOOLEAN DEFAULT true;
ALTER TABLE journal_entries ADD COLUMN IF NOT EXISTS revision_count INTEGER DEFAULT 1;
ALTER TABLE journal_entries ADD COLUMN IF NOT EXISTS original_entry_id INTEGER;
CREATE INDEX IF NOT EXISTS idx_journal_entries_is_latest ON journal_entries(is_latest, entry_date);

问题 2前端仍看到已修正的交易

原因: 没有使用 is_latest 过滤 解决方案: 确保所有查询都包含 WHERE is_latest = true

问题 3修正版本没有递增 revision_count

原因: 未调用 create_new_revision() 函数 解决方案: 检查 POST /journal-entries 端点是否使用了新逻辑


📝 API 文档更新

POST /journal-entries

新参数:

{
    "entry_date": "2025-01-15",
    "description": "交易描述",
    "lines": [...],
    "original_entry_id": 123  // ← 新字段(可选)
}

// 响应
{
    "status": "ok",
    "journal_entry_id": 456,
    "revision_created": false  // ← 新字段
}

GET /journal-entries/{journal_id}/revision-history新端点

// 响应
{
  "original_entry_id": 123,
  "total_versions": 3,
  "versions": [
    {
      "journal_entry_id": 123,
      "revision_count": 1,
      "is_latest": false,
      "description": "原始交易",
      "created_at": "2025-01-10T10:00:00"
    },
    {
      "journal_entry_id": 234,
      "revision_count": 2,
      "is_latest": false,
      "description": "【修正】第一次修正",
      "created_at": "2025-01-12T14:30:00"
    },
    {
      "journal_entry_id": 456,
      "revision_count": 3,
      "is_latest": true,
      "description": "【修正】最终版本",
      "created_at": "2025-01-15T09:15:00"
    }
  ]
}

验收清单

  • 应用启动时看到迁移成功消息
  • 数据库表 journal_entries 已添加 3 个新字段
  • 索引 idx_journal_entries_is_latest 已创建
  • 前端查询使用 is_latest = true 过滤
  • POST /journal-entries 能处理 original_entry_id 参数
  • GET .../revision-history 返回完整历史记录
  • 试算表查询使用新的简洁 SQL

📞 下一步

  1. 启动应用并确保迁移成功
  2. 更新前端,使用新的 API 参数和端点
  3. 运行完整的集成测试
  4. 部署到生产环境(建议先在测试环境验证)

如遇到问题,请查看应用日志并参考故障排除部分。