feat(t219): show pending-payment reconciliation
This commit is contained in:
@@ -14,6 +14,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"cmroubao/backend-api/internal/domain"
|
||||
"cmroubao/backend-api/internal/usecase"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
@@ -627,6 +628,196 @@ func TestTaskDetailDisablesAuthorizationAfterDelivery(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestTaskDetailRendersOrderSubmissionStatesWithoutPaymentActions(
|
||||
t *testing.T,
|
||||
) {
|
||||
now := time.Date(2026, 7, 28, 9, 30, 0, 0, time.UTC)
|
||||
tests := []struct {
|
||||
name string
|
||||
taskStatus string
|
||||
submission OrderSubmission
|
||||
expected []string
|
||||
forbidden []string
|
||||
}{
|
||||
{
|
||||
name: "reconciling",
|
||||
taskStatus: "WAITING_CONFIRMATION",
|
||||
submission: OrderSubmission{
|
||||
Status: "FENCED",
|
||||
StatusLabel: "正在对账",
|
||||
FencedAt: now,
|
||||
},
|
||||
expected: []string{
|
||||
"订单提交结果正在对账",
|
||||
"禁止重复提交",
|
||||
},
|
||||
forbidden: []string{"待人工确认付款", "验证完成,未提交订单"},
|
||||
},
|
||||
{
|
||||
name: "manual review",
|
||||
taskStatus: "WAITING_CONFIRMATION",
|
||||
submission: OrderSubmission{
|
||||
Status: "MANUAL_REVIEW",
|
||||
StatusLabel: "需要人工对账",
|
||||
ManualReasonLabel: "找到多个可能订单",
|
||||
FencedAt: now,
|
||||
ManualReviewAt: now.Add(time.Minute),
|
||||
},
|
||||
expected: []string{
|
||||
"需要人工对账",
|
||||
"找到多个可能订单",
|
||||
"禁止重新提交订单",
|
||||
},
|
||||
forbidden: []string{"待人工确认付款", "验证完成,未提交订单"},
|
||||
},
|
||||
{
|
||||
name: "pending payment",
|
||||
taskStatus: "SUCCEEDED",
|
||||
submission: OrderSubmission{
|
||||
Status: "RECONCILED",
|
||||
StatusLabel: "待人工确认付款",
|
||||
ExpectedTitle: "已授权灰色上衣",
|
||||
ExpectedSKU: "灰色,2XL",
|
||||
ExpectedQuantity: 2,
|
||||
ExpectedUnitPrice: "21.50",
|
||||
ExpectedTotalPrice: "43.00",
|
||||
PlatformOrderNo: "12345678901234567890",
|
||||
PlatformOrderedAt: now,
|
||||
PlatformOrderStatus: "PENDING_PAYMENT",
|
||||
EvidenceContentURL: "/api/v1/tasks/" + testTaskID +
|
||||
"/evidence/00000000-0000-4000-8000-000000000078/content",
|
||||
FencedAt: now.Add(-time.Minute),
|
||||
ReconciledAt: now.Add(time.Minute),
|
||||
},
|
||||
expected: []string{
|
||||
"待人工确认付款",
|
||||
"请采购员打开拼多多订单列表",
|
||||
"12345678901234567890",
|
||||
"灰色,2XL",
|
||||
"¥43.00",
|
||||
"待付款订单列表对账截图",
|
||||
},
|
||||
forbidden: []string{
|
||||
"验证完成,未提交订单",
|
||||
"重试提交",
|
||||
`href="pinduoduo`,
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
service := &fakeService{
|
||||
getResult: Task{
|
||||
ID: testTaskID,
|
||||
Title: "订单状态任务",
|
||||
SKU: "灰色,2XL",
|
||||
Quantity: 2,
|
||||
Status: test.taskStatus,
|
||||
ReferenceAssetID: "00000000-0000-4000-8000-000000000009",
|
||||
CreatedAt: now,
|
||||
UpdatedAt: now,
|
||||
OrderSubmissions: []OrderSubmission{test.submission},
|
||||
},
|
||||
}
|
||||
response := performRequest(
|
||||
t,
|
||||
newTestRouter(t, service),
|
||||
http.MethodGet,
|
||||
"/tasks/"+testTaskID,
|
||||
nil,
|
||||
"",
|
||||
)
|
||||
if response.Code != http.StatusOK {
|
||||
t.Fatalf(
|
||||
"detail status/body = %d/%s",
|
||||
response.Code,
|
||||
response.Body,
|
||||
)
|
||||
}
|
||||
body := response.Body.String()
|
||||
for _, expected := range test.expected {
|
||||
if !strings.Contains(body, expected) {
|
||||
t.Fatalf("detail missing %q: %s", expected, body)
|
||||
}
|
||||
}
|
||||
for _, forbidden := range test.forbidden {
|
||||
if strings.Contains(body, forbidden) {
|
||||
t.Fatalf("detail contains forbidden %q", forbidden)
|
||||
}
|
||||
}
|
||||
if regexp.MustCompile(
|
||||
`(?s)<(?:a|button)[^>]*>[^<]*(?:立即支付|确认支付|自动付款)`,
|
||||
).MatchString(body) {
|
||||
t.Fatal("detail exposes a payment action")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestTaskDetailKeepsHistoricalSucceededCopyWithoutSubmission(t *testing.T) {
|
||||
now := time.Date(2026, 7, 28, 9, 30, 0, 0, time.UTC)
|
||||
response := performRequest(
|
||||
t,
|
||||
newTestRouter(t, &fakeService{getResult: Task{
|
||||
ID: testTaskID,
|
||||
Title: "历史验证任务",
|
||||
SKU: "HISTORY-SKU",
|
||||
Quantity: 1,
|
||||
Status: "SUCCEEDED",
|
||||
ReferenceAssetID: "00000000-0000-4000-8000-000000000009",
|
||||
CreatedAt: now,
|
||||
UpdatedAt: now,
|
||||
}}),
|
||||
http.MethodGet,
|
||||
"/tasks/"+testTaskID,
|
||||
nil,
|
||||
"",
|
||||
)
|
||||
if response.Code != http.StatusOK ||
|
||||
!strings.Contains(
|
||||
response.Body.String(),
|
||||
"验证完成,未提交订单",
|
||||
) {
|
||||
t.Fatalf(
|
||||
"historical succeeded detail = %d/%s",
|
||||
response.Code,
|
||||
response.Body,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOrderSubmissionAdapterBuildsAuthenticatedEvidenceURL(t *testing.T) {
|
||||
orderNo := "12345678901234567890"
|
||||
status := "PENDING_PAYMENT"
|
||||
evidenceID := "00000000-0000-4000-8000-000000000078"
|
||||
orderedAt := time.Date(2026, 7, 28, 9, 30, 0, 0, time.UTC)
|
||||
submission := orderSubmissionFrom(domain.OrderSubmission{
|
||||
ID: "00000000-0000-4000-8000-000000000079",
|
||||
TaskID: testTaskID,
|
||||
Status: domain.OrderSubmissionReconciled,
|
||||
ExpectedTitle: "已授权商品",
|
||||
ExpectedSKU: "灰色,2XL",
|
||||
ExpectedQuantity: 2,
|
||||
ExpectedUnitPriceCents: 2150,
|
||||
ExpectedTotalPriceCents: 4300,
|
||||
PlatformOrderNo: &orderNo,
|
||||
PlatformOrderedAt: &orderedAt,
|
||||
PlatformOrderStatus: &status,
|
||||
ReconciliationEvidenceAssetID: &evidenceID,
|
||||
FencedAt: orderedAt.Add(-time.Minute),
|
||||
ReconciledAt: &orderedAt,
|
||||
})
|
||||
if submission.StatusLabel != "待人工确认付款" ||
|
||||
submission.PlatformOrderNo != orderNo ||
|
||||
submission.ExpectedUnitPrice != "21.50" ||
|
||||
submission.ExpectedTotalPrice != "43.00" ||
|
||||
submission.EvidenceContentURL !=
|
||||
"/api/v1/tasks/"+testTaskID+"/evidence/"+evidenceID+"/content" ||
|
||||
strings.Contains(submission.EvidenceContentURL, orderNo) {
|
||||
t.Fatalf("submission view = %+v", submission)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTaskDetailCancelModeFollowsLifecycleStatus(t *testing.T) {
|
||||
tests := []struct {
|
||||
status string
|
||||
|
||||
Reference in New Issue
Block a user