This commit is contained in:
2026-04-25 19:17:19 +08:00
parent ba463ae38d
commit 18c92584d9
10 changed files with 533 additions and 0 deletions

View File

@@ -199,3 +199,67 @@ func (r *GormSubordinateRepository) ListWalletAllocationsByParentAndChild(ctx co
}
return out, total, nil
}
// CreateQuotaPurchase 创建额度购买记录
func (r *GormSubordinateRepository) CreateQuotaPurchase(ctx context.Context, p *entities.SubordinateQuotaPurchase) error {
return r.withCtx(ctx).Create(p).Error
}
// ListQuotaPurchasesByParentAndChild 查询主对子额度购买记录
func (r *GormSubordinateRepository) ListQuotaPurchasesByParentAndChild(ctx context.Context, parentUserID, childUserID string, limit, offset int) ([]*entities.SubordinateQuotaPurchase, int64, error) {
var list []entities.SubordinateQuotaPurchase
var total int64
q := r.withCtx(ctx).Model(&entities.SubordinateQuotaPurchase{}).Where("parent_user_id = ? AND child_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.SubordinateQuotaPurchase, len(list))
for i := range list {
out[i] = &list[i]
}
return out, total, nil
}
// FindQuotaAccount 查询用户产品额度账户
func (r *GormSubordinateRepository) FindQuotaAccount(ctx context.Context, userID, productID string) (*entities.UserProductQuotaAccount, error) {
var account entities.UserProductQuotaAccount
err := r.withCtx(ctx).Where("user_id = ? AND product_id = ?", userID, productID).First(&account).Error
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, nil
}
return nil, err
}
return &account, nil
}
// CreateQuotaAccount 创建额度账户
func (r *GormSubordinateRepository) CreateQuotaAccount(ctx context.Context, account *entities.UserProductQuotaAccount) error {
return r.withCtx(ctx).Create(account).Error
}
// UpdateQuotaAccount 更新额度账户
func (r *GormSubordinateRepository) UpdateQuotaAccount(ctx context.Context, account *entities.UserProductQuotaAccount) error {
return r.withCtx(ctx).Save(account).Error
}
// ListQuotaAccountsByUser 查询用户全部额度账户
func (r *GormSubordinateRepository) ListQuotaAccountsByUser(ctx context.Context, userID string) ([]*entities.UserProductQuotaAccount, error) {
var list []entities.UserProductQuotaAccount
if err := r.withCtx(ctx).Where("user_id = ?", userID).Order("updated_at DESC").Find(&list).Error; err != nil {
return nil, err
}
out := make([]*entities.UserProductQuotaAccount, len(list))
for i := range list {
out[i] = &list[i]
}
return out, nil
}
// CreateQuotaLedger 创建额度流水
func (r *GormSubordinateRepository) CreateQuotaLedger(ctx context.Context, ledger *entities.UserProductQuotaLedger) error {
return r.withCtx(ctx).Create(ledger).Error
}

View File

@@ -209,3 +209,91 @@ func (h *SubordinateHandler) RemoveChildSubscription(c *gin.Context) {
}
h.response.Success(c, nil, "删除成功")
}
// PurchaseQuota 为下属购买额度
func (h *SubordinateHandler) PurchaseQuota(c *gin.Context) {
parentID := c.GetString("user_id")
if parentID == "" {
h.response.Unauthorized(c, "未登录")
return
}
var cmd commands.PurchaseChildQuotaCommand
if err := h.validator.BindAndValidate(c, &cmd); err != nil {
return
}
cmd.ParentUserID = parentID
if err := h.app.PurchaseChildQuota(c.Request.Context(), &cmd); err != nil {
h.logger.Error("为下属购买额度失败", zap.Error(err))
h.response.BadRequest(c, err.Error())
return
}
h.response.Success(c, nil, "购买额度成功")
}
// ListQuotaPurchases 下属额度购买记录
func (h *SubordinateHandler) ListQuotaPurchases(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.ListChildQuotaPurchasesCommand{
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.ListChildQuotaPurchases(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, "获取成功")
}
// ListChildQuotaAccounts 下属额度账户
func (h *SubordinateHandler) ListChildQuotaAccounts(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.ListChildQuotaAccounts(c.Request.Context(), &commands.ListChildQuotaAccountsCommand{
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, "获取成功")
}
// ListMyQuotaAccounts 当前登录用户额度账户
func (h *SubordinateHandler) ListMyQuotaAccounts(c *gin.Context) {
userID := c.GetString("user_id")
if userID == "" {
h.response.Unauthorized(c, "未登录")
return
}
res, err := h.app.ListMyQuotaAccounts(c.Request.Context(), userID)
if err != nil {
h.logger.Error("获取我的额度账户失败", zap.Error(err))
h.response.BadRequest(c, err.Error())
return
}
h.response.Success(c, res, "获取成功")
}

View File

@@ -40,6 +40,10 @@ func (r *SubordinateRoutes) Register(router *sharedhttp.GinRouter) {
sub.POST("/assign-subscription", r.handler.AssignSubscription)
sub.GET("/child-subscriptions", r.handler.ListChildSubscriptions)
sub.DELETE("/child-subscriptions/:subscription_id", r.handler.RemoveChildSubscription)
sub.POST("/purchase-quota", r.handler.PurchaseQuota)
sub.GET("/quota-purchases", r.handler.ListQuotaPurchases)
sub.GET("/child-quotas", r.handler.ListChildQuotaAccounts)
sub.GET("/my-quotas", r.handler.ListMyQuotaAccounts)
}
r.logger.Info("下属账号路由注册完成")