修复(#126): 修复家庭组邀请记录漏查验收分支
Co-authored-by: multica-agent <github@multica.ai>
This commit is contained in:
@@ -23,8 +23,9 @@ type InviteRelation struct {
|
||||
}
|
||||
|
||||
type paidOrderRow struct {
|
||||
UserId int64 `gorm:"column:user_id"`
|
||||
OrderNo string `gorm:"column:order_no"`
|
||||
UserId int64 `gorm:"column:user_id"`
|
||||
SubscriptionUserId int64 `gorm:"column:subscription_user_id"`
|
||||
OrderNo string `gorm:"column:order_no"`
|
||||
}
|
||||
|
||||
type systemLogRow struct {
|
||||
@@ -81,7 +82,7 @@ func QueryBenefits(ctx context.Context, db *gorm.DB, relations []InviteRelation)
|
||||
var paidOrders []paidOrderRow
|
||||
if err := db.WithContext(ctx).
|
||||
Table("`order`").
|
||||
Select("user_id, order_no").
|
||||
Select("user_id, subscription_user_id, order_no").
|
||||
Where("user_id IN ? AND status IN ?", inviteeIds, []int{2, 5}).
|
||||
Scan(&paidOrders).Error; err != nil {
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "query invitee paid orders failed: %v", err)
|
||||
@@ -92,11 +93,16 @@ func QueryBenefits(ctx context.Context, db *gorm.DB, relations []InviteRelation)
|
||||
|
||||
orderNos := make([]string, 0, len(paidOrders))
|
||||
orderToInvitee := make(map[string]int64, len(paidOrders))
|
||||
orderToSubscriptionUser := make(map[string]int64, len(paidOrders))
|
||||
inviterIds := make([]int64, 0, len(relations))
|
||||
inviteeAndInviterSet := make(map[int64]struct{}, len(relations)*2)
|
||||
for _, order := range paidOrders {
|
||||
orderNos = append(orderNos, order.OrderNo)
|
||||
orderToInvitee[order.OrderNo] = order.UserId
|
||||
if order.SubscriptionUserId > 0 && order.SubscriptionUserId != order.UserId {
|
||||
orderToSubscriptionUser[order.OrderNo] = order.SubscriptionUserId
|
||||
inviteeAndInviterSet[order.SubscriptionUserId] = struct{}{}
|
||||
}
|
||||
}
|
||||
for _, relation := range relations {
|
||||
inviterIds = append(inviterIds, relation.InviterId)
|
||||
@@ -111,7 +117,7 @@ func QueryBenefits(ctx context.Context, db *gorm.DB, relations []InviteRelation)
|
||||
if err := fillCommissionBenefits(ctx, db, result, orderToInvitee, inviteeToInviter, orderNos, inviterIds); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := fillGiftBenefits(ctx, db, result, orderToInvitee, inviteeToInviter, orderNos, inviteeAndInviterIds); err != nil {
|
||||
if err := fillGiftBenefits(ctx, db, result, orderToInvitee, inviteeToInviter, orderToSubscriptionUser, orderNos, inviteeAndInviterIds); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -143,7 +149,7 @@ func fillCommissionBenefits(ctx context.Context, db *gorm.DB, benefits map[int64
|
||||
return nil
|
||||
}
|
||||
|
||||
func fillGiftBenefits(ctx context.Context, db *gorm.DB, benefits map[int64]Benefits, orderToInvitee map[string]int64, inviteeToInviter map[int64]int64, orderNos []string, userIds []int64) error {
|
||||
func fillGiftBenefits(ctx context.Context, db *gorm.DB, benefits map[int64]Benefits, orderToInvitee map[string]int64, inviteeToInviter map[int64]int64, orderToSubscriptionUser map[string]int64, orderNos []string, userIds []int64) error {
|
||||
var rows []systemLogRow
|
||||
if err := db.WithContext(ctx).
|
||||
Table("system_logs").
|
||||
@@ -170,6 +176,8 @@ func fillGiftBenefits(ctx context.Context, db *gorm.DB, benefits map[int64]Benef
|
||||
benefit.InviterGiftDays += content.Amount
|
||||
case inviteeId:
|
||||
benefit.InviteeGiftDays += content.Amount
|
||||
case orderToSubscriptionUser[content.OrderNo]:
|
||||
benefit.InviteeGiftDays += content.Amount
|
||||
default:
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
package invite
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/DATA-DOG/go-sqlmock"
|
||||
"gorm.io/driver/mysql"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
func TestQueryBenefitsCountsFamilyOwnerGiftAsInviteeGift(t *testing.T) {
|
||||
db, mock, cleanup := newBenefitsTestDB(t)
|
||||
defer cleanup()
|
||||
|
||||
mock.ExpectQuery("COUNT(*) as cnt").
|
||||
WithArgs(int64(200), 2, 5).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"user_id", "cnt"}).AddRow(200, 1))
|
||||
mock.ExpectQuery("SELECT user_id, subscription_user_id, order_no FROM `order`").
|
||||
WithArgs(int64(200), 2, 5).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"user_id", "subscription_user_id", "order_no"}).AddRow(200, 900, "family-order"))
|
||||
mock.ExpectQuery("object_id IN").
|
||||
WithArgs(33, int64(100), "family-order", 331, 332).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"object_id", "content"}))
|
||||
mock.ExpectQuery("object_id IN").
|
||||
WithArgs(34, int64(900), int64(200), int64(100), "family-order").
|
||||
WillReturnRows(sqlmock.NewRows([]string{"object_id", "content"}).
|
||||
AddRow(900, `{"type":341,"order_no":"family-order","amount":7,"balance":7,"remark":"邀请赠送"}`))
|
||||
|
||||
benefits, err := QueryBenefits(context.Background(), db, []InviteRelation{{InviteeId: 200, InviterId: 100}})
|
||||
if err != nil {
|
||||
t.Fatalf("QueryBenefits returned error: %v", err)
|
||||
}
|
||||
|
||||
benefit := benefits[200]
|
||||
if benefit.InviteeGiftDays != 7 {
|
||||
t.Fatalf("InviteeGiftDays = %d, want 7", benefit.InviteeGiftDays)
|
||||
}
|
||||
if benefit.InviterGiftDays != 0 {
|
||||
t.Fatalf("InviterGiftDays = %d, want 0", benefit.InviterGiftDays)
|
||||
}
|
||||
assertBenefitsExpectations(t, mock)
|
||||
}
|
||||
|
||||
func TestQueryBenefitsKeepsDirectInviteeGift(t *testing.T) {
|
||||
db, mock, cleanup := newBenefitsTestDB(t)
|
||||
defer cleanup()
|
||||
|
||||
mock.ExpectQuery("COUNT(*) as cnt").
|
||||
WithArgs(int64(200), 2, 5).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"user_id", "cnt"}).AddRow(200, 1))
|
||||
mock.ExpectQuery("SELECT user_id, subscription_user_id, order_no FROM `order`").
|
||||
WithArgs(int64(200), 2, 5).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"user_id", "subscription_user_id", "order_no"}).AddRow(200, 0, "direct-order"))
|
||||
mock.ExpectQuery("object_id IN").
|
||||
WithArgs(33, int64(100), "direct-order", 331, 332).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"object_id", "content"}))
|
||||
mock.ExpectQuery("object_id IN").
|
||||
WithArgs(34, int64(200), int64(100), "direct-order").
|
||||
WillReturnRows(sqlmock.NewRows([]string{"object_id", "content"}).
|
||||
AddRow(200, `{"type":341,"order_no":"direct-order","amount":5,"balance":5,"remark":"邀请赠送"}`))
|
||||
|
||||
benefits, err := QueryBenefits(context.Background(), db, []InviteRelation{{InviteeId: 200, InviterId: 100}})
|
||||
if err != nil {
|
||||
t.Fatalf("QueryBenefits returned error: %v", err)
|
||||
}
|
||||
|
||||
if got := benefits[200].InviteeGiftDays; got != 5 {
|
||||
t.Fatalf("InviteeGiftDays = %d, want 5", got)
|
||||
}
|
||||
assertBenefitsExpectations(t, mock)
|
||||
}
|
||||
|
||||
func newBenefitsTestDB(t *testing.T) (*gorm.DB, sqlmock.Sqlmock, func()) {
|
||||
t.Helper()
|
||||
|
||||
sqlDB, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherFunc(func(expectedSQL, actualSQL string) error {
|
||||
if strings.Contains(actualSQL, expectedSQL) {
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("actual sql %q does not contain %q", actualSQL, expectedSQL)
|
||||
})))
|
||||
if err != nil {
|
||||
t.Fatalf("create sqlmock: %v", err)
|
||||
}
|
||||
|
||||
db, err := gorm.Open(mysql.New(mysql.Config{Conn: sqlDB, SkipInitializeWithVersion: true}), &gorm.Config{})
|
||||
if err != nil {
|
||||
_ = sqlDB.Close()
|
||||
t.Fatalf("open gorm db: %v", err)
|
||||
}
|
||||
|
||||
return db, mock, func() {
|
||||
_ = sqlDB.Close()
|
||||
}
|
||||
}
|
||||
|
||||
func assertBenefitsExpectations(t *testing.T, mock sqlmock.Sqlmock) {
|
||||
t.Helper()
|
||||
if err := mock.ExpectationsWereMet(); err != nil {
|
||||
t.Fatalf("unmet sql expectations: %v", err)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user