Files
tyapi-server/internal/domains/user/services/contract_aggregate_service.go
2025-07-28 01:46:39 +08:00

266 lines
9.0 KiB
Go
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.

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
}