263 lines
7.1 KiB
Go
263 lines
7.1 KiB
Go
|
|
package fadada
|
|||
|
|
|
|||
|
|
import (
|
|||
|
|
"fmt"
|
|||
|
|
"strings"
|
|||
|
|
"time"
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
// FillTemplate 填写文档模板并生成合同文件(POST /doc-template/fill-values)
|
|||
|
|
func (c *Client) FillTemplate(req *ContractFillRequest) (*ContractFileResult, error) {
|
|||
|
|
if err := c.config.ValidateTemplateFields(); err != nil {
|
|||
|
|
return nil, err
|
|||
|
|
}
|
|||
|
|
if err := validateContractFillRequest(req); err != nil {
|
|||
|
|
return nil, err
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
accessToken, err := c.ensureAccessToken()
|
|||
|
|
if err != nil {
|
|||
|
|
return nil, err
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
signDate := strings.TrimSpace(req.SignDate)
|
|||
|
|
if signDate == "" {
|
|||
|
|
signDate = time.Now().Format("2006年01月02日")
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
fileName := strings.TrimSpace(req.FileName)
|
|||
|
|
if fileName == "" {
|
|||
|
|
if c.config.Contract != nil && c.config.Contract.Name != "" {
|
|||
|
|
fileName = c.config.Contract.Name
|
|||
|
|
} else {
|
|||
|
|
fileName = "海宇数据-合作协议"
|
|||
|
|
}
|
|||
|
|
fileName = fmt.Sprintf("%s-%s", fileName, strings.TrimSpace(req.AgreementNo))
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
fieldValues := c.BuildTemplateFieldValues(&ContractFillRequest{
|
|||
|
|
AgreementNo: req.AgreementNo,
|
|||
|
|
CompanyName: req.CompanyName,
|
|||
|
|
UnifiedSocialCode: req.UnifiedSocialCode,
|
|||
|
|
EnterpriseAddress: req.EnterpriseAddress,
|
|||
|
|
AuthorizedRepName: req.AuthorizedRepName,
|
|||
|
|
SignDate: signDate,
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
docFieldValues := make([]docFieldValue, 0, len(fieldValues))
|
|||
|
|
for _, fv := range fieldValues {
|
|||
|
|
docFieldValues = append(docFieldValues, docFieldValue{
|
|||
|
|
FieldID: fv.FieldID,
|
|||
|
|
FieldValue: fv.FieldValue,
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
res, err := c.http.PostBiz(pathFillDocTemplateValues, accessToken, &fillDocTemplateReq{
|
|||
|
|
OwnerID: &openID{IDType: "corp", OpenID: c.config.OpenCorpID},
|
|||
|
|
DocTemplateID: c.config.TemplateID,
|
|||
|
|
FileName: fileName,
|
|||
|
|
DocFieldValues: docFieldValues,
|
|||
|
|
})
|
|||
|
|
if err != nil {
|
|||
|
|
return nil, err
|
|||
|
|
}
|
|||
|
|
if res.Code != successCode {
|
|||
|
|
return nil, fmt.Errorf("法大大填写模板失败: code=%s msg=%s requestId=%s", res.Code, res.Msg, res.RequestID)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var data fillDocTemplateData
|
|||
|
|
if err := decodeData(res.Data, &data); err != nil {
|
|||
|
|
return nil, fmt.Errorf("解析模板填单响应失败: %w", err)
|
|||
|
|
}
|
|||
|
|
if data.FileID == "" {
|
|||
|
|
return nil, fmt.Errorf("法大大填写模板失败: fileId 为空 requestId=%s", res.RequestID)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return &ContractFileResult{
|
|||
|
|
FileID: data.FileID,
|
|||
|
|
FileDownloadURL: data.FileDownloadURL,
|
|||
|
|
}, nil
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// FillSignTaskFields 向已创建的签署任务填写控件(POST /sign-task/field/fill-values)
|
|||
|
|
func (c *Client) FillSignTaskFields(signTaskID string, req *ContractFillRequest) error {
|
|||
|
|
if strings.TrimSpace(signTaskID) == "" {
|
|||
|
|
return fmt.Errorf("signTaskId 不能为空")
|
|||
|
|
}
|
|||
|
|
if err := c.config.ValidateTemplateFields(); err != nil {
|
|||
|
|
return err
|
|||
|
|
}
|
|||
|
|
if err := validateContractFillRequest(req); err != nil {
|
|||
|
|
return err
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
accessToken, err := c.ensureAccessToken()
|
|||
|
|
if err != nil {
|
|||
|
|
return err
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
docID, err := c.resolveSignTaskDocID(signTaskID, accessToken)
|
|||
|
|
if err != nil {
|
|||
|
|
return err
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
signDate := strings.TrimSpace(req.SignDate)
|
|||
|
|
if signDate == "" {
|
|||
|
|
signDate = time.Now().Format("2006年01月02日")
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
fieldValues := c.BuildTemplateFieldValues(&ContractFillRequest{
|
|||
|
|
AgreementNo: req.AgreementNo,
|
|||
|
|
CompanyName: req.CompanyName,
|
|||
|
|
UnifiedSocialCode: req.UnifiedSocialCode,
|
|||
|
|
EnterpriseAddress: req.EnterpriseAddress,
|
|||
|
|
AuthorizedRepName: req.AuthorizedRepName,
|
|||
|
|
SignDate: signDate,
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
docFieldValues := make([]docFieldValue, 0, len(fieldValues))
|
|||
|
|
for _, fv := range fieldValues {
|
|||
|
|
docFieldValues = append(docFieldValues, docFieldValue{
|
|||
|
|
DocID: docID,
|
|||
|
|
FieldDocID: docID,
|
|||
|
|
FieldID: fv.FieldID,
|
|||
|
|
FieldValue: fv.FieldValue,
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
res, err := c.http.PostBiz(pathFillSignTaskFieldValues, accessToken, &fillSignTaskFieldsReq{
|
|||
|
|
SignTaskID: signTaskID,
|
|||
|
|
DocFieldValues: docFieldValues,
|
|||
|
|
})
|
|||
|
|
if err != nil {
|
|||
|
|
return err
|
|||
|
|
}
|
|||
|
|
if res.Code != successCode {
|
|||
|
|
return fmt.Errorf("法大大签署任务填单失败: code=%s msg=%s requestId=%s", res.Code, res.Msg, res.RequestID)
|
|||
|
|
}
|
|||
|
|
return nil
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// resolveSignTaskDocID 解析签署任务文档 docId(填单必填)
|
|||
|
|
func (c *Client) resolveSignTaskDocID(signTaskID, accessToken string) (string, error) {
|
|||
|
|
if c.config != nil {
|
|||
|
|
if id := strings.TrimSpace(c.config.TemplateDocID); id != "" {
|
|||
|
|
return id, nil
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
res, err := c.http.PostBiz(pathGetSignTaskDetail, accessToken, &getSignTaskDetailReq{
|
|||
|
|
SignTaskID: signTaskID,
|
|||
|
|
})
|
|||
|
|
if err != nil {
|
|||
|
|
return "", fmt.Errorf("查询签署任务文档失败: %w", err)
|
|||
|
|
}
|
|||
|
|
if res.Code != successCode {
|
|||
|
|
return "", fmt.Errorf("查询签署任务文档失败: code=%s msg=%s requestId=%s", res.Code, res.Msg, res.RequestID)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var data getSignTaskDetailData
|
|||
|
|
if err := decodeData(res.Data, &data); err != nil {
|
|||
|
|
return "", fmt.Errorf("解析签署任务文档失败: %w", err)
|
|||
|
|
}
|
|||
|
|
for _, d := range data.Docs {
|
|||
|
|
if id := strings.TrimSpace(d.DocID); id != "" {
|
|||
|
|
return id, nil
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
return "", fmt.Errorf("签署任务未返回 docId,请在配置 fadada.template_doc_id 中填写模板文档ID")
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// BuildTemplateFieldValues 将业务字段映射为法大大控件编码/值
|
|||
|
|
func (c *Client) BuildTemplateFieldValues(req *ContractFillRequest) []TemplateFieldValue {
|
|||
|
|
fields := c.config.TemplateFields
|
|||
|
|
if fields == nil || req == nil {
|
|||
|
|
return nil
|
|||
|
|
}
|
|||
|
|
signDate := strings.TrimSpace(req.SignDate)
|
|||
|
|
agreementNo := strings.TrimSpace(req.AgreementNo)
|
|||
|
|
companyName := strings.TrimSpace(req.CompanyName)
|
|||
|
|
|
|||
|
|
pairs := make([]struct {
|
|||
|
|
fieldID string
|
|||
|
|
value string
|
|||
|
|
}, 0, len(fields.AgreementNo)+len(fields.PartyAName)+6)
|
|||
|
|
for _, id := range fields.AgreementNo {
|
|||
|
|
id = strings.TrimSpace(id)
|
|||
|
|
if id == "" {
|
|||
|
|
continue
|
|||
|
|
}
|
|||
|
|
pairs = append(pairs, struct {
|
|||
|
|
fieldID string
|
|||
|
|
value string
|
|||
|
|
}{id, agreementNo})
|
|||
|
|
}
|
|||
|
|
for _, id := range fields.PartyAName {
|
|||
|
|
id = strings.TrimSpace(id)
|
|||
|
|
if id == "" {
|
|||
|
|
continue
|
|||
|
|
}
|
|||
|
|
pairs = append(pairs, struct {
|
|||
|
|
fieldID string
|
|||
|
|
value string
|
|||
|
|
}{id, companyName})
|
|||
|
|
}
|
|||
|
|
pairs = append(pairs,
|
|||
|
|
struct {
|
|||
|
|
fieldID string
|
|||
|
|
value string
|
|||
|
|
}{fields.ContractDate, signDate},
|
|||
|
|
struct {
|
|||
|
|
fieldID string
|
|||
|
|
value string
|
|||
|
|
}{fields.PartyAUSCC, strings.TrimSpace(req.UnifiedSocialCode)},
|
|||
|
|
struct {
|
|||
|
|
fieldID string
|
|||
|
|
value string
|
|||
|
|
}{fields.PartyAAddress, strings.TrimSpace(req.EnterpriseAddress)},
|
|||
|
|
struct {
|
|||
|
|
fieldID string
|
|||
|
|
value string
|
|||
|
|
}{fields.PartyARep, strings.TrimSpace(req.AuthorizedRepName)},
|
|||
|
|
struct {
|
|||
|
|
fieldID string
|
|||
|
|
value string
|
|||
|
|
}{fields.PartyASignDate, signDate},
|
|||
|
|
struct {
|
|||
|
|
fieldID string
|
|||
|
|
value string
|
|||
|
|
}{fields.PartyBSignDate, signDate},
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
out := make([]TemplateFieldValue, 0, len(pairs))
|
|||
|
|
for _, p := range pairs {
|
|||
|
|
if p.fieldID == "" {
|
|||
|
|
continue
|
|||
|
|
}
|
|||
|
|
out = append(out, TemplateFieldValue{
|
|||
|
|
FieldID: p.fieldID,
|
|||
|
|
FieldValue: p.value,
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
return out
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func validateContractFillRequest(req *ContractFillRequest) error {
|
|||
|
|
if req == nil {
|
|||
|
|
return fmt.Errorf("合同填单请求不能为空")
|
|||
|
|
}
|
|||
|
|
if strings.TrimSpace(req.AgreementNo) == "" {
|
|||
|
|
return fmt.Errorf("协议编号不能为空")
|
|||
|
|
}
|
|||
|
|
if strings.TrimSpace(req.CompanyName) == "" {
|
|||
|
|
return fmt.Errorf("甲方企业名不能为空")
|
|||
|
|
}
|
|||
|
|
if strings.TrimSpace(req.UnifiedSocialCode) == "" {
|
|||
|
|
return fmt.Errorf("甲方统一信用代码不能为空")
|
|||
|
|
}
|
|||
|
|
if strings.TrimSpace(req.AuthorizedRepName) == "" {
|
|||
|
|
return fmt.Errorf("甲方授权代表不能为空")
|
|||
|
|
}
|
|||
|
|
return nil
|
|||
|
|
}
|