package services import ( "database/sql" "testing" "quyun/v2/app/commands/testx" super_dto "quyun/v2/app/http/super/v1/dto" "quyun/v2/app/requests" "quyun/v2/database" "quyun/v2/database/models" "quyun/v2/pkg/consts" "github.com/samber/lo" . "github.com/smartystreets/goconvey/convey" "github.com/stretchr/testify/suite" "go.ipao.vip/atom/contracts" "go.uber.org/dig" ) type SuperTestSuiteInjectParams struct { dig.In DB *sql.DB Initials []contracts.Initial `group:"initials"` } type SuperTestSuite struct { suite.Suite SuperTestSuiteInjectParams } func Test_Super(t *testing.T) { providers := testx.Default().With(Provide) testx.Serve(providers, t, func(p SuperTestSuiteInjectParams) { suite.Run(t, &SuperTestSuite{SuperTestSuiteInjectParams: p}) }) } func (s *SuperTestSuite) Test_ListUsers() { Convey("ListUsers", s.T(), func() { ctx := s.T().Context() database.Truncate(ctx, s.DB, models.TableNameUser) u1 := &models.User{Username: "user1", Nickname: "Alice"} u2 := &models.User{Username: "user2", Nickname: "Bob"} models.UserQuery.WithContext(ctx).Create(u1, u2) Convey("should list users", func() { filter := &super_dto.UserListFilter{ Pagination: requests.Pagination{Page: 1, Limit: 10}, } res, err := Super.ListUsers(ctx, filter) So(err, ShouldBeNil) So(res.Total, ShouldEqual, 2) items := res.Items.([]super_dto.UserItem) So(items[0].Username, ShouldEqual, "user2") // Desc order }) Convey("should filter users", func() { filter := &super_dto.UserListFilter{ Pagination: requests.Pagination{Page: 1, Limit: 10}, Username: lo.ToPtr("Alice"), } res, err := Super.ListUsers(ctx, filter) So(err, ShouldBeNil) So(res.Total, ShouldEqual, 1) items := res.Items.([]super_dto.UserItem) So(items[0].Username, ShouldEqual, "user1") }) }) } func (s *SuperTestSuite) Test_CreateTenant() { Convey("CreateTenant", s.T(), func() { ctx := s.T().Context() database.Truncate(ctx, s.DB, models.TableNameUser, models.TableNameTenant) u := &models.User{Username: "admin1"} models.UserQuery.WithContext(ctx).Create(u) Convey("should create tenant", func() { form := &super_dto.TenantCreateForm{ Name: "Super Tenant", Code: "st1", AdminUserID: u.ID, } err := Super.CreateTenant(ctx, form) So(err, ShouldBeNil) t, _ := models.TenantQuery.WithContext(ctx).Where(models.TenantQuery.Code.Eq("st1")).First() So(t, ShouldNotBeNil) So(t.Name, ShouldEqual, "Super Tenant") So(t.UserID, ShouldEqual, u.ID) So(t.Status, ShouldEqual, consts.TenantStatusVerified) }) }) } func (s *SuperTestSuite) Test_WithdrawalApproval() { Convey("Withdrawal Approval", s.T(), func() { ctx := s.T().Context() database.Truncate(ctx, s.DB, models.TableNameOrder, models.TableNameUser, models.TableNameTenantLedger) u := &models.User{Username: "user_w", Balance: 1000} // Initial 10.00 models.UserQuery.WithContext(ctx).Create(u) // Create Withdrawal Order (Pending) o1 := &models.Order{ UserID: u.ID, Type: consts.OrderTypeWithdrawal, Status: consts.OrderStatusCreated, AmountPaid: 500, } models.OrderQuery.WithContext(ctx).Create(o1) Convey("should list withdrawals", func() { filter := &super_dto.SuperOrderListFilter{Pagination: requests.Pagination{Page: 1, Limit: 10}} res, err := Super.ListWithdrawals(ctx, filter) So(err, ShouldBeNil) So(res.Total, ShouldEqual, 1) }) Convey("should approve withdrawal", func() { err := Super.ApproveWithdrawal(ctx, o1.ID) So(err, ShouldBeNil) oReload, _ := models.OrderQuery.WithContext(ctx).Where(models.OrderQuery.ID.Eq(o1.ID)).First() So(oReload.Status, ShouldEqual, consts.OrderStatusPaid) }) Convey("should reject withdrawal and refund", func() { // Another order o2 := &models.Order{ UserID: u.ID, Type: consts.OrderTypeWithdrawal, Status: consts.OrderStatusCreated, AmountPaid: 200, } models.OrderQuery.WithContext(ctx).Create(o2) // Assuming user balance was deducted when o2 was created (logic in creator service) // But here we set balance manually to 1000. Let's assume it was 1200 before. // Current balance 1000. Refund 200 -> Expect 1200. err := Super.RejectWithdrawal(ctx, o2.ID, "Invalid account") So(err, ShouldBeNil) oReload, _ := models.OrderQuery.WithContext(ctx).Where(models.OrderQuery.ID.Eq(o2.ID)).First() So(oReload.Status, ShouldEqual, consts.OrderStatusFailed) uReload, _ := models.UserQuery.WithContext(ctx).Where(models.UserQuery.ID.Eq(u.ID)).First() So(uReload.Balance, ShouldEqual, 1200) // Check Ledger l, _ := models.TenantLedgerQuery.WithContext(ctx).Where(models.TenantLedgerQuery.OrderID.Eq(o2.ID)).First() So(l, ShouldNotBeNil) So(l.Type, ShouldEqual, consts.TenantLedgerTypeAdjustment) }) }) }