feat: 实现账号与佣金管理模块
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 4m35s

新增功能:
- 店铺佣金查询:店铺佣金统计、店铺佣金记录列表、店铺提现记录
- 佣金提现审批:提现申请列表、审批通过、审批拒绝
- 提现配置管理:配置列表、新增配置、获取当前生效配置
- 企业管理:企业列表、创建、更新、删除、获取详情
- 企业卡授权:授权列表、批量授权、批量取消授权、统计
- 客户账号管理:账号列表、创建、更新状态、重置密码
- 我的佣金:佣金统计、佣金记录、提现申请、提现记录

数据库变更:
- 扩展 tb_commission_withdrawal_request 新增提现单号等字段
- 扩展 tb_account 新增 is_primary 字段
- 扩展 tb_commission_record 新增 shop_id、balance_after
- 扩展 tb_commission_withdrawal_setting 新增每日提现次数限制
- 扩展 tb_iot_card、tb_device 新增 shop_id 冗余字段
- 新建 tb_enterprise_card_authorization 企业卡授权表
- 新建 tb_asset_allocation_record 资产分配记录表
- 数据迁移:owner_type 枚举值 agent 统一为 shop

测试:
- 新增 7 个单元测试文件覆盖各服务
- 修复集成测试 Redis 依赖问题
This commit is contained in:
2026-01-21 18:20:44 +08:00
parent 1489abe668
commit 91c9bbfeb8
89 changed files with 11958 additions and 159 deletions

View File

@@ -101,7 +101,7 @@ func setupTestEnv(t *testing.T) *testEnv {
// 初始化 Store
accountStore := postgresStore.NewAccountStore(db, redisClient)
roleStore := postgresStore.NewRoleStore(db)
accountRoleStore := postgresStore.NewAccountRoleStore(db)
accountRoleStore := postgresStore.NewAccountRoleStore(db, redisClient)
// 初始化 Service
accService := accountService.New(accountStore, roleStore, accountRoleStore)

View File

@@ -10,10 +10,12 @@ import (
"time"
"github.com/gofiber/fiber/v2"
"github.com/redis/go-redis/v9"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/testcontainers/testcontainers-go"
testcontainers_postgres "github.com/testcontainers/testcontainers-go/modules/postgres"
testcontainers_redis "github.com/testcontainers/testcontainers-go/modules/redis"
"github.com/testcontainers/testcontainers-go/wait"
"gorm.io/driver/postgres"
"gorm.io/gorm"
@@ -34,6 +36,7 @@ import (
// permTestEnv 权限测试环境
type permTestEnv struct {
db *gorm.DB
redisClient *redis.Client
app *fiber.App
permissionService *permissionService.Service
cleanup func()
@@ -62,6 +65,17 @@ func setupPermTestEnv(t *testing.T) *permTestEnv {
pgConnStr, err := pgContainer.ConnectionString(ctx, "sslmode=disable")
require.NoError(t, err)
// 启动 Redis 容器
redisContainer, err := testcontainers_redis.Run(ctx,
"redis:6-alpine",
)
require.NoError(t, err, "启动 Redis 容器失败")
redisHost, err := redisContainer.Host(ctx)
require.NoError(t, err)
redisPort, err := redisContainer.MappedPort(ctx, "6379")
require.NoError(t, err)
// 连接数据库
db, err := gorm.Open(postgres.Open(pgConnStr), &gorm.Config{
Logger: logger.Default.LogMode(logger.Silent),
@@ -74,6 +88,11 @@ func setupPermTestEnv(t *testing.T) *permTestEnv {
)
require.NoError(t, err)
// 连接 Redis
redisClient := redis.NewClient(&redis.Options{
Addr: fmt.Sprintf("%s:%s", redisHost, redisPort.Port()),
})
// 初始化 Store
permStore := postgresStore.NewPermissionStore(db)
accountRoleStore := postgresStore.NewAccountRoleStore(db, redisClient)
@@ -101,12 +120,16 @@ func setupPermTestEnv(t *testing.T) *permTestEnv {
return &permTestEnv{
db: db,
redisClient: redisClient,
app: app,
permissionService: permSvc,
cleanup: func() {
if err := pgContainer.Terminate(ctx); err != nil {
t.Logf("终止 PostgreSQL 容器失败: %v", err)
}
if err := redisContainer.Terminate(ctx); err != nil {
t.Logf("终止 Redis 容器失败: %v", err)
}
},
}
}

View File

@@ -30,7 +30,7 @@ func TestPlatformAccountAPI_ListPlatformAccounts(t *testing.T) {
accountStore := postgresStore.NewAccountStore(db, redisClient)
roleStore := postgresStore.NewRoleStore(db)
accountRoleStore := postgresStore.NewAccountRoleStore(db)
accountRoleStore := postgresStore.NewAccountRoleStore(db, redisClient)
accService := accountService.New(accountStore, roleStore, accountRoleStore)
accountHandler := admin.NewAccountHandler(accService)
@@ -118,7 +118,7 @@ func TestPlatformAccountAPI_UpdatePassword(t *testing.T) {
accountStore := postgresStore.NewAccountStore(db, redisClient)
roleStore := postgresStore.NewRoleStore(db)
accountRoleStore := postgresStore.NewAccountRoleStore(db)
accountRoleStore := postgresStore.NewAccountRoleStore(db, redisClient)
accService := accountService.New(accountStore, roleStore, accountRoleStore)
accountHandler := admin.NewAccountHandler(accService)
@@ -192,7 +192,7 @@ func TestPlatformAccountAPI_UpdateStatus(t *testing.T) {
accountStore := postgresStore.NewAccountStore(db, redisClient)
roleStore := postgresStore.NewRoleStore(db)
accountRoleStore := postgresStore.NewAccountRoleStore(db)
accountRoleStore := postgresStore.NewAccountRoleStore(db, redisClient)
accService := accountService.New(accountStore, roleStore, accountRoleStore)
accountHandler := admin.NewAccountHandler(accService)
@@ -261,7 +261,7 @@ func TestPlatformAccountAPI_AssignRoles(t *testing.T) {
accountStore := postgresStore.NewAccountStore(db, redisClient)
roleStore := postgresStore.NewRoleStore(db)
accountRoleStore := postgresStore.NewAccountRoleStore(db)
accountRoleStore := postgresStore.NewAccountRoleStore(db, redisClient)
accService := accountService.New(accountStore, roleStore, accountRoleStore)
accountHandler := admin.NewAccountHandler(accService)

View File

@@ -2,13 +2,16 @@ package integration
import (
"context"
"fmt"
"testing"
"time"
"github.com/redis/go-redis/v9"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/testcontainers/testcontainers-go"
testcontainers_postgres "github.com/testcontainers/testcontainers-go/modules/postgres"
testcontainers_redis "github.com/testcontainers/testcontainers-go/modules/redis"
"github.com/testcontainers/testcontainers-go/wait"
"gorm.io/driver/postgres"
"gorm.io/gorm"
@@ -25,7 +28,6 @@ import (
func TestRolePermissionAssociation_AssignPermissions(t *testing.T) {
ctx := context.Background()
// 启动 PostgreSQL 容器
pgContainer, err := testcontainers_postgres.RunContainer(ctx,
testcontainers.WithImage("postgres:14-alpine"),
testcontainers_postgres.WithDatabase("testdb"),
@@ -40,16 +42,23 @@ func TestRolePermissionAssociation_AssignPermissions(t *testing.T) {
require.NoError(t, err, "启动 PostgreSQL 容器失败")
defer func() { _ = pgContainer.Terminate(ctx) }()
redisContainer, err := testcontainers_redis.Run(ctx, "redis:6-alpine")
require.NoError(t, err, "启动 Redis 容器失败")
defer func() { _ = redisContainer.Terminate(ctx) }()
pgConnStr, err := pgContainer.ConnectionString(ctx, "sslmode=disable")
require.NoError(t, err)
// 连接数据库
redisHost, err := redisContainer.Host(ctx)
require.NoError(t, err)
redisPort, err := redisContainer.MappedPort(ctx, "6379")
require.NoError(t, err)
db, err := gorm.Open(postgres.Open(pgConnStr), &gorm.Config{
Logger: logger.Default.LogMode(logger.Silent),
})
require.NoError(t, err)
// 自动迁移
err = db.AutoMigrate(
&model.Role{},
&model.Permission{},
@@ -57,10 +66,13 @@ func TestRolePermissionAssociation_AssignPermissions(t *testing.T) {
)
require.NoError(t, err)
// 初始化 Store 和 Service
redisClient := redis.NewClient(&redis.Options{
Addr: fmt.Sprintf("%s:%s", redisHost, redisPort.Port()),
})
roleStore := postgresStore.NewRoleStore(db)
permStore := postgresStore.NewPermissionStore(db)
rolePermStore := postgresStore.NewRolePermissionStore(db)
rolePermStore := postgresStore.NewRolePermissionStore(db, redisClient)
roleSvc := roleService.New(roleStore, permStore, rolePermStore)
// 创建测试用户上下文
@@ -242,7 +254,6 @@ func TestRolePermissionAssociation_AssignPermissions(t *testing.T) {
func TestRolePermissionAssociation_SoftDelete(t *testing.T) {
ctx := context.Background()
// 启动容器
pgContainer, err := testcontainers_postgres.RunContainer(ctx,
testcontainers.WithImage("postgres:14-alpine"),
testcontainers_postgres.WithDatabase("testdb"),
@@ -257,17 +268,27 @@ func TestRolePermissionAssociation_SoftDelete(t *testing.T) {
require.NoError(t, err)
defer func() { _ = pgContainer.Terminate(ctx) }()
redisContainer, err := testcontainers_redis.Run(ctx, "redis:6-alpine")
require.NoError(t, err, "启动 Redis 容器失败")
defer func() { _ = redisContainer.Terminate(ctx) }()
pgConnStr, _ := pgContainer.ConnectionString(ctx, "sslmode=disable")
// 设置环境
redisHost, _ := redisContainer.Host(ctx)
redisPort, _ := redisContainer.MappedPort(ctx, "6379")
db, _ := gorm.Open(postgres.Open(pgConnStr), &gorm.Config{
Logger: logger.Default.LogMode(logger.Silent),
})
_ = db.AutoMigrate(&model.Role{}, &model.Permission{}, &model.RolePermission{})
redisClient := redis.NewClient(&redis.Options{
Addr: fmt.Sprintf("%s:%s", redisHost, redisPort.Port()),
})
roleStore := postgresStore.NewRoleStore(db)
permStore := postgresStore.NewPermissionStore(db)
rolePermStore := postgresStore.NewRolePermissionStore(db)
rolePermStore := postgresStore.NewRolePermissionStore(db, redisClient)
roleSvc := roleService.New(roleStore, permStore, rolePermStore)
userCtx := middleware.SetUserContext(ctx, middleware.NewSimpleUserContext(1, constants.UserTypeSuperAdmin, 0))

View File

@@ -101,7 +101,7 @@ func setupRoleTestEnv(t *testing.T) *roleTestEnv {
// 初始化 Store
roleStore := postgresStore.NewRoleStore(db)
permissionStore := postgresStore.NewPermissionStore(db)
rolePermissionStore := postgresStore.NewRolePermissionStore(db)
rolePermissionStore := postgresStore.NewRolePermissionStore(db, redisClient)
// 初始化 Service
roleSvc := roleService.New(roleStore, permissionStore, rolePermissionStore)