v0.1
This commit is contained in:
266
internal/domains/user/services/contract_aggregate_service.go
Normal file
266
internal/domains/user/services/contract_aggregate_service.go
Normal file
@@ -0,0 +1,266 @@
|
||||
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
|
||||
}
|
||||
Reference in New Issue
Block a user