# 开票信息模板重构完成总结 ## 概述 成功创建了专门的开票信息模板表,将开票信息与开票申请进行了完全隔离,实现了更清晰的数据架构和更好的维护性。 ## 主要变更 ### 1. 数据库表结构 #### 新增表:`user_invoice_info` ```sql CREATE TABLE IF NOT EXISTS user_invoice_info ( id VARCHAR(36) PRIMARY KEY, user_id VARCHAR(36) NOT NULL UNIQUE, -- 开票信息字段 company_name VARCHAR(200) NOT NULL COMMENT '公司名称', taxpayer_id VARCHAR(50) NOT NULL COMMENT '纳税人识别号', bank_name VARCHAR(100) COMMENT '开户银行', bank_account VARCHAR(50) COMMENT '银行账号', company_address VARCHAR(500) COMMENT '企业地址', company_phone VARCHAR(20) COMMENT '企业电话', receiving_email VARCHAR(100) NOT NULL COMMENT '发票接收邮箱', -- 元数据 created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, deleted_at TIMESTAMP NULL, -- 索引 INDEX idx_user_id (user_id), INDEX idx_created_at (created_at), INDEX idx_updated_at (updated_at) ); ``` #### 修改表:`invoice_applications` - 移除了所有开票信息字段(`company_name`, `taxpayer_id`, `bank_name`, `bank_account`, `company_address`, `company_phone`, `receiving_email`) - 新增了 `user_invoice_info_id` 字段,用于关联用户开票信息 ### 2. 实体层变更 #### 新增实体:`UserInvoiceInfo` - 位置:`internal/domains/finance/entities/user_invoice_info.go` - 包含完整的开票信息字段 - 提供验证方法:`IsComplete()`, `IsCompleteForSpecialInvoice()`, `GetMissingFields()` #### 修改实体:`InvoiceApplication` - 移除了开票信息相关字段 - 新增 `UserInvoiceInfoID` 字段 - 更新了工厂方法 `NewInvoiceApplication` ### 3. 仓储层变更 #### 新增仓储接口:`UserInvoiceInfoRepository` - 位置:`internal/domains/finance/repositories/user_invoice_info_repository.go` - 提供基本的CRUD操作 #### 新增仓储实现:`GormUserInvoiceInfoRepository` - 位置:`internal/infrastructure/database/repositories/finance/user_invoice_info_repository_impl.go` - 基于GORM的实现 #### 修改仓储:`InvoiceApplicationRepository` - 移除了 `GetUserInvoiceInfo` 和 `UpdateUserInvoiceInfo` 方法 - 这些功能现在由专门的 `UserInvoiceInfoRepository` 处理 ### 4. 服务层变更 #### 新增服务:`UserInvoiceInfoService` - 位置:`internal/domains/finance/services/user_invoice_info_service.go` - 接口和实现放在同一个文件中 - 提供开票信息的管理功能 #### 修改服务:`InvoiceAggregateService` - 添加了 `UserInvoiceInfoRepository` 依赖 - 更新了 `ApplyInvoice` 方法,使用用户开票信息ID - 修改了事件发布逻辑,通过关联查询获取邮箱信息 ### 5. 应用服务层变更 #### 修改:`InvoiceApplicationService` - 添加了 `UserInvoiceInfoService` 依赖 - 更新了 `ApplyInvoice` 方法,从用户开票信息获取数据 - 更新了 `GetUserInvoiceInfo` 和 `UpdateUserInvoiceInfo` 方法 - 更新了 `GetUserInvoiceRecords` 方法,通过关联查询获取公司名称 #### 修改:`AdminInvoiceApplicationService` - 添加了 `UserInvoiceInfoRepository` 依赖 - 更新了 `GetPendingApplications` 方法,通过关联查询获取公司名称和邮箱 ### 6. 依赖注入配置 #### 更新容器配置:`container.go` - 添加了 `UserInvoiceInfoRepository` 的依赖注入 - 添加了 `UserInvoiceInfoService` 的依赖注入 - 更新了 `InvoiceAggregateService` 的依赖注入 - 更新了 `InvoiceApplicationService` 和 `AdminInvoiceApplicationService` 的依赖注入 - 为所有相关服务添加了正确的标签(`fx.ResultTags` 和 `fx.ParamTags`) ## 架构优势 ### 1. 数据隔离 - 开票信息与申请记录完全分离 - 避免了数据冗余和不一致问题 - 提高了数据完整性 ### 2. 更好的维护性 - 开票信息的变更不会影响历史申请记录 - 可以独立管理开票信息的生命周期 - 便于后续功能扩展 ### 3. 性能优化 - 减少了数据冗余 - 提高了查询效率 - 更好的索引策略 ### 4. 业务逻辑清晰 - 开票信息管理有专门的服务 - 申请流程更加清晰 - 便于实现复杂的业务规则 ## 数据流程 ### 1. 用户设置开票信息 ``` 用户填写开票信息 → UserInvoiceInfoService.CreateOrUpdateUserInvoiceInfo → UserInvoiceInfoRepository.Save ``` ### 2. 用户申请开票 ``` 用户申请开票 → InvoiceApplicationService.ApplyInvoice → 获取用户开票信息 → 创建申请记录(关联开票信息ID) ``` ### 3. 管理员处理申请 ``` 管理员处理申请 → 通过关联查询获取开票信息 → 处理申请 → 发送邮件 ``` ## 兼容性 ### 1. API接口保持不变 - 前端API调用方式无需修改 - 响应数据结构保持一致 - 向后兼容 ### 2. 数据库迁移 - 需要执行新的迁移脚本创建 `user_invoice_info` 表 - 需要迁移现有数据(如果有的话) - 需要更新 `invoice_applications` 表结构 ## 后续工作 ### 1. 数据库迁移 - 执行 `000002_create_user_invoice_info_table.sql` 创建新表 - 编写数据迁移脚本(如果需要) ### 2. 测试验证 - 单元测试 - 集成测试 - 端到端测试 ### 3. 文档更新 - API文档更新 - 数据库设计文档更新 - 开发指南更新 ## 总结 通过这次重构,我们成功实现了开票信息与开票申请的完全隔离,建立了更清晰的数据架构。新的设计具有更好的可维护性、扩展性和性能,同时保持了API的向后兼容性。这为后续的功能扩展和优化奠定了良好的基础。