f
This commit is contained in:
@@ -0,0 +1,201 @@
|
||||
package subordinate
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"go.uber.org/zap"
|
||||
"gorm.io/gorm"
|
||||
|
||||
"tyapi-server/internal/domains/subordinate/entities"
|
||||
"tyapi-server/internal/domains/subordinate/repositories"
|
||||
shared_database "tyapi-server/internal/shared/database"
|
||||
)
|
||||
|
||||
// GormSubordinateRepository 下属模块 GORM 实现
|
||||
type GormSubordinateRepository struct {
|
||||
db *gorm.DB
|
||||
logger *zap.Logger
|
||||
}
|
||||
|
||||
var _ repositories.SubordinateRepository = (*GormSubordinateRepository)(nil)
|
||||
|
||||
// NewGormSubordinateRepository 构造
|
||||
func NewGormSubordinateRepository(db *gorm.DB, logger *zap.Logger) *GormSubordinateRepository {
|
||||
return &GormSubordinateRepository{db: db, logger: logger}
|
||||
}
|
||||
|
||||
func (r *GormSubordinateRepository) withCtx(ctx context.Context) *gorm.DB {
|
||||
if tx, ok := shared_database.GetTx(ctx); ok {
|
||||
return tx.WithContext(ctx)
|
||||
}
|
||||
return r.db.WithContext(ctx)
|
||||
}
|
||||
|
||||
// CreateInvitation 创建邀请
|
||||
func (r *GormSubordinateRepository) CreateInvitation(ctx context.Context, inv *entities.SubordinateInvitation) error {
|
||||
return r.withCtx(ctx).Create(inv).Error
|
||||
}
|
||||
|
||||
// FindInvitationByTokenHash 按 token 哈希查询
|
||||
func (r *GormSubordinateRepository) FindInvitationByTokenHash(ctx context.Context, tokenHash string) (*entities.SubordinateInvitation, error) {
|
||||
var inv entities.SubordinateInvitation
|
||||
err := r.withCtx(ctx).Where("token_hash = ?", tokenHash).First(&inv).Error
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil, nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
return &inv, nil
|
||||
}
|
||||
|
||||
// FindInvitationByID 按ID
|
||||
func (r *GormSubordinateRepository) FindInvitationByID(ctx context.Context, id string) (*entities.SubordinateInvitation, error) {
|
||||
var inv entities.SubordinateInvitation
|
||||
err := r.withCtx(ctx).Where("id = ?", id).First(&inv).Error
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil, nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
return &inv, nil
|
||||
}
|
||||
|
||||
// UpdateInvitation 更新
|
||||
func (r *GormSubordinateRepository) UpdateInvitation(ctx context.Context, inv *entities.SubordinateInvitation) error {
|
||||
return r.withCtx(ctx).Save(inv).Error
|
||||
}
|
||||
|
||||
// ConsumeInvitation 原子核销邀请(仅 pending 可核销)
|
||||
func (r *GormSubordinateRepository) ConsumeInvitation(ctx context.Context, invitationID, childUserID string, consumedAt time.Time) (bool, error) {
|
||||
uid := childUserID
|
||||
res := r.withCtx(ctx).
|
||||
Model(&entities.SubordinateInvitation{}).
|
||||
Where("id = ? AND status = ?", invitationID, entities.InvitationStatusPending).
|
||||
Updates(map[string]interface{}{
|
||||
"status": entities.InvitationStatusConsumed,
|
||||
"consumed_by_user_id": &uid,
|
||||
"consumed_at": &consumedAt,
|
||||
})
|
||||
if res.Error != nil {
|
||||
return false, res.Error
|
||||
}
|
||||
return res.RowsAffected > 0, nil
|
||||
}
|
||||
|
||||
// ListInvitationsByParent 主账号邀请列表
|
||||
func (r *GormSubordinateRepository) ListInvitationsByParent(ctx context.Context, parentUserID string, limit, offset int) ([]*entities.SubordinateInvitation, int64, error) {
|
||||
var list []entities.SubordinateInvitation
|
||||
var total int64
|
||||
q := r.withCtx(ctx).Model(&entities.SubordinateInvitation{}).Where("parent_user_id = ?", parentUserID)
|
||||
if err := q.Count(&total).Error; err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
if err := q.Order("created_at DESC").Limit(limit).Offset(offset).Find(&list).Error; err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
out := make([]*entities.SubordinateInvitation, len(list))
|
||||
for i := range list {
|
||||
out[i] = &list[i]
|
||||
}
|
||||
return out, total, nil
|
||||
}
|
||||
|
||||
// CreateLink 创建主从
|
||||
func (r *GormSubordinateRepository) CreateLink(ctx context.Context, link *entities.UserSubordinateLink) error {
|
||||
return r.withCtx(ctx).Create(link).Error
|
||||
}
|
||||
|
||||
// FindLinkByChildUserID 按子查
|
||||
func (r *GormSubordinateRepository) FindLinkByChildUserID(ctx context.Context, childUserID string) (*entities.UserSubordinateLink, error) {
|
||||
var l entities.UserSubordinateLink
|
||||
err := r.withCtx(ctx).Where("child_user_id = ? AND status = ?", childUserID, entities.LinkStatusActive).First(&l).Error
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil, nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
return &l, nil
|
||||
}
|
||||
|
||||
// FindLinkByParentAndChild 精确查
|
||||
func (r *GormSubordinateRepository) FindLinkByParentAndChild(ctx context.Context, parentUserID, childUserID string) (*entities.UserSubordinateLink, error) {
|
||||
var l entities.UserSubordinateLink
|
||||
err := r.withCtx(ctx).Where("parent_user_id = ? AND child_user_id = ?", parentUserID, childUserID).First(&l).Error
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil, nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
return &l, nil
|
||||
}
|
||||
|
||||
// ListChildrenByParent 列出下属
|
||||
func (r *GormSubordinateRepository) ListChildrenByParent(ctx context.Context, parentUserID string, limit, offset int) ([]*entities.UserSubordinateLink, int64, error) {
|
||||
var list []entities.UserSubordinateLink
|
||||
var total int64
|
||||
q := r.withCtx(ctx).Model(&entities.UserSubordinateLink{}).Where("parent_user_id = ? AND status = ?", parentUserID, entities.LinkStatusActive)
|
||||
if err := q.Count(&total).Error; err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
if err := q.Order("created_at DESC").Limit(limit).Offset(offset).Find(&list).Error; err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
out := make([]*entities.UserSubordinateLink, len(list))
|
||||
for i := range list {
|
||||
out[i] = &list[i]
|
||||
}
|
||||
return out, total, nil
|
||||
}
|
||||
|
||||
// UpdateLink 更新
|
||||
func (r *GormSubordinateRepository) UpdateLink(ctx context.Context, link *entities.UserSubordinateLink) error {
|
||||
return r.withCtx(ctx).Save(link).Error
|
||||
}
|
||||
|
||||
// IsUserSubordinate 是否为主账号的下属(存在 active 的 child 记录)
|
||||
func (r *GormSubordinateRepository) IsUserSubordinate(ctx context.Context, userID string) (bool, error) {
|
||||
var n int64
|
||||
err := r.withCtx(ctx).Model(&entities.UserSubordinateLink{}).Where("child_user_id = ? AND status = ?", userID, entities.LinkStatusActive).Count(&n).Error
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return n > 0, nil
|
||||
}
|
||||
|
||||
// CreateWalletAllocation 记划拨
|
||||
func (r *GormSubordinateRepository) CreateWalletAllocation(ctx context.Context, a *entities.SubordinateWalletAllocation) error {
|
||||
// 幂等:同 business_ref 不重复
|
||||
var cnt int64
|
||||
if err := r.withCtx(ctx).Model(&entities.SubordinateWalletAllocation{}).Where("business_ref = ?", a.BusinessRef).Count(&cnt).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if cnt > 0 {
|
||||
return fmt.Errorf("划拨记录已存在")
|
||||
}
|
||||
return r.withCtx(ctx).Create(a).Error
|
||||
}
|
||||
|
||||
// ListWalletAllocationsByParentAndChild 查询主对子划拨记录
|
||||
func (r *GormSubordinateRepository) ListWalletAllocationsByParentAndChild(ctx context.Context, parentUserID, childUserID string, limit, offset int) ([]*entities.SubordinateWalletAllocation, int64, error) {
|
||||
var list []entities.SubordinateWalletAllocation
|
||||
var total int64
|
||||
q := r.withCtx(ctx).Model(&entities.SubordinateWalletAllocation{}).Where("from_user_id = ? AND to_user_id = ?", parentUserID, childUserID)
|
||||
if err := q.Count(&total).Error; err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
if err := q.Order("created_at DESC").Limit(limit).Offset(offset).Find(&list).Error; err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
out := make([]*entities.SubordinateWalletAllocation, len(list))
|
||||
for i := range list {
|
||||
out[i] = &list[i]
|
||||
}
|
||||
return out, total, nil
|
||||
}
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
|
||||
"go.uber.org/zap"
|
||||
"gorm.io/gorm"
|
||||
"gorm.io/gorm/clause"
|
||||
|
||||
"tyapi-server/internal/domains/user/entities"
|
||||
"tyapi-server/internal/domains/user/repositories"
|
||||
@@ -107,7 +108,48 @@ func (r *GormUserRepository) ExistsByUnifiedSocialCode(ctx context.Context, unif
|
||||
}
|
||||
|
||||
func (r *GormUserRepository) Update(ctx context.Context, user entities.User) error {
|
||||
return r.UpdateEntity(ctx, &user)
|
||||
db := r.GetDB(ctx)
|
||||
|
||||
return db.Transaction(func(tx *gorm.DB) error {
|
||||
// 避免 GORM 自动保存关联触发 ON CONFLICT(受历史库索引差异影响)
|
||||
if err := tx.WithContext(ctx).Omit(clause.Associations).Save(&user).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 企业信息单独按 user_id 做更新或创建,避免关联 upsert 依赖冲突约束
|
||||
if user.EnterpriseInfo == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
enterpriseInfo := *user.EnterpriseInfo
|
||||
enterpriseInfo.UserID = user.ID
|
||||
enterpriseInfo.User = nil
|
||||
|
||||
var count int64
|
||||
if err := tx.WithContext(ctx).
|
||||
Model(&entities.EnterpriseInfo{}).
|
||||
Where("user_id = ?", user.ID).
|
||||
Count(&count).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if count > 0 {
|
||||
updates := map[string]interface{}{
|
||||
"company_name": enterpriseInfo.CompanyName,
|
||||
"unified_social_code": enterpriseInfo.UnifiedSocialCode,
|
||||
"legal_person_name": enterpriseInfo.LegalPersonName,
|
||||
"legal_person_id": enterpriseInfo.LegalPersonID,
|
||||
"legal_person_phone": enterpriseInfo.LegalPersonPhone,
|
||||
"enterprise_address": enterpriseInfo.EnterpriseAddress,
|
||||
}
|
||||
return tx.WithContext(ctx).
|
||||
Model(&entities.EnterpriseInfo{}).
|
||||
Where("user_id = ?", user.ID).
|
||||
Updates(updates).Error
|
||||
}
|
||||
|
||||
return tx.WithContext(ctx).Create(&enterpriseInfo).Error
|
||||
})
|
||||
}
|
||||
|
||||
func (r *GormUserRepository) CreateBatch(ctx context.Context, users []entities.User) error {
|
||||
|
||||
211
internal/infrastructure/http/handlers/subordinate_handler.go
Normal file
211
internal/infrastructure/http/handlers/subordinate_handler.go
Normal file
@@ -0,0 +1,211 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"go.uber.org/zap"
|
||||
|
||||
subordinate_app "tyapi-server/internal/application/subordinate"
|
||||
"tyapi-server/internal/application/subordinate/dto/commands"
|
||||
"tyapi-server/internal/shared/interfaces"
|
||||
)
|
||||
|
||||
// SubordinateHandler 下属账号
|
||||
type SubordinateHandler struct {
|
||||
app subordinate_app.SubordinateApplicationService
|
||||
response interfaces.ResponseBuilder
|
||||
validator interfaces.RequestValidator
|
||||
logger *zap.Logger
|
||||
}
|
||||
|
||||
// NewSubordinateHandler 构造
|
||||
func NewSubordinateHandler(
|
||||
app subordinate_app.SubordinateApplicationService,
|
||||
response interfaces.ResponseBuilder,
|
||||
validator interfaces.RequestValidator,
|
||||
logger *zap.Logger,
|
||||
) *SubordinateHandler {
|
||||
return &SubordinateHandler{app: app, response: response, validator: validator, logger: logger}
|
||||
}
|
||||
|
||||
// SubPortalRegister 子站注册
|
||||
func (h *SubordinateHandler) SubPortalRegister(c *gin.Context) {
|
||||
var cmd commands.SubPortalRegisterCommand
|
||||
if err := h.validator.BindAndValidate(c, &cmd); err != nil {
|
||||
return
|
||||
}
|
||||
res, err := h.app.RegisterSubPortal(c.Request.Context(), &cmd)
|
||||
if err != nil {
|
||||
h.logger.Error("子站注册失败", zap.Error(err))
|
||||
h.response.BadRequest(c, err.Error())
|
||||
return
|
||||
}
|
||||
h.response.Created(c, res, "注册成功")
|
||||
}
|
||||
|
||||
// CreateInvitation 主账号创建邀请
|
||||
func (h *SubordinateHandler) CreateInvitation(c *gin.Context) {
|
||||
parentID := c.GetString("user_id")
|
||||
if parentID == "" {
|
||||
h.response.Unauthorized(c, "未登录")
|
||||
return
|
||||
}
|
||||
var body struct {
|
||||
ExpiresInHours int `json:"expires_in_hours"`
|
||||
}
|
||||
_ = c.ShouldBindJSON(&body)
|
||||
res, err := h.app.CreateInvitation(c.Request.Context(), &commands.CreateInvitationCommand{
|
||||
ParentUserID: parentID,
|
||||
ExpiresInHours: body.ExpiresInHours,
|
||||
})
|
||||
if err != nil {
|
||||
h.logger.Error("创建邀请失败", zap.Error(err))
|
||||
h.response.BadRequest(c, err.Error())
|
||||
return
|
||||
}
|
||||
h.response.Success(c, res, "邀请已创建")
|
||||
}
|
||||
|
||||
// ListSubordinates 下属列表
|
||||
func (h *SubordinateHandler) ListSubordinates(c *gin.Context) {
|
||||
parentID := c.GetString("user_id")
|
||||
if parentID == "" {
|
||||
h.response.Unauthorized(c, "未登录")
|
||||
return
|
||||
}
|
||||
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
|
||||
size, _ := strconv.Atoi(c.DefaultQuery("page_size", "20"))
|
||||
res, err := h.app.ListMySubordinates(c.Request.Context(), parentID, page, size)
|
||||
if err != nil {
|
||||
h.logger.Error("获取下属列表失败", zap.Error(err))
|
||||
h.response.InternalError(c, "获取下属列表失败")
|
||||
return
|
||||
}
|
||||
h.response.Success(c, res, "获取成功")
|
||||
}
|
||||
|
||||
// Allocate 划款
|
||||
func (h *SubordinateHandler) Allocate(c *gin.Context) {
|
||||
parentID := c.GetString("user_id")
|
||||
if parentID == "" {
|
||||
h.response.Unauthorized(c, "未登录")
|
||||
return
|
||||
}
|
||||
var cmd commands.AllocateToChildCommand
|
||||
if err := h.validator.BindAndValidate(c, &cmd); err != nil {
|
||||
return
|
||||
}
|
||||
cmd.ParentUserID = parentID
|
||||
if err := h.app.AllocateToChild(c.Request.Context(), &cmd); err != nil {
|
||||
h.logger.Error("划拨失败", zap.Error(err))
|
||||
h.response.BadRequest(c, err.Error())
|
||||
return
|
||||
}
|
||||
h.response.Success(c, nil, "划拨成功")
|
||||
}
|
||||
|
||||
// ListAllocations 下属划拨记录
|
||||
func (h *SubordinateHandler) ListAllocations(c *gin.Context) {
|
||||
parentID := c.GetString("user_id")
|
||||
if parentID == "" {
|
||||
h.response.Unauthorized(c, "未登录")
|
||||
return
|
||||
}
|
||||
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
|
||||
size, _ := strconv.Atoi(c.DefaultQuery("page_size", "20"))
|
||||
cmd := &commands.ListChildAllocationsCommand{
|
||||
ParentUserID: parentID,
|
||||
ChildUserID: c.Query("child_user_id"),
|
||||
Page: page,
|
||||
PageSize: size,
|
||||
}
|
||||
if cmd.ChildUserID == "" {
|
||||
h.response.BadRequest(c, "child_user_id 不能为空")
|
||||
return
|
||||
}
|
||||
res, err := h.app.ListChildAllocations(c.Request.Context(), cmd)
|
||||
if err != nil {
|
||||
h.logger.Error("获取划拨记录失败", zap.Error(err))
|
||||
h.response.BadRequest(c, err.Error())
|
||||
return
|
||||
}
|
||||
h.response.Success(c, res, "获取成功")
|
||||
}
|
||||
|
||||
// AssignSubscription 代配订阅
|
||||
func (h *SubordinateHandler) AssignSubscription(c *gin.Context) {
|
||||
parentID := c.GetString("user_id")
|
||||
if parentID == "" {
|
||||
h.response.Unauthorized(c, "未登录")
|
||||
return
|
||||
}
|
||||
var cmd commands.AssignChildSubscriptionCommand
|
||||
if err := h.validator.BindAndValidate(c, &cmd); err != nil {
|
||||
return
|
||||
}
|
||||
cmd.ParentUserID = parentID
|
||||
if err := h.app.AssignChildSubscription(c.Request.Context(), &cmd); err != nil {
|
||||
h.logger.Error("代配订阅失败", zap.Error(err))
|
||||
h.response.BadRequest(c, err.Error())
|
||||
return
|
||||
}
|
||||
h.response.Success(c, nil, "已保存下属订阅")
|
||||
}
|
||||
|
||||
// ListChildSubscriptions 下属订阅列表
|
||||
func (h *SubordinateHandler) ListChildSubscriptions(c *gin.Context) {
|
||||
parentID := c.GetString("user_id")
|
||||
if parentID == "" {
|
||||
h.response.Unauthorized(c, "未登录")
|
||||
return
|
||||
}
|
||||
childID := c.Query("child_user_id")
|
||||
if childID == "" {
|
||||
h.response.BadRequest(c, "child_user_id 不能为空")
|
||||
return
|
||||
}
|
||||
res, err := h.app.ListChildSubscriptions(c.Request.Context(), &commands.ListChildSubscriptionsCommand{
|
||||
ParentUserID: parentID,
|
||||
ChildUserID: childID,
|
||||
})
|
||||
if err != nil {
|
||||
h.logger.Error("获取下属订阅失败", zap.Error(err))
|
||||
h.response.BadRequest(c, err.Error())
|
||||
return
|
||||
}
|
||||
h.response.Success(c, res, "获取成功")
|
||||
}
|
||||
|
||||
// RemoveChildSubscription 删除下属订阅
|
||||
func (h *SubordinateHandler) RemoveChildSubscription(c *gin.Context) {
|
||||
parentID := c.GetString("user_id")
|
||||
if parentID == "" {
|
||||
h.response.Unauthorized(c, "未登录")
|
||||
return
|
||||
}
|
||||
var body struct {
|
||||
ChildUserID string `json:"child_user_id"`
|
||||
}
|
||||
_ = c.ShouldBindJSON(&body)
|
||||
if body.ChildUserID == "" {
|
||||
h.response.BadRequest(c, "child_user_id 不能为空")
|
||||
return
|
||||
}
|
||||
subID := c.Param("subscription_id")
|
||||
if subID == "" {
|
||||
h.response.BadRequest(c, "subscription_id 不能为空")
|
||||
return
|
||||
}
|
||||
err := h.app.RemoveChildSubscription(c.Request.Context(), &commands.RemoveChildSubscriptionCommand{
|
||||
ParentUserID: parentID,
|
||||
ChildUserID: body.ChildUserID,
|
||||
SubscriptionID: subID,
|
||||
})
|
||||
if err != nil {
|
||||
h.logger.Error("删除下属订阅失败", zap.Error(err))
|
||||
h.response.BadRequest(c, err.Error())
|
||||
return
|
||||
}
|
||||
h.response.Success(c, nil, "删除成功")
|
||||
}
|
||||
@@ -49,8 +49,6 @@ func (r *CertificationRoutes) Register(router *http.GinRouter) {
|
||||
authGroup := certificationGroup.Group("")
|
||||
authGroup.Use(r.auth.Handle())
|
||||
{
|
||||
authGroup.GET("", r.handler.ListCertifications) // 查询认证列表(管理员)
|
||||
|
||||
// 1. 获取认证详情
|
||||
authGroup.GET("/details", r.handler.GetCertification)
|
||||
|
||||
@@ -71,10 +69,6 @@ func (r *CertificationRoutes) Register(router *http.GinRouter) {
|
||||
|
||||
// 前端确认是否完成签署
|
||||
authGroup.POST("/confirm-sign", r.handler.ConfirmSign)
|
||||
|
||||
// 管理员代用户完成认证(暂不关联合同)
|
||||
authGroup.POST("/admin/complete-without-contract", r.handler.AdminCompleteCertificationWithoutContract)
|
||||
|
||||
}
|
||||
|
||||
// 管理端企业审核(需管理员权限,以状态机状态为准)
|
||||
@@ -82,6 +76,8 @@ func (r *CertificationRoutes) Register(router *http.GinRouter) {
|
||||
adminGroup.Use(r.auth.Handle())
|
||||
adminGroup.Use(r.admin.Handle())
|
||||
{
|
||||
adminGroup.GET("", r.handler.ListCertifications) // 查询认证列表(管理员)
|
||||
adminGroup.POST("/complete-without-contract", r.handler.AdminCompleteCertificationWithoutContract)
|
||||
adminGroup.POST("/transition-status", r.handler.AdminTransitionCertificationStatus)
|
||||
}
|
||||
adminCertGroup := adminGroup.Group("/submit-records")
|
||||
|
||||
46
internal/infrastructure/http/routes/subordinate_routes.go
Normal file
46
internal/infrastructure/http/routes/subordinate_routes.go
Normal file
@@ -0,0 +1,46 @@
|
||||
package routes
|
||||
|
||||
import (
|
||||
"tyapi-server/internal/infrastructure/http/handlers"
|
||||
sharedhttp "tyapi-server/internal/shared/http"
|
||||
"tyapi-server/internal/shared/middleware"
|
||||
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
// SubordinateRoutes 下属与邀请路由
|
||||
type SubordinateRoutes struct {
|
||||
handler *handlers.SubordinateHandler
|
||||
auth *middleware.JWTAuthMiddleware
|
||||
logger *zap.Logger
|
||||
}
|
||||
|
||||
// NewSubordinateRoutes 构造
|
||||
func NewSubordinateRoutes(
|
||||
handler *handlers.SubordinateHandler,
|
||||
auth *middleware.JWTAuthMiddleware,
|
||||
logger *zap.Logger,
|
||||
) *SubordinateRoutes {
|
||||
return &SubordinateRoutes{handler: handler, auth: auth, logger: logger}
|
||||
}
|
||||
|
||||
// Register 注册
|
||||
func (r *SubordinateRoutes) Register(router *sharedhttp.GinRouter) {
|
||||
g := router.GetEngine()
|
||||
|
||||
g.POST("/api/v1/sub-portal/register", r.handler.SubPortalRegister)
|
||||
|
||||
sub := g.Group("/api/v1/subordinate")
|
||||
sub.Use(r.auth.Handle())
|
||||
{
|
||||
sub.POST("/invitations", r.handler.CreateInvitation)
|
||||
sub.GET("/subordinates", r.handler.ListSubordinates)
|
||||
sub.POST("/allocate", r.handler.Allocate)
|
||||
sub.GET("/allocations", r.handler.ListAllocations)
|
||||
sub.POST("/assign-subscription", r.handler.AssignSubscription)
|
||||
sub.GET("/child-subscriptions", r.handler.ListChildSubscriptions)
|
||||
sub.DELETE("/child-subscriptions/:subscription_id", r.handler.RemoveChildSubscription)
|
||||
}
|
||||
|
||||
r.logger.Info("下属账号路由注册完成")
|
||||
}
|
||||
31
internal/infrastructure/subordinate/account_kind_provider.go
Normal file
31
internal/infrastructure/subordinate/account_kind_provider.go
Normal file
@@ -0,0 +1,31 @@
|
||||
package subordinate
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"tyapi-server/internal/domains/subordinate/repositories"
|
||||
"tyapi-server/internal/shared/auth"
|
||||
"tyapi-server/internal/shared/interfaces"
|
||||
)
|
||||
|
||||
// AccountKindProviderImpl 从主从表判断 account_kind
|
||||
type AccountKindProviderImpl struct {
|
||||
repo repositories.SubordinateRepository
|
||||
}
|
||||
|
||||
// NewAccountKindProviderImpl 构造
|
||||
func NewAccountKindProviderImpl(repo repositories.SubordinateRepository) interfaces.AccountKindProvider {
|
||||
return &AccountKindProviderImpl{repo: repo}
|
||||
}
|
||||
|
||||
// AccountKind 返回 standalone 或 subordinate
|
||||
func (p *AccountKindProviderImpl) AccountKind(ctx context.Context, userID string) (string, error) {
|
||||
ok, err := p.repo.IsUserSubordinate(ctx, userID)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if ok {
|
||||
return auth.AccountKindSubordinate, nil
|
||||
}
|
||||
return auth.AccountKindStandalone, nil
|
||||
}
|
||||
Reference in New Issue
Block a user