160 lines
4.7 KiB
Go
160 lines
4.7 KiB
Go
package syncer
|
||
|
||
import (
|
||
"xk-hy-transit-go/internal/hy"
|
||
"xk-hy-transit-go/internal/hyfile"
|
||
"xk-hy-transit-go/internal/xkapi"
|
||
)
|
||
|
||
// StepRunOptions 单 step 执行选项(自动 sync 与联调共用 executeStep)。
|
||
type StepRunOptions struct {
|
||
ItemLimit int // 0=处理 Pull 全部条数;>0 只处理前 N 条
|
||
CollectTrace bool // true 时填充 StepTestResult
|
||
}
|
||
|
||
// StepTestResult 联调页返回(recipe / verification)。
|
||
type StepTestResult struct {
|
||
Step string `json:"step"`
|
||
StepLabel string `json:"step_label"`
|
||
AnchorDate string `json:"anchor_date"`
|
||
BatchID int `json:"batch_id"`
|
||
PullSummary PullSummary `json:"pull_summary"`
|
||
Items []ItemStepTrace `json:"items"`
|
||
CallbackError string `json:"callback_error,omitempty"`
|
||
Summary StepOutcomeSummary `json:"summary"`
|
||
}
|
||
|
||
// PullSummary 拉取摘要。
|
||
type PullSummary struct {
|
||
Total int `json:"total"`
|
||
ValidationFailed int `json:"validation_failed"`
|
||
Processed int `json:"processed"`
|
||
}
|
||
|
||
// StepOutcomeSummary 本 step 处理结果统计。
|
||
type StepOutcomeSummary struct {
|
||
Success int `json:"success"`
|
||
Failed int `json:"failed"`
|
||
Skipped int `json:"skipped"`
|
||
}
|
||
|
||
// ItemStepTrace 单条联调追踪(与 processItem 一一对应)。
|
||
type ItemStepTrace struct {
|
||
RecordID int `json:"record_id"`
|
||
BizKey string `json:"biz_key"`
|
||
ValidationErrors []string `json:"validation_errors,omitempty"`
|
||
PayloadSnapshot string `json:"payload_snapshot,omitempty"`
|
||
PushPlainJSON string `json:"push_plain_json,omitempty"`
|
||
PushHeaders map[string]string `json:"push_headers,omitempty"`
|
||
RecipeFileUpload *RecipeFileUploadTrace `json:"recipe_file_upload,omitempty"`
|
||
Push PushTrace `json:"push"`
|
||
Callback xkapi.CallbackItem `json:"callback"`
|
||
}
|
||
|
||
// RecipeFileUploadTrace 处方 PDF 28211 上传追踪。
|
||
type RecipeFileUploadTrace struct {
|
||
Executed bool `json:"executed"`
|
||
Skipped bool `json:"skipped"`
|
||
SkipReason string `json:"skip_reason,omitempty"`
|
||
FileID string `json:"fileId,omitempty"`
|
||
HTTPStatus int `json:"httpStatus,omitempty"`
|
||
RawBody string `json:"rawBody,omitempty"`
|
||
Success bool `json:"success"`
|
||
Message string `json:"message,omitempty"`
|
||
LocalPDFPath string `json:"localPdfPath,omitempty"`
|
||
Error string `json:"error,omitempty"`
|
||
}
|
||
|
||
// PushTrace 监管 JSON 上报结果摘要。
|
||
type PushTrace struct {
|
||
HTTPCode int `json:"http_code,omitempty"`
|
||
MsgCode int `json:"msg_code,omitempty"`
|
||
Msg string `json:"msg,omitempty"`
|
||
TraceID string `json:"trace_id,omitempty"`
|
||
ResponseBody string `json:"response_body,omitempty"`
|
||
}
|
||
|
||
// itemTraceCtx processItem 内部填充,最终写入 ItemStepTrace。
|
||
type itemTraceCtx struct {
|
||
out *ItemStepTrace
|
||
}
|
||
|
||
func newItemTraceCtx(item xkapi.PullItem) *itemTraceCtx {
|
||
return &itemTraceCtx{out: &ItemStepTrace{
|
||
RecordID: item.RecordID,
|
||
BizKey: item.BizKey,
|
||
ValidationErrors: append([]string(nil), item.ValidationErrors...),
|
||
}}
|
||
}
|
||
|
||
func (c *itemTraceCtx) setPayloadSnapshot(payload map[string]any) {
|
||
if c == nil || c.out == nil || payload == nil {
|
||
return
|
||
}
|
||
c.out.PayloadSnapshot = mustJSON(payload)
|
||
}
|
||
|
||
func (c *itemTraceCtx) setPushReq(req *hy.UploadRequest) {
|
||
if c == nil || c.out == nil || req == nil {
|
||
return
|
||
}
|
||
c.out.PushPlainJSON = req.PlainJSON
|
||
c.out.PushHeaders = copyHeadersForTrace(req.Headers)
|
||
}
|
||
|
||
func copyHeadersForTrace(h map[string]string) map[string]string {
|
||
if h == nil {
|
||
return nil
|
||
}
|
||
out := make(map[string]string, len(h))
|
||
for k, v := range h {
|
||
if k == "secret" {
|
||
continue
|
||
}
|
||
out[k] = v
|
||
}
|
||
return out
|
||
}
|
||
|
||
func (c *itemTraceCtx) setRecipeUpload(up *hyfile.UploadPDFResult, localPath string, err error) {
|
||
if c == nil || c.out == nil {
|
||
return
|
||
}
|
||
tr := &RecipeFileUploadTrace{Executed: true, LocalPDFPath: localPath}
|
||
if up != nil {
|
||
tr.FileID = up.FileID
|
||
tr.HTTPStatus = up.HTTPStatus
|
||
tr.RawBody = up.RawBody
|
||
tr.Success = up.Success
|
||
tr.Message = up.Message
|
||
}
|
||
if err != nil {
|
||
tr.Error = err.Error()
|
||
}
|
||
c.out.RecipeFileUpload = tr
|
||
}
|
||
|
||
func (c *itemTraceCtx) setRecipeSkipped(reason string) {
|
||
if c == nil || c.out == nil {
|
||
return
|
||
}
|
||
c.out.RecipeFileUpload = &RecipeFileUploadTrace{
|
||
Skipped: true,
|
||
SkipReason: reason,
|
||
}
|
||
}
|
||
|
||
func (c *itemTraceCtx) finish(cb xkapi.CallbackItem) {
|
||
if c == nil || c.out == nil {
|
||
return
|
||
}
|
||
c.out.Callback = cb
|
||
c.out.Push = PushTrace{
|
||
HTTPCode: cb.HTTPCode,
|
||
MsgCode: cb.MsgCode,
|
||
Msg: cb.Msg,
|
||
TraceID: cb.TraceID,
|
||
ResponseBody: cb.ResponseBody,
|
||
}
|
||
}
|