92 lines
2.6 KiB
Go
92 lines
2.6 KiB
Go
package logic
|
||
|
||
import (
|
||
"context"
|
||
"errors"
|
||
"fmt"
|
||
|
||
"godemo/category/category"
|
||
"godemo/category/internal/model"
|
||
"godemo/category/internal/svc"
|
||
|
||
"github.com/zeromicro/go-zero/core/logx"
|
||
"github.com/zeromicro/go-zero/core/stores/sqlx"
|
||
"google.golang.org/grpc/codes"
|
||
"google.golang.org/grpc/status"
|
||
)
|
||
|
||
type DeleteCategoryLogic struct {
|
||
ctx context.Context
|
||
svcCtx *svc.ServiceContext
|
||
logx.Logger
|
||
}
|
||
|
||
func NewDeleteCategoryLogic(ctx context.Context, svcCtx *svc.ServiceContext) *DeleteCategoryLogic {
|
||
return &DeleteCategoryLogic{
|
||
ctx: ctx,
|
||
svcCtx: svcCtx,
|
||
Logger: logx.WithContext(ctx),
|
||
}
|
||
}
|
||
|
||
func (l *DeleteCategoryLogic) DeleteCategory(in *category.DeleteCategoryRequest) (*category.DeleteResponse, error) {
|
||
// 1. 参数校验
|
||
if in.Id == "" {
|
||
return nil, status.Error(codes.InvalidArgument, "分类ID不能为空")
|
||
}
|
||
|
||
// 2. 检查分类是否存在
|
||
_, err := l.svcCtx.CategoryModel.FindOne(l.ctx, in.Id)
|
||
if err != nil {
|
||
if errors.Is(err, model.ErrNotFound) {
|
||
return nil, status.Error(codes.NotFound, "分类不存在")
|
||
}
|
||
l.Logger.Errorf("查询分类失败: %v", err)
|
||
return nil, status.Error(codes.Internal, "内部错误")
|
||
}
|
||
|
||
// 3. 开启事务执行删除
|
||
err = l.svcCtx.CategoryModel.Transact(l.ctx, func(ctx context.Context, session sqlx.Session) error {
|
||
// 3.1 处理子分类(根据外键约束自动级联删除或设为NULL)
|
||
if err := l.handleChildren(ctx, session, in.Id); err != nil {
|
||
return err
|
||
}
|
||
|
||
// 3.2 删除主分类
|
||
if err := l.svcCtx.CategoryModel.WithSession(session).Delete(ctx, in.Id); err != nil {
|
||
return fmt.Errorf("删除分类失败: %w", err)
|
||
}
|
||
|
||
return nil
|
||
})
|
||
|
||
if err != nil {
|
||
l.Logger.Errorf("删除分类事务失败: %v", err)
|
||
return nil, status.Error(codes.Internal, "删除分类失败")
|
||
}
|
||
|
||
return &category.DeleteResponse{
|
||
Success: true,
|
||
}, nil
|
||
}
|
||
|
||
// handleChildren 处理子分类(根据外键约束配置决定行为)
|
||
func (l *DeleteCategoryLogic) handleChildren(ctx context.Context, session sqlx.Session, parentID string) error {
|
||
// 如果外键是 ON DELETE SET NULL,需要显式更新子分类
|
||
if l.needUpdateChildren() {
|
||
query := "UPDATE categories SET parent_id = NULL WHERE parent_id = $1"
|
||
if _, err := session.ExecCtx(ctx, query, parentID); err != nil {
|
||
return fmt.Errorf("更新子分类失败: %w", err)
|
||
}
|
||
}
|
||
// 如果是 ON DELETE CASCADE 则无需额外处理
|
||
return nil
|
||
}
|
||
|
||
// needUpdateChildren 根据配置决定是否需要更新子分类
|
||
func (l *DeleteCategoryLogic) needUpdateChildren() bool {
|
||
// 这里根据实际数据库外键约束配置返回
|
||
// 可以在 config 中添加配置项控制行为
|
||
return false // 默认假设是 ON DELETE CASCADE
|
||
}
|