diff --git a/internal/handler/public/user/queryCommissionReturnLogHandler_test.go b/internal/handler/public/user/queryCommissionReturnLogHandler_test.go index 965752d..b8371da 100644 --- a/internal/handler/public/user/queryCommissionReturnLogHandler_test.go +++ b/internal/handler/public/user/queryCommissionReturnLogHandler_test.go @@ -2,6 +2,7 @@ package user import ( "context" + "database/sql/driver" "fmt" "net/http" "net/http/httptest" @@ -25,7 +26,7 @@ func TestCommissionReturnLogHandler_HTTPResponse(t *testing.T) { db, mock, cleanup := newCommissionReturnHandlerTestDB(t) defer cleanup() - expectCommissionReturnHTTPQueries(mock, 42, 3) + expectCommissionReturnHTTPQueries(mock, 42, 3, logmodel.CommissionTypeRefund, logmodel.CommissionTypeWithdrawReject, logmodel.CommissionTypeWithdrawCancel) mock.ExpectQuery("SELECT * FROM `system_logs` WHERE `type` = ? AND object_id = ? AND (`content` LIKE ? OR `content` LIKE ? OR `content` LIKE ?) ORDER BY id DESC LIMIT ?"). WithArgs(logmodel.TypeCommission.Uint8(), int64(42), "%\"type\":333%", "%\"type\":337%", "%\"type\":338%", 10). WillReturnRows(sqlmock.NewRows([]string{"id", "type", "date", "object_id", "content", "created_at"}). @@ -62,12 +63,10 @@ func TestWithdrawalLogHandler_CommissionRefundHTTPResponse(t *testing.T) { db, mock, cleanup := newCommissionReturnHandlerTestDB(t) defer cleanup() - expectCommissionReturnHTTPQueries(mock, 42, 3) - mock.ExpectQuery("SELECT * FROM `system_logs` WHERE `type` = ? AND object_id = ? AND (`content` LIKE ? OR `content` LIKE ? OR `content` LIKE ?) ORDER BY id DESC LIMIT ?"). - WithArgs(logmodel.TypeCommission.Uint8(), int64(42), "%\"type\":333%", "%\"type\":337%", "%\"type\":338%", 10). + expectCommissionReturnHTTPQueries(mock, 42, 1, logmodel.CommissionTypeRefund) + mock.ExpectQuery("SELECT * FROM `system_logs` WHERE `type` = ? AND object_id = ? AND (`content` LIKE ?) ORDER BY id DESC LIMIT ?"). + WithArgs(logmodel.TypeCommission.Uint8(), int64(42), "%\"type\":333%", 10). WillReturnRows(sqlmock.NewRows([]string{"id", "type", "date", "object_id", "content", "created_at"}). - AddRow(int64(2003), logmodel.TypeCommission.Uint8(), "2023-11-14", int64(42), `{"type":338,"amount":1500,"order_no":"ORDER-3","timestamp":1700000003123}`, time.Unix(1700000000, 0)). - AddRow(int64(2002), logmodel.TypeCommission.Uint8(), "2023-11-14", int64(42), `{"type":337,"amount":2000,"order_no":"ORDER-2","timestamp":1700000002123}`, time.Unix(1700000000, 0)). AddRow(int64(2001), logmodel.TypeCommission.Uint8(), "2023-11-14", int64(42), `{"type":333,"amount":2500,"order_no":"ORDER-1","timestamp":1700000001123}`, time.Unix(1700000000, 0))) router := gin.New() @@ -85,7 +84,7 @@ func TestWithdrawalLogHandler_CommissionRefundHTTPResponse(t *testing.T) { body := strings.TrimSpace(rec.Body.String()) t.Logf("withdrawal_log commission_refund response: %s", body) - if !strings.Contains(body, `"biz_type":"commission_refund"`) || !strings.Contains(body, `"amount":1500`) || !strings.Contains(body, `"amount":2000`) || !strings.Contains(body, `"amount":2500`) { + if !strings.Contains(body, `"biz_type":"commission_refund"`) || !strings.Contains(body, `"amount":2500`) || strings.Contains(body, `"amount":1500`) || strings.Contains(body, `"amount":2000`) { t.Fatalf("response body = %s", body) } if err := mock.ExpectationsWereMet(); err != nil { @@ -125,8 +124,18 @@ func injectTestUser(userID int64) gin.HandlerFunc { } } -func expectCommissionReturnHTTPQueries(mock sqlmock.Sqlmock, userID int64, total int64) { - mock.ExpectQuery("SELECT count(*) FROM `system_logs` WHERE `type` = ? AND object_id = ? AND (`content` LIKE ? OR `content` LIKE ? OR `content` LIKE ?)"). - WithArgs(logmodel.TypeCommission.Uint8(), userID, "%\"type\":333%", "%\"type\":337%", "%\"type\":338%"). +func expectCommissionReturnHTTPQueries(mock sqlmock.Sqlmock, userID int64, total int64, eventTypes ...uint16) { + query := "SELECT count(*) FROM `system_logs` WHERE `type` = ? AND object_id = ?" + args := []driver.Value{logmodel.TypeCommission.Uint8(), userID} + if len(eventTypes) > 0 { + clauses := make([]string, 0, len(eventTypes)) + for _, eventType := range eventTypes { + clauses = append(clauses, "`content` LIKE ?") + args = append(args, fmt.Sprintf("%%\"type\":%d%%", eventType)) + } + query += " AND (" + strings.Join(clauses, " OR ") + ")" + } + mock.ExpectQuery(query). + WithArgs(args...). WillReturnRows(sqlmock.NewRows([]string{"count"}).AddRow(total)) } diff --git a/internal/logic/public/user/queryCommissionReturnLogLogic.go b/internal/logic/public/user/queryCommissionReturnLogLogic.go index 4c46137..55250a6 100644 --- a/internal/logic/public/user/queryCommissionReturnLogLogic.go +++ b/internal/logic/public/user/queryCommissionReturnLogLogic.go @@ -2,6 +2,8 @@ package user import ( "context" + "strconv" + "strings" "github.com/perfect-panel/server/internal/model/log" "github.com/perfect-panel/server/internal/model/user" @@ -81,15 +83,28 @@ func normalizePagination(page, size int) (int, int) { } func (l *QueryCommissionReturnLogLogic) queryCommissionReturnLogRecords(userID int64, page, size int) ([]commissionReturnLogRecord, int64, error) { + return l.queryCommissionReturnLogRecordsByEventTypes(userID, page, size, + log.CommissionTypeRefund, + log.CommissionTypeWithdrawReject, + log.CommissionTypeWithdrawCancel, + ) +} + +func (l *QueryCommissionReturnLogLogic) queryCommissionReturnLogRecordsByEventTypes(userID int64, page, size int, eventTypes ...uint16) ([]commissionReturnLogRecord, int64, error) { + if len(eventTypes) == 0 { + return []commissionReturnLogRecord{}, 0, nil + } + + likeClauses := make([]string, 0, len(eventTypes)) + args := make([]interface{}, 0, len(eventTypes)+2) + args = append(args, log.TypeCommission.Uint8(), userID) + for _, eventType := range eventTypes { + likeClauses = append(likeClauses, "`content` LIKE ?") + args = append(args, commissionReturnLogEventTypePattern(eventType)) + } query := l.svcCtx.DB.WithContext(l.ctx). Model(&log.SystemLog{}). - Where("`type` = ? AND object_id = ? AND (`content` LIKE ? OR `content` LIKE ? OR `content` LIKE ?)", - log.TypeCommission.Uint8(), - userID, - "%\"type\":333%", - "%\"type\":337%", - "%\"type\":338%", - ) + Where("`type` = ? AND object_id = ? AND ("+strings.Join(likeClauses, " OR ")+")", args...) var total int64 if err := query.Count(&total).Error; err != nil { @@ -133,6 +148,10 @@ func (l *QueryCommissionReturnLogLogic) queryCommissionReturnLogRecords(userID i return list, total, nil } +func commissionReturnLogEventTypePattern(eventType uint16) string { + return "%\"type\":" + strconv.FormatUint(uint64(eventType), 10) + "%" +} + func isCommissionReturnEventType(eventType uint16) bool { switch eventType { case log.CommissionTypeRefund, log.CommissionTypeWithdrawReject, log.CommissionTypeWithdrawCancel: diff --git a/internal/logic/public/user/queryWithdrawalLogLogic.go b/internal/logic/public/user/queryWithdrawalLogLogic.go index d86a75e..b8e74a0 100644 --- a/internal/logic/public/user/queryWithdrawalLogLogic.go +++ b/internal/logic/public/user/queryWithdrawalLogLogic.go @@ -3,6 +3,7 @@ package user import ( "context" + "github.com/perfect-panel/server/internal/model/log" "github.com/perfect-panel/server/internal/model/user" "github.com/perfect-panel/server/internal/svc" "github.com/perfect-panel/server/internal/types" @@ -90,7 +91,7 @@ func (l *QueryWithdrawalLogLogic) queryWithdrawalLogs(userID int64, page, size i func (l *QueryWithdrawalLogLogic) queryCommissionRefundLogs(userID int64, page, size int) (*types.QueryWithdrawalLogListResponse, error) { queryLogic := NewQueryCommissionReturnLogLogic(l.ctx, l.svcCtx) - rows, total, err := queryLogic.queryCommissionReturnLogRecords(userID, page, size) + rows, total, err := queryLogic.queryCommissionReturnLogRecordsByEventTypes(userID, page, size, log.CommissionTypeRefund) if err != nil { return nil, err } diff --git a/internal/logic/public/user/queryWithdrawalLogLogic_test.go b/internal/logic/public/user/queryWithdrawalLogLogic_test.go index f9ce32e..8e1f264 100644 --- a/internal/logic/public/user/queryWithdrawalLogLogic_test.go +++ b/internal/logic/public/user/queryWithdrawalLogLogic_test.go @@ -3,6 +3,7 @@ package user import ( "bytes" "context" + "database/sql/driver" "fmt" "strings" "testing" @@ -69,7 +70,7 @@ func TestQueryCommissionReturnLog_HappyPathIncludes333337338(t *testing.T) { db, mock, cleanup := newQueryWithdrawalLogTestDB(t) defer cleanup() - expectCommissionReturnQueries(mock, userID, 3) + expectCommissionReturnQueries(mock, userID, 3, logmodel.CommissionTypeRefund, logmodel.CommissionTypeWithdrawReject, logmodel.CommissionTypeWithdrawCancel) mock.ExpectQuery("SELECT * FROM `system_logs` WHERE `type` = ? AND object_id = ? AND (`content` LIKE ? OR `content` LIKE ? OR `content` LIKE ?) ORDER BY id DESC LIMIT ?"). WithArgs(logmodel.TypeCommission.Uint8(), userID, "%\"type\":333%", "%\"type\":337%", "%\"type\":338%", 10). WillReturnRows(sqlmock.NewRows([]string{"id", "type", "date", "object_id", "content", "created_at"}). @@ -95,19 +96,17 @@ func TestQueryCommissionReturnLog_HappyPathIncludes333337338(t *testing.T) { assertQueryWithdrawalLogExpectations(t, mock) } -func TestQueryWithdrawalLog_WithCommissionRefundBizTypeIncludes333337338(t *testing.T) { +func TestQueryWithdrawalLog_WithCommissionRefundBizTypeOnlyIncludes333(t *testing.T) { const userID = int64(42) createdAt := time.Unix(1700000000, 0) db, mock, cleanup := newQueryWithdrawalLogTestDB(t) defer cleanup() - expectCommissionReturnQueries(mock, userID, 3) - mock.ExpectQuery("SELECT * FROM `system_logs` WHERE `type` = ? AND object_id = ? AND (`content` LIKE ? OR `content` LIKE ? OR `content` LIKE ?) ORDER BY id DESC LIMIT ?"). - WithArgs(logmodel.TypeCommission.Uint8(), userID, "%\"type\":333%", "%\"type\":337%", "%\"type\":338%", 10). + expectCommissionReturnQueries(mock, userID, 1, logmodel.CommissionTypeRefund) + mock.ExpectQuery("SELECT * FROM `system_logs` WHERE `type` = ? AND object_id = ? AND (`content` LIKE ?) ORDER BY id DESC LIMIT ?"). + WithArgs(logmodel.TypeCommission.Uint8(), userID, "%\"type\":333%", 10). WillReturnRows(sqlmock.NewRows([]string{"id", "type", "date", "object_id", "content", "created_at"}). - AddRow(int64(2003), logmodel.TypeCommission.Uint8(), "2023-11-14", userID, `{"type":338,"amount":1500,"order_no":"ORDER-3","timestamp":1700000003123}`, createdAt). - AddRow(int64(2002), logmodel.TypeCommission.Uint8(), "2023-11-14", userID, `{"type":337,"amount":2000,"order_no":"ORDER-2","timestamp":1700000002123}`, createdAt). AddRow(int64(2001), logmodel.TypeCommission.Uint8(), "2023-11-14", userID, `{"type":333,"amount":2500,"order_no":"ORDER-1","timestamp":1700000001123}`, createdAt)) logic := newTestQueryWithdrawalLogLogic(t, db, userID) @@ -119,8 +118,8 @@ func TestQueryWithdrawalLog_WithCommissionRefundBizTypeIncludes333337338(t *test if err != nil { t.Fatalf("QueryWithdrawalLog unexpected error: %v", err) } - if resp.Total != 3 || len(resp.List) != 3 { - t.Fatalf("QueryWithdrawalLog response = %+v, want three commission returns", resp) + if resp.Total != 1 || len(resp.List) != 1 { + t.Fatalf("QueryWithdrawalLog response = %+v, want one commission refund", resp) } for _, item := range resp.List { if item.BizType != withdrawalLogBizTypeCommissionRefund { @@ -130,6 +129,9 @@ func TestQueryWithdrawalLog_WithCommissionRefundBizTypeIncludes333337338(t *test t.Fatalf("withdrawal-only fields should keep zero values, got %+v", item) } } + if resp.List[0].Id != 2001 { + t.Fatalf("commission refund item id = %d, want 2001", resp.List[0].Id) + } assertQueryWithdrawalLogExpectations(t, mock) } @@ -140,7 +142,7 @@ func TestQueryCommissionReturnLog_SkipsInvalidJSONAndLogsWarn(t *testing.T) { db, mock, cleanup := newQueryWithdrawalLogTestDB(t) defer cleanup() - expectCommissionReturnQueries(mock, userID, 2) + expectCommissionReturnQueries(mock, userID, 2, logmodel.CommissionTypeRefund, logmodel.CommissionTypeWithdrawReject, logmodel.CommissionTypeWithdrawCancel) mock.ExpectQuery("SELECT * FROM `system_logs` WHERE `type` = ? AND object_id = ? AND (`content` LIKE ? OR `content` LIKE ? OR `content` LIKE ?) ORDER BY id DESC LIMIT ?"). WithArgs(logmodel.TypeCommission.Uint8(), userID, "%\"type\":333%", "%\"type\":337%", "%\"type\":338%", 10). WillReturnRows(sqlmock.NewRows([]string{"id", "type", "date", "object_id", "content", "created_at"}). @@ -171,7 +173,7 @@ func TestQueryCommissionReturnLog_FiltersOtherUsersByObjectID(t *testing.T) { db, mock, cleanup := newQueryWithdrawalLogTestDB(t) defer cleanup() - expectCommissionReturnQueries(mock, userID, 0) + expectCommissionReturnQueries(mock, userID, 0, logmodel.CommissionTypeRefund, logmodel.CommissionTypeWithdrawReject, logmodel.CommissionTypeWithdrawCancel) mock.ExpectQuery("SELECT * FROM `system_logs` WHERE `type` = ? AND object_id = ? AND (`content` LIKE ? OR `content` LIKE ? OR `content` LIKE ?) ORDER BY id DESC LIMIT ?"). WithArgs(logmodel.TypeCommission.Uint8(), userID, "%\"type\":333%", "%\"type\":337%", "%\"type\":338%", 10). WillReturnRows(sqlmock.NewRows([]string{"id", "type", "date", "object_id", "content", "created_at"})) @@ -243,9 +245,19 @@ func newTestQueryCtx(userID int64) context.Context { return context.WithValue(context.Background(), constant.CtxKeyUser, &usermodel.User{Id: userID}) } -func expectCommissionReturnQueries(mock sqlmock.Sqlmock, userID int64, total int64) { - mock.ExpectQuery("SELECT count(*) FROM `system_logs` WHERE `type` = ? AND object_id = ? AND (`content` LIKE ? OR `content` LIKE ? OR `content` LIKE ?)"). - WithArgs(logmodel.TypeCommission.Uint8(), userID, "%\"type\":333%", "%\"type\":337%", "%\"type\":338%"). +func expectCommissionReturnQueries(mock sqlmock.Sqlmock, userID int64, total int64, eventTypes ...uint16) { + query := "SELECT count(*) FROM `system_logs` WHERE `type` = ? AND object_id = ?" + args := []driver.Value{logmodel.TypeCommission.Uint8(), userID} + if len(eventTypes) > 0 { + clauses := make([]string, 0, len(eventTypes)) + for _, eventType := range eventTypes { + clauses = append(clauses, "`content` LIKE ?") + args = append(args, fmt.Sprintf("%%\"type\":%d%%", eventType)) + } + query += " AND (" + strings.Join(clauses, " OR ") + ")" + } + mock.ExpectQuery(query). + WithArgs(args...). WillReturnRows(sqlmock.NewRows([]string{"count"}).AddRow(total)) }