package ec import ( "git.apinb.com/bsm-sdk/core/errcode" "git.apinb.com/bsm-sdk/core/infra" "git.apinb.com/heqiapp/platforms/backend/api/internal/impl" "git.apinb.com/heqiapp/platforms/backend/api/internal/logic/common" "git.apinb.com/heqiapp/platforms/backend/api/internal/models" "github.com/gin-gonic/gin" ) type categoryRequest struct { ParentIdentity string `json:"parent_identity"` Name string `json:"name" binding:"required,max=128"` SortNo int `json:"sort_no"` } type ecCategoryView struct { Identity string `json:"identity"` ParentIdentity string `json:"parent_identity,omitempty"` Name string `json:"name"` SortNo int `json:"sort_no"` Status int `json:"status"` } func ecCategoryViews(list []models.EcCategory) ([]ecCategoryView, error) { parents := make(map[uint64]string) for _, item := range list { if item.ParentID != 0 { parents[item.ParentID] = "" } } if len(parents) > 0 { var rows []struct { ID uint64 Identity string } ids := make([]uint64, 0, len(parents)) for id := range parents { ids = append(ids, id) } if err := impl.DBService.Model(&models.EcCategory{}).Select("id", "identity").Where("id IN ?", ids).Find(&rows).Error; err != nil { return nil, err } for _, row := range rows { parents[row.ID] = row.Identity } } views := make([]ecCategoryView, 0, len(list)) for _, item := range list { views = append(views, ecCategoryView{Identity: item.Identity, ParentIdentity: parents[item.ParentID], Name: item.Name, SortNo: item.SortNo, Status: item.Status}) } return views, nil } func ListEcCategory(ctx *gin.Context) { page, size := common.PageSize(ctx) var list []models.EcCategory var total int64 query := common.ActiveRecords(impl.DBService.Model(&models.EcCategory{})) if err := query.Count(&total).Error; err != nil { infra.Response.Error(ctx, err) return } if err := query.Order("sort_no asc, id asc").Offset((page - 1) * size).Limit(size).Find(&list).Error; err != nil { infra.Response.Error(ctx, err) return } views, err := ecCategoryViews(list) if err != nil { infra.Response.Error(ctx, err) return } infra.Response.Success(ctx, gin.H{"total": total, "list": views}) } func GetEcCategory(ctx *gin.Context) { var category models.EcCategory if err := common.ActiveRecords(impl.DBService).Where("identity = ?", ctx.Param("identity")).First(&category).Error; err != nil { common.RespondRecordError(ctx, err) return } views, err := ecCategoryViews([]models.EcCategory{category}) if err != nil { infra.Response.Error(ctx, err) return } infra.Response.Success(ctx, views[0]) } func CreateEcCategory(ctx *gin.Context) { var request categoryRequest if err := ctx.ShouldBindJSON(&request); err != nil { infra.Response.Error(ctx, errcode.ErrInvalidArgument) return } parentID, err := common.ResolveIdentityID(&models.EcCategory{}, request.ParentIdentity, false) if err != nil { infra.Response.Error(ctx, errcode.ErrInvalidArgument) return } category := models.EcCategory{Entity: common.NewEntity(common.StatusDraft), ParentID: parentID, Name: request.Name, SortNo: request.SortNo} if err := impl.DBService.Create(&category).Error; err != nil { infra.Response.Error(ctx, err) return } common.RespondCreatedResource(ctx, category) } func UpdateEcCategory(ctx *gin.Context) { var request categoryRequest if err := ctx.ShouldBindJSON(&request); err != nil { infra.Response.Error(ctx, errcode.ErrInvalidArgument) return } var category models.EcCategory if err := common.ActiveRecords(impl.DBService).Where("identity = ?", ctx.Param("identity")).First(&category).Error; err != nil { common.RespondRecordError(ctx, err) return } parentID, err := common.ResolveIdentityID(&models.EcCategory{}, request.ParentIdentity, false) if err != nil { infra.Response.Error(ctx, errcode.ErrInvalidArgument) return } var rows []models.EcCategory if err := impl.DBService.Select("id", "parent_id").Find(&rows).Error; err != nil { infra.Response.Error(ctx, err) return } parents := make(map[uint64]uint64, len(rows)) for _, row := range rows { parents[row.ID] = row.ParentID } if wouldCreateCategoryCycle(category.ID, parentID, parents) { infra.Response.Error(ctx, errcode.ErrInvalidArgument) return } common.UpdateAllowedByIdentity(ctx, &models.EcCategory{}, gin.H{"parent_id": parentID, "name": request.Name, "sort_no": request.SortNo}, []string{"parent_id", "name", "sort_no"}) } func wouldCreateCategoryCycle(categoryID, parentID uint64, parents map[uint64]uint64) bool { seen := map[uint64]bool{} for parentID != 0 { if parentID == categoryID || seen[parentID] { return true } seen[parentID] = true parentID = parents[parentID] } return false }