This commit is contained in:
2026-05-01 15:35:48 +08:00
parent 354856360b
commit 27f0e47162
4 changed files with 102 additions and 23 deletions

View File

@@ -1388,6 +1388,15 @@ func (s *CertificationApplicationServiceImpl) generateAndAddContractFile(
s.logger.Info("合同生成-步骤1-开始填充合同模板", s.logger.Info("合同生成-步骤1-开始填充合同模板",
zap.String("user_id", cert.UserID), zap.String("user_id", cert.UserID),
zap.String("company_name", companyName)) zap.String("company_name", companyName))
// 协议编号:已有则复用,否则新生成
if cert.ContractCode == "" {
cert.SetContractCode(user_entities.GenerateContractCode(user_entities.ContractTypeCooperation))
}
agreementNo := cert.ContractCode
signDate := time.Now().Format("2006年01月02日")
// 控件 key 与 e 签宝合同模板中控件名一致(新合同) // 控件 key 与 e 签宝合同模板中控件名一致(新合同)
fileComponent := map[string]string{ fileComponent := map[string]string{
"jfqym": companyName, "jfqym": companyName,
@@ -1395,6 +1404,12 @@ func (s *CertificationApplicationServiceImpl) generateAndAddContractFile(
"jfsqdb": authorizedRepName, "jfsqdb": authorizedRepName,
"jftyshxydm": unifiedSocialCode, "jftyshxydm": unifiedSocialCode,
"jflxdz": enterpriseAddress, "jflxdz": enterpriseAddress,
// 甲方
"xybh": agreementNo,
"qsrq1": signDate,
"qsrq3": signDate,
// 乙方
"qsrq2": signDate,
} }
fillTemplateResp, err := s.esignClient.FillTemplate(fileComponent) fillTemplateResp, err := s.esignClient.FillTemplate(fileComponent)
if err != nil { if err != nil {
@@ -1403,7 +1418,8 @@ func (s *CertificationApplicationServiceImpl) generateAndAddContractFile(
} }
s.logger.Info("合同生成-步骤1-模板填充成功", s.logger.Info("合同生成-步骤1-模板填充成功",
zap.String("user_id", cert.UserID), zap.String("user_id", cert.UserID),
zap.String("file_id", fillTemplateResp.FileID)) zap.String("file_id", fillTemplateResp.FileID),
zap.String("contract_code", agreementNo))
err = cert.AddContractFileID(fillTemplateResp.FileID, fillTemplateResp.FileDownloadUrl) err = cert.AddContractFileID(fillTemplateResp.FileID, fillTemplateResp.FileDownloadUrl)
if err != nil { if err != nil {
s.logger.Error("加入合同文件ID链接失败", zap.Error(err)) s.logger.Error("加入合同文件ID链接失败", zap.Error(err))
@@ -1566,8 +1582,8 @@ func (s *CertificationApplicationServiceImpl) handleContractAfterSignComplete(ct
s.logger.Info("合同文件已上传七牛云", zap.String("file_name", fileName), zap.String("qiniu_url", qiniuURL)) s.logger.Info("合同文件已上传七牛云", zap.String("file_name", fileName), zap.String("qiniu_url", qiniuURL))
// 4. 保存到合同聚合根 // 4. 保存到合同聚合根(复用认证阶段的合同编号)
_, err = s.contractAggregateService.CreateContract( _, err = s.contractAggregateService.CreateContractWithCode(
ctx, ctx,
user.EnterpriseInfo.ID, user.EnterpriseInfo.ID,
cert.UserID, cert.UserID,
@@ -1575,6 +1591,7 @@ func (s *CertificationApplicationServiceImpl) handleContractAfterSignComplete(ct
user_entities.ContractTypeCooperation, user_entities.ContractTypeCooperation,
fileId, fileId,
qiniuURL, qiniuURL,
cert.ContractCode,
) )
if err != nil { if err != nil {
s.logger.Error("保存合同信息到聚合根失败", zap.String("file_name", fileName), zap.Error(err)) s.logger.Error("保存合同信息到聚合根失败", zap.String("file_name", fileName), zap.Error(err))

View File

@@ -31,6 +31,7 @@ type Certification struct {
// === e签宝相关信息 === // === e签宝相关信息 ===
AuthFlowID string `gorm:"type:varchar(500)" json:"auth_flow_id,omitempty" comment:"企业认证流程ID"` AuthFlowID string `gorm:"type:varchar(500)" json:"auth_flow_id,omitempty" comment:"企业认证流程ID"`
AuthURL string `gorm:"type:varchar(500)" json:"auth_url,omitempty" comment:"企业认证链接"` AuthURL string `gorm:"type:varchar(500)" json:"auth_url,omitempty" comment:"企业认证链接"`
ContractCode string `gorm:"type:varchar(100)" json:"contract_code,omitempty" comment:"合同/协议编号"`
ContractFileID string `gorm:"type:varchar(500)" json:"contract_file_id,omitempty" comment:"合同文件ID"` ContractFileID string `gorm:"type:varchar(500)" json:"contract_file_id,omitempty" comment:"合同文件ID"`
EsignFlowID string `gorm:"type:varchar(500)" json:"esign_flow_id,omitempty" comment:"签署流程ID"` EsignFlowID string `gorm:"type:varchar(500)" json:"esign_flow_id,omitempty" comment:"签署流程ID"`
ContractURL string `gorm:"type:varchar(500)" json:"contract_url,omitempty" comment:"合同文件访问链接"` ContractURL string `gorm:"type:varchar(500)" json:"contract_url,omitempty" comment:"合同文件访问链接"`
@@ -332,6 +333,11 @@ func (c *Certification) AddContractFileID(contractFileID string, contractURL str
return nil return nil
} }
// SetContractCode 设置合同/协议编号
func (c *Certification) SetContractCode(contractCode string) {
c.ContractCode = contractCode
}
// UpdateContractInfo 更新合同信息 // UpdateContractInfo 更新合同信息
func (c *Certification) UpdateContractInfo(contractInfo *value_objects.ContractInfo) error { func (c *Certification) UpdateContractInfo(contractInfo *value_objects.ContractInfo) error {
// 验证合同信息 // 验证合同信息

View File

@@ -64,8 +64,22 @@ func (c *ContractInfo) BeforeCreate(tx *gorm.DB) error {
// ================ 工厂方法 ================ // ================ 工厂方法 ================
// NewContractInfo 创建新的合同信息 // NewContractInfo 创建新的合同信息(自动生成合同编号)
func NewContractInfo(enterpriseInfoID, userID, contractName string, contractType ContractType, contractFileID, contractFileURL string) (*ContractInfo, error) { func NewContractInfo(enterpriseInfoID, userID, contractName string, contractType ContractType, contractFileID, contractFileURL string) (*ContractInfo, error) {
contractCode := GenerateContractCode(contractType)
return newContractInfo(enterpriseInfoID, userID, contractName, contractType, contractFileID, contractFileURL, contractCode)
}
// NewContractInfoWithCode 创建新的合同信息(使用指定的合同编号)
func NewContractInfoWithCode(enterpriseInfoID, userID, contractName string, contractType ContractType, contractFileID, contractFileURL, contractCode string) (*ContractInfo, error) {
if contractCode == "" {
return nil, fmt.Errorf("合同编号不能为空")
}
return newContractInfo(enterpriseInfoID, userID, contractName, contractType, contractFileID, contractFileURL, contractCode)
}
// newContractInfo 创建合同信息的内部实现
func newContractInfo(enterpriseInfoID, userID, contractName string, contractType ContractType, contractFileID, contractFileURL, contractCode string) (*ContractInfo, error) {
if enterpriseInfoID == "" { if enterpriseInfoID == "" {
return nil, fmt.Errorf("企业信息ID不能为空") return nil, fmt.Errorf("企业信息ID不能为空")
} }
@@ -90,9 +104,6 @@ func NewContractInfo(enterpriseInfoID, userID, contractName string, contractType
return nil, fmt.Errorf("无效的合同类型: %s", contractType) return nil, fmt.Errorf("无效的合同类型: %s", contractType)
} }
// 生成合同编码
contractCode := GenerateContractCode(contractType)
contractInfo := &ContractInfo{ contractInfo := &ContractInfo{
ID: uuid.New().String(), ID: uuid.New().String(),
EnterpriseInfoID: enterpriseInfoID, EnterpriseInfoID: enterpriseInfoID,
@@ -338,22 +349,24 @@ type ContractInfoDeletedEvent struct {
} }
// GenerateContractCode 生成合同编码 // GenerateContractCode 生成合同编码
// 格式HYDATA-YYYYMMDD-R{6位随机数}R=入驻)
func GenerateContractCode(contractType ContractType) string { func GenerateContractCode(contractType ContractType) string {
prefix := "CON" now := time.Now()
dateStr := now.Format("20060102")
prefix := "R"
switch contractType { switch contractType {
case ContractTypeCooperation: case ContractTypeCooperation:
prefix += "01" prefix = "R" // 入驻
case ContractTypeReSign: case ContractTypeReSign:
prefix += "02" prefix = "B" // 补签
} }
// 获取当前日期格式为YYYYMMDD
now := time.Now()
dateStr := now.Format("20060102") // YYYYMMDD格式
// 生成一个随机的6位数字
randNum := fmt.Sprintf("%06d", rand.Intn(1000000)) randNum := fmt.Sprintf("%06d", rand.Intn(1000000))
return fmt.Sprintf("HYDATA-%s-%s%s", dateStr, prefix, randNum)
// 格式CON + 类型标识 + YYYYMMDD + 6位随机数 }
return fmt.Sprintf("%s%s%s", prefix, dateStr, randNum)
// GenerateContractCodeWithPrefix 使用指定前缀生成合同编码
func GenerateContractCodeWithPrefix(contractType ContractType) string {
return GenerateContractCode(contractType)
} }

View File

@@ -14,6 +14,7 @@ import (
type ContractAggregateService interface { type ContractAggregateService interface {
// 聚合根生命周期管理 // 聚合根生命周期管理
CreateContract(ctx context.Context, enterpriseInfoID, userID, contractName string, contractType entities.ContractType, contractFileID, contractFileURL string) (*entities.ContractInfo, error) CreateContract(ctx context.Context, enterpriseInfoID, userID, contractName string, contractType entities.ContractType, contractFileID, contractFileURL string) (*entities.ContractInfo, error)
CreateContractWithCode(ctx context.Context, enterpriseInfoID, userID, contractName string, contractType entities.ContractType, contractFileID, contractFileURL, contractCode string) (*entities.ContractInfo, error)
LoadContract(ctx context.Context, contractID string) (*entities.ContractInfo, error) LoadContract(ctx context.Context, contractID string) (*entities.ContractInfo, error)
SaveContract(ctx context.Context, contract *entities.ContractInfo) error SaveContract(ctx context.Context, contract *entities.ContractInfo) error
DeleteContract(ctx context.Context, contractID string) error DeleteContract(ctx context.Context, contractID string) error
@@ -94,6 +95,48 @@ func (s *ContractAggregateServiceImpl) CreateContract(
return contract, nil return contract, nil
} }
// CreateContractWithCode 使用指定编号创建合同信息
func (s *ContractAggregateServiceImpl) CreateContractWithCode(
ctx context.Context,
enterpriseInfoID, userID, contractName string,
contractType entities.ContractType,
contractFileID, contractFileURL, contractCode string,
) (*entities.ContractInfo, error) {
s.logger.Debug("使用指定编号创建合同信息",
zap.String("enterprise_info_id", enterpriseInfoID),
zap.String("user_id", userID),
zap.String("contract_code", contractCode))
exists, err := s.ExistsByContractFileID(ctx, contractFileID)
if err != nil {
return nil, fmt.Errorf("检查合同文件ID失败: %w", err)
}
if exists {
return nil, fmt.Errorf("合同文件ID已存在")
}
contract, err := entities.NewContractInfoWithCode(enterpriseInfoID, userID, contractName, contractType, contractFileID, contractFileURL, contractCode)
if err != nil {
return nil, fmt.Errorf("创建合同信息失败: %w", err)
}
if err := s.ValidateBusinessRules(ctx, contract); err != nil {
return nil, fmt.Errorf("业务规则验证失败: %w", err)
}
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("contract_code", contractCode),
zap.String("enterprise_info_id", enterpriseInfoID))
return contract, nil
}
// LoadContract 加载合同信息 // LoadContract 加载合同信息
func (s *ContractAggregateServiceImpl) LoadContract(ctx context.Context, contractID string) (*entities.ContractInfo, error) { func (s *ContractAggregateServiceImpl) LoadContract(ctx context.Context, contractID string) (*entities.ContractInfo, error) {
s.logger.Debug("加载合同信息", zap.String("contract_id", contractID)) s.logger.Debug("加载合同信息", zap.String("contract_id", contractID))