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