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

283 lines
7.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 【新版本追踪系统 - 实施指南】
## 📋 概要
这是一个完整的修正版本追踪系统的实施方案,可以自动添加所需的数据库字段,并在应用启动时执行迁移。
---
## 🔧 已完成的变更
### 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. **部署到生产环境(建议先在测试环境验证)**
---
**如遇到问题,请查看应用日志并参考故障排除部分。**