package services import ( "database/sql" "testing" "quyun/v2/app/commands/testx" order_dto "quyun/v2/app/http/v1/dto" "quyun/v2/database" "quyun/v2/database/models" "quyun/v2/pkg/consts" . "github.com/smartystreets/goconvey/convey" "github.com/stretchr/testify/suite" "go.ipao.vip/atom/contracts" "go.uber.org/dig" ) type OrderTestSuiteInjectParams struct { dig.In DB *sql.DB Initials []contracts.Initial `group:"initials"` } type OrderTestSuite struct { suite.Suite OrderTestSuiteInjectParams } func Test_Order(t *testing.T) { providers := testx.Default().With(Provide) testx.Serve(providers, t, func(p OrderTestSuiteInjectParams) { suite.Run(t, &OrderTestSuite{OrderTestSuiteInjectParams: p}) }) } func (s *OrderTestSuite) Test_PurchaseFlow() { Convey("Purchase Flow", s.T(), func() { ctx := s.T().Context() tenantID := int64(0) 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 creator := &models.User{Username: "creator2", Phone: "13800000002"} 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, } models.ContentQuery.WithContext(ctx).Create(content) 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", } models.MediaAssetQuery.WithContext(ctx).Create(asset) 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) Convey("should get full order details", func() { // Create & Pay createRes, _ := Order.Create( ctx, tenantID, buyer.ID, &order_dto.OrderCreateForm{ContentID: content.ID}, ) res, err := Order.Pay(ctx, tenantID, buyer.ID, createRes.OrderID, &order_dto.OrderPayForm{Method: "balance"}) So(err, ShouldBeNil) So(res.Status, ShouldEqual, string(consts.OrderStatusPaid)) // Get Detail detail, err := Order.GetUserOrder(ctx, tenantID, buyer.ID, createRes.OrderID) So(err, ShouldBeNil) So(detail.TenantName, ShouldEqual, "Best Shop") So(len(detail.Items), ShouldEqual, 1) So(detail.Items[0].Title, ShouldEqual, "Amazing Song") So(detail.Items[0].Cover, ShouldContainSubstring, "cover.jpg") So(detail.Amount, ShouldEqual, 5.00) }) }) } func (s *OrderTestSuite) Test_PlatformCommission() { Convey("Platform Commission", s.T(), func() { ctx := s.T().Context() tenantID := int64(0) 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} models.UserQuery.WithContext(ctx).Create(creator) // Tenant t := &models.Tenant{UserID: creator.ID, Name: "Shop C", Status: consts.TenantStatusVerified} models.TenantQuery.WithContext(ctx).Create(t) tenantID = t.ID // Buyer buyer := &models.User{Username: "buyer_c", Balance: 2000} models.UserQuery.WithContext(ctx).Create(buyer) // buyerCtx := context.WithValue(ctx, consts.CtxKeyUser, buyer.ID) // Order (10.00 CNY = 1000) o := &models.Order{ TenantID: t.ID, UserID: buyer.ID, AmountPaid: 1000, Status: consts.OrderStatusCreated, } models.OrderQuery.WithContext(ctx).Create(o) models.OrderItemQuery.WithContext(ctx).Create(&models.OrderItem{OrderID: o.ID, ContentID: 999}) // Fake content Convey("should deduct 10% fee", func() { payForm := &order_dto.OrderPayForm{Method: "balance"} _, err := Order.Pay(ctx, tenantID, buyer.ID, o.ID, payForm) So(err, ShouldBeNil) // Verify Creator Balance (1000 - 10% = 900) cReload, _ := models.UserQuery.WithContext(ctx).Where(models.UserQuery.ID.Eq(creator.ID)).First() So(cReload.Balance, ShouldEqual, 900) // Verify Ledger l, _ := models.TenantLedgerQuery.WithContext(ctx).Where(models.TenantLedgerQuery.OrderID.Eq(o.ID)).First() So(l.Amount, ShouldEqual, 900) }) }) }