This commit is contained in:
2026-07-21 15:53:29 +08:00
parent 024b6614ba
commit c943f575d5
40 changed files with 5362 additions and 275 deletions

View File

@@ -0,0 +1,262 @@
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
}