MRobot/FINANCE_IMPORT_FIX.md
2025-11-25 17:26:46 +08:00

6.5 KiB
Raw Blame History

导入账户查询问题 - 解决方案文档

🐛 问题描述

用户反馈:导入的账户无法进行查询操作。

问题表现

  1. 账户成功导入UI显示导入成功
  2. 账户出现在账户列表中
  3. 但是使用查询功能时无法显示结果
  4. 做账页面也可能无法显示导入账户的记录

🔍 根本原因

问题源于 import_account_package 方法中的两个bug

Bug #1: 元数据ID不同步

问题流程:
1. ZIP包中存储原始账户ID (例如: f78adb43-cf2c-49be-8e36-361908db6d68)
2. 导入时如果账户已存在创建新ID (例如: 1c4b2c9f-1629-463d-b7a0-cbcff93c99)
3. 新ID用于创建文件夹
4. 但metadata.json中的ID仍然是原始ID
5. 加载时,目录名(新ID)与metadata中的ID(原始ID)不匹配
6. load_all_accounts() 无法正确识别账户

Bug #2: UI刷新不完整

问题流程:
1. 导入后只调用 refresh_account_list()
2. 但没有设置导入账户为当前选中账户
3. 用户可能仍在查看旧账户的数据
4. 查询页面没有被清空

解决方案

修复1: 同步metadata中的账户ID

文件: app/tools/finance_manager.py

修改:

def import_account_package(self, zip_path: str) -> Optional[str]:
    """导入账户压缩包返回导入的账户ID"""
    try:
        zip_path = Path(zip_path)
        if not zip_path.exists():
            return None
        
        # 先加载元数据以获取账户ID
        with zipfile.ZipFile(zip_path, 'r') as zipf:
            metadata_content = zipf.read('metadata.json')
            metadata = json.loads(metadata_content)
            account_id = metadata['id']
        
        # 如果账户已存在创建新ID
        if account_id in self.accounts:
            account_id = str(uuid.uuid4())
            # ✅ 关键修复: 更新元数据中的ID
            metadata['id'] = account_id
        
        # 解压到临时目录
        temp_dir = self.data_root / f"_temp_{uuid.uuid4()}"
        with zipfile.ZipFile(zip_path, 'r') as zipf:
            zipf.extractall(temp_dir)
        
        # ✅ 关键修复: 更新临时目录中的元数据文件
        metadata_file = temp_dir / 'metadata.json'
        with open(metadata_file, 'w', encoding='utf-8') as f:
            json.dump(metadata, f, ensure_ascii=False, indent=2)
        
        # 移动到正式目录
        account_dir = self._get_account_dir(account_id)
        if account_dir.exists():
            shutil.rmtree(account_dir)
        
        shutil.move(str(temp_dir), str(account_dir))
        
        # 重新加载账户
        self.load_all_accounts()
        return account_id
    except Exception as e:
        print(f"导入账户出错: {e}")
        return None

修复2: 完整的UI刷新流程

文件: app/finance_interface.py

修改:

def import_account(self):
    """导入账户ZIP包"""
    zip_file, _ = QFileDialog.getOpenFileName(
        self, "选择要导入的账户文件",
        "", "ZIP文件 (*.zip)"
    )
    
    if zip_file:
        account_id = self.finance_manager.import_account_package(zip_file)
        if account_id:
            # ✅ 关键修复: 刷新账户列表
            self.refresh_account_list()
            
            # ✅ 关键修复: 找到新导入的账户并设置为当前账户
            for i in range(self.account_combo.count()):
                if self.account_combo.itemData(i) == account_id:
                    self.account_combo.setCurrentIndex(i)
                    break
            
            # ✅ 关键修复: 清空查询结果以显示新导入账户的数据
            self.query_result_table.setRowCount(0)
            
            InfoBar.success("账户导入成功", "", duration=2000, parent=self)
        else:
            QMessageBox.warning(self, "错误", "导入账户失败")

修复3: 账户切换时清空查询结果

文件: app/finance_interface.py

修改:

def on_account_changed(self):
    """账户改变时刷新显示"""
    account_id = self.get_current_account_id()
    if account_id:
        self.refresh_records_display()
        # ✅ 关键修复: 切换账户时清空查询结果
        self.query_result_table.setRowCount(0)

🧪 验证

运行测试脚本 test_import_query.py 验证修复:

python test_import_query.py

预期输出:

✅ 找到有数据的测试账户: '测试账户'
✅ 导出成功
✅ 导入成功
✅ 导入的账户信息: 名称: 测试账户, 交易数: 1
✅ 无条件查询: 1 条记录
✅ 按交易人'测试商家'查询: 1 条记录

📝 使用流程

修复后,导入账户的完整流程:

  1. 打开财务做账模块

    • 点击左侧"财务做账"导航
  2. 点击"导出"标签页

    • 选择要导入的ZIP文件
    • 点击"导入账户"按钮
  3. 验证导入结果

    • 新账户自动出现在账户列表中
    • 新账户自动设置为当前选中账户
    • 做账页显示导入的交易记录
    • 可以立即在查询页进行查询

🔧 技术细节

数据结构

assets/Finance_Data/
└── accounts/
    └── [账户ID]/
        ├── metadata.json          ← 关键: ID必须与文件夹名一致
        └── [交易ID]/
            ├── data.json
            ├── invoice/
            ├── payment/
            └── purchase/

关键对象关系

FinanceManager.accounts = {
    '账户ID': Account(...),
    ...
}

Account.id ↔ 文件夹名称 ↔ metadata.json中的id

加载流程

load_all_accounts()
  ├─ 遍历 accounts/ 目录
  ├─ 加载每个目录下的 metadata.json
  ├─ 使用 metadata['id'] 作为关键字
  └─ 如果ID与文件夹名不匹配 → 账户加载失败

⚠️ 重要提醒

  1. ID一致性: 账户ID必须在三个地方一致

    • 文件夹名称
    • metadata.json中的id字段
    • FinanceManager.accounts字典的键
  2. 元数据更新: 创建新ID时必须更新元数据文件

  3. 重新加载: 导入后必须调用load_all_accounts()刷新内存中的账户

📊 测试结果

测试项 修复前 修复后
账户导入 成功 成功
账户识别 失败 成功
数据查询 无结果 正常
UI更新 不完整 完整
做账显示 无数据 显示数据

更新日期: 2025-11-25

修复状态: 完成

测试状态: 通过

生产准备: 就绪