199 lines
6.3 KiB
Go
199 lines
6.3 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"time"
|
|
|
|
"github.com/google/uuid"
|
|
"github.com/perfect-panel/server/internal/config"
|
|
"github.com/perfect-panel/server/internal/model/order"
|
|
"github.com/perfect-panel/server/internal/model/subscribe"
|
|
"github.com/perfect-panel/server/internal/model/user"
|
|
"github.com/perfect-panel/server/internal/svc"
|
|
"github.com/perfect-panel/server/pkg/orm"
|
|
"github.com/perfect-panel/server/pkg/tool"
|
|
orderLogic "github.com/perfect-panel/server/queue/logic/order"
|
|
"github.com/redis/go-redis/v9"
|
|
)
|
|
|
|
func main() {
|
|
// 1. Setup Configuration
|
|
c := config.Config{
|
|
MySQL: orm.Config{
|
|
Addr: "127.0.0.1:3306",
|
|
Dbname: "dev_ppanel", // Using dev_ppanel as default, change if needed
|
|
Username: "root",
|
|
Password: "rootpassword",
|
|
Config: "charset=utf8mb4&parseTime=true&loc=Asia%2FShanghai",
|
|
MaxIdleConns: 10,
|
|
MaxOpenConns: 10,
|
|
},
|
|
Redis: config.RedisConfig{
|
|
Host: "127.0.0.1:6379",
|
|
DB: 0,
|
|
},
|
|
Invite: config.InviteConfig{
|
|
GiftDays: 3, // Default gift days
|
|
},
|
|
}
|
|
|
|
// 2. Connect to Database & Redis
|
|
db, err := orm.ConnectMysql(orm.Mysql{Config: c.MySQL})
|
|
if err != nil {
|
|
panic(fmt.Sprintf("DB Connection failed: %v", err))
|
|
}
|
|
rds := redis.NewClient(&redis.Options{
|
|
Addr: c.Redis.Host,
|
|
DB: c.Redis.DB,
|
|
})
|
|
|
|
// 3. Initialize ServiceContext
|
|
serviceCtx := svc.NewServiceContext(c)
|
|
serviceCtx.DB = db
|
|
serviceCtx.Redis = rds
|
|
// We don't need queue/scheduler for this unit test
|
|
|
|
ctx := context.Background()
|
|
|
|
// 4. Run Scenarios
|
|
fmt.Println("=== Starting Invite Reward Test ===")
|
|
|
|
// Scenario 1: Commission 0 (Expect Gift Days)
|
|
runScenario(ctx, serviceCtx, "Scenario_0_Commission", 0)
|
|
|
|
// Scenario 2: Commission 10 (Expect Money)
|
|
runScenario(ctx, serviceCtx, "Scenario_10_Commission", 10)
|
|
}
|
|
|
|
func runScenario(ctx context.Context, s *svc.ServiceContext, name string, referralPercentage int64) {
|
|
fmt.Printf("\n--- Running %s (ReferralPercentage: %d%%) ---\n", name, referralPercentage)
|
|
|
|
// Update Config
|
|
s.Config.Invite.ReferralPercentage = referralPercentage
|
|
|
|
// Cleanup old data (Partial cleanup since we don't have email to query)
|
|
// We'll rely on unique ReferCode / UUIDs to avoid collisions but DB might grow.
|
|
// Actually we should try to clean up.
|
|
// Since we removed Email from struct, we can't use it to query easily unless we check `auth_methods`.
|
|
// For this test, let's just create new users.
|
|
|
|
// Create Referrer
|
|
referrer := &user.User{
|
|
Password: tool.EncodePassWord("123456"),
|
|
ReferCode: fmt.Sprintf("REF%d", time.Now().UnixNano())[:20],
|
|
ReferralPercentage: 0, // Use global settings
|
|
Commission: 0,
|
|
}
|
|
// Use DB directly to ensure ID is updated in struct
|
|
if err := s.DB.Create(referrer).Error; err != nil {
|
|
fmt.Printf("Create Referrer Failed: %v\n", err)
|
|
return
|
|
}
|
|
// Force active subscription for referrer so they can receive gift time
|
|
createActiveSubscription(ctx, s, referrer.Id)
|
|
|
|
fmt.Printf("Created Referrer: ID=%d, Commission=%d\n", referrer.Id, referrer.Commission)
|
|
|
|
// Create User (Invitee)
|
|
invitee := &user.User{
|
|
Password: tool.EncodePassWord("123456"),
|
|
RefererId: referrer.Id,
|
|
}
|
|
if err := s.DB.Create(invitee).Error; err != nil {
|
|
fmt.Printf("Create Invitee Failed: %v\n", err)
|
|
return
|
|
}
|
|
// Force active subscription for invitee to receive gift time
|
|
_ = createActiveSubscription(ctx, s, invitee.Id)
|
|
|
|
fmt.Printf("Created Invitee: ID=%d, RefererID=%d\n", invitee.Id, invitee.RefererId)
|
|
|
|
// Create Order
|
|
orderInfo := &order.Order{
|
|
OrderNo: tool.GenerateTradeNo(),
|
|
UserId: invitee.Id,
|
|
Amount: 10000, // 100.00
|
|
Price: 10000,
|
|
FeeAmount: 0,
|
|
Status: 2, // Paid
|
|
Type: 1, // Subscribe
|
|
IsNew: true,
|
|
SubscribeId: 1, // Assume plan 1 exists
|
|
Quantity: 1,
|
|
}
|
|
// We need a dummy subscribe plan in DB or use existing
|
|
ensureSubscribePlan(ctx, s, 1)
|
|
|
|
// Execute Logic
|
|
logic := orderLogic.NewActivateOrderLogic(s)
|
|
|
|
// We only simulate the commission part logic or NewPurchase
|
|
// logic.NewPurchase does a lot of things.
|
|
// Let's call NewPurchase to be realistic, but we need to ensure dependencies exist.
|
|
// Instead of full NewPurchase which might fail on other things,
|
|
// let's verify if we can just call handleCommission? No it's private.
|
|
// So we call NewPurchase.
|
|
|
|
err := logic.NewPurchase(ctx, orderInfo)
|
|
if err != nil {
|
|
fmt.Printf("NewPurchase failed (expected for mocked env): %v\n", err)
|
|
// If it failed because of things we don't care (like sending email), check data anyway
|
|
} else {
|
|
fmt.Println("NewPurchase executed successfully.")
|
|
}
|
|
|
|
// Wait for async goroutines
|
|
time.Sleep(2 * time.Second)
|
|
|
|
// Check Results
|
|
// 1. Check Referrer Commission
|
|
refRes, _ := s.UserModel.FindOne(ctx, referrer.Id)
|
|
fmt.Printf("Result Referrer Commission: %d (Expected: %d)\n", refRes.Commission, int64(float64(orderInfo.Amount)*float64(referralPercentage)/100))
|
|
|
|
// 2. Check Gift Days (Check expiration time changes)
|
|
// We compare with the initial subscription time
|
|
// But since we just created it, it's simpler to check if 'ExpiryTime' is far in the future or extended.
|
|
// For 0 commission, we expect gift days.
|
|
|
|
refSub, _ := s.UserModel.FindActiveSubscribe(ctx, referrer.Id)
|
|
invSub, _ := s.UserModel.FindActiveSubscribe(ctx, invitee.Id)
|
|
// Avoid panic if sub not found
|
|
if refSub != nil {
|
|
fmt.Printf("Result Referrer Sub Expire: %v\n", refSub.ExpireTime)
|
|
} else {
|
|
fmt.Println("Result Referrer Sub Expire: nil")
|
|
}
|
|
if invSub != nil {
|
|
// NewPurchase renews/creates sub, so it should be valid + duration
|
|
fmt.Printf("Result Invitee Sub Expire: %v\n", invSub.ExpireTime)
|
|
} else {
|
|
fmt.Println("Result Invitee Sub Expire: nil")
|
|
}
|
|
}
|
|
|
|
func createActiveSubscription(ctx context.Context, s *svc.ServiceContext, userId int64) *user.Subscribe {
|
|
sub := &user.Subscribe{
|
|
UserId: userId,
|
|
Status: 1,
|
|
ExpireTime: time.Now().Add(30 * 24 * time.Hour), // 30 days initial
|
|
Token: uuid.New().String(),
|
|
UUID: uuid.New().String(),
|
|
}
|
|
s.UserModel.InsertSubscribe(ctx, sub)
|
|
return sub
|
|
}
|
|
|
|
func ensureSubscribePlan(ctx context.Context, s *svc.ServiceContext, id int64) {
|
|
_, err := s.SubscribeModel.FindOne(ctx, id)
|
|
if err != nil {
|
|
s.SubscribeModel.Insert(ctx, &subscribe.Subscribe{
|
|
Id: id,
|
|
Name: "Test Plan",
|
|
UnitTime: "Day", // Days
|
|
UnitPrice: 100,
|
|
Sell: &[]bool{true}[0],
|
|
})
|
|
}
|
|
}
|