feat: add agent user edit, card type permission check and balance deduction
- Backend: check AgentApplicationCardType.can_generate before allowing card recharge - Backend: deduct agent balance and record consumption when creating user with card - Backend: add GET /agent/users/:id and PUT /agent/users/:id for user edit - Backend: extract checkAgentUserPermission helper, refactor handleUpdateUserStatus - Frontend: add user edit page ([id].vue) with username/email/password - Frontend: add edit action in user list dropdown menu - Frontend: add route for agent user edit page - Add i18n keys for agent user edit
This commit is contained in:
@@ -15,6 +15,7 @@ import (
|
||||
"verification-platform-backend/pkg/utils"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
func SetupAgentRoutes(r *gin.RouterGroup) {
|
||||
@@ -25,6 +26,8 @@ func SetupAgentRoutes(r *gin.RouterGroup) {
|
||||
r.POST("/cards/generate", handleGenerateCards)
|
||||
r.GET("/users", handleGetUsers)
|
||||
r.POST("/users", handleCreateUser)
|
||||
r.PUT("/users/:id", handleUpdateUser)
|
||||
r.GET("/users/:id", handleGetUser)
|
||||
r.PUT("/users/:id/status", handleUpdateUserStatus)
|
||||
r.GET("/finance", handleGetFinance)
|
||||
r.GET("/profile", handleGetProfile)
|
||||
@@ -1005,13 +1008,33 @@ func handleCreateUser(c *gin.Context) {
|
||||
}
|
||||
|
||||
var cardType *model.CardType
|
||||
var agentCardType *model.AgentApplicationCardType
|
||||
if req.CardTypeID != nil && *req.CardTypeID > 0 {
|
||||
var ct model.CardType
|
||||
if err := database.DB.Where("id = ? AND application_id = ?", *req.CardTypeID, req.ApplicationID).First(&ct).Error; err != nil {
|
||||
response.Error(c, 400, "卡密类型不存在或不属于该应用")
|
||||
return
|
||||
}
|
||||
|
||||
var act model.AgentApplicationCardType
|
||||
if err := database.DB.Where("agent_application_id = ? AND card_type_id = ? AND can_generate = ?", agentApp.ID, *req.CardTypeID, true).First(&act).Error; err != nil {
|
||||
response.Error(c, 403, "无权使用该卡类充值")
|
||||
return
|
||||
}
|
||||
|
||||
totalPrice := act.Price * float64(req.CardQuantity)
|
||||
var agent model.User
|
||||
if err := database.DB.First(&agent, userID).Error; err != nil {
|
||||
response.Error(c, 404, "代理不存在")
|
||||
return
|
||||
}
|
||||
if agent.Balance < totalPrice {
|
||||
response.Error(c, 400, fmt.Sprintf("余额不足,当前余额: %.2f,需要: %.2f", agent.Balance, totalPrice))
|
||||
return
|
||||
}
|
||||
|
||||
cardType = &ct
|
||||
agentCardType = &act
|
||||
}
|
||||
|
||||
tx := database.DB.Begin()
|
||||
@@ -1121,6 +1144,27 @@ func handleCreateUser(c *gin.Context) {
|
||||
response.Error(c, 500, "充值失败")
|
||||
return
|
||||
}
|
||||
|
||||
totalPrice := agentCardType.Price * float64(req.CardQuantity)
|
||||
if err := tx.Model(&model.User{}).Where("id = ?", userID).Update("balance", gorm.Expr("balance - ?", totalPrice)).Error; err != nil {
|
||||
tx.Rollback()
|
||||
response.Error(c, 500, "扣除余额失败")
|
||||
return
|
||||
}
|
||||
|
||||
consumeRecord := model.RechargeRecord{
|
||||
UserID: userID,
|
||||
OrderNo: generateAgentOrderNo("C"),
|
||||
Amount: -totalPrice,
|
||||
Status: "success",
|
||||
PaymentType: "balance",
|
||||
Remark: fmt.Sprintf("创建用户充值卡密: %s x%d", cardType.Name, req.CardQuantity),
|
||||
}
|
||||
if err := tx.Create(&consumeRecord).Error; err != nil {
|
||||
tx.Rollback()
|
||||
response.Error(c, 500, "记录消费失败")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if err := tx.Commit().Error; err != nil {
|
||||
@@ -1171,27 +1215,7 @@ func handleUpdateUserStatus(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
agentIDs := []uint{userID}
|
||||
var childAgents []model.User
|
||||
database.DB.Where("parent_agent_id = ? AND role = ?", userID, "agent").Find(&childAgents)
|
||||
for _, child := range childAgents {
|
||||
agentIDs = append(agentIDs, child.ID)
|
||||
}
|
||||
|
||||
var cardIDs []uint
|
||||
database.DB.Model(&model.Card{}).Where("agent_id IN ?", agentIDs).Pluck("id", &cardIDs)
|
||||
|
||||
if len(cardIDs) == 0 {
|
||||
response.Error(c, 403, "无权限操作该用户")
|
||||
return
|
||||
}
|
||||
|
||||
var count int64
|
||||
database.DB.Model(&model.RechargeRecord{}).
|
||||
Where("user_id = ? AND card_id IN ? AND status = ?", user.ID, cardIDs, "success").
|
||||
Count(&count)
|
||||
|
||||
if count == 0 {
|
||||
if !checkAgentUserPermission(userID, user.ID) {
|
||||
response.Error(c, 403, "无权限操作该用户")
|
||||
return
|
||||
}
|
||||
@@ -1207,3 +1231,92 @@ func handleUpdateUserStatus(c *gin.Context) {
|
||||
|
||||
response.Success(c, user)
|
||||
}
|
||||
|
||||
func checkAgentUserPermission(userID uint, appUserID uint) bool {
|
||||
agentIDs := []uint{userID}
|
||||
var childAgents []model.User
|
||||
database.DB.Where("parent_agent_id = ? AND role = ?", userID, "agent").Find(&childAgents)
|
||||
for _, child := range childAgents {
|
||||
agentIDs = append(agentIDs, child.ID)
|
||||
}
|
||||
|
||||
var cardIDs []uint
|
||||
database.DB.Model(&model.Card{}).Where("agent_id IN ?", agentIDs).Pluck("id", &cardIDs)
|
||||
|
||||
if len(cardIDs) == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
var count int64
|
||||
database.DB.Model(&model.RechargeRecord{}).
|
||||
Where("user_id = ? AND card_id IN ? AND status = ?", appUserID, cardIDs, "success").
|
||||
Count(&count)
|
||||
|
||||
return count > 0
|
||||
}
|
||||
|
||||
func handleGetUser(c *gin.Context) {
|
||||
userID := c.GetUint("user_id")
|
||||
id := c.Param("id")
|
||||
|
||||
var user model.AppUser
|
||||
if err := database.DB.Preload("Application").First(&user, id).Error; err != nil {
|
||||
response.Error(c, 404, "用户不存在")
|
||||
return
|
||||
}
|
||||
|
||||
if !checkAgentUserPermission(userID, user.ID) {
|
||||
response.Error(c, 403, "无权限查看该用户")
|
||||
return
|
||||
}
|
||||
|
||||
response.Success(c, gin.H{
|
||||
"user": user,
|
||||
})
|
||||
}
|
||||
|
||||
func handleUpdateUser(c *gin.Context) {
|
||||
userID := c.GetUint("user_id")
|
||||
id := c.Param("id")
|
||||
|
||||
var req struct {
|
||||
Username string `json:"username"`
|
||||
Email string `json:"email"`
|
||||
Password string `json:"password"`
|
||||
}
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
response.Error(c, 400, "参数错误")
|
||||
return
|
||||
}
|
||||
|
||||
var user model.AppUser
|
||||
if err := database.DB.First(&user, id).Error; err != nil {
|
||||
response.Error(c, 404, "用户不存在")
|
||||
return
|
||||
}
|
||||
|
||||
if !checkAgentUserPermission(userID, user.ID) {
|
||||
response.Error(c, 403, "无权限修改该用户")
|
||||
return
|
||||
}
|
||||
|
||||
if req.Username != "" {
|
||||
user.Username = req.Username
|
||||
}
|
||||
if req.Email != "" {
|
||||
user.Email = req.Email
|
||||
}
|
||||
if req.Password != "" {
|
||||
user.Password = req.Password
|
||||
}
|
||||
|
||||
if err := database.DB.Save(&user).Error; err != nil {
|
||||
response.Error(c, 500, "更新用户失败")
|
||||
return
|
||||
}
|
||||
|
||||
logDesc := fmt.Sprintf("代理更新用户: %s", user.Username)
|
||||
service.LogOperation(c, "update", "app_user", &user.ID, logDesc, nil)
|
||||
|
||||
response.Success(c, user)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user