package services import ( "context" "fmt" "tyapi-server/internal/domains/user/entities" "tyapi-server/internal/domains/user/repositories" "go.uber.org/zap" ) // ContractAggregateService 合同信息聚合服务接口 type ContractAggregateService interface { // 聚合根生命周期管理 CreateContract(ctx context.Context, enterpriseInfoID, userID, contractName string, contractType entities.ContractType, contractFileID, contractFileURL string) (*entities.ContractInfo, error) LoadContract(ctx context.Context, contractID string) (*entities.ContractInfo, error) SaveContract(ctx context.Context, contract *entities.ContractInfo) error DeleteContract(ctx context.Context, contractID string) error // 查询方法 FindByEnterpriseInfoID(ctx context.Context, enterpriseInfoID string) ([]*entities.ContractInfo, error) FindByUserID(ctx context.Context, userID string) ([]*entities.ContractInfo, error) FindByContractType(ctx context.Context, enterpriseInfoID string, contractType entities.ContractType) ([]*entities.ContractInfo, error) ExistsByContractFileID(ctx context.Context, contractFileID string) (bool, error) // 业务规则验证 ValidateBusinessRules(ctx context.Context, contract *entities.ContractInfo) error } // ContractAggregateServiceImpl 合同信息聚合服务实现 type ContractAggregateServiceImpl struct { contractRepo repositories.ContractInfoRepository logger *zap.Logger } // NewContractAggregateService 创建合同信息聚合服务 func NewContractAggregateService( contractRepo repositories.ContractInfoRepository, logger *zap.Logger, ) ContractAggregateService { return &ContractAggregateServiceImpl{ contractRepo: contractRepo, logger: logger, } } // ================ 聚合根生命周期管理 ================ // CreateContract 创建合同信息 func (s *ContractAggregateServiceImpl) CreateContract( ctx context.Context, enterpriseInfoID, userID, contractName string, contractType entities.ContractType, contractFileID, contractFileURL string, ) (*entities.ContractInfo, error) { s.logger.Debug("创建合同信息", zap.String("enterprise_info_id", enterpriseInfoID), zap.String("user_id", userID), zap.String("contract_name", contractName), zap.String("contract_type", string(contractType))) // 1. 检查合同文件ID是否已存在 exists, err := s.ExistsByContractFileID(ctx, contractFileID) if err != nil { return nil, fmt.Errorf("检查合同文件ID失败: %w", err) } if exists { return nil, fmt.Errorf("合同文件ID已存在") } // 2. 创建合同信息聚合根 contract, err := entities.NewContractInfo(enterpriseInfoID, userID, contractName, contractType, contractFileID, contractFileURL) if err != nil { return nil, fmt.Errorf("创建合同信息失败: %w", err) } // 3. 验证业务规则 if err := s.ValidateBusinessRules(ctx, contract); err != nil { return nil, fmt.Errorf("业务规则验证失败: %w", err) } // 4. 保存聚合根 err = s.SaveContract(ctx, contract) if err != nil { return nil, fmt.Errorf("保存合同信息失败: %w", err) } s.logger.Info("合同信息创建成功", zap.String("contract_id", contract.ID), zap.String("enterprise_info_id", enterpriseInfoID), zap.String("contract_name", contractName)) return contract, nil } // LoadContract 加载合同信息 func (s *ContractAggregateServiceImpl) LoadContract(ctx context.Context, contractID string) (*entities.ContractInfo, error) { s.logger.Debug("加载合同信息", zap.String("contract_id", contractID)) contract, err := s.contractRepo.FindByID(ctx, contractID) if err != nil { s.logger.Error("加载合同信息失败", zap.Error(err)) return nil, fmt.Errorf("加载合同信息失败: %w", err) } if contract == nil { return nil, fmt.Errorf("合同信息不存在") } return contract, nil } // SaveContract 保存合同信息 func (s *ContractAggregateServiceImpl) SaveContract(ctx context.Context, contract *entities.ContractInfo) error { s.logger.Debug("保存合同信息", zap.String("contract_id", contract.ID)) // 1. 验证业务规则 if err := s.ValidateBusinessRules(ctx, contract); err != nil { return fmt.Errorf("业务规则验证失败: %w", err) } // 2. 保存聚合根 err := s.contractRepo.Save(ctx, contract) if err != nil { s.logger.Error("保存合同信息失败", zap.Error(err)) return fmt.Errorf("保存合同信息失败: %w", err) } // 3. 发布领域事件 // TODO: 实现领域事件发布机制 // 4. 清除领域事件 contract.ClearDomainEvents() s.logger.Info("合同信息保存成功", zap.String("contract_id", contract.ID)) return nil } // DeleteContract 删除合同信息 func (s *ContractAggregateServiceImpl) DeleteContract(ctx context.Context, contractID string) error { s.logger.Debug("删除合同信息", zap.String("contract_id", contractID)) // 1. 加载合同信息 contract, err := s.LoadContract(ctx, contractID) if err != nil { return fmt.Errorf("加载合同信息失败: %w", err) } // 2. 调用聚合根方法删除 err = contract.DeleteContract() if err != nil { return fmt.Errorf("删除合同信息失败: %w", err) } // 3. 保存聚合根(软删除) err = s.SaveContract(ctx, contract) if err != nil { return fmt.Errorf("保存删除状态失败: %w", err) } s.logger.Info("合同信息删除成功", zap.String("contract_id", contractID)) return nil } // ================ 查询方法 ================ // FindByEnterpriseInfoID 根据企业信息ID查找合同 func (s *ContractAggregateServiceImpl) FindByEnterpriseInfoID(ctx context.Context, enterpriseInfoID string) ([]*entities.ContractInfo, error) { s.logger.Debug("根据企业信息ID查找合同", zap.String("enterprise_info_id", enterpriseInfoID)) contracts, err := s.contractRepo.FindByEnterpriseInfoID(ctx, enterpriseInfoID) if err != nil { s.logger.Error("查找合同失败", zap.Error(err)) return nil, fmt.Errorf("查找合同失败: %w", err) } return contracts, nil } // FindByUserID 根据用户ID查找合同 func (s *ContractAggregateServiceImpl) FindByUserID(ctx context.Context, userID string) ([]*entities.ContractInfo, error) { s.logger.Debug("根据用户ID查找合同", zap.String("user_id", userID)) contracts, err := s.contractRepo.FindByUserID(ctx, userID) if err != nil { s.logger.Error("查找合同失败", zap.Error(err)) return nil, fmt.Errorf("查找合同失败: %w", err) } return contracts, nil } // FindByContractType 根据合同类型查找合同 func (s *ContractAggregateServiceImpl) FindByContractType(ctx context.Context, enterpriseInfoID string, contractType entities.ContractType) ([]*entities.ContractInfo, error) { s.logger.Debug("根据合同类型查找合同", zap.String("enterprise_info_id", enterpriseInfoID), zap.String("contract_type", string(contractType))) contracts, err := s.contractRepo.FindByContractType(ctx, enterpriseInfoID, contractType) if err != nil { s.logger.Error("查找合同失败", zap.Error(err)) return nil, fmt.Errorf("查找合同失败: %w", err) } return contracts, nil } // ExistsByContractFileID 检查合同文件ID是否存在 func (s *ContractAggregateServiceImpl) ExistsByContractFileID(ctx context.Context, contractFileID string) (bool, error) { s.logger.Debug("检查合同文件ID是否存在", zap.String("contract_file_id", contractFileID)) exists, err := s.contractRepo.ExistsByContractFileID(ctx, contractFileID) if err != nil { s.logger.Error("检查合同文件ID失败", zap.Error(err)) return false, fmt.Errorf("检查合同文件ID失败: %w", err) } return exists, nil } // ================ 业务规则验证 ================ // ValidateBusinessRules 验证业务规则 func (s *ContractAggregateServiceImpl) ValidateBusinessRules(ctx context.Context, contract *entities.ContractInfo) error { // 1. 实体级验证 if err := contract.ValidateBusinessRules(); err != nil { return fmt.Errorf("实体级验证失败: %w", err) } // 2. 跨聚合根级验证 if err := s.validateCrossAggregateRules(ctx, contract); err != nil { return fmt.Errorf("跨聚合根级验证失败: %w", err) } // 3. 领域级验证 if err := s.validateDomainRules(ctx, contract); err != nil { return fmt.Errorf("领域级验证失败: %w", err) } return nil } // validateCrossAggregateRules 跨聚合根级验证 func (s *ContractAggregateServiceImpl) validateCrossAggregateRules(ctx context.Context, contract *entities.ContractInfo) error { // 检查合同文件ID唯一性(排除当前合同) if contract.ID != "" { exists, err := s.contractRepo.ExistsByContractFileIDExcludeID(ctx, contract.ContractFileID, contract.ID) if err != nil { return fmt.Errorf("检查合同文件ID唯一性失败: %w", err) } if exists { return fmt.Errorf("合同文件ID已存在") } } return nil } // validateDomainRules 领域级验证 func (s *ContractAggregateServiceImpl) validateDomainRules(ctx context.Context, contract *entities.ContractInfo) error { // 可以添加领域级别的业务规则验证 // 例如:检查企业是否已认证、检查用户权限等 return nil }