package account import ( "context" "testing" "time" "github.com/break/junhong_cmp_fiber/internal/model" "github.com/break/junhong_cmp_fiber/internal/model/dto" "github.com/break/junhong_cmp_fiber/internal/store/postgres" "github.com/break/junhong_cmp_fiber/pkg/constants" "github.com/break/junhong_cmp_fiber/pkg/errors" "github.com/break/junhong_cmp_fiber/pkg/middleware" "github.com/break/junhong_cmp_fiber/tests/testutils" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" ) type MockAuditService struct { mock.Mock } func (m *MockAuditService) LogOperation(ctx context.Context, log *model.AccountOperationLog) { m.Called(ctx, log) } type MockShopStore struct { mock.Mock } func (m *MockShopStore) GetByID(ctx context.Context, id uint) (*model.Shop, error) { args := m.Called(ctx, id) if args.Get(0) == nil { return nil, args.Error(1) } return args.Get(0).(*model.Shop), args.Error(1) } func (m *MockShopStore) GetSubordinateShopIDs(ctx context.Context, shopID uint) ([]uint, error) { args := m.Called(ctx, shopID) if args.Get(0) == nil { return nil, args.Error(1) } return args.Get(0).([]uint), args.Error(1) } type MockEnterpriseStore struct { mock.Mock } func (m *MockEnterpriseStore) GetByID(ctx context.Context, id uint) (*model.Enterprise, error) { args := m.Called(ctx, id) if args.Get(0) == nil { return nil, args.Error(1) } return args.Get(0).(*model.Enterprise), args.Error(1) } func TestAccountService_Create_SuperAdminSuccess(t *testing.T) { tx := testutils.NewTestTransaction(t) rdb := testutils.GetTestRedis(t) testutils.CleanTestRedisKeys(t, rdb) accountStore := postgres.NewAccountStore(tx, rdb) roleStore := postgres.NewRoleStore(tx) accountRoleStore := postgres.NewAccountRoleStore(tx, rdb) mockAudit := new(MockAuditService) mockShop := new(MockShopStore) mockEnterprise := new(MockEnterpriseStore) svc := New(accountStore, roleStore, accountRoleStore, mockShop, mockEnterprise, mockAudit) ctx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{ UserID: 1, UserType: constants.UserTypeSuperAdmin, }) username := "test_super_" + time.Now().Format("20060102150405") phone := "1" + time.Now().Format("0601021504") req := &dto.CreateAccountRequest{ Username: username, Phone: phone, Password: "TestPass123", UserType: constants.UserTypePlatform, } mockAudit.On("LogOperation", mock.Anything, mock.Anything).Return() resp, err := svc.Create(ctx, req) require.NoError(t, err) assert.NotZero(t, resp.ID) assert.Equal(t, username, resp.Username) assert.Equal(t, phone, resp.Phone) assert.Equal(t, constants.UserTypePlatform, resp.UserType) assert.Equal(t, constants.StatusEnabled, resp.Status) mockAudit.AssertCalled(t, "LogOperation", mock.Anything, mock.Anything) } func TestAccountService_Create_PlatformUserCreatePlatformAccount(t *testing.T) { tx := testutils.NewTestTransaction(t) rdb := testutils.GetTestRedis(t) testutils.CleanTestRedisKeys(t, rdb) accountStore := postgres.NewAccountStore(tx, rdb) roleStore := postgres.NewRoleStore(tx) accountRoleStore := postgres.NewAccountRoleStore(tx, rdb) mockAudit := new(MockAuditService) mockShop := new(MockShopStore) mockEnterprise := new(MockEnterpriseStore) svc := New(accountStore, roleStore, accountRoleStore, mockShop, mockEnterprise, mockAudit) ctx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{ UserID: 1, UserType: constants.UserTypePlatform, }) username := "test_platform_" + time.Now().Format("20060102150405") phone := "1" + time.Now().Format("0601021504") req := &dto.CreateAccountRequest{ Username: username, Phone: phone, Password: "TestPass123", UserType: constants.UserTypePlatform, } mockAudit.On("LogOperation", mock.Anything, mock.Anything).Return() resp, err := svc.Create(ctx, req) require.NoError(t, err) assert.NotZero(t, resp.ID) assert.Equal(t, username, resp.Username) mockAudit.AssertCalled(t, "LogOperation", mock.Anything, mock.Anything) } func TestAccountService_Create_PlatformUserCreateAgentAccount(t *testing.T) { tx := testutils.NewTestTransaction(t) rdb := testutils.GetTestRedis(t) testutils.CleanTestRedisKeys(t, rdb) accountStore := postgres.NewAccountStore(tx, rdb) roleStore := postgres.NewRoleStore(tx) accountRoleStore := postgres.NewAccountRoleStore(tx, rdb) mockAudit := new(MockAuditService) mockShop := new(MockShopStore) mockEnterprise := new(MockEnterpriseStore) svc := New(accountStore, roleStore, accountRoleStore, mockShop, mockEnterprise, mockAudit) ctx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{ UserID: 1, UserType: constants.UserTypePlatform, }) shopID := uint(1) username := "test_agent_" + time.Now().Format("20060102150405") phone := "1" + time.Now().Format("0601021504") req := &dto.CreateAccountRequest{ Username: username, Phone: phone, Password: "TestPass123", UserType: constants.UserTypeAgent, ShopID: &shopID, } mockAudit.On("LogOperation", mock.Anything, mock.Anything).Return() resp, err := svc.Create(ctx, req) require.NoError(t, err) assert.NotZero(t, resp.ID) assert.Equal(t, constants.UserTypeAgent, resp.UserType) assert.Equal(t, &shopID, resp.ShopID) mockAudit.AssertCalled(t, "LogOperation", mock.Anything, mock.Anything) } func TestAccountService_Create_AgentCreateSubordinateShopAccount(t *testing.T) { tx := testutils.NewTestTransaction(t) rdb := testutils.GetTestRedis(t) testutils.CleanTestRedisKeys(t, rdb) accountStore := postgres.NewAccountStore(tx, rdb) roleStore := postgres.NewRoleStore(tx) accountRoleStore := postgres.NewAccountRoleStore(tx, rdb) mockAudit := new(MockAuditService) mockShop := new(MockShopStore) mockEnterprise := new(MockEnterpriseStore) svc := New(accountStore, roleStore, accountRoleStore, mockShop, mockEnterprise, mockAudit) agentShopID := uint(10) subordinateShopID := uint(11) ctx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{ UserID: 1, UserType: constants.UserTypeAgent, ShopID: agentShopID, }) username := "test_sub_agent_" + time.Now().Format("20060102150405") phone := "1" + time.Now().Format("0601021504") req := &dto.CreateAccountRequest{ Username: username, Phone: phone, Password: "TestPass123", UserType: constants.UserTypeAgent, ShopID: &subordinateShopID, } mockShop.On("GetSubordinateShopIDs", mock.Anything, agentShopID).Return([]uint{agentShopID, subordinateShopID}, nil) mockAudit.On("LogOperation", mock.Anything, mock.Anything).Return() resp, err := svc.Create(ctx, req) require.NoError(t, err) assert.NotZero(t, resp.ID) assert.Equal(t, &subordinateShopID, resp.ShopID) mockShop.AssertCalled(t, "GetSubordinateShopIDs", mock.Anything, agentShopID) mockAudit.AssertCalled(t, "LogOperation", mock.Anything, mock.Anything) } func TestAccountService_Create_AgentCreateOtherShopAccountForbidden(t *testing.T) { tx := testutils.NewTestTransaction(t) rdb := testutils.GetTestRedis(t) testutils.CleanTestRedisKeys(t, rdb) accountStore := postgres.NewAccountStore(tx, rdb) roleStore := postgres.NewRoleStore(tx) accountRoleStore := postgres.NewAccountRoleStore(tx, rdb) mockAudit := new(MockAuditService) mockShop := new(MockShopStore) mockEnterprise := new(MockEnterpriseStore) svc := New(accountStore, roleStore, accountRoleStore, mockShop, mockEnterprise, mockAudit) agentShopID := uint(10) otherShopID := uint(99) ctx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{ UserID: 1, UserType: constants.UserTypeAgent, ShopID: agentShopID, }) username := "test_forbidden_" + time.Now().Format("20060102150405") phone := "1" + time.Now().Format("0601021504") req := &dto.CreateAccountRequest{ Username: username, Phone: phone, Password: "TestPass123", UserType: constants.UserTypeAgent, ShopID: &otherShopID, } mockShop.On("GetSubordinateShopIDs", mock.Anything, agentShopID).Return([]uint{agentShopID}, nil) _, err := svc.Create(ctx, req) require.Error(t, err) appErr, ok := err.(*errors.AppError) require.True(t, ok) assert.Equal(t, errors.CodeForbidden, appErr.Code) } func TestAccountService_Create_AgentCreatePlatformAccountForbidden(t *testing.T) { tx := testutils.NewTestTransaction(t) rdb := testutils.GetTestRedis(t) testutils.CleanTestRedisKeys(t, rdb) accountStore := postgres.NewAccountStore(tx, rdb) roleStore := postgres.NewRoleStore(tx) accountRoleStore := postgres.NewAccountRoleStore(tx, rdb) mockAudit := new(MockAuditService) mockShop := new(MockShopStore) mockEnterprise := new(MockEnterpriseStore) svc := New(accountStore, roleStore, accountRoleStore, mockShop, mockEnterprise, mockAudit) ctx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{ UserID: 1, UserType: constants.UserTypeAgent, ShopID: 10, }) username := "test_platform_forbidden_" + time.Now().Format("20060102150405") phone := "1" + time.Now().Format("0601021504") req := &dto.CreateAccountRequest{ Username: username, Phone: phone, Password: "TestPass123", UserType: constants.UserTypePlatform, } _, err := svc.Create(ctx, req) require.Error(t, err) appErr, ok := err.(*errors.AppError) require.True(t, ok) assert.Equal(t, errors.CodeForbidden, appErr.Code) } func TestAccountService_Create_EnterpriseUserForbidden(t *testing.T) { tx := testutils.NewTestTransaction(t) rdb := testutils.GetTestRedis(t) testutils.CleanTestRedisKeys(t, rdb) accountStore := postgres.NewAccountStore(tx, rdb) roleStore := postgres.NewRoleStore(tx) accountRoleStore := postgres.NewAccountRoleStore(tx, rdb) mockAudit := new(MockAuditService) mockShop := new(MockShopStore) mockEnterprise := new(MockEnterpriseStore) svc := New(accountStore, roleStore, accountRoleStore, mockShop, mockEnterprise, mockAudit) ctx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{ UserID: 1, UserType: constants.UserTypeEnterprise, EnterpriseID: 1, }) username := "test_enterprise_forbidden_" + time.Now().Format("20060102150405") phone := "1" + time.Now().Format("0601021504") req := &dto.CreateAccountRequest{ Username: username, Phone: phone, Password: "TestPass123", UserType: constants.UserTypePlatform, } _, err := svc.Create(ctx, req) require.Error(t, err) appErr, ok := err.(*errors.AppError) require.True(t, ok) assert.Equal(t, errors.CodeForbidden, appErr.Code) } func TestAccountService_Create_UsernameDuplicate(t *testing.T) { tx := testutils.NewTestTransaction(t) rdb := testutils.GetTestRedis(t) testutils.CleanTestRedisKeys(t, rdb) accountStore := postgres.NewAccountStore(tx, rdb) roleStore := postgres.NewRoleStore(tx) accountRoleStore := postgres.NewAccountRoleStore(tx, rdb) mockAudit := new(MockAuditService) mockShop := new(MockShopStore) mockEnterprise := new(MockEnterpriseStore) svc := New(accountStore, roleStore, accountRoleStore, mockShop, mockEnterprise, mockAudit) ctx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{ UserID: 1, UserType: constants.UserTypeSuperAdmin, }) username := "test_dup_" + time.Now().Format("20060102150405") phone1 := "1" + time.Now().Format("0601021504") phone2 := "1" + time.Now().Format("0601021505") req1 := &dto.CreateAccountRequest{ Username: username, Phone: phone1, Password: "TestPass123", UserType: constants.UserTypePlatform, } mockAudit.On("LogOperation", mock.Anything, mock.Anything).Return() _, err := svc.Create(ctx, req1) require.NoError(t, err) req2 := &dto.CreateAccountRequest{ Username: username, Phone: phone2, Password: "TestPass123", UserType: constants.UserTypePlatform, } _, err = svc.Create(ctx, req2) require.Error(t, err) appErr, ok := err.(*errors.AppError) require.True(t, ok) assert.Equal(t, errors.CodeUsernameExists, appErr.Code) } func TestAccountService_Create_PhoneDuplicate(t *testing.T) { tx := testutils.NewTestTransaction(t) rdb := testutils.GetTestRedis(t) testutils.CleanTestRedisKeys(t, rdb) accountStore := postgres.NewAccountStore(tx, rdb) roleStore := postgres.NewRoleStore(tx) accountRoleStore := postgres.NewAccountRoleStore(tx, rdb) mockAudit := new(MockAuditService) mockShop := new(MockShopStore) mockEnterprise := new(MockEnterpriseStore) svc := New(accountStore, roleStore, accountRoleStore, mockShop, mockEnterprise, mockAudit) ctx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{ UserID: 1, UserType: constants.UserTypeSuperAdmin, }) phone := "1" + time.Now().Format("0601021504") username1 := "test_phone_dup1_" + time.Now().Format("20060102150405") username2 := "test_phone_dup2_" + time.Now().Format("20060102150405") req1 := &dto.CreateAccountRequest{ Username: username1, Phone: phone, Password: "TestPass123", UserType: constants.UserTypePlatform, } mockAudit.On("LogOperation", mock.Anything, mock.Anything).Return() _, err := svc.Create(ctx, req1) require.NoError(t, err) req2 := &dto.CreateAccountRequest{ Username: username2, Phone: phone, Password: "TestPass123", UserType: constants.UserTypePlatform, } _, err = svc.Create(ctx, req2) require.Error(t, err) appErr, ok := err.(*errors.AppError) require.True(t, ok) assert.Equal(t, errors.CodePhoneExists, appErr.Code) } func TestAccountService_Create_Unauthorized(t *testing.T) { tx := testutils.NewTestTransaction(t) rdb := testutils.GetTestRedis(t) testutils.CleanTestRedisKeys(t, rdb) accountStore := postgres.NewAccountStore(tx, rdb) roleStore := postgres.NewRoleStore(tx) accountRoleStore := postgres.NewAccountRoleStore(tx, rdb) mockAudit := new(MockAuditService) mockShop := new(MockShopStore) mockEnterprise := new(MockEnterpriseStore) svc := New(accountStore, roleStore, accountRoleStore, mockShop, mockEnterprise, mockAudit) ctx := context.Background() username := "test_unauth_" + time.Now().Format("20060102150405") phone := "1" + time.Now().Format("0601021504") req := &dto.CreateAccountRequest{ Username: username, Phone: phone, Password: "TestPass123", UserType: constants.UserTypePlatform, } _, err := svc.Create(ctx, req) require.Error(t, err) appErr, ok := err.(*errors.AppError) require.True(t, ok) assert.Equal(t, errors.CodeUnauthorized, appErr.Code) } // ============ Update 方法测试 ============ func TestAccountService_Update_Success(t *testing.T) { tx := testutils.NewTestTransaction(t) rdb := testutils.GetTestRedis(t) testutils.CleanTestRedisKeys(t, rdb) accountStore := postgres.NewAccountStore(tx, rdb) roleStore := postgres.NewRoleStore(tx) accountRoleStore := postgres.NewAccountRoleStore(tx, rdb) mockAudit := new(MockAuditService) mockShop := new(MockShopStore) mockEnterprise := new(MockEnterpriseStore) svc := New(accountStore, roleStore, accountRoleStore, mockShop, mockEnterprise, mockAudit) ctx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{ UserID: 1, UserType: constants.UserTypeSuperAdmin, }) username := "test_update_" + time.Now().Format("20060102150405") phone := "1" + time.Now().Format("0601021504") req := &dto.CreateAccountRequest{ Username: username, Phone: phone, Password: "TestPass123", UserType: constants.UserTypePlatform, } mockAudit.On("LogOperation", mock.Anything, mock.Anything).Return() created, err := svc.Create(ctx, req) require.NoError(t, err) newUsername := "updated_" + time.Now().Format("20060102150405") updateReq := &dto.UpdateAccountRequest{ Username: &newUsername, } updated, err := svc.Update(ctx, created.ID, updateReq) require.NoError(t, err) assert.Equal(t, newUsername, updated.Username) mockAudit.AssertCalled(t, "LogOperation", mock.Anything, mock.Anything) } func TestAccountService_Update_NotFound(t *testing.T) { tx := testutils.NewTestTransaction(t) rdb := testutils.GetTestRedis(t) testutils.CleanTestRedisKeys(t, rdb) accountStore := postgres.NewAccountStore(tx, rdb) roleStore := postgres.NewRoleStore(tx) accountRoleStore := postgres.NewAccountRoleStore(tx, rdb) mockAudit := new(MockAuditService) mockShop := new(MockShopStore) mockEnterprise := new(MockEnterpriseStore) svc := New(accountStore, roleStore, accountRoleStore, mockShop, mockEnterprise, mockAudit) ctx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{ UserID: 1, UserType: constants.UserTypeSuperAdmin, }) newUsername := "test" updateReq := &dto.UpdateAccountRequest{ Username: &newUsername, } _, err := svc.Update(ctx, 99999, updateReq) require.Error(t, err) appErr, ok := err.(*errors.AppError) require.True(t, ok) assert.Equal(t, errors.CodeForbidden, appErr.Code) } func TestAccountService_Update_AgentUnauthorized(t *testing.T) { tx := testutils.NewTestTransaction(t) rdb := testutils.GetTestRedis(t) testutils.CleanTestRedisKeys(t, rdb) accountStore := postgres.NewAccountStore(tx, rdb) roleStore := postgres.NewRoleStore(tx) accountRoleStore := postgres.NewAccountRoleStore(tx, rdb) mockAudit := new(MockAuditService) mockShop := new(MockShopStore) mockEnterprise := new(MockEnterpriseStore) svc := New(accountStore, roleStore, accountRoleStore, mockShop, mockEnterprise, mockAudit) superAdminCtx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{ UserID: 1, UserType: constants.UserTypeSuperAdmin, }) username := "test_agent_unauth_" + time.Now().Format("20060102150405") phone := "1" + time.Now().Format("0601021504") req := &dto.CreateAccountRequest{ Username: username, Phone: phone, Password: "TestPass123", UserType: constants.UserTypePlatform, } mockAudit.On("LogOperation", mock.Anything, mock.Anything).Return() created, err := svc.Create(superAdminCtx, req) require.NoError(t, err) agentCtx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{ UserID: 2, UserType: constants.UserTypeAgent, ShopID: 10, }) newUsername := "updated" updateReq := &dto.UpdateAccountRequest{ Username: &newUsername, } mockShop.On("GetSubordinateShopIDs", mock.Anything, uint(10)).Return([]uint{10}, nil) _, err = svc.Update(agentCtx, created.ID, updateReq) require.Error(t, err) appErr, ok := err.(*errors.AppError) require.True(t, ok) assert.Equal(t, errors.CodeForbidden, appErr.Code) } func TestAccountService_Update_UsernameDuplicate(t *testing.T) { tx := testutils.NewTestTransaction(t) rdb := testutils.GetTestRedis(t) testutils.CleanTestRedisKeys(t, rdb) accountStore := postgres.NewAccountStore(tx, rdb) roleStore := postgres.NewRoleStore(tx) accountRoleStore := postgres.NewAccountRoleStore(tx, rdb) mockAudit := new(MockAuditService) mockShop := new(MockShopStore) mockEnterprise := new(MockEnterpriseStore) svc := New(accountStore, roleStore, accountRoleStore, mockShop, mockEnterprise, mockAudit) ctx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{ UserID: 1, UserType: constants.UserTypeSuperAdmin, }) username1 := "test_dup1_" + time.Now().Format("20060102150405") username2 := "test_dup2_" + time.Now().Format("20060102150405") phone1 := "1" + time.Now().Format("0601021504") phone2 := "1" + time.Now().Format("0601021505") req1 := &dto.CreateAccountRequest{ Username: username1, Phone: phone1, Password: "TestPass123", UserType: constants.UserTypePlatform, } req2 := &dto.CreateAccountRequest{ Username: username2, Phone: phone2, Password: "TestPass123", UserType: constants.UserTypePlatform, } mockAudit.On("LogOperation", mock.Anything, mock.Anything).Return() acc1, err := svc.Create(ctx, req1) require.NoError(t, err) _, err = svc.Create(ctx, req2) require.NoError(t, err) updateReq := &dto.UpdateAccountRequest{ Username: &username2, } _, err = svc.Update(ctx, acc1.ID, updateReq) require.Error(t, err) appErr, ok := err.(*errors.AppError) require.True(t, ok) assert.Equal(t, errors.CodeUsernameExists, appErr.Code) } func TestAccountService_Update_PhoneDuplicate(t *testing.T) { tx := testutils.NewTestTransaction(t) rdb := testutils.GetTestRedis(t) testutils.CleanTestRedisKeys(t, rdb) accountStore := postgres.NewAccountStore(tx, rdb) roleStore := postgres.NewRoleStore(tx) accountRoleStore := postgres.NewAccountRoleStore(tx, rdb) mockAudit := new(MockAuditService) mockShop := new(MockShopStore) mockEnterprise := new(MockEnterpriseStore) svc := New(accountStore, roleStore, accountRoleStore, mockShop, mockEnterprise, mockAudit) ctx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{ UserID: 1, UserType: constants.UserTypeSuperAdmin, }) username1 := "test_phone_dup1_" + time.Now().Format("20060102150405") username2 := "test_phone_dup2_" + time.Now().Format("20060102150405") phone1 := "1" + time.Now().Format("0601021504") phone2 := "1" + time.Now().Format("0601021505") req1 := &dto.CreateAccountRequest{ Username: username1, Phone: phone1, Password: "TestPass123", UserType: constants.UserTypePlatform, } req2 := &dto.CreateAccountRequest{ Username: username2, Phone: phone2, Password: "TestPass123", UserType: constants.UserTypePlatform, } mockAudit.On("LogOperation", mock.Anything, mock.Anything).Return() acc1, err := svc.Create(ctx, req1) require.NoError(t, err) _, err = svc.Create(ctx, req2) require.NoError(t, err) updateReq := &dto.UpdateAccountRequest{ Phone: &phone2, } _, err = svc.Update(ctx, acc1.ID, updateReq) require.Error(t, err) appErr, ok := err.(*errors.AppError) require.True(t, ok) assert.Equal(t, errors.CodePhoneExists, appErr.Code) } // ============ Delete 方法测试 ============ func TestAccountService_Delete_Success(t *testing.T) { tx := testutils.NewTestTransaction(t) rdb := testutils.GetTestRedis(t) testutils.CleanTestRedisKeys(t, rdb) accountStore := postgres.NewAccountStore(tx, rdb) roleStore := postgres.NewRoleStore(tx) accountRoleStore := postgres.NewAccountRoleStore(tx, rdb) mockAudit := new(MockAuditService) mockShop := new(MockShopStore) mockEnterprise := new(MockEnterpriseStore) svc := New(accountStore, roleStore, accountRoleStore, mockShop, mockEnterprise, mockAudit) ctx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{ UserID: 1, UserType: constants.UserTypeSuperAdmin, }) username := "test_delete_" + time.Now().Format("20060102150405") phone := "1" + time.Now().Format("0601021504") req := &dto.CreateAccountRequest{ Username: username, Phone: phone, Password: "TestPass123", UserType: constants.UserTypePlatform, } mockAudit.On("LogOperation", mock.Anything, mock.Anything).Return() created, err := svc.Create(ctx, req) require.NoError(t, err) err = svc.Delete(ctx, created.ID) require.NoError(t, err) _, err = svc.Get(ctx, created.ID) require.Error(t, err) mockAudit.AssertCalled(t, "LogOperation", mock.Anything, mock.Anything) } func TestAccountService_Delete_NotFound(t *testing.T) { tx := testutils.NewTestTransaction(t) rdb := testutils.GetTestRedis(t) testutils.CleanTestRedisKeys(t, rdb) accountStore := postgres.NewAccountStore(tx, rdb) roleStore := postgres.NewRoleStore(tx) accountRoleStore := postgres.NewAccountRoleStore(tx, rdb) mockAudit := new(MockAuditService) mockShop := new(MockShopStore) mockEnterprise := new(MockEnterpriseStore) svc := New(accountStore, roleStore, accountRoleStore, mockShop, mockEnterprise, mockAudit) ctx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{ UserID: 1, UserType: constants.UserTypeSuperAdmin, }) err := svc.Delete(ctx, 99999) require.Error(t, err) appErr, ok := err.(*errors.AppError) require.True(t, ok) assert.Equal(t, errors.CodeForbidden, appErr.Code) } func TestAccountService_Delete_AgentUnauthorized(t *testing.T) { tx := testutils.NewTestTransaction(t) rdb := testutils.GetTestRedis(t) testutils.CleanTestRedisKeys(t, rdb) accountStore := postgres.NewAccountStore(tx, rdb) roleStore := postgres.NewRoleStore(tx) accountRoleStore := postgres.NewAccountRoleStore(tx, rdb) mockAudit := new(MockAuditService) mockShop := new(MockShopStore) mockEnterprise := new(MockEnterpriseStore) svc := New(accountStore, roleStore, accountRoleStore, mockShop, mockEnterprise, mockAudit) superAdminCtx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{ UserID: 1, UserType: constants.UserTypeSuperAdmin, }) username := "test_delete_unauth_" + time.Now().Format("20060102150405") phone := "1" + time.Now().Format("0601021504") req := &dto.CreateAccountRequest{ Username: username, Phone: phone, Password: "TestPass123", UserType: constants.UserTypePlatform, } mockAudit.On("LogOperation", mock.Anything, mock.Anything).Return() created, err := svc.Create(superAdminCtx, req) require.NoError(t, err) agentCtx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{ UserID: 2, UserType: constants.UserTypeAgent, ShopID: 10, }) mockShop.On("GetSubordinateShopIDs", mock.Anything, uint(10)).Return([]uint{10}, nil) err = svc.Delete(agentCtx, created.ID) require.Error(t, err) appErr, ok := err.(*errors.AppError) require.True(t, ok) assert.Equal(t, errors.CodeForbidden, appErr.Code) } // ============ AssignRoles 方法测试 ============ func TestAccountService_AssignRoles_Success(t *testing.T) { tx := testutils.NewTestTransaction(t) rdb := testutils.GetTestRedis(t) testutils.CleanTestRedisKeys(t, rdb) accountStore := postgres.NewAccountStore(tx, rdb) roleStore := postgres.NewRoleStore(tx) accountRoleStore := postgres.NewAccountRoleStore(tx, rdb) mockAudit := new(MockAuditService) mockShop := new(MockShopStore) mockEnterprise := new(MockEnterpriseStore) svc := New(accountStore, roleStore, accountRoleStore, mockShop, mockEnterprise, mockAudit) ctx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{ UserID: 1, UserType: constants.UserTypeSuperAdmin, }) username := "test_assign_roles_" + time.Now().Format("20060102150405") phone := "1" + time.Now().Format("0601021504") req := &dto.CreateAccountRequest{ Username: username, Phone: phone, Password: "TestPass123", UserType: constants.UserTypePlatform, } mockAudit.On("LogOperation", mock.Anything, mock.Anything).Return() created, err := svc.Create(ctx, req) require.NoError(t, err) role := &model.Role{ RoleName: "test_role_" + time.Now().Format("20060102150405"), RoleType: constants.RoleTypePlatform, Status: constants.StatusEnabled, } errRole := roleStore.Create(ctx, role) require.NoError(t, errRole) ars, err := svc.AssignRoles(ctx, created.ID, []uint{role.ID}) require.NoError(t, err) assert.Len(t, ars, 1) assert.Equal(t, created.ID, ars[0].AccountID) assert.Equal(t, role.ID, ars[0].RoleID) mockAudit.AssertCalled(t, "LogOperation", mock.Anything, mock.Anything) } func TestAccountService_AssignRoles_SuperAdminForbidden(t *testing.T) { tx := testutils.NewTestTransaction(t) rdb := testutils.GetTestRedis(t) testutils.CleanTestRedisKeys(t, rdb) accountStore := postgres.NewAccountStore(tx, rdb) roleStore := postgres.NewRoleStore(tx) accountRoleStore := postgres.NewAccountRoleStore(tx, rdb) mockAudit := new(MockAuditService) mockShop := new(MockShopStore) mockEnterprise := new(MockEnterpriseStore) svc := New(accountStore, roleStore, accountRoleStore, mockShop, mockEnterprise, mockAudit) ctx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{ UserID: 1, UserType: constants.UserTypeSuperAdmin, }) username := "test_super_admin_" + time.Now().Format("20060102150405") phone := "1" + time.Now().Format("0601021504") req := &dto.CreateAccountRequest{ Username: username, Phone: phone, Password: "TestPass123", UserType: constants.UserTypeSuperAdmin, } mockAudit.On("LogOperation", mock.Anything, mock.Anything).Return() created, err := svc.Create(ctx, req) require.NoError(t, err) _, err = svc.AssignRoles(ctx, created.ID, []uint{1}) require.Error(t, err) appErr, ok := err.(*errors.AppError) require.True(t, ok) assert.Equal(t, errors.CodeInvalidParam, appErr.Code) } func TestAccountService_AssignRoles_RoleTypeMismatch(t *testing.T) { tx := testutils.NewTestTransaction(t) rdb := testutils.GetTestRedis(t) testutils.CleanTestRedisKeys(t, rdb) accountStore := postgres.NewAccountStore(tx, rdb) roleStore := postgres.NewRoleStore(tx) accountRoleStore := postgres.NewAccountRoleStore(tx, rdb) mockAudit := new(MockAuditService) mockShop := new(MockShopStore) mockEnterprise := new(MockEnterpriseStore) svc := New(accountStore, roleStore, accountRoleStore, mockShop, mockEnterprise, mockAudit) ctx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{ UserID: 1, UserType: constants.UserTypeSuperAdmin, }) username := "test_role_mismatch_" + time.Now().Format("20060102150405") phone := "1" + time.Now().Format("0601021504") req := &dto.CreateAccountRequest{ Username: username, Phone: phone, Password: "TestPass123", UserType: constants.UserTypeAgent, ShopID: ptrUint(1), } mockAudit.On("LogOperation", mock.Anything, mock.Anything).Return() created, err := svc.Create(ctx, req) require.NoError(t, err) role := &model.Role{ RoleName: "test_platform_role_" + time.Now().Format("20060102150405"), RoleType: constants.RoleTypePlatform, Status: constants.StatusEnabled, } errRole := roleStore.Create(ctx, role) require.NoError(t, errRole) _, err = svc.AssignRoles(ctx, created.ID, []uint{role.ID}) require.Error(t, err) appErr, ok := err.(*errors.AppError) require.True(t, ok) assert.Equal(t, errors.CodeInvalidParam, appErr.Code) } func TestAccountService_AssignRoles_EmptyArrayClearsRoles(t *testing.T) { tx := testutils.NewTestTransaction(t) rdb := testutils.GetTestRedis(t) testutils.CleanTestRedisKeys(t, rdb) accountStore := postgres.NewAccountStore(tx, rdb) roleStore := postgres.NewRoleStore(tx) accountRoleStore := postgres.NewAccountRoleStore(tx, rdb) mockAudit := new(MockAuditService) mockShop := new(MockShopStore) mockEnterprise := new(MockEnterpriseStore) svc := New(accountStore, roleStore, accountRoleStore, mockShop, mockEnterprise, mockAudit) ctx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{ UserID: 1, UserType: constants.UserTypeSuperAdmin, }) username := "test_clear_roles_" + time.Now().Format("20060102150405") phone := "1" + time.Now().Format("0601021504") req := &dto.CreateAccountRequest{ Username: username, Phone: phone, Password: "TestPass123", UserType: constants.UserTypePlatform, } mockAudit.On("LogOperation", mock.Anything, mock.Anything).Return() created, err := svc.Create(ctx, req) require.NoError(t, err) role := &model.Role{ RoleName: "test_role_clear_" + time.Now().Format("20060102150405"), RoleType: constants.RoleTypePlatform, Status: constants.StatusEnabled, } errRole := roleStore.Create(ctx, role) require.NoError(t, errRole) _, err = svc.AssignRoles(ctx, created.ID, []uint{role.ID}) require.NoError(t, err) ars, err := svc.AssignRoles(ctx, created.ID, []uint{}) require.NoError(t, err) assert.Len(t, ars, 0) } // ============ RemoveRole 方法测试 ============ func TestAccountService_RemoveRole_Success(t *testing.T) { tx := testutils.NewTestTransaction(t) rdb := testutils.GetTestRedis(t) testutils.CleanTestRedisKeys(t, rdb) accountStore := postgres.NewAccountStore(tx, rdb) roleStore := postgres.NewRoleStore(tx) accountRoleStore := postgres.NewAccountRoleStore(tx, rdb) mockAudit := new(MockAuditService) mockShop := new(MockShopStore) mockEnterprise := new(MockEnterpriseStore) svc := New(accountStore, roleStore, accountRoleStore, mockShop, mockEnterprise, mockAudit) ctx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{ UserID: 1, UserType: constants.UserTypeSuperAdmin, }) username := "test_remove_role_" + time.Now().Format("20060102150405") phone := "1" + time.Now().Format("0601021504") req := &dto.CreateAccountRequest{ Username: username, Phone: phone, Password: "TestPass123", UserType: constants.UserTypePlatform, } mockAudit.On("LogOperation", mock.Anything, mock.Anything).Return() created, err := svc.Create(ctx, req) require.NoError(t, err) role := &model.Role{ RoleName: "test_role_remove_" + time.Now().Format("20060102150405"), RoleType: constants.RoleTypePlatform, Status: constants.StatusEnabled, } errRole := roleStore.Create(ctx, role) require.NoError(t, errRole) _, err = svc.AssignRoles(ctx, created.ID, []uint{role.ID}) require.NoError(t, err) err = svc.RemoveRole(ctx, created.ID, role.ID) require.NoError(t, err) roles, err := svc.GetRoles(ctx, created.ID) require.NoError(t, err) assert.Len(t, roles, 0) mockAudit.AssertCalled(t, "LogOperation", mock.Anything, mock.Anything) } func TestAccountService_RemoveRole_AccountNotFound(t *testing.T) { tx := testutils.NewTestTransaction(t) rdb := testutils.GetTestRedis(t) testutils.CleanTestRedisKeys(t, rdb) accountStore := postgres.NewAccountStore(tx, rdb) roleStore := postgres.NewRoleStore(tx) accountRoleStore := postgres.NewAccountRoleStore(tx, rdb) mockAudit := new(MockAuditService) mockShop := new(MockShopStore) mockEnterprise := new(MockEnterpriseStore) svc := New(accountStore, roleStore, accountRoleStore, mockShop, mockEnterprise, mockAudit) ctx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{ UserID: 1, UserType: constants.UserTypeSuperAdmin, }) err := svc.RemoveRole(ctx, 99999, 1) require.Error(t, err) appErr, ok := err.(*errors.AppError) require.True(t, ok) assert.Equal(t, errors.CodeForbidden, appErr.Code) } // ============ GetRoles 方法测试 ============ func TestAccountService_GetRoles_Success(t *testing.T) { tx := testutils.NewTestTransaction(t) rdb := testutils.GetTestRedis(t) testutils.CleanTestRedisKeys(t, rdb) accountStore := postgres.NewAccountStore(tx, rdb) roleStore := postgres.NewRoleStore(tx) accountRoleStore := postgres.NewAccountRoleStore(tx, rdb) mockAudit := new(MockAuditService) mockShop := new(MockShopStore) mockEnterprise := new(MockEnterpriseStore) svc := New(accountStore, roleStore, accountRoleStore, mockShop, mockEnterprise, mockAudit) ctx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{ UserID: 1, UserType: constants.UserTypeSuperAdmin, }) username := "test_get_roles_" + time.Now().Format("20060102150405") phone := "1" + time.Now().Format("0601021504") req := &dto.CreateAccountRequest{ Username: username, Phone: phone, Password: "TestPass123", UserType: constants.UserTypePlatform, } mockAudit.On("LogOperation", mock.Anything, mock.Anything).Return() created, err := svc.Create(ctx, req) require.NoError(t, err) role := &model.Role{ RoleName: "test_role_get_" + time.Now().Format("20060102150405"), RoleType: constants.RoleTypePlatform, Status: constants.StatusEnabled, } errRole := roleStore.Create(ctx, role) require.NoError(t, errRole) _, err = svc.AssignRoles(ctx, created.ID, []uint{role.ID}) require.NoError(t, err) roles, err := svc.GetRoles(ctx, created.ID) require.NoError(t, err) assert.Len(t, roles, 1) assert.Equal(t, role.ID, roles[0].ID) } func TestAccountService_GetRoles_EmptyArray(t *testing.T) { tx := testutils.NewTestTransaction(t) rdb := testutils.GetTestRedis(t) testutils.CleanTestRedisKeys(t, rdb) accountStore := postgres.NewAccountStore(tx, rdb) roleStore := postgres.NewRoleStore(tx) accountRoleStore := postgres.NewAccountRoleStore(tx, rdb) mockAudit := new(MockAuditService) mockShop := new(MockShopStore) mockEnterprise := new(MockEnterpriseStore) svc := New(accountStore, roleStore, accountRoleStore, mockShop, mockEnterprise, mockAudit) ctx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{ UserID: 1, UserType: constants.UserTypeSuperAdmin, }) username := "test_no_roles_" + time.Now().Format("20060102150405") phone := "1" + time.Now().Format("0601021504") req := &dto.CreateAccountRequest{ Username: username, Phone: phone, Password: "TestPass123", UserType: constants.UserTypePlatform, } mockAudit.On("LogOperation", mock.Anything, mock.Anything).Return() created, err := svc.Create(ctx, req) require.NoError(t, err) roles, err := svc.GetRoles(ctx, created.ID) require.NoError(t, err) assert.Len(t, roles, 0) } // ============ List 方法测试 ============ func TestAccountService_List_Success(t *testing.T) { tx := testutils.NewTestTransaction(t) rdb := testutils.GetTestRedis(t) testutils.CleanTestRedisKeys(t, rdb) accountStore := postgres.NewAccountStore(tx, rdb) roleStore := postgres.NewRoleStore(tx) accountRoleStore := postgres.NewAccountRoleStore(tx, rdb) mockAudit := new(MockAuditService) mockShop := new(MockShopStore) mockEnterprise := new(MockEnterpriseStore) svc := New(accountStore, roleStore, accountRoleStore, mockShop, mockEnterprise, mockAudit) ctx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{ UserID: 1, UserType: constants.UserTypeSuperAdmin, }) username := "test_list_" + time.Now().Format("20060102150405") phone := "1" + time.Now().Format("0601021504") req := &dto.CreateAccountRequest{ Username: username, Phone: phone, Password: "TestPass123", UserType: constants.UserTypePlatform, } mockAudit.On("LogOperation", mock.Anything, mock.Anything).Return() _, err := svc.Create(ctx, req) require.NoError(t, err) listReq := &dto.AccountListRequest{ Page: 1, PageSize: 20, } accounts, total, err := svc.List(ctx, listReq) require.NoError(t, err) assert.Greater(t, total, int64(0)) assert.Greater(t, len(accounts), 0) } func TestAccountService_List_FilterByUsername(t *testing.T) { tx := testutils.NewTestTransaction(t) rdb := testutils.GetTestRedis(t) testutils.CleanTestRedisKeys(t, rdb) accountStore := postgres.NewAccountStore(tx, rdb) roleStore := postgres.NewRoleStore(tx) accountRoleStore := postgres.NewAccountRoleStore(tx, rdb) mockAudit := new(MockAuditService) mockShop := new(MockShopStore) mockEnterprise := new(MockEnterpriseStore) svc := New(accountStore, roleStore, accountRoleStore, mockShop, mockEnterprise, mockAudit) ctx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{ UserID: 1, UserType: constants.UserTypeSuperAdmin, }) username := "test_filter_" + time.Now().Format("20060102150405") phone := "1" + time.Now().Format("0601021504") req := &dto.CreateAccountRequest{ Username: username, Phone: phone, Password: "TestPass123", UserType: constants.UserTypePlatform, } mockAudit.On("LogOperation", mock.Anything, mock.Anything).Return() _, err := svc.Create(ctx, req) require.NoError(t, err) listReq := &dto.AccountListRequest{ Page: 1, PageSize: 20, Username: username, } accounts, total, err := svc.List(ctx, listReq) require.NoError(t, err) assert.Greater(t, total, int64(0)) assert.Greater(t, len(accounts), 0) assert.Equal(t, username, accounts[0].Username) } // ============ ValidatePassword 方法测试 ============ func TestAccountService_ValidatePassword_Correct(t *testing.T) { tx := testutils.NewTestTransaction(t) rdb := testutils.GetTestRedis(t) testutils.CleanTestRedisKeys(t, rdb) accountStore := postgres.NewAccountStore(tx, rdb) roleStore := postgres.NewRoleStore(tx) accountRoleStore := postgres.NewAccountRoleStore(tx, rdb) mockAudit := new(MockAuditService) mockShop := new(MockShopStore) mockEnterprise := new(MockEnterpriseStore) svc := New(accountStore, roleStore, accountRoleStore, mockShop, mockEnterprise, mockAudit) ctx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{ UserID: 1, UserType: constants.UserTypeSuperAdmin, }) password := "TestPass123" username := "test_validate_pwd_" + time.Now().Format("20060102150405") phone := "1" + time.Now().Format("0601021504") req := &dto.CreateAccountRequest{ Username: username, Phone: phone, Password: password, UserType: constants.UserTypePlatform, } mockAudit.On("LogOperation", mock.Anything, mock.Anything).Return() created, err := svc.Create(ctx, req) require.NoError(t, err) isValid := svc.ValidatePassword(password, created.Password) assert.True(t, isValid) } func TestAccountService_ValidatePassword_Incorrect(t *testing.T) { tx := testutils.NewTestTransaction(t) rdb := testutils.GetTestRedis(t) testutils.CleanTestRedisKeys(t, rdb) accountStore := postgres.NewAccountStore(tx, rdb) roleStore := postgres.NewRoleStore(tx) accountRoleStore := postgres.NewAccountRoleStore(tx, rdb) mockAudit := new(MockAuditService) mockShop := new(MockShopStore) mockEnterprise := new(MockEnterpriseStore) svc := New(accountStore, roleStore, accountRoleStore, mockShop, mockEnterprise, mockAudit) ctx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{ UserID: 1, UserType: constants.UserTypeSuperAdmin, }) password := "TestPass123" username := "test_validate_pwd_wrong_" + time.Now().Format("20060102150405") phone := "1" + time.Now().Format("0601021504") req := &dto.CreateAccountRequest{ Username: username, Phone: phone, Password: password, UserType: constants.UserTypePlatform, } mockAudit.On("LogOperation", mock.Anything, mock.Anything).Return() created, err := svc.Create(ctx, req) require.NoError(t, err) isValid := svc.ValidatePassword("WrongPassword", created.Password) assert.False(t, isValid) } // ============ UpdatePassword 方法测试 ============ func TestAccountService_UpdatePassword_Success(t *testing.T) { tx := testutils.NewTestTransaction(t) rdb := testutils.GetTestRedis(t) testutils.CleanTestRedisKeys(t, rdb) accountStore := postgres.NewAccountStore(tx, rdb) roleStore := postgres.NewRoleStore(tx) accountRoleStore := postgres.NewAccountRoleStore(tx, rdb) mockAudit := new(MockAuditService) mockShop := new(MockShopStore) mockEnterprise := new(MockEnterpriseStore) svc := New(accountStore, roleStore, accountRoleStore, mockShop, mockEnterprise, mockAudit) ctx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{ UserID: 1, UserType: constants.UserTypeSuperAdmin, }) password := "TestPass123" username := "test_update_pwd_" + time.Now().Format("20060102150405") phone := "1" + time.Now().Format("0601021504") req := &dto.CreateAccountRequest{ Username: username, Phone: phone, Password: password, UserType: constants.UserTypePlatform, } mockAudit.On("LogOperation", mock.Anything, mock.Anything).Return() created, err := svc.Create(ctx, req) require.NoError(t, err) newPassword := "NewPass456" err = svc.UpdatePassword(ctx, created.ID, newPassword) require.NoError(t, err) updated, err := svc.Get(ctx, created.ID) require.NoError(t, err) isValid := svc.ValidatePassword(newPassword, updated.Password) assert.True(t, isValid) isOldValid := svc.ValidatePassword(password, updated.Password) assert.False(t, isOldValid) } // ============ UpdateStatus 方法测试 ============ func TestAccountService_UpdateStatus_Success(t *testing.T) { tx := testutils.NewTestTransaction(t) rdb := testutils.GetTestRedis(t) testutils.CleanTestRedisKeys(t, rdb) accountStore := postgres.NewAccountStore(tx, rdb) roleStore := postgres.NewRoleStore(tx) accountRoleStore := postgres.NewAccountRoleStore(tx, rdb) mockAudit := new(MockAuditService) mockShop := new(MockShopStore) mockEnterprise := new(MockEnterpriseStore) svc := New(accountStore, roleStore, accountRoleStore, mockShop, mockEnterprise, mockAudit) ctx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{ UserID: 1, UserType: constants.UserTypeSuperAdmin, }) username := "test_update_status_" + time.Now().Format("20060102150405") phone := "1" + time.Now().Format("0601021504") req := &dto.CreateAccountRequest{ Username: username, Phone: phone, Password: "TestPass123", UserType: constants.UserTypePlatform, } mockAudit.On("LogOperation", mock.Anything, mock.Anything).Return() created, err := svc.Create(ctx, req) require.NoError(t, err) assert.Equal(t, constants.StatusEnabled, created.Status) err = svc.UpdateStatus(ctx, created.ID, constants.StatusDisabled) require.NoError(t, err) updated, err := svc.Get(ctx, created.ID) require.NoError(t, err) assert.Equal(t, constants.StatusDisabled, updated.Status) } // ============ 辅助函数 ============ func TestAccountService_Get_Success(t *testing.T) { tx := testutils.NewTestTransaction(t) rdb := testutils.GetTestRedis(t) testutils.CleanTestRedisKeys(t, rdb) accountStore := postgres.NewAccountStore(tx, rdb) roleStore := postgres.NewRoleStore(tx) accountRoleStore := postgres.NewAccountRoleStore(tx, rdb) mockAudit := new(MockAuditService) mockShop := new(MockShopStore) mockEnterprise := new(MockEnterpriseStore) svc := New(accountStore, roleStore, accountRoleStore, mockShop, mockEnterprise, mockAudit) ctx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{ UserID: 1, UserType: constants.UserTypeSuperAdmin, }) username := "test_get_" + time.Now().Format("20060102150405") phone := "1" + time.Now().Format("0601021504") req := &dto.CreateAccountRequest{ Username: username, Phone: phone, Password: "TestPass123", UserType: constants.UserTypePlatform, } mockAudit.On("LogOperation", mock.Anything, mock.Anything).Return() created, err := svc.Create(ctx, req) require.NoError(t, err) retrieved, err := svc.Get(ctx, created.ID) require.NoError(t, err) assert.Equal(t, created.ID, retrieved.ID) assert.Equal(t, username, retrieved.Username) } func TestAccountService_Get_NotFound(t *testing.T) { tx := testutils.NewTestTransaction(t) rdb := testutils.GetTestRedis(t) testutils.CleanTestRedisKeys(t, rdb) accountStore := postgres.NewAccountStore(tx, rdb) roleStore := postgres.NewRoleStore(tx) accountRoleStore := postgres.NewAccountRoleStore(tx, rdb) mockAudit := new(MockAuditService) mockShop := new(MockShopStore) mockEnterprise := new(MockEnterpriseStore) svc := New(accountStore, roleStore, accountRoleStore, mockShop, mockEnterprise, mockAudit) ctx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{ UserID: 1, UserType: constants.UserTypeSuperAdmin, }) _, err := svc.Get(ctx, 99999) require.Error(t, err) appErr, ok := err.(*errors.AppError) require.True(t, ok) assert.Equal(t, errors.CodeAccountNotFound, appErr.Code) } func TestAccountService_UpdatePassword_AccountNotFound(t *testing.T) { tx := testutils.NewTestTransaction(t) rdb := testutils.GetTestRedis(t) testutils.CleanTestRedisKeys(t, rdb) accountStore := postgres.NewAccountStore(tx, rdb) roleStore := postgres.NewRoleStore(tx) accountRoleStore := postgres.NewAccountRoleStore(tx, rdb) mockAudit := new(MockAuditService) mockShop := new(MockShopStore) mockEnterprise := new(MockEnterpriseStore) svc := New(accountStore, roleStore, accountRoleStore, mockShop, mockEnterprise, mockAudit) ctx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{ UserID: 1, UserType: constants.UserTypeSuperAdmin, }) err := svc.UpdatePassword(ctx, 99999, "NewPass456") require.Error(t, err) appErr, ok := err.(*errors.AppError) require.True(t, ok) assert.Equal(t, errors.CodeAccountNotFound, appErr.Code) } func TestAccountService_UpdateStatus_AccountNotFound(t *testing.T) { tx := testutils.NewTestTransaction(t) rdb := testutils.GetTestRedis(t) testutils.CleanTestRedisKeys(t, rdb) accountStore := postgres.NewAccountStore(tx, rdb) roleStore := postgres.NewRoleStore(tx) accountRoleStore := postgres.NewAccountRoleStore(tx, rdb) mockAudit := new(MockAuditService) mockShop := new(MockShopStore) mockEnterprise := new(MockEnterpriseStore) svc := New(accountStore, roleStore, accountRoleStore, mockShop, mockEnterprise, mockAudit) ctx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{ UserID: 1, UserType: constants.UserTypeSuperAdmin, }) err := svc.UpdateStatus(ctx, 99999, constants.StatusDisabled) require.Error(t, err) appErr, ok := err.(*errors.AppError) require.True(t, ok) assert.Equal(t, errors.CodeAccountNotFound, appErr.Code) } func TestAccountService_UpdatePassword_Unauthorized(t *testing.T) { tx := testutils.NewTestTransaction(t) rdb := testutils.GetTestRedis(t) testutils.CleanTestRedisKeys(t, rdb) accountStore := postgres.NewAccountStore(tx, rdb) roleStore := postgres.NewRoleStore(tx) accountRoleStore := postgres.NewAccountRoleStore(tx, rdb) mockAudit := new(MockAuditService) mockShop := new(MockShopStore) mockEnterprise := new(MockEnterpriseStore) svc := New(accountStore, roleStore, accountRoleStore, mockShop, mockEnterprise, mockAudit) ctx := context.Background() err := svc.UpdatePassword(ctx, 1, "NewPass456") require.Error(t, err) appErr, ok := err.(*errors.AppError) require.True(t, ok) assert.Equal(t, errors.CodeUnauthorized, appErr.Code) } func TestAccountService_UpdateStatus_Unauthorized(t *testing.T) { tx := testutils.NewTestTransaction(t) rdb := testutils.GetTestRedis(t) testutils.CleanTestRedisKeys(t, rdb) accountStore := postgres.NewAccountStore(tx, rdb) roleStore := postgres.NewRoleStore(tx) accountRoleStore := postgres.NewAccountRoleStore(tx, rdb) mockAudit := new(MockAuditService) mockShop := new(MockShopStore) mockEnterprise := new(MockEnterpriseStore) svc := New(accountStore, roleStore, accountRoleStore, mockShop, mockEnterprise, mockAudit) ctx := context.Background() err := svc.UpdateStatus(ctx, 1, constants.StatusDisabled) require.Error(t, err) appErr, ok := err.(*errors.AppError) require.True(t, ok) assert.Equal(t, errors.CodeUnauthorized, appErr.Code) } func TestAccountService_Delete_Unauthorized(t *testing.T) { tx := testutils.NewTestTransaction(t) rdb := testutils.GetTestRedis(t) testutils.CleanTestRedisKeys(t, rdb) accountStore := postgres.NewAccountStore(tx, rdb) roleStore := postgres.NewRoleStore(tx) accountRoleStore := postgres.NewAccountRoleStore(tx, rdb) mockAudit := new(MockAuditService) mockShop := new(MockShopStore) mockEnterprise := new(MockEnterpriseStore) svc := New(accountStore, roleStore, accountRoleStore, mockShop, mockEnterprise, mockAudit) ctx := context.Background() err := svc.Delete(ctx, 1) require.Error(t, err) appErr, ok := err.(*errors.AppError) require.True(t, ok) assert.Equal(t, errors.CodeUnauthorized, appErr.Code) } func TestAccountService_AssignRoles_Unauthorized(t *testing.T) { tx := testutils.NewTestTransaction(t) rdb := testutils.GetTestRedis(t) testutils.CleanTestRedisKeys(t, rdb) accountStore := postgres.NewAccountStore(tx, rdb) roleStore := postgres.NewRoleStore(tx) accountRoleStore := postgres.NewAccountRoleStore(tx, rdb) mockAudit := new(MockAuditService) mockShop := new(MockShopStore) mockEnterprise := new(MockEnterpriseStore) svc := New(accountStore, roleStore, accountRoleStore, mockShop, mockEnterprise, mockAudit) ctx := context.Background() _, err := svc.AssignRoles(ctx, 1, []uint{1}) require.Error(t, err) appErr, ok := err.(*errors.AppError) require.True(t, ok) assert.Equal(t, errors.CodeUnauthorized, appErr.Code) } func TestAccountService_RemoveRole_Unauthorized(t *testing.T) { tx := testutils.NewTestTransaction(t) rdb := testutils.GetTestRedis(t) testutils.CleanTestRedisKeys(t, rdb) accountStore := postgres.NewAccountStore(tx, rdb) roleStore := postgres.NewRoleStore(tx) accountRoleStore := postgres.NewAccountRoleStore(tx, rdb) mockAudit := new(MockAuditService) mockShop := new(MockShopStore) mockEnterprise := new(MockEnterpriseStore) svc := New(accountStore, roleStore, accountRoleStore, mockShop, mockEnterprise, mockAudit) ctx := context.Background() err := svc.RemoveRole(ctx, 1, 1) require.Error(t, err) appErr, ok := err.(*errors.AppError) require.True(t, ok) assert.Equal(t, errors.CodeUnauthorized, appErr.Code) } func TestAccountService_Update_Unauthorized(t *testing.T) { tx := testutils.NewTestTransaction(t) rdb := testutils.GetTestRedis(t) testutils.CleanTestRedisKeys(t, rdb) accountStore := postgres.NewAccountStore(tx, rdb) roleStore := postgres.NewRoleStore(tx) accountRoleStore := postgres.NewAccountRoleStore(tx, rdb) mockAudit := new(MockAuditService) mockShop := new(MockShopStore) mockEnterprise := new(MockEnterpriseStore) svc := New(accountStore, roleStore, accountRoleStore, mockShop, mockEnterprise, mockAudit) ctx := context.Background() newUsername := "test" updateReq := &dto.UpdateAccountRequest{ Username: &newUsername, } _, err := svc.Update(ctx, 1, updateReq) require.Error(t, err) appErr, ok := err.(*errors.AppError) require.True(t, ok) assert.Equal(t, errors.CodeUnauthorized, appErr.Code) } func TestAccountService_AssignRoles_NotFound(t *testing.T) { tx := testutils.NewTestTransaction(t) rdb := testutils.GetTestRedis(t) testutils.CleanTestRedisKeys(t, rdb) accountStore := postgres.NewAccountStore(tx, rdb) roleStore := postgres.NewRoleStore(tx) accountRoleStore := postgres.NewAccountRoleStore(tx, rdb) mockAudit := new(MockAuditService) mockShop := new(MockShopStore) mockEnterprise := new(MockEnterpriseStore) svc := New(accountStore, roleStore, accountRoleStore, mockShop, mockEnterprise, mockAudit) ctx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{ UserID: 1, UserType: constants.UserTypeSuperAdmin, }) _, err := svc.AssignRoles(ctx, 99999, []uint{1}) require.Error(t, err) appErr, ok := err.(*errors.AppError) require.True(t, ok) assert.Equal(t, errors.CodeForbidden, appErr.Code) } func TestAccountService_GetRoles_NotFound(t *testing.T) { tx := testutils.NewTestTransaction(t) rdb := testutils.GetTestRedis(t) testutils.CleanTestRedisKeys(t, rdb) accountStore := postgres.NewAccountStore(tx, rdb) roleStore := postgres.NewRoleStore(tx) accountRoleStore := postgres.NewAccountRoleStore(tx, rdb) mockAudit := new(MockAuditService) mockShop := new(MockShopStore) mockEnterprise := new(MockEnterpriseStore) svc := New(accountStore, roleStore, accountRoleStore, mockShop, mockEnterprise, mockAudit) ctx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{ UserID: 1, UserType: constants.UserTypeSuperAdmin, }) _, err := svc.GetRoles(ctx, 99999) require.Error(t, err) appErr, ok := err.(*errors.AppError) require.True(t, ok) assert.Equal(t, errors.CodeAccountNotFound, appErr.Code) } func TestAccountService_List_FilterByUserType(t *testing.T) { tx := testutils.NewTestTransaction(t) rdb := testutils.GetTestRedis(t) testutils.CleanTestRedisKeys(t, rdb) accountStore := postgres.NewAccountStore(tx, rdb) roleStore := postgres.NewRoleStore(tx) accountRoleStore := postgres.NewAccountRoleStore(tx, rdb) mockAudit := new(MockAuditService) mockShop := new(MockShopStore) mockEnterprise := new(MockEnterpriseStore) svc := New(accountStore, roleStore, accountRoleStore, mockShop, mockEnterprise, mockAudit) ctx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{ UserID: 1, UserType: constants.UserTypeSuperAdmin, }) username := "test_filter_type_" + time.Now().Format("20060102150405") phone := "1" + time.Now().Format("0601021504") req := &dto.CreateAccountRequest{ Username: username, Phone: phone, Password: "TestPass123", UserType: constants.UserTypePlatform, } mockAudit.On("LogOperation", mock.Anything, mock.Anything).Return() _, err := svc.Create(ctx, req) require.NoError(t, err) userType := constants.UserTypePlatform listReq := &dto.AccountListRequest{ Page: 1, PageSize: 20, UserType: &userType, } accounts, total, err := svc.List(ctx, listReq) require.NoError(t, err) assert.Greater(t, total, int64(0)) assert.Greater(t, len(accounts), 0) } func TestAccountService_List_FilterByStatus(t *testing.T) { tx := testutils.NewTestTransaction(t) rdb := testutils.GetTestRedis(t) testutils.CleanTestRedisKeys(t, rdb) accountStore := postgres.NewAccountStore(tx, rdb) roleStore := postgres.NewRoleStore(tx) accountRoleStore := postgres.NewAccountRoleStore(tx, rdb) mockAudit := new(MockAuditService) mockShop := new(MockShopStore) mockEnterprise := new(MockEnterpriseStore) svc := New(accountStore, roleStore, accountRoleStore, mockShop, mockEnterprise, mockAudit) ctx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{ UserID: 1, UserType: constants.UserTypeSuperAdmin, }) username := "test_filter_status_" + time.Now().Format("20060102150405") phone := "1" + time.Now().Format("0601021504") req := &dto.CreateAccountRequest{ Username: username, Phone: phone, Password: "TestPass123", UserType: constants.UserTypePlatform, } mockAudit.On("LogOperation", mock.Anything, mock.Anything).Return() _, err := svc.Create(ctx, req) require.NoError(t, err) status := constants.StatusEnabled listReq := &dto.AccountListRequest{ Page: 1, PageSize: 20, Status: &status, } accounts, total, err := svc.List(ctx, listReq) require.NoError(t, err) assert.Greater(t, total, int64(0)) assert.Greater(t, len(accounts), 0) } func TestAccountService_List_FilterByPhone(t *testing.T) { tx := testutils.NewTestTransaction(t) rdb := testutils.GetTestRedis(t) testutils.CleanTestRedisKeys(t, rdb) accountStore := postgres.NewAccountStore(tx, rdb) roleStore := postgres.NewRoleStore(tx) accountRoleStore := postgres.NewAccountRoleStore(tx, rdb) mockAudit := new(MockAuditService) mockShop := new(MockShopStore) mockEnterprise := new(MockEnterpriseStore) svc := New(accountStore, roleStore, accountRoleStore, mockShop, mockEnterprise, mockAudit) ctx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{ UserID: 1, UserType: constants.UserTypeSuperAdmin, }) username := "test_filter_phone_" + time.Now().Format("20060102150405") phone := "1" + time.Now().Format("0601021504") req := &dto.CreateAccountRequest{ Username: username, Phone: phone, Password: "TestPass123", UserType: constants.UserTypePlatform, } mockAudit.On("LogOperation", mock.Anything, mock.Anything).Return() _, err := svc.Create(ctx, req) require.NoError(t, err) listReq := &dto.AccountListRequest{ Page: 1, PageSize: 20, Phone: phone, } accounts, total, err := svc.List(ctx, listReq) require.NoError(t, err) assert.Greater(t, total, int64(0)) assert.Greater(t, len(accounts), 0) } func TestAccountService_Update_UpdatePassword(t *testing.T) { tx := testutils.NewTestTransaction(t) rdb := testutils.GetTestRedis(t) testutils.CleanTestRedisKeys(t, rdb) accountStore := postgres.NewAccountStore(tx, rdb) roleStore := postgres.NewRoleStore(tx) accountRoleStore := postgres.NewAccountRoleStore(tx, rdb) mockAudit := new(MockAuditService) mockShop := new(MockShopStore) mockEnterprise := new(MockEnterpriseStore) svc := New(accountStore, roleStore, accountRoleStore, mockShop, mockEnterprise, mockAudit) ctx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{ UserID: 1, UserType: constants.UserTypeSuperAdmin, }) username := "test_update_pwd_" + time.Now().Format("20060102150405") phone := "1" + time.Now().Format("0601021504") req := &dto.CreateAccountRequest{ Username: username, Phone: phone, Password: "TestPass123", UserType: constants.UserTypePlatform, } mockAudit.On("LogOperation", mock.Anything, mock.Anything).Return() created, err := svc.Create(ctx, req) require.NoError(t, err) newPassword := "NewPass456" updateReq := &dto.UpdateAccountRequest{ Password: &newPassword, } updated, err := svc.Update(ctx, created.ID, updateReq) require.NoError(t, err) isValid := svc.ValidatePassword(newPassword, updated.Password) assert.True(t, isValid) } func TestAccountService_Update_UpdateStatus(t *testing.T) { tx := testutils.NewTestTransaction(t) rdb := testutils.GetTestRedis(t) testutils.CleanTestRedisKeys(t, rdb) accountStore := postgres.NewAccountStore(tx, rdb) roleStore := postgres.NewRoleStore(tx) accountRoleStore := postgres.NewAccountRoleStore(tx, rdb) mockAudit := new(MockAuditService) mockShop := new(MockShopStore) mockEnterprise := new(MockEnterpriseStore) svc := New(accountStore, roleStore, accountRoleStore, mockShop, mockEnterprise, mockAudit) ctx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{ UserID: 1, UserType: constants.UserTypeSuperAdmin, }) username := "test_update_status_" + time.Now().Format("20060102150405") phone := "1" + time.Now().Format("0601021504") req := &dto.CreateAccountRequest{ Username: username, Phone: phone, Password: "TestPass123", UserType: constants.UserTypePlatform, } mockAudit.On("LogOperation", mock.Anything, mock.Anything).Return() created, err := svc.Create(ctx, req) require.NoError(t, err) status := constants.StatusDisabled updateReq := &dto.UpdateAccountRequest{ Status: &status, } updated, err := svc.Update(ctx, created.ID, updateReq) require.NoError(t, err) assert.Equal(t, constants.StatusDisabled, updated.Status) } func TestAccountService_Update_UpdatePhone(t *testing.T) { tx := testutils.NewTestTransaction(t) rdb := testutils.GetTestRedis(t) testutils.CleanTestRedisKeys(t, rdb) accountStore := postgres.NewAccountStore(tx, rdb) roleStore := postgres.NewRoleStore(tx) accountRoleStore := postgres.NewAccountRoleStore(tx, rdb) mockAudit := new(MockAuditService) mockShop := new(MockShopStore) mockEnterprise := new(MockEnterpriseStore) svc := New(accountStore, roleStore, accountRoleStore, mockShop, mockEnterprise, mockAudit) ctx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{ UserID: 1, UserType: constants.UserTypeSuperAdmin, }) username := "test_update_phone_" + time.Now().Format("20060102150405") phone := "1" + time.Now().Format("0601021504") req := &dto.CreateAccountRequest{ Username: username, Phone: phone, Password: "TestPass123", UserType: constants.UserTypePlatform, } mockAudit.On("LogOperation", mock.Anything, mock.Anything).Return() created, err := svc.Create(ctx, req) require.NoError(t, err) newPhone := "1" + time.Now().Format("0601021505") updateReq := &dto.UpdateAccountRequest{ Phone: &newPhone, } updated, err := svc.Update(ctx, created.ID, updateReq) require.NoError(t, err) assert.Equal(t, newPhone, updated.Phone) } func TestAccountService_AssignRoles_AgentUnauthorized(t *testing.T) { tx := testutils.NewTestTransaction(t) rdb := testutils.GetTestRedis(t) testutils.CleanTestRedisKeys(t, rdb) accountStore := postgres.NewAccountStore(tx, rdb) roleStore := postgres.NewRoleStore(tx) accountRoleStore := postgres.NewAccountRoleStore(tx, rdb) mockAudit := new(MockAuditService) mockShop := new(MockShopStore) mockEnterprise := new(MockEnterpriseStore) svc := New(accountStore, roleStore, accountRoleStore, mockShop, mockEnterprise, mockAudit) superAdminCtx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{ UserID: 1, UserType: constants.UserTypeSuperAdmin, }) username := "test_agent_assign_" + time.Now().Format("20060102150405") phone := "1" + time.Now().Format("0601021504") req := &dto.CreateAccountRequest{ Username: username, Phone: phone, Password: "TestPass123", UserType: constants.UserTypePlatform, } mockAudit.On("LogOperation", mock.Anything, mock.Anything).Return() created, err := svc.Create(superAdminCtx, req) require.NoError(t, err) agentCtx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{ UserID: 2, UserType: constants.UserTypeAgent, ShopID: 10, }) mockShop.On("GetSubordinateShopIDs", mock.Anything, uint(10)).Return([]uint{10}, nil) _, err = svc.AssignRoles(agentCtx, created.ID, []uint{1}) require.Error(t, err) appErr, ok := err.(*errors.AppError) require.True(t, ok) assert.Equal(t, errors.CodeForbidden, appErr.Code) } func TestAccountService_Create_EnterpriseAccountSuccess(t *testing.T) { tx := testutils.NewTestTransaction(t) rdb := testutils.GetTestRedis(t) testutils.CleanTestRedisKeys(t, rdb) accountStore := postgres.NewAccountStore(tx, rdb) roleStore := postgres.NewRoleStore(tx) accountRoleStore := postgres.NewAccountRoleStore(tx, rdb) mockAudit := new(MockAuditService) mockShop := new(MockShopStore) mockEnterprise := new(MockEnterpriseStore) svc := New(accountStore, roleStore, accountRoleStore, mockShop, mockEnterprise, mockAudit) ctx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{ UserID: 1, UserType: constants.UserTypePlatform, }) enterpriseID := uint(1) username := "test_enterprise_" + time.Now().Format("20060102150405") phone := "1" + time.Now().Format("0601021504") req := &dto.CreateAccountRequest{ Username: username, Phone: phone, Password: "TestPass123", UserType: constants.UserTypeEnterprise, EnterpriseID: &enterpriseID, } mockEnterprise.On("GetByID", mock.Anything, enterpriseID).Return(&model.Enterprise{}, nil) mockAudit.On("LogOperation", mock.Anything, mock.Anything).Return() resp, err := svc.Create(ctx, req) require.NoError(t, err) assert.NotZero(t, resp.ID) assert.Equal(t, constants.UserTypeEnterprise, resp.UserType) assert.Equal(t, &enterpriseID, resp.EnterpriseID) mockAudit.AssertCalled(t, "LogOperation", mock.Anything, mock.Anything) } func TestAccountService_Create_AgentMissingShopID(t *testing.T) { tx := testutils.NewTestTransaction(t) rdb := testutils.GetTestRedis(t) testutils.CleanTestRedisKeys(t, rdb) accountStore := postgres.NewAccountStore(tx, rdb) roleStore := postgres.NewRoleStore(tx) accountRoleStore := postgres.NewAccountRoleStore(tx, rdb) mockAudit := new(MockAuditService) mockShop := new(MockShopStore) mockEnterprise := new(MockEnterpriseStore) svc := New(accountStore, roleStore, accountRoleStore, mockShop, mockEnterprise, mockAudit) ctx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{ UserID: 1, UserType: constants.UserTypePlatform, }) username := "test_agent_no_shop_" + time.Now().Format("20060102150405") phone := "1" + time.Now().Format("0601021504") req := &dto.CreateAccountRequest{ Username: username, Phone: phone, Password: "TestPass123", UserType: constants.UserTypeAgent, } _, err := svc.Create(ctx, req) require.Error(t, err) appErr, ok := err.(*errors.AppError) require.True(t, ok) assert.Equal(t, errors.CodeInvalidParam, appErr.Code) } func TestAccountService_Create_EnterpriseMissingEnterpriseID(t *testing.T) { tx := testutils.NewTestTransaction(t) rdb := testutils.GetTestRedis(t) testutils.CleanTestRedisKeys(t, rdb) accountStore := postgres.NewAccountStore(tx, rdb) roleStore := postgres.NewRoleStore(tx) accountRoleStore := postgres.NewAccountRoleStore(tx, rdb) mockAudit := new(MockAuditService) mockShop := new(MockShopStore) mockEnterprise := new(MockEnterpriseStore) svc := New(accountStore, roleStore, accountRoleStore, mockShop, mockEnterprise, mockAudit) ctx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{ UserID: 1, UserType: constants.UserTypePlatform, }) username := "test_enterprise_no_id_" + time.Now().Format("20060102150405") phone := "1" + time.Now().Format("0601021504") req := &dto.CreateAccountRequest{ Username: username, Phone: phone, Password: "TestPass123", UserType: constants.UserTypeEnterprise, } _, err := svc.Create(ctx, req) require.Error(t, err) appErr, ok := err.(*errors.AppError) require.True(t, ok) assert.Equal(t, errors.CodeInvalidParam, appErr.Code) } func TestAccountService_RemoveRole_AgentUnauthorized(t *testing.T) { tx := testutils.NewTestTransaction(t) rdb := testutils.GetTestRedis(t) testutils.CleanTestRedisKeys(t, rdb) accountStore := postgres.NewAccountStore(tx, rdb) roleStore := postgres.NewRoleStore(tx) accountRoleStore := postgres.NewAccountRoleStore(tx, rdb) mockAudit := new(MockAuditService) mockShop := new(MockShopStore) mockEnterprise := new(MockEnterpriseStore) svc := New(accountStore, roleStore, accountRoleStore, mockShop, mockEnterprise, mockAudit) superAdminCtx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{ UserID: 1, UserType: constants.UserTypeSuperAdmin, }) username := "test_remove_role_agent_" + time.Now().Format("20060102150405") phone := "1" + time.Now().Format("0601021504") req := &dto.CreateAccountRequest{ Username: username, Phone: phone, Password: "TestPass123", UserType: constants.UserTypePlatform, } mockAudit.On("LogOperation", mock.Anything, mock.Anything).Return() created, err := svc.Create(superAdminCtx, req) require.NoError(t, err) agentCtx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{ UserID: 2, UserType: constants.UserTypeAgent, ShopID: 10, }) mockShop.On("GetSubordinateShopIDs", mock.Anything, uint(10)).Return([]uint{10}, nil) err = svc.RemoveRole(agentCtx, created.ID, 1) require.Error(t, err) appErr, ok := err.(*errors.AppError) require.True(t, ok) assert.Equal(t, errors.CodeForbidden, appErr.Code) } func TestAccountService_AssignRoles_MultipleRoles(t *testing.T) { tx := testutils.NewTestTransaction(t) rdb := testutils.GetTestRedis(t) testutils.CleanTestRedisKeys(t, rdb) accountStore := postgres.NewAccountStore(tx, rdb) roleStore := postgres.NewRoleStore(tx) accountRoleStore := postgres.NewAccountRoleStore(tx, rdb) mockAudit := new(MockAuditService) mockShop := new(MockShopStore) mockEnterprise := new(MockEnterpriseStore) svc := New(accountStore, roleStore, accountRoleStore, mockShop, mockEnterprise, mockAudit) ctx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{ UserID: 1, UserType: constants.UserTypeSuperAdmin, }) username := "test_multi_roles_" + time.Now().Format("20060102150405") phone := "1" + time.Now().Format("0601021504") req := &dto.CreateAccountRequest{ Username: username, Phone: phone, Password: "TestPass123", UserType: constants.UserTypePlatform, } mockAudit.On("LogOperation", mock.Anything, mock.Anything).Return() created, err := svc.Create(ctx, req) require.NoError(t, err) role1 := &model.Role{ RoleName: "test_role1_" + time.Now().Format("20060102150405"), RoleType: constants.RoleTypePlatform, Status: constants.StatusEnabled, } errRole := roleStore.Create(ctx, role1) require.NoError(t, errRole) role2 := &model.Role{ RoleName: "test_role2_" + time.Now().Format("20060102150405"), RoleType: constants.RoleTypePlatform, Status: constants.StatusEnabled, } errRole = roleStore.Create(ctx, role2) require.NoError(t, errRole) ars, err := svc.AssignRoles(ctx, created.ID, []uint{role1.ID, role2.ID}) require.NoError(t, err) assert.Len(t, ars, 2) roles, err := svc.GetRoles(ctx, created.ID) require.NoError(t, err) assert.Len(t, roles, 2) } func TestAccountService_Update_AllFields(t *testing.T) { tx := testutils.NewTestTransaction(t) rdb := testutils.GetTestRedis(t) testutils.CleanTestRedisKeys(t, rdb) accountStore := postgres.NewAccountStore(tx, rdb) roleStore := postgres.NewRoleStore(tx) accountRoleStore := postgres.NewAccountRoleStore(tx, rdb) mockAudit := new(MockAuditService) mockShop := new(MockShopStore) mockEnterprise := new(MockEnterpriseStore) svc := New(accountStore, roleStore, accountRoleStore, mockShop, mockEnterprise, mockAudit) ctx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{ UserID: 1, UserType: constants.UserTypeSuperAdmin, }) username := "test_update_all_" + time.Now().Format("20060102150405") phone := "1" + time.Now().Format("0601021504") req := &dto.CreateAccountRequest{ Username: username, Phone: phone, Password: "TestPass123", UserType: constants.UserTypePlatform, } mockAudit.On("LogOperation", mock.Anything, mock.Anything).Return() created, err := svc.Create(ctx, req) require.NoError(t, err) newUsername := "updated_" + time.Now().Format("20060102150405") newPhone := "1" + time.Now().Format("0601021505") newPassword := "NewPass456" newStatus := constants.StatusDisabled updateReq := &dto.UpdateAccountRequest{ Username: &newUsername, Phone: &newPhone, Password: &newPassword, Status: &newStatus, } updated, err := svc.Update(ctx, created.ID, updateReq) require.NoError(t, err) assert.Equal(t, newUsername, updated.Username) assert.Equal(t, newPhone, updated.Phone) assert.Equal(t, newStatus, updated.Status) isValid := svc.ValidatePassword(newPassword, updated.Password) assert.True(t, isValid) } func TestAccountService_ListPlatformAccounts_Success(t *testing.T) { tx := testutils.NewTestTransaction(t) rdb := testutils.GetTestRedis(t) testutils.CleanTestRedisKeys(t, rdb) accountStore := postgres.NewAccountStore(tx, rdb) roleStore := postgres.NewRoleStore(tx) accountRoleStore := postgres.NewAccountRoleStore(tx, rdb) mockAudit := new(MockAuditService) mockShop := new(MockShopStore) mockEnterprise := new(MockEnterpriseStore) svc := New(accountStore, roleStore, accountRoleStore, mockShop, mockEnterprise, mockAudit) ctx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{ UserID: 1, UserType: constants.UserTypeSuperAdmin, }) username := "test_platform_list_" + time.Now().Format("20060102150405") phone := "1" + time.Now().Format("0601021504") req := &dto.CreateAccountRequest{ Username: username, Phone: phone, Password: "TestPass123", UserType: constants.UserTypePlatform, } mockAudit.On("LogOperation", mock.Anything, mock.Anything).Return() _, err := svc.Create(ctx, req) require.NoError(t, err) listReq := &dto.PlatformAccountListRequest{ Page: 1, PageSize: 20, } accounts, total, err := svc.ListPlatformAccounts(ctx, listReq) require.NoError(t, err) assert.Greater(t, total, int64(0)) assert.Greater(t, len(accounts), 0) } func TestAccountService_CreateSystemAccount_Success(t *testing.T) { tx := testutils.NewTestTransaction(t) rdb := testutils.GetTestRedis(t) testutils.CleanTestRedisKeys(t, rdb) accountStore := postgres.NewAccountStore(tx, rdb) roleStore := postgres.NewRoleStore(tx) accountRoleStore := postgres.NewAccountRoleStore(tx, rdb) mockAudit := new(MockAuditService) mockShop := new(MockShopStore) mockEnterprise := new(MockEnterpriseStore) svc := New(accountStore, roleStore, accountRoleStore, mockShop, mockEnterprise, mockAudit) ctx := context.Background() username := "test_system_" + time.Now().Format("20060102150405") phone := "1" + time.Now().Format("0601021504") account := &model.Account{ Username: username, Phone: phone, Password: "TestPass123", UserType: constants.UserTypePlatform, Status: constants.StatusEnabled, } err := svc.CreateSystemAccount(ctx, account) require.NoError(t, err) assert.NotZero(t, account.ID) } func TestAccountService_CreateSystemAccount_MissingUsername(t *testing.T) { tx := testutils.NewTestTransaction(t) rdb := testutils.GetTestRedis(t) testutils.CleanTestRedisKeys(t, rdb) accountStore := postgres.NewAccountStore(tx, rdb) roleStore := postgres.NewRoleStore(tx) accountRoleStore := postgres.NewAccountRoleStore(tx, rdb) mockAudit := new(MockAuditService) mockShop := new(MockShopStore) mockEnterprise := new(MockEnterpriseStore) svc := New(accountStore, roleStore, accountRoleStore, mockShop, mockEnterprise, mockAudit) ctx := context.Background() account := &model.Account{ Username: "", Phone: "13800000000", Password: "TestPass123", UserType: constants.UserTypePlatform, Status: constants.StatusEnabled, } err := svc.CreateSystemAccount(ctx, account) require.Error(t, err) appErr, ok := err.(*errors.AppError) require.True(t, ok) assert.Equal(t, errors.CodeInvalidParam, appErr.Code) } func TestAccountService_CreateSystemAccount_MissingPhone(t *testing.T) { tx := testutils.NewTestTransaction(t) rdb := testutils.GetTestRedis(t) testutils.CleanTestRedisKeys(t, rdb) accountStore := postgres.NewAccountStore(tx, rdb) roleStore := postgres.NewRoleStore(tx) accountRoleStore := postgres.NewAccountRoleStore(tx, rdb) mockAudit := new(MockAuditService) mockShop := new(MockShopStore) mockEnterprise := new(MockEnterpriseStore) svc := New(accountStore, roleStore, accountRoleStore, mockShop, mockEnterprise, mockAudit) ctx := context.Background() account := &model.Account{ Username: "test_system", Phone: "", Password: "TestPass123", UserType: constants.UserTypePlatform, Status: constants.StatusEnabled, } err := svc.CreateSystemAccount(ctx, account) require.Error(t, err) appErr, ok := err.(*errors.AppError) require.True(t, ok) assert.Equal(t, errors.CodeInvalidParam, appErr.Code) } func TestAccountService_CreateSystemAccount_MissingPassword(t *testing.T) { tx := testutils.NewTestTransaction(t) rdb := testutils.GetTestRedis(t) testutils.CleanTestRedisKeys(t, rdb) accountStore := postgres.NewAccountStore(tx, rdb) roleStore := postgres.NewRoleStore(tx) accountRoleStore := postgres.NewAccountRoleStore(tx, rdb) mockAudit := new(MockAuditService) mockShop := new(MockShopStore) mockEnterprise := new(MockEnterpriseStore) svc := New(accountStore, roleStore, accountRoleStore, mockShop, mockEnterprise, mockAudit) ctx := context.Background() account := &model.Account{ Username: "test_system", Phone: "13800000000", Password: "", UserType: constants.UserTypePlatform, Status: constants.StatusEnabled, } err := svc.CreateSystemAccount(ctx, account) require.Error(t, err) appErr, ok := err.(*errors.AppError) require.True(t, ok) assert.Equal(t, errors.CodeInvalidParam, appErr.Code) } func TestAccountService_CreateSystemAccount_UsernameDuplicate(t *testing.T) { tx := testutils.NewTestTransaction(t) rdb := testutils.GetTestRedis(t) testutils.CleanTestRedisKeys(t, rdb) accountStore := postgres.NewAccountStore(tx, rdb) roleStore := postgres.NewRoleStore(tx) accountRoleStore := postgres.NewAccountRoleStore(tx, rdb) mockAudit := new(MockAuditService) mockShop := new(MockShopStore) mockEnterprise := new(MockEnterpriseStore) svc := New(accountStore, roleStore, accountRoleStore, mockShop, mockEnterprise, mockAudit) ctx := context.Background() username := "test_system_dup_" + time.Now().Format("20060102150405") phone1 := "1" + time.Now().Format("0601021504") phone2 := "1" + time.Now().Format("0601021505") account1 := &model.Account{ Username: username, Phone: phone1, Password: "TestPass123", UserType: constants.UserTypePlatform, Status: constants.StatusEnabled, } err := svc.CreateSystemAccount(ctx, account1) require.NoError(t, err) account2 := &model.Account{ Username: username, Phone: phone2, Password: "TestPass123", UserType: constants.UserTypePlatform, Status: constants.StatusEnabled, } err = svc.CreateSystemAccount(ctx, account2) require.Error(t, err) appErr, ok := err.(*errors.AppError) require.True(t, ok) assert.Equal(t, errors.CodeUsernameExists, appErr.Code) } func TestAccountService_CreateSystemAccount_PhoneDuplicate(t *testing.T) { tx := testutils.NewTestTransaction(t) rdb := testutils.GetTestRedis(t) testutils.CleanTestRedisKeys(t, rdb) accountStore := postgres.NewAccountStore(tx, rdb) roleStore := postgres.NewRoleStore(tx) accountRoleStore := postgres.NewAccountRoleStore(tx, rdb) mockAudit := new(MockAuditService) mockShop := new(MockShopStore) mockEnterprise := new(MockEnterpriseStore) svc := New(accountStore, roleStore, accountRoleStore, mockShop, mockEnterprise, mockAudit) ctx := context.Background() username1 := "test_system_phone1_" + time.Now().Format("20060102150405") username2 := "test_system_phone2_" + time.Now().Format("20060102150405") phone := "1" + time.Now().Format("0601021504") account1 := &model.Account{ Username: username1, Phone: phone, Password: "TestPass123", UserType: constants.UserTypePlatform, Status: constants.StatusEnabled, } err := svc.CreateSystemAccount(ctx, account1) require.NoError(t, err) account2 := &model.Account{ Username: username2, Phone: phone, Password: "TestPass123", UserType: constants.UserTypePlatform, Status: constants.StatusEnabled, } err = svc.CreateSystemAccount(ctx, account2) require.Error(t, err) appErr, ok := err.(*errors.AppError) require.True(t, ok) assert.Equal(t, errors.CodePhoneExists, appErr.Code) } func TestAccountService_ListPlatformAccounts_FilterByUsername(t *testing.T) { tx := testutils.NewTestTransaction(t) rdb := testutils.GetTestRedis(t) testutils.CleanTestRedisKeys(t, rdb) accountStore := postgres.NewAccountStore(tx, rdb) roleStore := postgres.NewRoleStore(tx) accountRoleStore := postgres.NewAccountRoleStore(tx, rdb) mockAudit := new(MockAuditService) mockShop := new(MockShopStore) mockEnterprise := new(MockEnterpriseStore) svc := New(accountStore, roleStore, accountRoleStore, mockShop, mockEnterprise, mockAudit) ctx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{ UserID: 1, UserType: constants.UserTypeSuperAdmin, }) username := "test_platform_filter_" + time.Now().Format("20060102150405") phone := "1" + time.Now().Format("0601021504") req := &dto.CreateAccountRequest{ Username: username, Phone: phone, Password: "TestPass123", UserType: constants.UserTypePlatform, } mockAudit.On("LogOperation", mock.Anything, mock.Anything).Return() _, err := svc.Create(ctx, req) require.NoError(t, err) listReq := &dto.PlatformAccountListRequest{ Page: 1, PageSize: 20, Username: username, } accounts, total, err := svc.ListPlatformAccounts(ctx, listReq) require.NoError(t, err) assert.Greater(t, total, int64(0)) assert.Greater(t, len(accounts), 0) } func TestAccountService_ListPlatformAccounts_FilterByPhone(t *testing.T) { tx := testutils.NewTestTransaction(t) rdb := testutils.GetTestRedis(t) testutils.CleanTestRedisKeys(t, rdb) accountStore := postgres.NewAccountStore(tx, rdb) roleStore := postgres.NewRoleStore(tx) accountRoleStore := postgres.NewAccountRoleStore(tx, rdb) mockAudit := new(MockAuditService) mockShop := new(MockShopStore) mockEnterprise := new(MockEnterpriseStore) svc := New(accountStore, roleStore, accountRoleStore, mockShop, mockEnterprise, mockAudit) ctx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{ UserID: 1, UserType: constants.UserTypeSuperAdmin, }) username := "test_platform_phone_" + time.Now().Format("20060102150405") phone := "1" + time.Now().Format("0601021504") req := &dto.CreateAccountRequest{ Username: username, Phone: phone, Password: "TestPass123", UserType: constants.UserTypePlatform, } mockAudit.On("LogOperation", mock.Anything, mock.Anything).Return() _, err := svc.Create(ctx, req) require.NoError(t, err) listReq := &dto.PlatformAccountListRequest{ Page: 1, PageSize: 20, Phone: phone, } accounts, total, err := svc.ListPlatformAccounts(ctx, listReq) require.NoError(t, err) assert.Greater(t, total, int64(0)) assert.Greater(t, len(accounts), 0) } func TestAccountService_ListPlatformAccounts_FilterByStatus(t *testing.T) { tx := testutils.NewTestTransaction(t) rdb := testutils.GetTestRedis(t) testutils.CleanTestRedisKeys(t, rdb) accountStore := postgres.NewAccountStore(tx, rdb) roleStore := postgres.NewRoleStore(tx) accountRoleStore := postgres.NewAccountRoleStore(tx, rdb) mockAudit := new(MockAuditService) mockShop := new(MockShopStore) mockEnterprise := new(MockEnterpriseStore) svc := New(accountStore, roleStore, accountRoleStore, mockShop, mockEnterprise, mockAudit) ctx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{ UserID: 1, UserType: constants.UserTypeSuperAdmin, }) username := "test_platform_status_" + time.Now().Format("20060102150405") phone := "1" + time.Now().Format("0601021504") req := &dto.CreateAccountRequest{ Username: username, Phone: phone, Password: "TestPass123", UserType: constants.UserTypePlatform, } mockAudit.On("LogOperation", mock.Anything, mock.Anything).Return() _, err := svc.Create(ctx, req) require.NoError(t, err) status := constants.StatusEnabled listReq := &dto.PlatformAccountListRequest{ Page: 1, PageSize: 20, Status: &status, } accounts, total, err := svc.ListPlatformAccounts(ctx, listReq) require.NoError(t, err) assert.Greater(t, total, int64(0)) assert.Greater(t, len(accounts), 0) } func TestAccountService_Create_PlatformUserCreateEnterpriseAccount(t *testing.T) { tx := testutils.NewTestTransaction(t) rdb := testutils.GetTestRedis(t) testutils.CleanTestRedisKeys(t, rdb) accountStore := postgres.NewAccountStore(tx, rdb) roleStore := postgres.NewRoleStore(tx) accountRoleStore := postgres.NewAccountRoleStore(tx, rdb) mockAudit := new(MockAuditService) mockShop := new(MockShopStore) mockEnterprise := new(MockEnterpriseStore) svc := New(accountStore, roleStore, accountRoleStore, mockShop, mockEnterprise, mockAudit) ctx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{ UserID: 1, UserType: constants.UserTypePlatform, }) enterpriseID := uint(1) username := "test_enterprise_create_" + time.Now().Format("20060102150405") phone := "1" + time.Now().Format("0601021504") req := &dto.CreateAccountRequest{ Username: username, Phone: phone, Password: "TestPass123", UserType: constants.UserTypeEnterprise, EnterpriseID: &enterpriseID, } mockEnterprise.On("GetByID", mock.Anything, enterpriseID).Return(&model.Enterprise{}, nil) mockAudit.On("LogOperation", mock.Anything, mock.Anything).Return() resp, err := svc.Create(ctx, req) require.NoError(t, err) assert.NotZero(t, resp.ID) assert.Equal(t, constants.UserTypeEnterprise, resp.UserType) mockAudit.AssertCalled(t, "LogOperation", mock.Anything, mock.Anything) } func TestAccountService_List_DefaultPagination(t *testing.T) { tx := testutils.NewTestTransaction(t) rdb := testutils.GetTestRedis(t) testutils.CleanTestRedisKeys(t, rdb) accountStore := postgres.NewAccountStore(tx, rdb) roleStore := postgres.NewRoleStore(tx) accountRoleStore := postgres.NewAccountRoleStore(tx, rdb) mockAudit := new(MockAuditService) mockShop := new(MockShopStore) mockEnterprise := new(MockEnterpriseStore) svc := New(accountStore, roleStore, accountRoleStore, mockShop, mockEnterprise, mockAudit) ctx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{ UserID: 1, UserType: constants.UserTypeSuperAdmin, }) listReq := &dto.AccountListRequest{ Page: 0, PageSize: 0, } accounts, total, err := svc.List(ctx, listReq) require.NoError(t, err) assert.Greater(t, total, int64(0)) assert.Greater(t, len(accounts), 0) } func TestAccountService_ListPlatformAccounts_DefaultPagination(t *testing.T) { tx := testutils.NewTestTransaction(t) rdb := testutils.GetTestRedis(t) testutils.CleanTestRedisKeys(t, rdb) accountStore := postgres.NewAccountStore(tx, rdb) roleStore := postgres.NewRoleStore(tx) accountRoleStore := postgres.NewAccountRoleStore(tx, rdb) mockAudit := new(MockAuditService) mockShop := new(MockShopStore) mockEnterprise := new(MockEnterpriseStore) svc := New(accountStore, roleStore, accountRoleStore, mockShop, mockEnterprise, mockAudit) ctx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{ UserID: 1, UserType: constants.UserTypeSuperAdmin, }) listReq := &dto.PlatformAccountListRequest{ Page: 0, PageSize: 0, } accounts, total, err := svc.ListPlatformAccounts(ctx, listReq) require.NoError(t, err) assert.Greater(t, total, int64(0)) assert.Greater(t, len(accounts), 0) } func TestAccountService_AssignRoles_RoleNotFound(t *testing.T) { tx := testutils.NewTestTransaction(t) rdb := testutils.GetTestRedis(t) testutils.CleanTestRedisKeys(t, rdb) accountStore := postgres.NewAccountStore(tx, rdb) roleStore := postgres.NewRoleStore(tx) accountRoleStore := postgres.NewAccountRoleStore(tx, rdb) mockAudit := new(MockAuditService) mockShop := new(MockShopStore) mockEnterprise := new(MockEnterpriseStore) svc := New(accountStore, roleStore, accountRoleStore, mockShop, mockEnterprise, mockAudit) ctx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{ UserID: 1, UserType: constants.UserTypeSuperAdmin, }) username := "test_role_not_found_" + time.Now().Format("20060102150405") phone := "1" + time.Now().Format("0601021504") req := &dto.CreateAccountRequest{ Username: username, Phone: phone, Password: "TestPass123", UserType: constants.UserTypePlatform, } mockAudit.On("LogOperation", mock.Anything, mock.Anything).Return() created, err := svc.Create(ctx, req) require.NoError(t, err) _, err = svc.AssignRoles(ctx, created.ID, []uint{99999}) require.Error(t, err) appErr, ok := err.(*errors.AppError) require.True(t, ok) assert.Equal(t, errors.CodeRoleNotFound, appErr.Code) } func TestAccountService_Update_SameUsername(t *testing.T) { tx := testutils.NewTestTransaction(t) rdb := testutils.GetTestRedis(t) testutils.CleanTestRedisKeys(t, rdb) accountStore := postgres.NewAccountStore(tx, rdb) roleStore := postgres.NewRoleStore(tx) accountRoleStore := postgres.NewAccountRoleStore(tx, rdb) mockAudit := new(MockAuditService) mockShop := new(MockShopStore) mockEnterprise := new(MockEnterpriseStore) svc := New(accountStore, roleStore, accountRoleStore, mockShop, mockEnterprise, mockAudit) ctx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{ UserID: 1, UserType: constants.UserTypeSuperAdmin, }) username := "test_same_username_" + time.Now().Format("20060102150405") phone := "1" + time.Now().Format("0601021504") req := &dto.CreateAccountRequest{ Username: username, Phone: phone, Password: "TestPass123", UserType: constants.UserTypePlatform, } mockAudit.On("LogOperation", mock.Anything, mock.Anything).Return() created, err := svc.Create(ctx, req) require.NoError(t, err) updateReq := &dto.UpdateAccountRequest{ Username: &username, } updated, err := svc.Update(ctx, created.ID, updateReq) require.NoError(t, err) assert.Equal(t, username, updated.Username) } func TestAccountService_Update_SamePhone(t *testing.T) { tx := testutils.NewTestTransaction(t) rdb := testutils.GetTestRedis(t) testutils.CleanTestRedisKeys(t, rdb) accountStore := postgres.NewAccountStore(tx, rdb) roleStore := postgres.NewRoleStore(tx) accountRoleStore := postgres.NewAccountRoleStore(tx, rdb) mockAudit := new(MockAuditService) mockShop := new(MockShopStore) mockEnterprise := new(MockEnterpriseStore) svc := New(accountStore, roleStore, accountRoleStore, mockShop, mockEnterprise, mockAudit) ctx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{ UserID: 1, UserType: constants.UserTypeSuperAdmin, }) username := "test_same_phone_" + time.Now().Format("20060102150405") phone := "1" + time.Now().Format("0601021504") req := &dto.CreateAccountRequest{ Username: username, Phone: phone, Password: "TestPass123", UserType: constants.UserTypePlatform, } mockAudit.On("LogOperation", mock.Anything, mock.Anything).Return() created, err := svc.Create(ctx, req) require.NoError(t, err) updateReq := &dto.UpdateAccountRequest{ Phone: &phone, } updated, err := svc.Update(ctx, created.ID, updateReq) require.NoError(t, err) assert.Equal(t, phone, updated.Phone) } func TestAccountService_AssignRoles_DuplicateRoles(t *testing.T) { tx := testutils.NewTestTransaction(t) rdb := testutils.GetTestRedis(t) testutils.CleanTestRedisKeys(t, rdb) accountStore := postgres.NewAccountStore(tx, rdb) roleStore := postgres.NewRoleStore(tx) accountRoleStore := postgres.NewAccountRoleStore(tx, rdb) mockAudit := new(MockAuditService) mockShop := new(MockShopStore) mockEnterprise := new(MockEnterpriseStore) svc := New(accountStore, roleStore, accountRoleStore, mockShop, mockEnterprise, mockAudit) ctx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{ UserID: 1, UserType: constants.UserTypeSuperAdmin, }) username := "test_dup_roles_" + time.Now().Format("20060102150405") phone := "1" + time.Now().Format("0601021504") req := &dto.CreateAccountRequest{ Username: username, Phone: phone, Password: "TestPass123", UserType: constants.UserTypePlatform, } mockAudit.On("LogOperation", mock.Anything, mock.Anything).Return() created, err := svc.Create(ctx, req) require.NoError(t, err) role := &model.Role{ RoleName: "test_role_dup_" + time.Now().Format("20060102150405"), RoleType: constants.RoleTypePlatform, Status: constants.StatusEnabled, } errRole := roleStore.Create(ctx, role) require.NoError(t, errRole) ars, err := svc.AssignRoles(ctx, created.ID, []uint{role.ID, role.ID}) require.NoError(t, err) assert.Len(t, ars, 1) } func TestAccountService_Create_PlatformUserCreateAgentWithShop(t *testing.T) { tx := testutils.NewTestTransaction(t) rdb := testutils.GetTestRedis(t) testutils.CleanTestRedisKeys(t, rdb) accountStore := postgres.NewAccountStore(tx, rdb) roleStore := postgres.NewRoleStore(tx) accountRoleStore := postgres.NewAccountRoleStore(tx, rdb) mockAudit := new(MockAuditService) mockShop := new(MockShopStore) mockEnterprise := new(MockEnterpriseStore) svc := New(accountStore, roleStore, accountRoleStore, mockShop, mockEnterprise, mockAudit) ctx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{ UserID: 1, UserType: constants.UserTypePlatform, }) shopID := uint(1) username := "test_agent_shop_" + time.Now().Format("20060102150405") phone := "1" + time.Now().Format("0601021504") req := &dto.CreateAccountRequest{ Username: username, Phone: phone, Password: "TestPass123", UserType: constants.UserTypeAgent, ShopID: &shopID, } mockShop.On("GetSubordinateShopIDs", mock.Anything, uint(1)).Return([]uint{1}, nil) mockAudit.On("LogOperation", mock.Anything, mock.Anything).Return() resp, err := svc.Create(ctx, req) require.NoError(t, err) assert.NotZero(t, resp.ID) assert.Equal(t, constants.UserTypeAgent, resp.UserType) assert.Equal(t, &shopID, resp.ShopID) mockAudit.AssertCalled(t, "LogOperation", mock.Anything, mock.Anything) } func TestAccountService_AssignRoles_CustomerAccountType(t *testing.T) { tx := testutils.NewTestTransaction(t) rdb := testutils.GetTestRedis(t) testutils.CleanTestRedisKeys(t, rdb) accountStore := postgres.NewAccountStore(tx, rdb) roleStore := postgres.NewRoleStore(tx) accountRoleStore := postgres.NewAccountRoleStore(tx, rdb) mockAudit := new(MockAuditService) mockShop := new(MockShopStore) mockEnterprise := new(MockEnterpriseStore) svc := New(accountStore, roleStore, accountRoleStore, mockShop, mockEnterprise, mockAudit) ctx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{ UserID: 1, UserType: constants.UserTypeSuperAdmin, }) shopID := uint(1) username := "test_agent_role_" + time.Now().Format("20060102150405") phone := "1" + time.Now().Format("0601021504") req := &dto.CreateAccountRequest{ Username: username, Phone: phone, Password: "TestPass123", UserType: constants.UserTypeAgent, ShopID: &shopID, } mockShop.On("GetSubordinateShopIDs", mock.Anything, uint(1)).Return([]uint{1}, nil) mockAudit.On("LogOperation", mock.Anything, mock.Anything).Return() created, err := svc.Create(ctx, req) require.NoError(t, err) role := &model.Role{ RoleName: "test_customer_role_" + time.Now().Format("20060102150405"), RoleType: constants.RoleTypeCustomer, Status: constants.StatusEnabled, } errRole := roleStore.Create(ctx, role) require.NoError(t, errRole) ars, err := svc.AssignRoles(ctx, created.ID, []uint{role.ID}) require.NoError(t, err) assert.Len(t, ars, 1) } func TestAccountService_Delete_AgentAccountWithShop(t *testing.T) { tx := testutils.NewTestTransaction(t) rdb := testutils.GetTestRedis(t) testutils.CleanTestRedisKeys(t, rdb) accountStore := postgres.NewAccountStore(tx, rdb) roleStore := postgres.NewRoleStore(tx) accountRoleStore := postgres.NewAccountRoleStore(tx, rdb) mockAudit := new(MockAuditService) mockShop := new(MockShopStore) mockEnterprise := new(MockEnterpriseStore) svc := New(accountStore, roleStore, accountRoleStore, mockShop, mockEnterprise, mockAudit) superAdminCtx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{ UserID: 1, UserType: constants.UserTypeSuperAdmin, }) shopID := uint(1) username := "test_delete_agent_" + time.Now().Format("20060102150405") phone := "1" + time.Now().Format("0601021504") req := &dto.CreateAccountRequest{ Username: username, Phone: phone, Password: "TestPass123", UserType: constants.UserTypeAgent, ShopID: &shopID, } mockShop.On("GetSubordinateShopIDs", mock.Anything, uint(1)).Return([]uint{1}, nil) mockAudit.On("LogOperation", mock.Anything, mock.Anything).Return() created, err := svc.Create(superAdminCtx, req) require.NoError(t, err) agentCtx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{ UserID: 2, UserType: constants.UserTypeAgent, ShopID: 1, }) mockShop.On("GetSubordinateShopIDs", mock.Anything, uint(1)).Return([]uint{1}, nil) err = svc.Delete(agentCtx, created.ID) require.NoError(t, err) _, err = svc.Get(superAdminCtx, created.ID) require.Error(t, err) } func TestAccountService_Update_AgentAccountWithShop(t *testing.T) { tx := testutils.NewTestTransaction(t) rdb := testutils.GetTestRedis(t) testutils.CleanTestRedisKeys(t, rdb) accountStore := postgres.NewAccountStore(tx, rdb) roleStore := postgres.NewRoleStore(tx) accountRoleStore := postgres.NewAccountRoleStore(tx, rdb) mockAudit := new(MockAuditService) mockShop := new(MockShopStore) mockEnterprise := new(MockEnterpriseStore) svc := New(accountStore, roleStore, accountRoleStore, mockShop, mockEnterprise, mockAudit) superAdminCtx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{ UserID: 1, UserType: constants.UserTypeSuperAdmin, }) shopID := uint(1) username := "test_update_agent_" + time.Now().Format("20060102150405") phone := "1" + time.Now().Format("0601021504") req := &dto.CreateAccountRequest{ Username: username, Phone: phone, Password: "TestPass123", UserType: constants.UserTypeAgent, ShopID: &shopID, } mockShop.On("GetSubordinateShopIDs", mock.Anything, uint(1)).Return([]uint{1}, nil) mockAudit.On("LogOperation", mock.Anything, mock.Anything).Return() created, err := svc.Create(superAdminCtx, req) require.NoError(t, err) agentCtx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{ UserID: 2, UserType: constants.UserTypeAgent, ShopID: 1, }) mockShop.On("GetSubordinateShopIDs", mock.Anything, uint(1)).Return([]uint{1}, nil) newUsername := "updated_agent_" + time.Now().Format("20060102150405") updateReq := &dto.UpdateAccountRequest{ Username: &newUsername, } updated, err := svc.Update(agentCtx, created.ID, updateReq) require.NoError(t, err) assert.Equal(t, newUsername, updated.Username) } func TestAccountService_AssignRoles_AgentAccountWithShop(t *testing.T) { tx := testutils.NewTestTransaction(t) rdb := testutils.GetTestRedis(t) testutils.CleanTestRedisKeys(t, rdb) accountStore := postgres.NewAccountStore(tx, rdb) roleStore := postgres.NewRoleStore(tx) accountRoleStore := postgres.NewAccountRoleStore(tx, rdb) mockAudit := new(MockAuditService) mockShop := new(MockShopStore) mockEnterprise := new(MockEnterpriseStore) svc := New(accountStore, roleStore, accountRoleStore, mockShop, mockEnterprise, mockAudit) superAdminCtx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{ UserID: 1, UserType: constants.UserTypeSuperAdmin, }) shopID := uint(1) username := "test_assign_agent_" + time.Now().Format("20060102150405") phone := "1" + time.Now().Format("0601021504") req := &dto.CreateAccountRequest{ Username: username, Phone: phone, Password: "TestPass123", UserType: constants.UserTypeAgent, ShopID: &shopID, } mockShop.On("GetSubordinateShopIDs", mock.Anything, uint(1)).Return([]uint{1}, nil) mockAudit.On("LogOperation", mock.Anything, mock.Anything).Return() created, err := svc.Create(superAdminCtx, req) require.NoError(t, err) role := &model.Role{ RoleName: "test_agent_role_" + time.Now().Format("20060102150405"), RoleType: constants.RoleTypeCustomer, Status: constants.StatusEnabled, } errRole := roleStore.Create(superAdminCtx, role) require.NoError(t, errRole) agentCtx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{ UserID: 2, UserType: constants.UserTypeAgent, ShopID: 1, }) mockShop.On("GetSubordinateShopIDs", mock.Anything, uint(1)).Return([]uint{1}, nil) ars, err := svc.AssignRoles(agentCtx, created.ID, []uint{role.ID}) require.NoError(t, err) assert.Len(t, ars, 1) } func TestAccountService_RemoveRole_AgentAccountWithShop(t *testing.T) { tx := testutils.NewTestTransaction(t) rdb := testutils.GetTestRedis(t) testutils.CleanTestRedisKeys(t, rdb) accountStore := postgres.NewAccountStore(tx, rdb) roleStore := postgres.NewRoleStore(tx) accountRoleStore := postgres.NewAccountRoleStore(tx, rdb) mockAudit := new(MockAuditService) mockShop := new(MockShopStore) mockEnterprise := new(MockEnterpriseStore) svc := New(accountStore, roleStore, accountRoleStore, mockShop, mockEnterprise, mockAudit) superAdminCtx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{ UserID: 1, UserType: constants.UserTypeSuperAdmin, }) shopID := uint(1) username := "test_remove_agent_" + time.Now().Format("20060102150405") phone := "1" + time.Now().Format("0601021504") req := &dto.CreateAccountRequest{ Username: username, Phone: phone, Password: "TestPass123", UserType: constants.UserTypeAgent, ShopID: &shopID, } mockShop.On("GetSubordinateShopIDs", mock.Anything, uint(1)).Return([]uint{1}, nil) mockAudit.On("LogOperation", mock.Anything, mock.Anything).Return() created, err := svc.Create(superAdminCtx, req) require.NoError(t, err) role := &model.Role{ RoleName: "test_remove_agent_role_" + time.Now().Format("20060102150405"), RoleType: constants.RoleTypeCustomer, Status: constants.StatusEnabled, } errRole := roleStore.Create(superAdminCtx, role) require.NoError(t, errRole) _, err = svc.AssignRoles(superAdminCtx, created.ID, []uint{role.ID}) require.NoError(t, err) agentCtx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{ UserID: 2, UserType: constants.UserTypeAgent, ShopID: 1, }) mockShop.On("GetSubordinateShopIDs", mock.Anything, uint(1)).Return([]uint{1}, nil) err = svc.RemoveRole(agentCtx, created.ID, role.ID) require.NoError(t, err) roles, err := svc.GetRoles(superAdminCtx, created.ID) require.NoError(t, err) assert.Len(t, roles, 0) } func TestAccountService_Create_EnterpriseAccountWithShop(t *testing.T) { tx := testutils.NewTestTransaction(t) rdb := testutils.GetTestRedis(t) testutils.CleanTestRedisKeys(t, rdb) accountStore := postgres.NewAccountStore(tx, rdb) roleStore := postgres.NewRoleStore(tx) accountRoleStore := postgres.NewAccountRoleStore(tx, rdb) mockAudit := new(MockAuditService) mockShop := new(MockShopStore) mockEnterprise := new(MockEnterpriseStore) svc := New(accountStore, roleStore, accountRoleStore, mockShop, mockEnterprise, mockAudit) ctx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{ UserID: 1, UserType: constants.UserTypePlatform, }) shopID := uint(1) enterpriseID := uint(1) username := "test_enterprise_shop_" + time.Now().Format("20060102150405") phone := "1" + time.Now().Format("0601021504") req := &dto.CreateAccountRequest{ Username: username, Phone: phone, Password: "TestPass123", UserType: constants.UserTypeEnterprise, ShopID: &shopID, EnterpriseID: &enterpriseID, } mockShop.On("GetSubordinateShopIDs", mock.Anything, uint(1)).Return([]uint{1}, nil) mockEnterprise.On("GetByID", mock.Anything, enterpriseID).Return(&model.Enterprise{}, nil) mockAudit.On("LogOperation", mock.Anything, mock.Anything).Return() resp, err := svc.Create(ctx, req) require.NoError(t, err) assert.NotZero(t, resp.ID) assert.Equal(t, constants.UserTypeEnterprise, resp.UserType) assert.Equal(t, &enterpriseID, resp.EnterpriseID) mockAudit.AssertCalled(t, "LogOperation", mock.Anything, mock.Anything) } func TestAccountService_Delete_PlatformAccountByAgent(t *testing.T) { tx := testutils.NewTestTransaction(t) rdb := testutils.GetTestRedis(t) testutils.CleanTestRedisKeys(t, rdb) accountStore := postgres.NewAccountStore(tx, rdb) roleStore := postgres.NewRoleStore(tx) accountRoleStore := postgres.NewAccountRoleStore(tx, rdb) mockAudit := new(MockAuditService) mockShop := new(MockShopStore) mockEnterprise := new(MockEnterpriseStore) svc := New(accountStore, roleStore, accountRoleStore, mockShop, mockEnterprise, mockAudit) superAdminCtx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{ UserID: 1, UserType: constants.UserTypeSuperAdmin, }) username := "test_delete_platform_" + time.Now().Format("20060102150405") phone := "1" + time.Now().Format("0601021504") req := &dto.CreateAccountRequest{ Username: username, Phone: phone, Password: "TestPass123", UserType: constants.UserTypePlatform, } mockAudit.On("LogOperation", mock.Anything, mock.Anything).Return() created, err := svc.Create(superAdminCtx, req) require.NoError(t, err) agentCtx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{ UserID: 2, UserType: constants.UserTypeAgent, ShopID: 10, }) err = svc.Delete(agentCtx, created.ID) require.Error(t, err) appErr, ok := err.(*errors.AppError) require.True(t, ok) assert.Equal(t, errors.CodeForbidden, appErr.Code) } func TestAccountService_Update_PlatformAccountByAgent(t *testing.T) { tx := testutils.NewTestTransaction(t) rdb := testutils.GetTestRedis(t) testutils.CleanTestRedisKeys(t, rdb) accountStore := postgres.NewAccountStore(tx, rdb) roleStore := postgres.NewRoleStore(tx) accountRoleStore := postgres.NewAccountRoleStore(tx, rdb) mockAudit := new(MockAuditService) mockShop := new(MockShopStore) mockEnterprise := new(MockEnterpriseStore) svc := New(accountStore, roleStore, accountRoleStore, mockShop, mockEnterprise, mockAudit) superAdminCtx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{ UserID: 1, UserType: constants.UserTypeSuperAdmin, }) username := "test_update_platform_" + time.Now().Format("20060102150405") phone := "1" + time.Now().Format("0601021504") req := &dto.CreateAccountRequest{ Username: username, Phone: phone, Password: "TestPass123", UserType: constants.UserTypePlatform, } mockAudit.On("LogOperation", mock.Anything, mock.Anything).Return() created, err := svc.Create(superAdminCtx, req) require.NoError(t, err) agentCtx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{ UserID: 2, UserType: constants.UserTypeAgent, ShopID: 10, }) newUsername := "updated" updateReq := &dto.UpdateAccountRequest{ Username: &newUsername, } _, err = svc.Update(agentCtx, created.ID, updateReq) require.Error(t, err) appErr, ok := err.(*errors.AppError) require.True(t, ok) assert.Equal(t, errors.CodeForbidden, appErr.Code) } func TestAccountService_AssignRoles_PlatformAccountByAgent(t *testing.T) { tx := testutils.NewTestTransaction(t) rdb := testutils.GetTestRedis(t) testutils.CleanTestRedisKeys(t, rdb) accountStore := postgres.NewAccountStore(tx, rdb) roleStore := postgres.NewRoleStore(tx) accountRoleStore := postgres.NewAccountRoleStore(tx, rdb) mockAudit := new(MockAuditService) mockShop := new(MockShopStore) mockEnterprise := new(MockEnterpriseStore) svc := New(accountStore, roleStore, accountRoleStore, mockShop, mockEnterprise, mockAudit) superAdminCtx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{ UserID: 1, UserType: constants.UserTypeSuperAdmin, }) username := "test_assign_platform_" + time.Now().Format("20060102150405") phone := "1" + time.Now().Format("0601021504") req := &dto.CreateAccountRequest{ Username: username, Phone: phone, Password: "TestPass123", UserType: constants.UserTypePlatform, } mockAudit.On("LogOperation", mock.Anything, mock.Anything).Return() created, err := svc.Create(superAdminCtx, req) require.NoError(t, err) agentCtx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{ UserID: 2, UserType: constants.UserTypeAgent, ShopID: 10, }) _, err = svc.AssignRoles(agentCtx, created.ID, []uint{1}) require.Error(t, err) appErr, ok := err.(*errors.AppError) require.True(t, ok) assert.Equal(t, errors.CodeForbidden, appErr.Code) } func TestAccountService_RemoveRole_PlatformAccountByAgent(t *testing.T) { tx := testutils.NewTestTransaction(t) rdb := testutils.GetTestRedis(t) testutils.CleanTestRedisKeys(t, rdb) accountStore := postgres.NewAccountStore(tx, rdb) roleStore := postgres.NewRoleStore(tx) accountRoleStore := postgres.NewAccountRoleStore(tx, rdb) mockAudit := new(MockAuditService) mockShop := new(MockShopStore) mockEnterprise := new(MockEnterpriseStore) svc := New(accountStore, roleStore, accountRoleStore, mockShop, mockEnterprise, mockAudit) superAdminCtx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{ UserID: 1, UserType: constants.UserTypeSuperAdmin, }) username := "test_remove_platform_" + time.Now().Format("20060102150405") phone := "1" + time.Now().Format("0601021504") req := &dto.CreateAccountRequest{ Username: username, Phone: phone, Password: "TestPass123", UserType: constants.UserTypePlatform, } mockAudit.On("LogOperation", mock.Anything, mock.Anything).Return() created, err := svc.Create(superAdminCtx, req) require.NoError(t, err) agentCtx := middleware.SetUserContext(context.Background(), &middleware.UserContextInfo{ UserID: 2, UserType: constants.UserTypeAgent, ShopID: 10, }) err = svc.RemoveRole(agentCtx, created.ID, 1) require.Error(t, err) appErr, ok := err.(*errors.AppError) require.True(t, ok) assert.Equal(t, errors.CodeForbidden, appErr.Code) } func ptrUint(v uint) *uint { return &v }