增加零号主收入结算确认

This commit is contained in:
yml2213
2026-08-29 01:31:08 +08:00
parent 527e5ed228
commit 2487a2d83f
7 changed files with 101 additions and 5 deletions
+2 -1
View File
@@ -133,7 +133,8 @@ type CounterCheckoutRequest struct {
}
type AdminActionRequest struct {
Reason string `json:"reason" binding:"required"`
Reason string `json:"reason" binding:"required"`
ConfirmZeroOwnerIncome bool `json:"confirm_zero_owner_income"`
}
type PlatformHandoffRequest struct {
@@ -44,6 +44,8 @@ func writeOrderError(c *gin.Context, err error) {
response.Error(c, http.StatusConflict, "checkout_cannot_submit", "当前订单不能发起结账")
case errors.Is(err, ErrCheckoutCannotConfirm):
response.Error(c, http.StatusConflict, "checkout_cannot_confirm", "当前结账不能确认")
case errors.Is(err, ErrZeroOwnerIncomeConfirmation):
response.Error(c, http.StatusConflict, "zero_owner_income_confirmation_required", "号主收入为 0,请确认后再结算")
case errors.Is(err, ErrCheckoutCannotCounter):
response.Error(c, http.StatusConflict, "checkout_cannot_counter", "当前结账不能修改")
case errors.Is(err, ErrCheckoutMaxRounds):
@@ -159,6 +159,9 @@ func (r *Repository) AdminPlatformCheckoutConfirm(ctx context.Context, adminID u
if normalizeCheckoutTurn(checkout) != checkoutTurnOwner {
return ErrCheckoutCannotConfirm
}
if checkout.OwnerIncomeAmountCent == 0 && !req.ConfirmZeroOwnerIncome {
return ErrZeroOwnerIncomeConfirmation
}
if err := ensureCheckoutCompletable(order, checkout); err != nil {
return err
}
@@ -196,6 +199,7 @@ func (r *Repository) AdminPlatformCheckoutConfirm(ctx context.Context, adminID u
"after_settlement_status": order.SettlementStatus,
"offline_settlement_status": order.OfflineSettlementStatus,
"offline_settlement_amount_cent": order.OfflineSettlementAmountCent,
"confirm_zero_owner_income": req.ConfirmZeroOwnerIncome,
})
})
if err != nil {
@@ -2,6 +2,7 @@ package order
import (
"context"
"errors"
"testing"
"time"
@@ -1794,3 +1795,48 @@ func createOpenPlatformCheckout(t *testing.T, db *gorm.DB, order model.RentalOrd
}
return checkout
}
func TestAdminPlatformCheckoutConfirmRequiresExplicitConfirmationForZeroOwnerIncome(t *testing.T) {
db := setupOrderTestDB(t)
repo := NewRepository(db, Dependencies{
RefundStarter: RefundStarterFunc(func(context.Context, uint64, int64, string, string) (string, error) {
return "pending", nil
}),
})
const adminID uint64 = 7001
_, renter, order := createPlatformManagedCheckoutOrder(t, db, adminID)
checkout := createOpenPlatformCheckout(t, db, order, renter.ID)
checkout.OwnerIncomeAmountCent = 0
if err := db.Save(&checkout).Error; err != nil {
t.Fatalf("将号主收入调整为零失败: %v", err)
}
err := repo.AdminPlatformCheckoutConfirm(t.Context(), *order.ManagedAdminID, order.ID, AdminActionRequest{
Reason: "客服核对结算",
}, AuditMeta{})
if !errors.Is(err, ErrZeroOwnerIncomeConfirmation) {
t.Fatalf("未确认零收入时 error = %v, want %v", err, ErrZeroOwnerIncomeConfirmation)
}
var pending model.RentalOrder
if err := db.First(&pending, order.ID).Error; err != nil {
t.Fatalf("读取订单失败: %v", err)
}
if pending.Status != orderStatusPendingCheckoutConfirm {
t.Fatalf("未确认零收入后订单状态 = %s, want %s", pending.Status, orderStatusPendingCheckoutConfirm)
}
if err := repo.AdminPlatformCheckoutConfirm(t.Context(), *order.ManagedAdminID, order.ID, AdminActionRequest{
Reason: "已确认号主收入为零",
ConfirmZeroOwnerIncome: true,
}, AuditMeta{}); err != nil {
t.Fatalf("确认零收入后结算失败: %v", err)
}
var completed model.RentalOrder
if err := db.First(&completed, order.ID).Error; err != nil {
t.Fatalf("读取完成订单失败: %v", err)
}
if completed.Status != orderStatusCompleted {
t.Fatalf("确认零收入后订单状态 = %s, want %s", completed.Status, orderStatusCompleted)
}
}
@@ -22,6 +22,7 @@ var (
ErrOrderCannotComplete = errors.New("order cannot complete")
ErrCheckoutCannotSubmit = errors.New("checkout cannot submit")
ErrCheckoutCannotConfirm = errors.New("checkout cannot confirm")
ErrZeroOwnerIncomeConfirmation = errors.New("zero owner income confirmation required")
ErrCheckoutCannotCounter = errors.New("checkout cannot counter")
ErrCheckoutMaxRounds = errors.New("checkout max rounds reached")
ErrCheckoutDepositShortfall = errors.New("checkout deposit shortfall")