feat: 更新服务方法,显式接受用户ID参数,简化上下文调用

This commit is contained in:
2025-12-30 23:23:56 +08:00
parent e6a8e3f321
commit 317db2daad
10 changed files with 216 additions and 91 deletions

View File

@@ -126,7 +126,7 @@ func (s *ContentTestSuite) Test_Get() {
ctx = context.WithValue(ctx, consts.CtxKeyUser, author.ID)
Convey("should get detail with assets", func() {
detail, err := Content.Get(ctx, cast.ToString(content.ID))
detail, err := Content.Get(ctx, author.ID, cast.ToString(content.ID))
So(err, ShouldBeNil)
So(detail.Title, ShouldEqual, "Detail Content")
So(detail.AuthorName, ShouldEqual, "Author1")
@@ -154,7 +154,7 @@ func (s *ContentTestSuite) Test_CreateComment() {
form := &content_dto.CommentCreateForm{
Content: "Nice!",
}
err := Content.CreateComment(ctx, cast.ToString(c.ID), form)
err := Content.CreateComment(ctx, u.ID, cast.ToString(c.ID), form)
So(err, ShouldBeNil)
count, _ := models.CommentQuery.WithContext(ctx).Where(models.CommentQuery.ContentID.Eq(c.ID)).Count()
@@ -193,7 +193,7 @@ func (s *ContentTestSuite) Test_Library() {
})
Convey("should get library content with details", func() {
list, err := Content.GetLibrary(ctx)
list, err := Content.GetLibrary(ctx, u.ID)
So(err, ShouldBeNil)
So(len(list), ShouldEqual, 1)
So(list[0].Title, ShouldEqual, "Paid Content")
@@ -219,7 +219,7 @@ func (s *ContentTestSuite) Test_Interact() {
Convey("Like flow", func() {
// Add Like
err := Content.AddLike(ctx, cast.ToString(c.ID))
err := Content.AddLike(ctx, u.ID, cast.ToString(c.ID))
So(err, ShouldBeNil)
// Verify count
@@ -227,13 +227,13 @@ func (s *ContentTestSuite) Test_Interact() {
So(cReload.Likes, ShouldEqual, 1)
// Get Likes
likes, err := Content.GetLikes(ctx)
likes, err := Content.GetLikes(ctx, u.ID)
So(err, ShouldBeNil)
So(len(likes), ShouldEqual, 1)
So(likes[0].ID, ShouldEqual, cast.ToString(c.ID))
// Remove Like
err = Content.RemoveLike(ctx, cast.ToString(c.ID))
err = Content.RemoveLike(ctx, u.ID, cast.ToString(c.ID))
So(err, ShouldBeNil)
// Verify count
@@ -243,21 +243,21 @@ func (s *ContentTestSuite) Test_Interact() {
Convey("Favorite flow", func() {
// Add Favorite
err := Content.AddFavorite(ctx, cast.ToString(c.ID))
err := Content.AddFavorite(ctx, u.ID, cast.ToString(c.ID))
So(err, ShouldBeNil)
// Get Favorites
favs, err := Content.GetFavorites(ctx)
favs, err := Content.GetFavorites(ctx, u.ID)
So(err, ShouldBeNil)
So(len(favs), ShouldEqual, 1)
So(favs[0].ID, ShouldEqual, cast.ToString(c.ID))
// Remove Favorite
err = Content.RemoveFavorite(ctx, cast.ToString(c.ID))
err = Content.RemoveFavorite(ctx, u.ID, cast.ToString(c.ID))
So(err, ShouldBeNil)
// Get Favorites
favs, err = Content.GetFavorites(ctx)
favs, err = Content.GetFavorites(ctx, u.ID)
So(err, ShouldBeNil)
So(len(favs), ShouldEqual, 0)
})
@@ -325,7 +325,7 @@ func (s *ContentTestSuite) Test_PreviewLogic() {
models.UserQuery.WithContext(ctx).Create(guest)
guestCtx := context.WithValue(ctx, consts.CtxKeyUser, guest.ID)
detail, err := Content.Get(guestCtx, cast.ToString(c.ID))
detail, err := Content.Get(guestCtx, 0, cast.ToString(c.ID))
So(err, ShouldBeNil)
So(len(detail.MediaUrls), ShouldEqual, 1)
So(detail.MediaUrls[0].URL, ShouldEndWith, "preview.mp4")
@@ -334,7 +334,7 @@ func (s *ContentTestSuite) Test_PreviewLogic() {
Convey("owner should see all", func() {
ownerCtx := context.WithValue(ctx, consts.CtxKeyUser, author.ID)
detail, err := Content.Get(ownerCtx, cast.ToString(c.ID))
detail, err := Content.Get(ownerCtx, author.ID, cast.ToString(c.ID))
So(err, ShouldBeNil)
So(len(detail.MediaUrls), ShouldEqual, 2)
So(detail.IsPurchased, ShouldBeTrue)
@@ -349,7 +349,7 @@ func (s *ContentTestSuite) Test_PreviewLogic() {
UserID: buyer.ID, ContentID: c.ID, Status: consts.ContentAccessStatusActive,
})
detail, err := Content.Get(buyerCtx, cast.ToString(c.ID))
detail, err := Content.Get(buyerCtx, buyer.ID, cast.ToString(c.ID))
So(err, ShouldBeNil)
So(len(detail.MediaUrls), ShouldEqual, 2)
So(detail.IsPurchased, ShouldBeTrue)
@@ -369,7 +369,7 @@ func (s *ContentTestSuite) Test_ViewCounting() {
models.ContentQuery.WithContext(ctx).Create(c)
Convey("should increment views", func() {
_, err := Content.Get(ctx, cast.ToString(c.ID))
_, err := Content.Get(ctx, 0, cast.ToString(c.ID))
So(err, ShouldBeNil)
cReload, _ := models.ContentQuery.WithContext(ctx).Where(models.ContentQuery.ID.Eq(c.ID)).First()

View File

@@ -7,7 +7,6 @@ import (
"quyun/v2/app/errorx"
coupon_dto "quyun/v2/app/http/v1/dto"
"quyun/v2/database/models"
"quyun/v2/pkg/consts"
"github.com/spf13/cast"
)
@@ -15,7 +14,11 @@ import (
// @provider
type coupon struct{}
func (s *coupon) ListUserCoupons(ctx context.Context, userID int64, status string) ([]coupon_dto.UserCouponItem, error) {
func (s *coupon) ListUserCoupons(
ctx context.Context,
userID int64,
status string,
) ([]coupon_dto.UserCouponItem, error) {
if userID == 0 {
return nil, errorx.ErrUnauthorized
}
@@ -111,11 +114,13 @@ func (s *coupon) Validate(ctx context.Context, userID, userCouponID, amount int6
func (s *coupon) MarkUsed(ctx context.Context, tx *models.Query, userCouponID, orderID int64) error {
now := time.Now()
// Update User Coupon
info, err := tx.UserCoupon.WithContext(ctx).Where(tx.UserCoupon.ID.Eq(userCouponID), tx.UserCoupon.Status.Eq("unused")).Updates(&models.UserCoupon{
Status: "used",
OrderID: orderID,
UsedAt: now,
})
info, err := tx.UserCoupon.WithContext(ctx).
Where(tx.UserCoupon.ID.Eq(userCouponID), tx.UserCoupon.Status.Eq("unused")).
Updates(&models.UserCoupon{
Status: "used",
OrderID: orderID,
UsedAt: now,
})
if err != nil {
return err
}

View File

@@ -1,7 +1,6 @@
package services
import (
"context"
"database/sql"
"testing"
@@ -42,7 +41,16 @@ func Test_Coupon(t *testing.T) {
func (s *CouponTestSuite) Test_CouponFlow() {
Convey("Coupon Flow", s.T(), func() {
ctx := s.T().Context()
database.Truncate(ctx, s.DB, models.TableNameCoupon, models.TableNameUserCoupon, models.TableNameOrder, models.TableNameUser, models.TableNameContent, models.TableNameContentPrice)
database.Truncate(
ctx,
s.DB,
models.TableNameCoupon,
models.TableNameUserCoupon,
models.TableNameOrder,
models.TableNameUser,
models.TableNameContent,
models.TableNameContentPrice,
)
user := &models.User{Username: "coupon_user", Phone: "13800000001"}
models.UserQuery.WithContext(ctx).Create(user)
@@ -90,8 +98,7 @@ func (s *CouponTestSuite) Test_CouponFlow() {
UserCouponID: cast.ToString(uc.ID),
}
// Simulate Auth context for Order service
authCtx := context.WithValue(ctx, consts.CtxKeyUser, user.ID)
res, err := Order.Create(authCtx, form)
res, err := Order.Create(ctx, user.ID, form)
So(err, ShouldBeNil)
// Verify Order

View File

@@ -51,7 +51,7 @@ func (s *CreatorTestSuite) Test_Apply() {
form := &creator_dto.ApplyForm{
Name: "My Channel",
}
err := Creator.Apply(ctx, form)
err := Creator.Apply(ctx, u.ID, form)
So(err, ShouldBeNil)
t, _ := models.TenantQuery.WithContext(ctx).Where(models.TenantQuery.UserID.Eq(u.ID)).First()
@@ -73,7 +73,15 @@ func (s *CreatorTestSuite) Test_Apply() {
func (s *CreatorTestSuite) Test_CreateContent() {
Convey("CreateContent", s.T(), func() {
ctx := s.T().Context()
database.Truncate(ctx, s.DB, models.TableNameTenant, models.TableNameContent, models.TableNameContentAsset, models.TableNameContentPrice, models.TableNameUser)
database.Truncate(
ctx,
s.DB,
models.TableNameTenant,
models.TableNameContent,
models.TableNameContentAsset,
models.TableNameContentPrice,
models.TableNameUser,
)
u := &models.User{Username: "creator2", Phone: "13700000002"}
models.UserQuery.WithContext(ctx).Create(u)
@@ -90,7 +98,7 @@ func (s *CreatorTestSuite) Test_CreateContent() {
Price: 9.99,
// MediaIDs: ... need media asset
}
err := Creator.CreateContent(ctx, form)
err := Creator.CreateContent(ctx, u.ID, form)
So(err, ShouldBeNil)
c, _ := models.ContentQuery.WithContext(ctx).Where(models.ContentQuery.Title.Eq("New Song")).First()
@@ -109,7 +117,15 @@ func (s *CreatorTestSuite) Test_CreateContent() {
func (s *CreatorTestSuite) Test_UpdateContent() {
Convey("UpdateContent", s.T(), func() {
ctx := s.T().Context()
database.Truncate(ctx, s.DB, models.TableNameTenant, models.TableNameContent, models.TableNameContentAsset, models.TableNameContentPrice, models.TableNameUser)
database.Truncate(
ctx,
s.DB,
models.TableNameTenant,
models.TableNameContent,
models.TableNameContentAsset,
models.TableNameContentPrice,
models.TableNameUser,
)
u := &models.User{Username: "creator3", Phone: "13700000003"}
models.UserQuery.WithContext(ctx).Create(u)
@@ -120,7 +136,8 @@ func (s *CreatorTestSuite) Test_UpdateContent() {
c := &models.Content{TenantID: t.ID, UserID: u.ID, Title: "Old Title", Genre: "audio"}
models.ContentQuery.WithContext(ctx).Create(c)
models.ContentPriceQuery.WithContext(ctx).Create(&models.ContentPrice{TenantID: t.ID, UserID: u.ID, ContentID: c.ID, PriceAmount: 100})
models.ContentPriceQuery.WithContext(ctx).
Create(&models.ContentPrice{TenantID: t.ID, UserID: u.ID, ContentID: c.ID, PriceAmount: 100})
Convey("should update content", func() {
form := &creator_dto.ContentUpdateForm{
@@ -128,7 +145,7 @@ func (s *CreatorTestSuite) Test_UpdateContent() {
Genre: "video",
Price: 20.00,
}
err := Creator.UpdateContent(ctx, cast.ToString(c.ID), form)
err := Creator.UpdateContent(ctx, u.ID, cast.ToString(c.ID), form)
So(err, ShouldBeNil)
// Verify
@@ -145,7 +162,15 @@ func (s *CreatorTestSuite) Test_UpdateContent() {
func (s *CreatorTestSuite) Test_Dashboard() {
Convey("Dashboard", s.T(), func() {
ctx := s.T().Context()
database.Truncate(ctx, s.DB, models.TableNameTenant, models.TableNameTenantUser, models.TableNameTenantLedger, models.TableNameUser, models.TableNameOrder)
database.Truncate(
ctx,
s.DB,
models.TableNameTenant,
models.TableNameTenantUser,
models.TableNameTenantLedger,
models.TableNameUser,
models.TableNameOrder,
)
u := &models.User{Username: "creator4", Phone: "13700000004"}
models.UserQuery.WithContext(ctx).Create(u)
@@ -165,11 +190,15 @@ func (s *CreatorTestSuite) Test_Dashboard() {
models.TenantLedgerQuery.WithContext(ctx).Create(
&models.TenantLedger{TenantID: t.ID, Type: consts.TenantLedgerTypeDebitPurchase, Amount: 1000}, // 10.00
&models.TenantLedger{TenantID: t.ID, Type: consts.TenantLedgerTypeDebitPurchase, Amount: 2000}, // 20.00
&models.TenantLedger{TenantID: t.ID, Type: consts.TenantLedgerTypeCreditRefund, Amount: 500}, // -5.00 (Refund, currently Dashboard sums DebitPurchase only, ideally should subtract refunds, but let's stick to implementation)
&models.TenantLedger{
TenantID: t.ID,
Type: consts.TenantLedgerTypeCreditRefund,
Amount: 500,
}, // -5.00 (Refund, currently Dashboard sums DebitPurchase only, ideally should subtract refunds, but let's stick to implementation)
)
Convey("should get stats", func() {
stats, err := Creator.Dashboard(ctx)
stats, err := Creator.Dashboard(ctx, u.ID)
So(err, ShouldBeNil)
So(stats.TotalFollowers.Value, ShouldEqual, 2)
// Implementation sums 'debit_purchase' only based on my code
@@ -198,21 +227,21 @@ func (s *CreatorTestSuite) Test_PayoutAccount() {
Account: "user@example.com",
Realname: "John Doe",
}
err := Creator.AddPayoutAccount(ctx, form)
err := Creator.AddPayoutAccount(ctx, u.ID, form)
So(err, ShouldBeNil)
// List
list, err := Creator.ListPayoutAccounts(ctx)
list, err := Creator.ListPayoutAccounts(ctx, u.ID)
So(err, ShouldBeNil)
So(len(list), ShouldEqual, 1)
So(list[0].Account, ShouldEqual, "user@example.com")
// Remove
err = Creator.RemovePayoutAccount(ctx, list[0].ID)
err = Creator.RemovePayoutAccount(ctx, u.ID, list[0].ID)
So(err, ShouldBeNil)
// Verify Empty
list, err = Creator.ListPayoutAccounts(ctx)
list, err = Creator.ListPayoutAccounts(ctx, u.ID)
So(err, ShouldBeNil)
So(len(list), ShouldEqual, 0)
})
@@ -222,7 +251,15 @@ func (s *CreatorTestSuite) Test_PayoutAccount() {
func (s *CreatorTestSuite) Test_Withdraw() {
Convey("Withdraw", s.T(), func() {
ctx := s.T().Context()
database.Truncate(ctx, s.DB, models.TableNameTenant, models.TableNamePayoutAccount, models.TableNameUser, models.TableNameOrder, models.TableNameTenantLedger)
database.Truncate(
ctx,
s.DB,
models.TableNameTenant,
models.TableNamePayoutAccount,
models.TableNameUser,
models.TableNameOrder,
models.TableNameTenantLedger,
)
u := &models.User{Username: "creator6", Phone: "13700000006", Balance: 5000} // 50.00
models.UserQuery.WithContext(ctx).Create(u)
@@ -231,7 +268,14 @@ func (s *CreatorTestSuite) Test_Withdraw() {
t := &models.Tenant{UserID: u.ID, Name: "Channel 6", Code: "127", Status: consts.TenantStatusVerified}
models.TenantQuery.WithContext(ctx).Create(t)
pa := &models.PayoutAccount{TenantID: t.ID, UserID: u.ID, Type: "bank", Name: "Bank", Account: "123", Realname: "Creator"}
pa := &models.PayoutAccount{
TenantID: t.ID,
UserID: u.ID,
Type: "bank",
Name: "Bank",
Account: "123",
Realname: "Creator",
}
models.PayoutAccountQuery.WithContext(ctx).Create(pa)
Convey("should withdraw successfully", func() {
@@ -239,7 +283,7 @@ func (s *CreatorTestSuite) Test_Withdraw() {
Amount: 20.00,
AccountID: cast.ToString(pa.ID),
}
err := Creator.Withdraw(ctx, form)
err := Creator.Withdraw(ctx, u.ID, form)
So(err, ShouldBeNil)
// Verify Balance Deducted
@@ -247,7 +291,9 @@ func (s *CreatorTestSuite) Test_Withdraw() {
So(uReload.Balance, ShouldEqual, 3000)
// Verify Order Created
o, _ := models.OrderQuery.WithContext(ctx).Where(models.OrderQuery.TenantID.Eq(t.ID), models.OrderQuery.Type.Eq(consts.OrderTypeWithdrawal)).First()
o, _ := models.OrderQuery.WithContext(ctx).
Where(models.OrderQuery.TenantID.Eq(t.ID), models.OrderQuery.Type.Eq(consts.OrderTypeWithdrawal)).
First()
So(o, ShouldNotBeNil)
So(o.AmountPaid, ShouldEqual, 2000)
@@ -262,7 +308,7 @@ func (s *CreatorTestSuite) Test_Withdraw() {
Amount: 100.00,
AccountID: cast.ToString(pa.ID),
}
err := Creator.Withdraw(ctx, form)
err := Creator.Withdraw(ctx, u.ID, form)
So(err, ShouldNotBeNil)
})
})
@@ -279,7 +325,7 @@ func (s *CreatorTestSuite) Test_Refund() {
// Creator
creator := &models.User{Username: "creator7", Phone: "13700000007", Balance: 5000} // Has funds
models.UserQuery.WithContext(ctx).Create(creator)
creatorCtx := context.WithValue(ctx, consts.CtxKeyUser, creator.ID)
// creatorCtx := context.WithValue(ctx, consts.CtxKeyUser, creator.ID)
// Tenant
t := &models.Tenant{UserID: creator.ID, Name: "Channel 7", Code: "128", Status: consts.TenantStatusVerified}
@@ -298,11 +344,12 @@ func (s *CreatorTestSuite) Test_Refund() {
}
models.OrderQuery.WithContext(ctx).Create(o)
models.OrderItemQuery.WithContext(ctx).Create(&models.OrderItem{OrderID: o.ID, ContentID: 100}) // Fake content
models.ContentAccessQuery.WithContext(ctx).Create(&models.ContentAccess{UserID: buyer.ID, ContentID: 100, Status: consts.ContentAccessStatusActive})
models.ContentAccessQuery.WithContext(ctx).
Create(&models.ContentAccess{UserID: buyer.ID, ContentID: 100, Status: consts.ContentAccessStatusActive})
Convey("should accept refund", func() {
form := &creator_dto.RefundForm{Action: "accept", Reason: "Defective"}
err := Creator.ProcessRefund(creatorCtx, cast.ToString(o.ID), form)
err := Creator.ProcessRefund(ctx, creator.ID, cast.ToString(o.ID), form)
So(err, ShouldBeNil)
// Verify Order
@@ -317,7 +364,9 @@ func (s *CreatorTestSuite) Test_Refund() {
So(bReload.Balance, ShouldEqual, 1000) // 0 + 1000
// Verify Access
acc, _ := models.ContentAccessQuery.WithContext(ctx).Where(models.ContentAccessQuery.UserID.Eq(buyer.ID)).First()
acc, _ := models.ContentAccessQuery.WithContext(ctx).
Where(models.ContentAccessQuery.UserID.Eq(buyer.ID)).
First()
So(acc.Status, ShouldEqual, consts.ContentAccessStatusRevoked)
})
})

View File

@@ -9,7 +9,6 @@ import (
"quyun/v2/app/jobs/args"
"quyun/v2/app/requests"
"quyun/v2/database/models"
"quyun/v2/pkg/consts"
"quyun/v2/providers/job"
"github.com/spf13/cast"

View File

@@ -50,7 +50,7 @@ func (s *NotificationTestSuite) Test_CRUD() {
err := Notification.Send(ctx, uID, "system", "Welcome", "Hello World")
So(err, ShouldBeNil)
list, err := Notification.List(ctx, 1, "")
list, err := Notification.List(ctx, uID, 1, "")
So(err, ShouldBeNil)
So(list.Total, ShouldEqual, 1)
@@ -61,7 +61,7 @@ func (s *NotificationTestSuite) Test_CRUD() {
// Mark Read
// Need ID
n, _ := models.NotificationQuery.WithContext(ctx).Where(models.NotificationQuery.UserID.Eq(uID)).First()
err = Notification.MarkRead(ctx, cast.ToString(n.ID))
err = Notification.MarkRead(ctx, uID, cast.ToString(n.ID))
So(err, ShouldBeNil)
nReload, _ := models.NotificationQuery.WithContext(ctx).Where(models.NotificationQuery.ID.Eq(n.ID)).First()

View File

@@ -1,7 +1,6 @@
package services
import (
"context"
"database/sql"
"testing"
@@ -52,25 +51,40 @@ func (s *OrderTestSuite) Test_PurchaseFlow() {
creator := &models.User{Username: "creator", Phone: "13800000001"}
models.UserQuery.WithContext(ctx).Create(creator)
// Tenant
tenant := &models.Tenant{UserID: creator.ID, Name: "Music Shop", Code: "shop1", Status: consts.TenantStatusVerified}
tenant := &models.Tenant{
UserID: creator.ID,
Name: "Music Shop",
Code: "shop1",
Status: consts.TenantStatusVerified,
}
models.TenantQuery.WithContext(ctx).Create(tenant)
// Content
content := &models.Content{TenantID: tenant.ID, UserID: creator.ID, Title: "Song A", Status: consts.ContentStatusPublished}
content := &models.Content{
TenantID: tenant.ID,
UserID: creator.ID,
Title: "Song A",
Status: consts.ContentStatusPublished,
}
models.ContentQuery.WithContext(ctx).Create(content)
// Price (10.00 CNY = 1000 cents)
price := &models.ContentPrice{TenantID: tenant.ID, ContentID: content.ID, PriceAmount: 1000, Currency: consts.CurrencyCNY}
price := &models.ContentPrice{
TenantID: tenant.ID,
ContentID: content.ID,
PriceAmount: 1000,
Currency: consts.CurrencyCNY,
}
models.ContentPriceQuery.WithContext(ctx).Create(price)
// Buyer
buyer := &models.User{Username: "buyer", Phone: "13900000001", Balance: 2000} // Has 20.00
models.UserQuery.WithContext(ctx).Create(buyer)
buyerCtx := context.WithValue(ctx, consts.CtxKeyUser, buyer.ID)
// buyerCtx := context.WithValue(ctx, consts.CtxKeyUser, buyer.ID)
Convey("should create and pay order successfully", func() {
// Step 1: Create Order
form := &order_dto.OrderCreateForm{ContentID: cast.ToString(content.ID)}
createRes, err := Order.Create(buyerCtx, form)
createRes, err := Order.Create(ctx, buyer.ID, form)
So(err, ShouldBeNil)
So(createRes.OrderID, ShouldNotBeEmpty)
@@ -82,7 +96,7 @@ func (s *OrderTestSuite) Test_PurchaseFlow() {
// Step 2: Pay Order
payForm := &order_dto.OrderPayForm{Method: "balance"}
_, err = Order.Pay(buyerCtx, createRes.OrderID, payForm)
_, err = Order.Pay(ctx, buyer.ID, createRes.OrderID, payForm)
So(err, ShouldBeNil)
// Verify Order Paid
@@ -95,7 +109,9 @@ func (s *OrderTestSuite) Test_PurchaseFlow() {
So(b.Balance, ShouldEqual, 1000) // 2000 - 1000
// Verify Access Granted
access, _ := models.ContentAccessQuery.WithContext(ctx).Where(models.ContentAccessQuery.UserID.Eq(buyer.ID), models.ContentAccessQuery.ContentID.Eq(content.ID)).First()
access, _ := models.ContentAccessQuery.WithContext(ctx).
Where(models.ContentAccessQuery.UserID.Eq(buyer.ID), models.ContentAccessQuery.ContentID.Eq(content.ID)).
First()
So(access, ShouldNotBeNil)
So(access.Status, ShouldEqual, consts.ContentAccessStatusActive)
@@ -110,14 +126,16 @@ func (s *OrderTestSuite) Test_PurchaseFlow() {
Convey("should fail pay if insufficient balance", func() {
// Set balance to 5.00
models.UserQuery.WithContext(ctx).Where(models.UserQuery.ID.Eq(buyer.ID)).Update(models.UserQuery.Balance, 500)
models.UserQuery.WithContext(ctx).
Where(models.UserQuery.ID.Eq(buyer.ID)).
Update(models.UserQuery.Balance, 500)
form := &order_dto.OrderCreateForm{ContentID: cast.ToString(content.ID)}
createRes, err := Order.Create(buyerCtx, form)
createRes, err := Order.Create(ctx, buyer.ID, form)
So(err, ShouldBeNil)
payForm := &order_dto.OrderPayForm{Method: "balance"}
_, err = Order.Pay(buyerCtx, createRes.OrderID, payForm)
_, err = Order.Pay(ctx, buyer.ID, createRes.OrderID, payForm)
So(err, ShouldNotBeNil)
// Error should be QuotaExceeded or similar
})
@@ -127,10 +145,19 @@ func (s *OrderTestSuite) Test_PurchaseFlow() {
func (s *OrderTestSuite) Test_OrderDetails() {
Convey("Order Details", s.T(), func() {
ctx := s.T().Context()
database.Truncate(ctx, s.DB,
models.TableNameOrder, models.TableNameOrderItem, models.TableNameUser,
models.TableNameContent, models.TableNameContentPrice, models.TableNameTenant,
models.TableNameContentAccess, models.TableNameTenantLedger, models.TableNameMediaAsset, models.TableNameContentAsset,
database.Truncate(
ctx,
s.DB,
models.TableNameOrder,
models.TableNameOrderItem,
models.TableNameUser,
models.TableNameContent,
models.TableNameContentPrice,
models.TableNameTenant,
models.TableNameContentAccess,
models.TableNameTenantLedger,
models.TableNameMediaAsset,
models.TableNameContentAsset,
)
// Setup
@@ -138,28 +165,48 @@ func (s *OrderTestSuite) Test_OrderDetails() {
models.UserQuery.WithContext(ctx).Create(creator)
tenant := &models.Tenant{UserID: creator.ID, Name: "Best Shop", Status: consts.TenantStatusVerified}
models.TenantQuery.WithContext(ctx).Create(tenant)
content := &models.Content{TenantID: tenant.ID, UserID: creator.ID, Title: "Amazing Song", Status: consts.ContentStatusPublished}
content := &models.Content{
TenantID: tenant.ID,
UserID: creator.ID,
Title: "Amazing Song",
Status: consts.ContentStatusPublished,
}
models.ContentQuery.WithContext(ctx).Create(content)
price := &models.ContentPrice{TenantID: tenant.ID, ContentID: content.ID, PriceAmount: 500, Currency: consts.CurrencyCNY}
price := &models.ContentPrice{
TenantID: tenant.ID,
ContentID: content.ID,
PriceAmount: 500,
Currency: consts.CurrencyCNY,
}
models.ContentPriceQuery.WithContext(ctx).Create(price)
// Asset (Cover)
asset := &models.MediaAsset{TenantID: tenant.ID, UserID: creator.ID, Type: consts.MediaAssetTypeImage, ObjectKey: "cover.jpg"}
asset := &models.MediaAsset{
TenantID: tenant.ID,
UserID: creator.ID,
Type: consts.MediaAssetTypeImage,
ObjectKey: "cover.jpg",
}
models.MediaAssetQuery.WithContext(ctx).Create(asset)
models.ContentAssetQuery.WithContext(ctx).Create(&models.ContentAsset{ContentID: content.ID, AssetID: asset.ID, Role: consts.ContentAssetRoleCover})
models.ContentAssetQuery.WithContext(ctx).
Create(&models.ContentAsset{ContentID: content.ID, AssetID: asset.ID, Role: consts.ContentAssetRoleCover})
// Buyer
buyer := &models.User{Username: "buyer2", Phone: "13900000002", Balance: 1000}
models.UserQuery.WithContext(ctx).Create(buyer)
buyerCtx := context.WithValue(ctx, consts.CtxKeyUser, buyer.ID)
// buyerCtx := context.WithValue(ctx, consts.CtxKeyUser, buyer.ID)
Convey("should get full order details", func() {
// Create & Pay
createRes, _ := Order.Create(buyerCtx, &order_dto.OrderCreateForm{ContentID: cast.ToString(content.ID)})
Order.Pay(buyerCtx, createRes.OrderID, &order_dto.OrderPayForm{Method: "balance"})
createRes, _ := Order.Create(
ctx,
buyer.ID,
&order_dto.OrderCreateForm{ContentID: cast.ToString(content.ID)},
)
Order.Pay(ctx, buyer.ID, createRes.OrderID, &order_dto.OrderPayForm{Method: "balance"})
// Get Detail
detail, err := Order.GetUserOrder(buyerCtx, createRes.OrderID)
detail, err := Order.GetUserOrder(ctx, buyer.ID, createRes.OrderID)
So(err, ShouldBeNil)
So(detail.TenantName, ShouldEqual, "Best Shop")
So(len(detail.Items), ShouldEqual, 1)
@@ -173,7 +220,16 @@ func (s *OrderTestSuite) Test_OrderDetails() {
func (s *OrderTestSuite) Test_PlatformCommission() {
Convey("Platform Commission", s.T(), func() {
ctx := s.T().Context()
database.Truncate(ctx, s.DB, models.TableNameUser, models.TableNameOrder, models.TableNameOrderItem, models.TableNameTenant, models.TableNameTenantLedger, models.TableNameContentAccess)
database.Truncate(
ctx,
s.DB,
models.TableNameUser,
models.TableNameOrder,
models.TableNameOrderItem,
models.TableNameTenant,
models.TableNameTenantLedger,
models.TableNameContentAccess,
)
// Creator
creator := &models.User{Username: "creator_c", Balance: 0}
@@ -184,7 +240,7 @@ func (s *OrderTestSuite) Test_PlatformCommission() {
// Buyer
buyer := &models.User{Username: "buyer_c", Balance: 2000}
models.UserQuery.WithContext(ctx).Create(buyer)
buyerCtx := context.WithValue(ctx, consts.CtxKeyUser, buyer.ID)
// buyerCtx := context.WithValue(ctx, consts.CtxKeyUser, buyer.ID)
// Order (10.00 CNY = 1000)
o := &models.Order{
@@ -198,7 +254,7 @@ func (s *OrderTestSuite) Test_PlatformCommission() {
Convey("should deduct 10% fee", func() {
payForm := &order_dto.OrderPayForm{Method: "balance"}
_, err := Order.Pay(buyerCtx, cast.ToString(o.ID), payForm)
_, err := Order.Pay(ctx, buyer.ID, cast.ToString(o.ID), payForm)
So(err, ShouldBeNil)
// Verify Creator Balance (1000 - 10% = 900)
@@ -215,7 +271,16 @@ func (s *OrderTestSuite) Test_PlatformCommission() {
func (s *OrderTestSuite) Test_ExternalPayment() {
Convey("External Payment", s.T(), func() {
ctx := s.T().Context()
database.Truncate(ctx, s.DB, models.TableNameUser, models.TableNameOrder, models.TableNameOrderItem, models.TableNameTenant, models.TableNameTenantLedger, models.TableNameContentAccess)
database.Truncate(
ctx,
s.DB,
models.TableNameUser,
models.TableNameOrder,
models.TableNameOrderItem,
models.TableNameTenant,
models.TableNameTenantLedger,
models.TableNameContentAccess,
)
// Creator
creator := &models.User{Username: "creator_ext", Balance: 0}

View File

@@ -52,27 +52,27 @@ func (s *TenantTestSuite) Test_Follow() {
models.TenantQuery.WithContext(ctx).Create(t)
Convey("should follow tenant", func() {
err := Tenant.Follow(ctx, cast.ToString(t.ID))
err := Tenant.Follow(ctx, u.ID, cast.ToString(t.ID))
So(err, ShouldBeNil)
// Verify stats
profile, err := Tenant.GetPublicProfile(ctx, cast.ToString(t.ID))
profile, err := Tenant.GetPublicProfile(ctx, u.ID, cast.ToString(t.ID))
So(err, ShouldBeNil)
So(profile.IsFollowing, ShouldBeTrue)
So(profile.Stats.Followers, ShouldEqual, 1)
// List Followed
list, err := Tenant.ListFollowed(ctx)
list, err := Tenant.ListFollowed(ctx, u.ID)
So(err, ShouldBeNil)
So(len(list), ShouldEqual, 1)
So(list[0].Name, ShouldEqual, "Tenant A")
// Unfollow
err = Tenant.Unfollow(ctx, cast.ToString(t.ID))
err = Tenant.Unfollow(ctx, u.ID, cast.ToString(t.ID))
So(err, ShouldBeNil)
// Verify
profile, err = Tenant.GetPublicProfile(ctx, cast.ToString(t.ID))
profile, err = Tenant.GetPublicProfile(ctx, u.ID, cast.ToString(t.ID))
So(err, ShouldBeNil)
So(profile.IsFollowing, ShouldBeFalse)
So(profile.Stats.Followers, ShouldEqual, 0)

View File

@@ -87,7 +87,7 @@ func (s *UserTestSuite) Test_Me() {
// Mock context with user ID
ctx = context.WithValue(ctx, consts.CtxKeyUser, userID)
user, err := User.Me(ctx)
user, err := User.Me(ctx, userID)
So(err, ShouldBeNil)
So(user.ID, ShouldEqual, resp.User.ID)
So(user.Phone, ShouldEqual, phone)
@@ -95,7 +95,7 @@ func (s *UserTestSuite) Test_Me() {
Convey("should fail without auth", func() {
// No user ID in context
user, err := User.Me(ctx)
user, err := User.Me(ctx, 0)
So(err, ShouldNotBeNil)
So(user, ShouldBeNil)
})
@@ -118,11 +118,11 @@ func (s *UserTestSuite) Test_Update() {
Bio: "New Bio",
Gender: consts.GenderMale,
}
err := User.Update(ctx, form)
err := User.Update(ctx, userID, form)
So(err, ShouldBeNil)
// Verify
u, _ := User.Me(ctx)
u, _ := User.Me(ctx, userID)
So(u.Nickname, ShouldEqual, "NewName")
So(u.Bio, ShouldEqual, "New Bio")
So(u.Gender, ShouldEqual, consts.GenderMale)
@@ -145,11 +145,11 @@ func (s *UserTestSuite) Test_RealName() {
Realname: "张三",
IDCard: "123456789012345678",
}
err := User.RealName(ctx, form)
err := User.RealName(ctx, userID, form)
So(err, ShouldBeNil)
// Verify
u, _ := User.Me(ctx)
u, _ := User.Me(ctx, userID)
So(u.IsRealNameVerified, ShouldBeTrue)
})
})
@@ -175,7 +175,7 @@ func (s *UserTestSuite) Test_GetNotifications() {
})
Convey("should return notifications", func() {
list, err := User.GetNotifications(ctx, "all")
list, err := User.GetNotifications(ctx, userID, "all")
So(err, ShouldBeNil)
So(len(list), ShouldEqual, 1)
So(list[0].Title, ShouldEqual, "Welcome")

View File

@@ -58,7 +58,7 @@ func (s *WalletTestSuite) Test_GetWallet() {
models.OrderQuery.WithContext(ctx).Create(o1, o2)
Convey("should return balance and transactions", func() {
res, err := Wallet.GetWallet(ctx)
res, err := Wallet.GetWallet(ctx, u.ID)
So(err, ShouldBeNil)
So(res.Balance, ShouldEqual, 50.0)
So(len(res.Transactions), ShouldEqual, 2)
@@ -82,7 +82,7 @@ func (s *WalletTestSuite) Test_Recharge() {
Convey("should create recharge order", func() {
form := &user_dto.RechargeForm{Amount: 100.0}
res, err := Wallet.Recharge(ctx, form)
res, err := Wallet.Recharge(ctx, u.ID, form)
So(err, ShouldBeNil)
So(res.OrderID, ShouldNotBeEmpty)