perf(query): 优化后台手机号精确查询
This commit is contained in:
@@ -11,7 +11,7 @@ import (
|
||||
|
||||
func (r *Repository) Disbursements(ctx context.Context, query DisbursementQuery) (*DisbursementListDTO, error) {
|
||||
var summary DisbursementListSummaryDTO
|
||||
summaryDB := r.applyDisbursementFilters(r.disbursementListBaseQuery(ctx), query)
|
||||
summaryDB := r.applyDisbursementFilters(r.disbursementListBaseQuery(ctx, query.Keyword), query)
|
||||
if err := summaryDB.Select(`COUNT(*) AS record_count,
|
||||
COALESCE(SUM(CASE WHEN status = 'paid' THEN actual_amount_cent ELSE 0 END), 0) AS paid_amount_cent,
|
||||
COALESCE(SUM(CASE WHEN status = 'paid' THEN 1 ELSE 0 END), 0) AS paid_count,
|
||||
@@ -30,7 +30,7 @@ func (r *Repository) Disbursements(ctx context.Context, query DisbursementQuery)
|
||||
orderColumn = "paid_at"
|
||||
}
|
||||
offset := (query.Page - 1) * query.PageSize
|
||||
rowsDB := r.applyDisbursementFilters(r.disbursementListBaseQuery(ctx), query)
|
||||
rowsDB := r.applyDisbursementFilters(r.disbursementListBaseQuery(ctx, query.Keyword), query)
|
||||
if err := rowsDB.Order(orderColumn + " DESC").
|
||||
Order("source_id DESC").
|
||||
Offset(offset).
|
||||
@@ -52,7 +52,7 @@ func (r *Repository) Disbursements(ctx context.Context, query DisbursementQuery)
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (r *Repository) disbursementListBaseQuery(ctx context.Context) *gorm.DB {
|
||||
func (r *Repository) disbursementListBaseQuery(ctx context.Context, phoneKeyword string) *gorm.DB {
|
||||
db := r.db.WithContext(ctx)
|
||||
platformManaged := db.Table("rental_orders AS ro").
|
||||
Select(`'platform_managed' AS source_type,
|
||||
@@ -213,6 +213,11 @@ func (r *Repository) disbursementListBaseQuery(ctx context.Context) *gorm.DB {
|
||||
Joins("LEFT JOIN users AS u ON u.id = wr.user_id").
|
||||
Joins("LEFT JOIN admin_users AS operator ON operator.id = COALESCE(wr.paid_by, wr.reviewed_by)")
|
||||
|
||||
if phoneKeyword = strings.TrimSpace(phoneKeyword); isPhoneKeyword(phoneKeyword) {
|
||||
withdrawal = withdrawal.Where("wr.user_id = (SELECT id FROM users WHERE phone = ?)", phoneKeyword)
|
||||
return db.Table("(?) AS d", withdrawal)
|
||||
}
|
||||
|
||||
manualOffline := db.Table("manual_disbursements AS md").
|
||||
Select(`'manual_offline' AS source_type,
|
||||
md.id AS source_id,
|
||||
@@ -267,9 +272,15 @@ func (r *Repository) applyDisbursementFilters(db *gorm.DB, query DisbursementQue
|
||||
db = db.Where("d.user_id = ?", query.UserID)
|
||||
}
|
||||
if query.Keyword != "" {
|
||||
like := "%" + query.Keyword + "%"
|
||||
db = db.Where(`(d.business_no LIKE ? OR d.payee_name LIKE ? OR d.payee_phone LIKE ?
|
||||
OR d.uploader_name LIKE ? OR d.account_name LIKE ? OR d.account_no LIKE ?)`, like, like, like, like, like, like)
|
||||
keyword := strings.TrimSpace(query.Keyword)
|
||||
if isPhoneKeyword(keyword) {
|
||||
// 完整手机号只可能命中提现收款人,先经 users(phone) 唯一索引解析用户。
|
||||
db = db.Where("d.source_type = ? AND d.user_id = (SELECT id FROM users WHERE phone = ?)", "withdrawal", keyword)
|
||||
} else {
|
||||
like := "%" + keyword + "%"
|
||||
db = db.Where(`(d.business_no LIKE ? OR d.payee_name LIKE ? OR d.payee_phone LIKE ?
|
||||
OR d.uploader_name LIKE ? OR d.account_name LIKE ? OR d.account_no LIKE ?)`, like, like, like, like, like, like)
|
||||
}
|
||||
}
|
||||
if query.Operator != "" {
|
||||
like := "%" + query.Operator + "%"
|
||||
@@ -288,6 +299,18 @@ func (r *Repository) applyDisbursementFilters(db *gorm.DB, query DisbursementQue
|
||||
return db
|
||||
}
|
||||
|
||||
func isPhoneKeyword(s string) bool {
|
||||
if len(s) != 11 || s[0] != '1' {
|
||||
return false
|
||||
}
|
||||
for i := 0; i < len(s); i++ {
|
||||
if s[i] < '0' || s[i] > '9' {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
type disbursementItemRow struct {
|
||||
SourceType string
|
||||
SourceID uint64
|
||||
|
||||
@@ -95,6 +95,22 @@ func TestDisbursementListCombinesPlatformSettlementsAndWithdrawals(t *testing.T)
|
||||
if result.Summary.ReviewPendingAmountCent != 5000 || result.Summary.ReviewPendingCount != 1 {
|
||||
t.Fatalf("待审核 = %d/%d, want 5000/1", result.Summary.ReviewPendingAmountCent, result.Summary.ReviewPendingCount)
|
||||
}
|
||||
phoneFiltered, err := repo.Disbursements(t.Context(), DisbursementQuery{
|
||||
Keyword: "13900000000",
|
||||
Page: 1,
|
||||
PageSize: 20,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("按完整手机号查询出款失败: %v", err)
|
||||
}
|
||||
if phoneFiltered.Total != 3 {
|
||||
t.Fatalf("按完整手机号查询记录数 = %d, want 3", phoneFiltered.Total)
|
||||
}
|
||||
for _, item := range phoneFiltered.Items {
|
||||
if item.SourceType != "withdrawal" || item.PayeePhone != "13900000000" {
|
||||
t.Fatalf("完整手机号筛选返回了不匹配记录: %+v", item)
|
||||
}
|
||||
}
|
||||
|
||||
var platformItem *DisbursementItemDTO
|
||||
for index := range result.Items {
|
||||
|
||||
Reference in New Issue
Block a user