9.1 KiB
9.1 KiB
【新版本追踪系統 - 完整變更摘要】
實施日期: 2025 年初
系統: 日記條目修正追踪
狀態: 準備就緒,等待部署
📊 高层视图
這次更新實現了一個完整的修正版本追踪系統,用來替代舊的複雜逆仕訳邏輯。
Before(舊系統)
原始交易 (ID: 123) ──→ 逆仕訳 (ID: 456) ──→ 修正交易 (ID: 789)
[複雜 parent_entry_id 追踪]
After(新系統)
原始交易 (ID: 123, revision_count: 1, is_latest: false, original_entry_id: NULL)
↓
修正版本 (ID: 234, revision_count: 2, is_latest: false, original_entry_id: 123)
↓
最終版本 (ID: 345, revision_count: 3, is_latest: true, original_entry_id: 123)
🔧 技術變更詳情
1. 数据库表结构 (journal_entries)
新增三個欄位
| 欄位名 | 類型 | 預設值 | 用途 |
|---|---|---|---|
is_latest |
BOOLEAN | true | 標記是否為最新版本 |
revision_count |
INTEGER | 1 | 版本編號(1=原始,2+=修正) |
original_entry_id |
INTEGER | NULL | 指向原始交易的ID |
新增索引
-- 用於快速查詢最新交易(試算表經常使用)
CREATE INDEX idx_journal_entries_is_latest ON journal_entries(is_latest, entry_date DESC);
-- 用於快速查詢修正歷史
CREATE INDEX idx_journal_entries_original_id ON journal_entries(original_entry_id);
2. 後端代碼變更
文件結構
backend/app/
├── db_auto_migration.py [新增] 自動遷移腳本
├── core/
│ └── revision_manager.py [新增] 版本管理模塊
├── routers/
│ └── journal_entries.py [修改] 簡化為使用新系統
└── main.py [修改] 添加啟動事件運行遷移
核心函數
revision_manager.py:
# 創建新修正版本(自動標記舊版本過時)
create_new_revision(
conn,
entry_date,
description,
fiscal_year,
lines,
created_by="system",
original_entry_id=None
) → int # 返回新交易的 ID
# 獲取修正歷史
get_revision_history(conn, original_entry_id) → list
# 獲取當前版本
get_current_version(conn, journal_entry_id) → dict
journal_entries.py 路由變更:
# POST /journal-entries 簡化
@router.post("")
def create_journal_entry(req: JournalEntryRequest):
# 使用 revision_manager.create_new_revision()
# 自動處理版本遞增和標記
# GET /journal-entries 優化
@router.get("")
def get_journal_entries(...):
# 新方式: WHERE is_latest = true
# 舊方式: 複雜的 parent_entry_id 檢查和 NOT IN 子查詢
# 新增修正歷史端點
@router.get("/{journal_id}/revision-history")
def get_revision_history(journal_id: int):
# 返回指定交易的所有版本
3. SQL 查詢優化
試算表查詢
舊方式(複雜,低效):
SELECT je.* 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 -- 排除已被修正的交易
AND je.description NOT LIKE '%[逆仕訳]%' -- 排除逆仕訳
- ❌ 消耗資源:LEFT JOIN + NOT IN 子查詢
- ❌ 性能:需要掃描所有記錄查找修正
- ❌ 複雜:邏輯散布在多個條件中
新方式(簡潔,高效):
SELECT je.* FROM journal_entries je
WHERE je.is_deleted = false
AND je.is_latest = true
- ✅ 高效:直接使用索引
idx_journal_entries_is_latest - ✅ 簡潔:單一條件
- ✅ 明確:語意清晰
性能提升預估:
- 查詢時間: -60% ~ -80%
- 資源消耗: -70%
- 索引使用效率: +100%(直接索引掃描)
🔄 工作流程 - 修正一筆交易
場景:需要修正交易 ID 123
1. 前端調用
POST /journal-entries
{
entry_date: "2025-01-15",
description: "【修正】銷售收入",
lines: [
{ account_id: 101, debit: 10000, credit: 0 },
{ account_id: 202, debit: 0, credit: 10000 }
],
original_entry_id: 123 // ← 新參數
}
2. 後端處理
# POST /journal-entries 端點
entry_id = create_new_revision(
conn=conn,
entry_date=date(2025, 1, 15),
description="【修正】銷售收入",
fiscal_year=2025,
lines=[...],
original_entry_id=123
)
# create_new_revision() 內部操作:
# 1. 查詢交易 123 的當前 revision_count(假設為 1)
# 2. 標記交易 123: is_latest = false
# 3. 創建新交易:
# - journal_entry_id = 456
# - revision_count = 2
# - is_latest = true
# - original_entry_id = 123
# 4. 返回 456
3. 前端收到回應
{
"status": "ok",
"journal_entry_id": 456,
"revision_created": true
}
4. 試算表查詢
# 舊行為:只看交易 123(找不到因為已被標記為過時)
# 新行為:只看交易 456(因為 is_latest = true)
SELECT * FROM journal_entries
WHERE is_deleted = false AND is_latest = true
# 結果:包括交易 456,不包括交易 123
5. 修正歷史查詢
GET /journal-entries/456/revision-history
# 結果:
# [
# {journal_entry_id: 123, revision_count: 1, is_latest: false, ...},
# {journal_entry_id: 456, revision_count: 2, is_latest: true, ...}
# ]
📁 文件清單
新增文件
| 文件 | 用途 | 大小 |
|---|---|---|
backend/app/db_auto_migration.py |
自動遷移腳本 | ~2.5KB |
backend/app/core/revision_manager.py |
版本管理核心模塊 | ~4KB |
backend/sql/migration_revision_tracking_manual.sql |
手動 SQL 遷移 | ~2KB |
test_environment.py |
環境驗證工具 | ~3KB |
IMPLEMENTATION_GUIDE.md |
實施指南 | ~6KB |
修改文件
| 文件 | 變更內容 | 影響範圍 |
|---|---|---|
backend/app/main.py |
添加啟動事件運行遷移 | 應用初始化 |
backend/app/routers/journal_entries.py |
簡化後端邏輯,整合新系統 | 所有日記條目操作 |
未修改文件
(其他所有文件保持不變)
✅ 遷移驗收清單
前置條件
- 已備份生產數據庫
- 已準備回滾計劃
- 已通知相關用户
技術驗收
- 自動遷移腳本無語法錯誤
- 新字段已添加到
journal_entries表 - 索引已創建並可用
- 後端代碼編譯無誤
功能驗收
- 應用啟動時自動運行遷移
- 可成功創建新交易
- 可成功創建修正版本(original_entry_id 有效)
- 試算表查詢僅顯示
is_latest = true的交易 - 修正歷史端點返回完整版本列表
性能驗收
- 試算表查詢響應時間 < 500ms(50000+ 記錄)
- 索引命中率 > 95%
- 無慢查詢告警
用户驗收
- 前端修正流程正常工作
- 已修正的交易不再出現在主列表中
- 用户可查看修正歷史記錄
🎯 已解決的問題
❌ 舊系統問題
-
複雜的逆仕訳邏輯
- 需要生成對沖交易
- 難以追踪修正歷史
- 用户容易混淆
-
低效的試算表查詢
- 使用 LEFT JOIN + NOT IN 子查詢
- 需要掃描大量記錄
- 性能隨着數據增長而惡化
-
修正版本管理困難
- 沒有清晰的版本編號
- 無法區分原始交易與修正版本
- 修正歷史散亂,難以查詢
✅ 新系統優勢
-
清晰的版本追踪
- 每個版本都有唯一的 revision_count
- is_latest 標誌明確標記當前版本
- original_entry_id 清楚指向原始交易
-
高效的查詢性能
- 直接使用索引查詢
- 簡單明需的 SQL 條件
- 性能與數據量無關
-
更好的用户體驗
- 修正流程更直觀
- 可查看完整的修正歷史
- 不需要理解複雜的逆仕訳概念
🚀 部署計劃
第 1 階段:準備(立即)
1. 備份生產數據庫
2. 在測試環境驗證遷移
3. 准備回滾計劃
第 2 階段:部署(確認後)
1. 更新應用代碼
2. 重啟應用(自動運行遷移)
3. 驗證遷移成功
4. 運行集成測試
第 3 階段:驗證(部署後)
1. 檢查應用日誌
2. 測試核心功能
3. 驗證性能指標
4. 通知相關團隊
📞 支持與聯系
如有疑問或遇到問題,請參考:
所有文件已準備就緒,可隨時部署。