fix(order): 修正仲裁后号主实际收入
This commit is contained in:
@@ -129,7 +129,8 @@ type AdminOrderListItemDTO struct {
|
|||||||
SettlementStatus string `json:"settlement_status"`
|
SettlementStatus string `json:"settlement_status"`
|
||||||
CreatedAt time.Time `json:"created_at"`
|
CreatedAt time.Time `json:"created_at"`
|
||||||
// OwnerIncomeAmountCent 为号主实际到手金额(分),仅在已结账/已仲裁订单上返回;
|
// OwnerIncomeAmountCent 为号主实际到手金额(分),仅在已结账/已仲裁订单上返回;
|
||||||
// 用指针区分「未结账(null)」与「到手 0 元」。数据来自结账表最新一行。
|
// 用指针区分「未结账(null)」与「到手 0 元」。平台代管订单取线下结算金额,
|
||||||
|
// 其他订单取号主钱包最终入账合计。
|
||||||
OwnerIncomeAmountCent *int64 `json:"owner_income_amount_cent,omitempty"`
|
OwnerIncomeAmountCent *int64 `json:"owner_income_amount_cent,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -199,7 +199,7 @@ func (r *Repository) ListAdmin(ctx context.Context, query AdminOrderQuery) (*Adm
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(incomeOrderIDs) > 0 {
|
if len(incomeOrderIDs) > 0 {
|
||||||
ownerIncome, err = r.latestOwnerIncomeByOrder(ctx, incomeOrderIDs)
|
ownerIncome, err = r.ownerActualIncomeByOrder(ctx, incomeOrderIDs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -255,48 +255,42 @@ func (r *Repository) adminOrderCountQuery(ctx context.Context, query AdminOrderQ
|
|||||||
return r.adminOrderJoinQuery(ctx)
|
return r.adminOrderJoinQuery(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
// latestOwnerIncomeByOrder 批量读取每单「最新一次结账」的号主实际到手金额(分)。
|
// ownerActualIncomeByOrder 批量读取每单号主最终实际结算金额(分)。
|
||||||
//
|
//
|
||||||
// 后台订单列表专用:一次查询覆盖整页,不会退化为逐行查询的 N+1。
|
// 结账行只能代表协商结果,不能代表仲裁后的最终落账:
|
||||||
// 只取结账表两列,不加载 content / evidence_urls 等大字段。
|
// - 平台代管订单:最终金额写入 rental_orders.offline_settlement_amount_cent;
|
||||||
|
// - 普通钱包订单:最终金额以 wallet_ledger 中号主的实际入账合计为准。
|
||||||
//
|
//
|
||||||
// 语义:多轮还价是原地更新同一行,但订单可能经历多次结账流程,
|
// 仲裁可能不更新历史结账行,甚至 dispute.checkout_id 为空,因此不能继续取
|
||||||
// 因此按 order_id 取 MAX(id) 作为最终结账行。
|
// order_checkouts 的 owner_income_amount_cent,否则列表会显示仲裁前金额。
|
||||||
//
|
func (r *Repository) ownerActualIncomeByOrder(ctx context.Context, orderIDs []uint64) (map[uint64]int64, error) {
|
||||||
// 执行计划(MySQL 8.4 实测,EXPLAIN FORMAT=TREE):
|
|
||||||
//
|
|
||||||
// -> Nested loop inner join
|
|
||||||
// -> Materialize
|
|
||||||
// -> Group aggregate: max(order_checkouts.id)
|
|
||||||
// -> Covering index scan on order_checkouts using idx_order_checkouts_order_id
|
|
||||||
// -> Single-row index lookup on oc using PRIMARY (id=latest.latest_id)
|
|
||||||
//
|
|
||||||
// 用 STRAIGHT_JOIN 固定连接顺序:先物化「每单最新结账 id」小集合(走
|
|
||||||
// idx_order_checkouts_order_id 覆盖索引),再按主键逐行取金额。避免优化器
|
|
||||||
// 在数据量增长后改选全表扫描;开销只与当前页订单数相关,与结账表总量无关。
|
|
||||||
func (r *Repository) latestOwnerIncomeByOrder(ctx context.Context, orderIDs []uint64) (map[uint64]int64, error) {
|
|
||||||
result := make(map[uint64]int64, len(orderIDs))
|
result := make(map[uint64]int64, len(orderIDs))
|
||||||
if len(orderIDs) == 0 {
|
if len(orderIDs) == 0 {
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
latest := r.db.WithContext(ctx).
|
|
||||||
Table("order_checkouts").
|
|
||||||
Select("order_id, MAX(id) AS latest_id").
|
|
||||||
Where("order_id IN ?", orderIDs).
|
|
||||||
Group("order_id")
|
|
||||||
var rows []struct {
|
var rows []struct {
|
||||||
OrderID uint64
|
ID uint64
|
||||||
OwnerIncomeAmountCent int64
|
OwnerIncomeAmountCent int64
|
||||||
}
|
}
|
||||||
if err := r.db.WithContext(ctx).
|
if err := r.db.WithContext(ctx).
|
||||||
Table("(?) AS latest", latest).
|
Table("rental_orders AS o").
|
||||||
Select("oc.order_id, oc.owner_income_amount_cent").
|
Select(`o.id,
|
||||||
Joins("STRAIGHT_JOIN order_checkouts AS oc ON oc.id = latest.latest_id").
|
CASE WHEN o.settlement_mode = 'platform_managed'
|
||||||
|
THEN COALESCE(o.offline_settlement_amount_cent, 0)
|
||||||
|
ELSE COALESCE(SUM(wl.amount_cent), 0)
|
||||||
|
END AS owner_income_amount_cent`).
|
||||||
|
Joins(`LEFT JOIN wallet_ledger AS wl
|
||||||
|
ON wl.order_id = o.id
|
||||||
|
AND wl.user_id = o.owner_id
|
||||||
|
AND wl.direction = 'in'
|
||||||
|
AND wl.biz_type IN ?`, []string{walletBizOwnerIncome, walletBizDepositCompensation, "arbitration_owner_income"}).
|
||||||
|
Where("o.id IN ?", orderIDs).
|
||||||
|
Group("o.id, o.settlement_mode, o.offline_settlement_amount_cent").
|
||||||
Scan(&rows).Error; err != nil {
|
Scan(&rows).Error; err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
for _, row := range rows {
|
for _, row := range rows {
|
||||||
result[row.OrderID] = row.OwnerIncomeAmountCent
|
result[row.ID] = row.OwnerIncomeAmountCent
|
||||||
}
|
}
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2160,23 +2160,25 @@ func createOpenPlatformCheckout(t *testing.T, db *gorm.DB, order model.RentalOrd
|
|||||||
return checkout
|
return checkout
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestListAdminUsesFinalizedCheckoutOwnerIncome 校验后台订单列表带回「号主实际收入」,
|
// TestListAdminPlatformManagedArbitrationUsesOfflineSettlement 校验平台代管订单仲裁后
|
||||||
// 且金额取自结账表最终行(已结账/已仲裁时才是定论值)。
|
// 列表读取线下实际结算金额,不能继续展示旧结账行中的金额。
|
||||||
func TestListAdminUsesFinalizedCheckoutOwnerIncome(t *testing.T) {
|
func TestListAdminPlatformManagedArbitrationUsesOfflineSettlement(t *testing.T) {
|
||||||
db := setupOrderTestDB(t)
|
db := setupOrderTestDB(t)
|
||||||
repo := NewRepository(db)
|
repo := NewRepository(db)
|
||||||
adminID := uint64(7002)
|
adminID := uint64(7002)
|
||||||
_, renter, order := createPlatformManagedCheckoutOrder(t, db, adminID)
|
_, renter, order := createPlatformManagedCheckoutOrder(t, db, adminID)
|
||||||
order.Status = orderStatusCompleted
|
order.Status = orderStatusCompleted
|
||||||
order.SettlementStatus = settlementStatusSettled
|
order.SettlementStatus = settlementStatusArbitrated
|
||||||
|
order.OfflineSettlementStatus = offlineSettlementStatusSettled
|
||||||
|
order.OfflineSettlementAmountCent = 382
|
||||||
if err := db.Save(&order).Error; err != nil {
|
if err := db.Save(&order).Error; err != nil {
|
||||||
t.Fatalf("save completed order failed: %v", err)
|
t.Fatalf("save arbitrated order failed: %v", err)
|
||||||
}
|
}
|
||||||
checkout := createOpenPlatformCheckout(t, db, order, renter.ID)
|
checkout := createOpenPlatformCheckout(t, db, order, renter.ID)
|
||||||
checkout.Status = checkoutStatusAccepted
|
// 模拟仲裁前遗留的结账金额,列表不能把它当成最终收入。
|
||||||
checkout.OwnerIncomeAmountCent = 6000
|
checkout.OwnerIncomeAmountCent = 6000
|
||||||
if err := db.Save(&checkout).Error; err != nil {
|
if err := db.Save(&checkout).Error; err != nil {
|
||||||
t.Fatalf("save finalized checkout failed: %v", err)
|
t.Fatalf("save stale checkout failed: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
result, err := repo.ListAdmin(t.Context(), AdminOrderQuery{Page: 1, PageSize: 20})
|
result, err := repo.ListAdmin(t.Context(), AdminOrderQuery{Page: 1, PageSize: 20})
|
||||||
@@ -2186,16 +2188,15 @@ func TestListAdminUsesFinalizedCheckoutOwnerIncome(t *testing.T) {
|
|||||||
if len(result.Items) != 1 {
|
if len(result.Items) != 1 {
|
||||||
t.Fatalf("ListAdmin() returned %d items, want 1", len(result.Items))
|
t.Fatalf("ListAdmin() returned %d items, want 1", len(result.Items))
|
||||||
}
|
}
|
||||||
if result.Items[0].SettlementStatus != settlementStatusSettled {
|
if result.Items[0].SettlementStatus != settlementStatusArbitrated {
|
||||||
t.Fatalf("settlement status = %q, want %q", result.Items[0].SettlementStatus, settlementStatusSettled)
|
t.Fatalf("settlement status = %q, want %q", result.Items[0].SettlementStatus, settlementStatusArbitrated)
|
||||||
}
|
}
|
||||||
// 列表需直接展示号主实际收入,供客服在列表页核对结算。
|
|
||||||
income := result.Items[0].OwnerIncomeAmountCent
|
income := result.Items[0].OwnerIncomeAmountCent
|
||||||
if income == nil {
|
if income == nil {
|
||||||
t.Fatalf("owner income = nil, want 6000 for settled order")
|
t.Fatalf("owner income = nil, want 382 for platform-managed arbitrated order")
|
||||||
}
|
}
|
||||||
if *income != 6000 {
|
if *income != 382 {
|
||||||
t.Fatalf("owner income = %d, want 6000", *income)
|
t.Fatalf("owner income = %d, want 382", *income)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2227,28 +2228,54 @@ func TestListAdminOmitsOwnerIncomeWhileNegotiating(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestListAdminOwnerIncomeUsesLatestCheckout 校验一单存在多行结账记录时取最新一行(MAX(id))。
|
// TestListAdminWalletArbitrationUsesWalletIncome 校验普通钱包订单仲裁后列表汇总
|
||||||
func TestListAdminOwnerIncomeUsesLatestCheckout(t *testing.T) {
|
// 号主实际钱包入账,而不是读取仲裁前遗留的结账金额。
|
||||||
|
func TestListAdminWalletArbitrationUsesWalletIncome(t *testing.T) {
|
||||||
db := setupOrderTestDB(t)
|
db := setupOrderTestDB(t)
|
||||||
repo := NewRepository(db)
|
repo := NewRepository(db)
|
||||||
adminID := uint64(7004)
|
adminID := uint64(7004)
|
||||||
_, renter, order := createPlatformManagedCheckoutOrder(t, db, adminID)
|
owner, renter, order := createPlatformManagedCheckoutOrder(t, db, adminID)
|
||||||
order.Status = orderStatusCompleted
|
order.Status = orderStatusCompleted
|
||||||
order.SettlementStatus = settlementStatusSettled
|
order.SettlementStatus = settlementStatusArbitrated
|
||||||
|
order.SettlementMode = settlementModeOwnerWallet
|
||||||
|
order.OfflineSettlementStatus = offlineSettlementStatusNone
|
||||||
|
order.OfflineSettlementAmountCent = 0
|
||||||
if err := db.Save(&order).Error; err != nil {
|
if err := db.Save(&order).Error; err != nil {
|
||||||
t.Fatalf("save completed order failed: %v", err)
|
t.Fatalf("save arbitrated order failed: %v", err)
|
||||||
}
|
}
|
||||||
first := createOpenPlatformCheckout(t, db, order, renter.ID)
|
checkout := createOpenPlatformCheckout(t, db, order, renter.ID)
|
||||||
first.Status = checkoutStatusAccepted
|
checkout.OwnerIncomeAmountCent = 56013
|
||||||
first.OwnerIncomeAmountCent = 1111
|
if err := db.Save(&checkout).Error; err != nil {
|
||||||
if err := db.Save(&first).Error; err != nil {
|
t.Fatalf("save stale checkout failed: %v", err)
|
||||||
t.Fatalf("save first checkout failed: %v", err)
|
|
||||||
}
|
}
|
||||||
second := createOpenPlatformCheckout(t, db, order, renter.ID)
|
|
||||||
second.Status = checkoutStatusAccepted
|
orderID := order.ID
|
||||||
second.OwnerIncomeAmountCent = 2222
|
ledgers := []model.WalletLedger{
|
||||||
if err := db.Save(&second).Error; err != nil {
|
{
|
||||||
t.Fatalf("save second checkout failed: %v", err)
|
LedgerNo: "WL-ARBITRATION-OWNER",
|
||||||
|
UserID: owner.ID,
|
||||||
|
OrderID: &orderID,
|
||||||
|
Direction: "in",
|
||||||
|
AmountCent: 38613,
|
||||||
|
BalanceType: "available",
|
||||||
|
BizType: "arbitration_owner_income",
|
||||||
|
BizNo: order.OrderNo,
|
||||||
|
Remark: "仲裁按实际消耗结算给号主",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
LedgerNo: "WL-ARBITRATION-OTHER-USER",
|
||||||
|
UserID: renter.ID,
|
||||||
|
OrderID: &orderID,
|
||||||
|
Direction: "in",
|
||||||
|
AmountCent: 999999,
|
||||||
|
BalanceType: "available",
|
||||||
|
BizType: "arbitration_owner_income",
|
||||||
|
BizNo: order.OrderNo,
|
||||||
|
Remark: "不应计入号主收入",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
if err := db.Create(&ledgers).Error; err != nil {
|
||||||
|
t.Fatalf("create wallet ledgers failed: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
result, err := repo.ListAdmin(t.Context(), AdminOrderQuery{Page: 1, PageSize: 20})
|
result, err := repo.ListAdmin(t.Context(), AdminOrderQuery{Page: 1, PageSize: 20})
|
||||||
@@ -2259,8 +2286,36 @@ func TestListAdminOwnerIncomeUsesLatestCheckout(t *testing.T) {
|
|||||||
t.Fatalf("ListAdmin() returned %d items, want 1", len(result.Items))
|
t.Fatalf("ListAdmin() returned %d items, want 1", len(result.Items))
|
||||||
}
|
}
|
||||||
income := result.Items[0].OwnerIncomeAmountCent
|
income := result.Items[0].OwnerIncomeAmountCent
|
||||||
if income == nil || *income != 2222 {
|
if income == nil || *income != 38613 {
|
||||||
t.Fatalf("owner income = %v, want 2222 from latest checkout row", income)
|
t.Fatalf("owner income = %v, want 38613 from arbitration wallet income", income)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestListAdminArbitratedWithoutPayoutReturnsZero 校验仲裁已经形成终态但无实际入账时,
|
||||||
|
// 列表返回明确的 0 元,而不是因为缺少结账行显示为未知(null)。
|
||||||
|
func TestListAdminArbitratedWithoutPayoutReturnsZero(t *testing.T) {
|
||||||
|
db := setupOrderTestDB(t)
|
||||||
|
repo := NewRepository(db)
|
||||||
|
adminID := uint64(7005)
|
||||||
|
_, _, order := createPlatformManagedCheckoutOrder(t, db, adminID)
|
||||||
|
order.Status = orderStatusClosed
|
||||||
|
order.SettlementStatus = settlementStatusArbitrated
|
||||||
|
order.OfflineSettlementStatus = offlineSettlementStatusNone
|
||||||
|
order.OfflineSettlementAmountCent = 0
|
||||||
|
if err := db.Save(&order).Error; err != nil {
|
||||||
|
t.Fatalf("save arbitrated order failed: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err := repo.ListAdmin(t.Context(), AdminOrderQuery{Page: 1, PageSize: 20})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("ListAdmin() error = %v", err)
|
||||||
|
}
|
||||||
|
if len(result.Items) != 1 {
|
||||||
|
t.Fatalf("ListAdmin() returned %d items, want 1", len(result.Items))
|
||||||
|
}
|
||||||
|
income := result.Items[0].OwnerIncomeAmountCent
|
||||||
|
if income == nil || *income != 0 {
|
||||||
|
t.Fatalf("owner income = %v, want explicit zero for arbitrated order without payout", income)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2513,23 +2568,24 @@ func seedSettledAdminOrders(t *testing.T, db *gorm.DB, from, to int) {
|
|||||||
t.Fatalf("create listing %d failed: %v", i, err)
|
t.Fatalf("create listing %d failed: %v", i, err)
|
||||||
}
|
}
|
||||||
order := model.RentalOrder{
|
order := model.RentalOrder{
|
||||||
OrderNo: fmt.Sprintf("ORD-N1-%04d", i),
|
OrderNo: fmt.Sprintf("ORD-N1-%04d", i),
|
||||||
ListingID: listing.ID,
|
ListingID: listing.ID,
|
||||||
AccountID: account.ID,
|
AccountID: account.ID,
|
||||||
OwnerID: owner.ID,
|
OwnerID: owner.ID,
|
||||||
RenterID: renter.ID,
|
RenterID: renter.ID,
|
||||||
Status: orderStatusCompleted,
|
Status: orderStatusCompleted,
|
||||||
SettlementStatus: settlementStatusSettled,
|
SettlementStatus: settlementStatusSettled,
|
||||||
HandoffMode: handoffModePlatform,
|
HandoffMode: handoffModePlatform,
|
||||||
SettlementMode: settlementModePlatformManaged,
|
SettlementMode: settlementModePlatformManaged,
|
||||||
ManagedAdminID: &adminID,
|
ManagedAdminID: &adminID,
|
||||||
RentAmountCent: 10000,
|
RentAmountCent: 10000,
|
||||||
OwnerRentAmountCent: 8000,
|
OwnerRentAmountCent: 8000,
|
||||||
PlatformFeeCent: 2000,
|
PlatformFeeCent: 2000,
|
||||||
DepositAmountCent: 1000,
|
DepositAmountCent: 1000,
|
||||||
EstimatedDurationHours: 24,
|
EstimatedDurationHours: 24,
|
||||||
OfflineSettlementStatus: offlineSettlementStatusNone,
|
OfflineSettlementStatus: offlineSettlementStatusNone,
|
||||||
AccountSnapshot: datatypes.JSON([]byte(`{"haf_coin_amount":1000000}`)),
|
OfflineSettlementAmountCent: int64(1000 + i),
|
||||||
|
AccountSnapshot: datatypes.JSON([]byte(`{"haf_coin_amount":1000000}`)),
|
||||||
}
|
}
|
||||||
if err := db.Create(&order).Error; err != nil {
|
if err := db.Create(&order).Error; err != nil {
|
||||||
t.Fatalf("create order %d failed: %v", i, err)
|
t.Fatalf("create order %d failed: %v", i, err)
|
||||||
@@ -2600,26 +2656,28 @@ func (c *sqlCaptureLogger) Trace(_ context.Context, _ time.Time, fc func() (stri
|
|||||||
c.statements = append(c.statements, sql)
|
c.statements = append(c.statements, sql)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestLatestOwnerIncomeQueryIsSingleBatchStatement 锁定号主实际收入的取数形态:
|
// TestOwnerActualIncomeQueryIsSingleBatchStatement 锁定号主实际收入的取数形态:
|
||||||
// 整页一条语句、用 STRAIGHT_JOIN 固定「先物化最新结账 id,再按主键取金额」的顺序。
|
// 整页一条语句,平台代管读取线下结算金额,其他订单汇总钱包最终入账。
|
||||||
// 该形态对应 EXPLAIN:覆盖索引扫描 + 主键单行查找,不随行数产生额外查询。
|
func TestOwnerActualIncomeQueryIsSingleBatchStatement(t *testing.T) {
|
||||||
func TestLatestOwnerIncomeQueryIsSingleBatchStatement(t *testing.T) {
|
|
||||||
capture := &sqlCaptureLogger{Interface: logger.Default.LogMode(logger.Silent)}
|
capture := &sqlCaptureLogger{Interface: logger.Default.LogMode(logger.Silent)}
|
||||||
db := setupOrderTestDB(t).Session(&gorm.Session{Logger: capture})
|
db := setupOrderTestDB(t).Session(&gorm.Session{Logger: capture})
|
||||||
repo := NewRepository(db)
|
repo := NewRepository(db)
|
||||||
|
|
||||||
if _, err := repo.latestOwnerIncomeByOrder(t.Context(), []uint64{11, 12, 13}); err != nil {
|
if _, err := repo.ownerActualIncomeByOrder(t.Context(), []uint64{11, 12, 13}); err != nil {
|
||||||
t.Fatalf("latestOwnerIncomeByOrder() error = %v", err)
|
t.Fatalf("ownerActualIncomeByOrder() error = %v", err)
|
||||||
}
|
}
|
||||||
if len(capture.statements) != 1 {
|
if len(capture.statements) != 1 {
|
||||||
t.Fatalf("取数语句条数 = %d, want 1(多行必须合并为单条批量查询)", len(capture.statements))
|
t.Fatalf("取数语句条数 = %d, want 1(多行必须合并为单条批量查询)", len(capture.statements))
|
||||||
}
|
}
|
||||||
sql := capture.statements[0]
|
sql := capture.statements[0]
|
||||||
if !strings.Contains(sql, "STRAIGHT_JOIN order_checkouts") {
|
if !strings.Contains(sql, "LEFT JOIN wallet_ledger AS wl") {
|
||||||
t.Fatalf("缺少 STRAIGHT_JOIN 固定连接顺序,实际 SQL:\n%s", sql)
|
t.Fatalf("缺少钱包入账汇总,实际 SQL:\n%s", sql)
|
||||||
|
}
|
||||||
|
if !strings.Contains(sql, "offline_settlement_amount_cent") {
|
||||||
|
t.Fatalf("缺少平台代管线下结算金额,实际 SQL:\n%s", sql)
|
||||||
}
|
}
|
||||||
if !strings.Contains(sql, "GROUP BY") {
|
if !strings.Contains(sql, "GROUP BY") {
|
||||||
t.Fatalf("缺少按 order_id 分组的 MAX(id) 子查询,实际 SQL:\n%s", sql)
|
t.Fatalf("缺少按订单分组汇总,实际 SQL:\n%s", sql)
|
||||||
}
|
}
|
||||||
if strings.Contains(sql, "SELECT *") {
|
if strings.Contains(sql, "SELECT *") {
|
||||||
t.Fatalf("应只取所需列,避免读取 content/evidence_urls 大字段,实际 SQL:\n%s", sql)
|
t.Fatalf("应只取所需列,避免读取 content/evidence_urls 大字段,实际 SQL:\n%s", sql)
|
||||||
|
|||||||
@@ -42,6 +42,8 @@ require_pattern "backend/internal/modules/pickup/repository.go" "if pageSize > 1
|
|||||||
require_pattern "backend/internal/modules/order/queries.go" "o.order_no = ?" "订单列表订单号唯一索引直达"
|
require_pattern "backend/internal/modules/order/queries.go" "o.order_no = ?" "订单列表订单号唯一索引直达"
|
||||||
require_pattern "backend/internal/modules/order/queries.go" "l.listing_no = ?" "订单列表商品号唯一索引直达"
|
require_pattern "backend/internal/modules/order/queries.go" "l.listing_no = ?" "订单列表商品号唯一索引直达"
|
||||||
require_pattern "backend/internal/modules/order/queries.go" "o.owner_id = (SELECT id FROM users WHERE phone = ?)" "订单列表手机号解析用户索引直达"
|
require_pattern "backend/internal/modules/order/queries.go" "o.owner_id = (SELECT id FROM users WHERE phone = ?)" "订单列表手机号解析用户索引直达"
|
||||||
|
require_pattern "backend/internal/modules/order/queries.go" "LEFT JOIN wallet_ledger AS wl" "订单列表号主实际收入取最终钱包入账"
|
||||||
|
require_pattern "backend/internal/modules/order/queries.go" "offline_settlement_amount_cent" "订单列表平台代管收入取线下结算金额"
|
||||||
require_pattern "backend/internal/modules/order/queries.go" "page == 1 && len(rows) < pageSize" "订单列表首页面单扫描短路"
|
require_pattern "backend/internal/modules/order/queries.go" "page == 1 && len(rows) < pageSize" "订单列表首页面单扫描短路"
|
||||||
|
|
||||||
require_pattern "backend/internal/modules/pickup/repository.go" "p.pickup_no = ?" "提号列表提号单号唯一索引直达"
|
require_pattern "backend/internal/modules/pickup/repository.go" "p.pickup_no = ?" "提号列表提号单号唯一索引直达"
|
||||||
|
|||||||
Reference in New Issue
Block a user