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

## 📋 概要

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

---

## 🔧 已完成的变更

### 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 查询优化

```python
# 旧方式（复杂）
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` 中的连接参数正确：

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

### 步骤 2：启动应用

```bash
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

================================================================================
✓ 自動遷移完成！
================================================================================
```

---

## 🔄 修正流程（新方式）

### 示例：修正一笔交易

**前端调用：**

```javascript
// 创建修正版本（引用原交易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` = `true`，`revision_count` = 2
3. ✅ 新交易的 `original_entry_id` = 123
4. ✅ 索引确保查询性能最优

---

## 📊 试算表查询优化

### 旧查询（复杂）

```sql
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  -- 排除已被修正的交易
```

### 新查询（简洁）

```sql
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` 用户身份运行：

```sql
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

**新参数：**

```json
{
    "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（新端点）

```json
// 响应
{
  "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. **部署到生产环境（建议先在测试环境验证）**

---

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