mirror of
https://gitee.com/dromara/mayfly-go
synced 2025-11-02 23:40:24 +08:00
164 lines
5.0 KiB
Go
164 lines
5.0 KiB
Go
package application
|
|
|
|
import (
|
|
"context"
|
|
"mayfly-go/internal/flow/application/dto"
|
|
"mayfly-go/internal/flow/domain/entity"
|
|
"mayfly-go/internal/flow/domain/repository"
|
|
"mayfly-go/internal/flow/imsg"
|
|
msgapp "mayfly-go/internal/msg/application"
|
|
msgdto "mayfly-go/internal/msg/application/dto"
|
|
tagapp "mayfly-go/internal/tag/application"
|
|
tagentity "mayfly-go/internal/tag/domain/entity"
|
|
"mayfly-go/pkg/base"
|
|
"mayfly-go/pkg/errorx"
|
|
"mayfly-go/pkg/model"
|
|
"mayfly-go/pkg/utils/jsonx"
|
|
)
|
|
|
|
type Procdef interface {
|
|
base.App[*entity.Procdef]
|
|
|
|
GetPageList(condition *entity.Procdef, pageParam model.PageParam, orderBy ...string) (*model.PageResult[*entity.ProcdefPagePO], error)
|
|
|
|
// 保存流程实例信息
|
|
SaveProcdef(ctx context.Context, def *dto.SaveProcdef) error
|
|
|
|
// SaveFlowDef 保存流程定义流程信息
|
|
SaveFlowDef(ctx context.Context, def *dto.SaveFlowDef) error
|
|
|
|
// 删除流程实例信息
|
|
DeleteProcdef(ctx context.Context, defId uint64) error
|
|
|
|
// GetProcdefByCodePath 根据资源编号路径获取对应的流程定义
|
|
GetProcdefByCodePath(ctx context.Context, codePaths ...string) *entity.Procdef
|
|
|
|
// GetProcdefByResource 根据资源获取对应的流程定义
|
|
GetProcdefByResource(ctx context.Context, resourceType int8, resourceCode string) *entity.Procdef
|
|
}
|
|
|
|
type procdefAppImpl struct {
|
|
base.AppImpl[*entity.Procdef, repository.Procdef]
|
|
|
|
procinstApp Procinst `inject:"T"`
|
|
|
|
msgTmplBizApp msgapp.MsgTmplBiz `inject:"T"`
|
|
tagTreeApp tagapp.TagTree `inject:"T"`
|
|
tagTreeRelateApp tagapp.TagTreeRelate `inject:"T"`
|
|
}
|
|
|
|
var _ (Procdef) = (*procdefAppImpl)(nil)
|
|
|
|
func (p *procdefAppImpl) GetPageList(condition *entity.Procdef, pageParam model.PageParam, orderBy ...string) (*model.PageResult[*entity.ProcdefPagePO], error) {
|
|
return p.Repo.GetPageList(condition, pageParam, orderBy...)
|
|
}
|
|
|
|
func (p *procdefAppImpl) SaveProcdef(ctx context.Context, defParam *dto.SaveProcdef) error {
|
|
def := defParam.Procdef
|
|
if err := entity.ProcdefStatusEnum.Valid(def.Status); err != nil {
|
|
return err
|
|
}
|
|
|
|
if def.Id == 0 {
|
|
if p.GetByCond(&entity.Procdef{DefKey: def.DefKey}) == nil {
|
|
return errorx.NewBizI(ctx, imsg.ErrProcdefKeyExist)
|
|
}
|
|
} else {
|
|
// 防止误修改key
|
|
def.DefKey = ""
|
|
}
|
|
|
|
return p.Tx(ctx, func(ctx context.Context) error {
|
|
return p.Save(ctx, def)
|
|
}, func(ctx context.Context) error {
|
|
// 保存通知消息模板
|
|
if err := p.msgTmplBizApp.SaveBizTmpl(ctx, &msgdto.MsgTmplBizSave{
|
|
TmplId: defParam.MsgTmplId,
|
|
BizType: FlowTaskNotifyBizKey,
|
|
BizId: def.Id,
|
|
}); err != nil {
|
|
return err
|
|
}
|
|
return p.tagTreeRelateApp.RelateTag(ctx, tagentity.TagRelateTypeFlowDef, def.Id, defParam.CodePaths...)
|
|
})
|
|
}
|
|
|
|
func (p *procdefAppImpl) SaveFlowDef(ctx context.Context, def *dto.SaveFlowDef) error {
|
|
if err := validateFlowDef(ctx, def.FlowDef); err != nil {
|
|
return err
|
|
}
|
|
|
|
procdef := &entity.Procdef{
|
|
FlowDef: jsonx.ToStr(def.FlowDef),
|
|
}
|
|
procdef.Id = def.Id
|
|
return p.Save(ctx, procdef)
|
|
}
|
|
|
|
func (p *procdefAppImpl) DeleteProcdef(ctx context.Context, defId uint64) error {
|
|
if err := p.canModify(ctx, defId); err != nil {
|
|
return err
|
|
}
|
|
return p.DeleteById(ctx, defId)
|
|
}
|
|
|
|
func (p *procdefAppImpl) GetProcdefByCodePath(ctx context.Context, codePaths ...string) *entity.Procdef {
|
|
relateIds, err := p.tagTreeRelateApp.GetRelateIds(ctx, tagentity.TagRelateTypeFlowDef, codePaths...)
|
|
if err != nil || len(relateIds) == 0 {
|
|
return nil
|
|
}
|
|
|
|
procdefId := relateIds[len(relateIds)-1]
|
|
procdef, err := p.GetById(procdefId)
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
if procdef.Status == entity.ProcdefStatusDisable {
|
|
return nil
|
|
}
|
|
return procdef
|
|
}
|
|
|
|
func (p *procdefAppImpl) GetProcdefByResource(ctx context.Context, resourceType int8, resourceCode string) *entity.Procdef {
|
|
resourceCodePaths := p.tagTreeApp.ListTagPathByTypeAndCode(resourceType, resourceCode)
|
|
return p.GetProcdefByCodePath(ctx, resourceCodePaths...)
|
|
}
|
|
|
|
// 判断该流程实例是否可以执行修改操作
|
|
func (p *procdefAppImpl) canModify(ctx context.Context, prodefId uint64) error {
|
|
if activeInstCount := p.procinstApp.CountByCond(&entity.Procinst{ProcdefId: prodefId, Status: entity.ProcinstStatusActive}); activeInstCount > 0 {
|
|
return errorx.NewBizI(ctx, imsg.ErrExistProcinstRunning)
|
|
}
|
|
if suspInstCount := p.procinstApp.CountByCond(&entity.Procinst{ProcdefId: prodefId, Status: entity.ProcinstStatusSuspended}); suspInstCount > 0 {
|
|
return errorx.NewBizI(ctx, imsg.ErrExistProcinstSuspended)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// validateFlowDef 校验流程定义信息
|
|
func validateFlowDef(ctx context.Context, p *entity.FlowDef) error {
|
|
// 检查是否有开始节点
|
|
startNodes := p.GetNodeByType(FlowNodeTypeStart)
|
|
if len(startNodes) != 1 {
|
|
return errorx.NewBiz("not one start node")
|
|
}
|
|
|
|
// 检查是否有结束节点
|
|
endNodes := p.GetNodeByType(FlowNodeTypeEnd)
|
|
if len(endNodes) != 1 {
|
|
return errorx.NewBiz("not one end node")
|
|
}
|
|
|
|
// 校验节点自身逻辑
|
|
for _, node := range p.Nodes {
|
|
nh, _ := nodeBehaviorRegistry.GetNode(node.Type)
|
|
if nh != nil {
|
|
if err := nh.Validate(ctx, p, node); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|