feat(t207): audit local procurement results

This commit is contained in:
QiuSW
2026-07-27 12:23:05 +08:00
parent a00c1e3e17
commit 4533df7abc
37 changed files with 4004 additions and 115 deletions
@@ -2,7 +2,9 @@ package webui
import (
"context"
"encoding/json"
"errors"
"strings"
"cmroubao/backend-api/internal/domain"
"cmroubao/backend-api/internal/transport/authcommon"
@@ -176,9 +178,82 @@ func taskFromPurchase(task domain.PurchaseTask) Task {
func taskFromDetail(detail domain.TaskDetail) Task {
task := taskFromPurchase(detail.Task)
task.ReferenceAssetID = detail.Asset.ID
task.ExecutionReport = executionReportFrom(detail.Report)
return task
}
func executionReportFrom(report *domain.ExecutionReport) *ExecutionReport {
if report == nil {
return nil
}
result := &ExecutionReport{
Events: make([]ExecutionReportEvent, 0, len(report.Events)),
Evidence: make([]ExecutionReportEvidence, 0, len(report.EvidenceAssets)),
}
for _, event := range report.Events {
result.Events = append(result.Events, ExecutionReportEvent{
Step: event.Step,
Type: event.Type,
Message: event.Message,
OccurredAt: event.OccurredAt,
ReceivedAfterExecutionExpiry: event.ReceivedAfterExecutionExpiry,
})
}
for _, evidence := range report.EvidenceAssets {
result.Evidence = append(result.Evidence, ExecutionReportEvidence{
ID: evidence.ID,
ContentURL: "/api/v1/tasks/" + evidence.TaskID + "/evidence/" + evidence.ID + "/content",
SHA256: evidence.SHA256,
SizeBytes: evidence.SizeBytes,
CreatedAt: evidence.CreatedAt,
ReceivedAfterExecutionExpiry: evidence.ReceivedAfterExecutionExpiry,
})
}
if batch := report.CandidateBatch; batch != nil {
result.Mode = batch.ExecutionMode
result.SearchQuery = batch.SearchQuery
result.Provenance = prettyAuditJSON(batch.ProvenanceJSON)
result.Candidates = prettyAuditJSON(&batch.CandidatesJSON)
result.Recommendation = prettyAuditJSON(batch.RecommendationJSON)
}
if outcome := report.Outcome; outcome != nil {
result.Outcome = &ExecutionReportOutcome{
ResultType: outcome.ResultType,
Outcome: stringValue(outcome.Outcome),
OperatorReason: stringValue(outcome.OperatorReason),
ErrorCode: stringValue(outcome.ErrorCode),
ErrorMessage: stringValue(outcome.ErrorMessage),
ErrorStep: stringValue(outcome.ErrorStep),
OrderSubmitted: outcome.OrderSubmitted,
ReceivedAt: outcome.ReceivedAt,
ReceivedAfterExecutionExpiry: outcome.ReceivedAfterExecutionExpiry,
}
}
return result
}
func prettyAuditJSON(value *string) string {
if value == nil || strings.TrimSpace(*value) == "" {
return ""
}
var decoded any
if err := json.Unmarshal([]byte(*value), &decoded); err != nil {
return ""
}
formatted, err := json.MarshalIndent(decoded, "", " ")
if err != nil {
return ""
}
return string(formatted)
}
func stringValue(value *string) string {
if value == nil {
return ""
}
return *value
}
func mapUsecaseError(err error) error {
var typed *usecase.Error
if !errors.As(err, &typed) {