package flow_definition import ( "approveflow/app/provider/abstract/connect" "context" "fmt" "github.com/Superdanda/hade/framework" "github.com/Superdanda/hade/framework/contract" "github.com/pkg/errors" ) type FlowDefinitionService struct { container framework.Container } func (f *FlowDefinitionService) CreateFlow(ctx context.Context, flow *ApprovalFlow) error { return f.GetFlowRepository().SaveFlow(ctx, flow) } func (f *FlowDefinitionService) GetFlow(ctx context.Context, flowID int64) (*ApprovalFlow, error) { return f.GetFlowRepository().GetFlowByID(ctx, flowID) } func (f *FlowDefinitionService) GetFlowPage(ctx context.Context, pageNum, pageSize int, flow *ApprovalFlow) ([]*ApprovalFlow, int64, error) { return f.GetFlowRepository().ListFlows(ctx, pageNum, pageSize, flow) } func (f *FlowDefinitionService) UpdateFlow(ctx context.Context, flow *ApprovalFlow) error { return f.GetFlowRepository().SaveFlow(ctx, flow) } func (f *FlowDefinitionService) DeleteFlow(ctx context.Context, flowID int64) error { flowById, err := f.GetFlowRepository().GetFlowByID(ctx, flowID) if err != nil { return err } flowById.Delete() return f.GetFlowRepository().SaveFlow(ctx, flowById) } func (f *FlowDefinitionService) AddStepWithPosition(ctx context.Context, flowID int64, step *ApprovalStep, fromStepId string, toStepKey string) error { return f.handlerFlow(ctx, flowID, func(ctx context.Context, flow *ApprovalFlow) error { fromStep, err := flow.GetStepByKey(fromStepId) toStep, err := flow.GetStepByKey(toStepKey) if err != nil { return err } err = connect.InsertNodeBetween(flow, fromStep, toStep, step) return err }) } func (f *FlowDefinitionService) AddStep(ctx context.Context, flowID int64, step *ApprovalStep) error { flowById, err := f.GetFlowRepository().GetFlowByID(ctx, flowID) if err != nil { return err } err = flowById.AddStep(step) if err != nil { return err } return f.GetFlowRepository().SaveFlow(ctx, flowById) } func (f *FlowDefinitionService) GetSteps(ctx context.Context, flowID int64) ([]*ApprovalStep, error) { flowById, err := f.GetFlowRepository().GetFlowByID(ctx, flowID) if err != nil { return nil, err } return flowById.Steps, nil } func (f *FlowDefinitionService) UpdateStep(ctx context.Context, flowID int64, step *ApprovalStep) error { flowById, err := f.GetFlowRepository().GetFlowByID(ctx, flowID) if err != nil { return err } steps := flowById.Steps for index, stepExist := range steps { if stepExist.ID == step.ID { steps[index] = step } } return nil } func (f *FlowDefinitionService) DeleteStep(ctx context.Context, flowID int64, stepID int64) error { return f.handlerStep(ctx, flowID, stepID, func(ctx context.Context, flow *ApprovalFlow, step *ApprovalStep) error { step.Delete() return nil }) } func (f *FlowDefinitionService) AddRule(ctx context.Context, flowID int64, stepID int64, rule *ApprovalRule) error { return f.handlerStep(ctx, flowID, stepID, func(ctx context.Context, flow *ApprovalFlow, step *ApprovalStep) error { step.Rules = append(step.Rules, rule) return nil }) } func (f *FlowDefinitionService) GetRules(ctx context.Context, flowID int64, stepID int64) ([]*ApprovalRule, error) { _, id, err := f.findStepByStepId(ctx, flowID, stepID) if err != nil { return nil, err } return id.Rules, nil } func (f *FlowDefinitionService) UpdateRule(ctx context.Context, flowID int64, stepID int64, rule *ApprovalRule) error { return f.handlerStep(ctx, flowID, stepID, func(ctx context.Context, flow *ApprovalFlow, step *ApprovalStep) error { existingRule, err := step.GetRuleById(rule.ID) if err != nil { return err } // Update the fields of the existing rule existingRule.Name = rule.Name existingRule.Action = rule.Action existingRule.Priority = rule.Priority existingRule.ConditionExpression = rule.ConditionExpression return nil }) } func (f *FlowDefinitionService) DeleteRule(ctx context.Context, flowID int64, stepID int64, ruleID int64) error { return f.handlerStep(ctx, flowID, stepID, func(ctx context.Context, flow *ApprovalFlow, step *ApprovalStep) error { rule, err := step.GetRuleById(ruleID) if err != nil { return err } rule.Delete() return nil }) } func (f *FlowDefinitionService) AddDynamicStepConfig(ctx context.Context, flowID int64, stepID int64, config *DynamicApprovalStepConfig) error { return f.handlerStep(ctx, flowID, stepID, func(ctx context.Context, flow *ApprovalFlow, step *ApprovalStep) error { step.AddDynamicConfig(config) return nil }) } func (f *FlowDefinitionService) GetDynamicStepConfigs(ctx context.Context, flowID int64) ([]*DynamicApprovalStepConfig, error) { // Retrieve dynamic configurations for the flow flowByID, err := f.GetFlowRepository().GetFlowByID(ctx, flowID) if err != nil { return nil, err } configs := make([]*DynamicApprovalStepConfig, 0, len(flowByID.Steps)) for _, step := range flowByID.Steps { configs = append(configs, step.DynamicConfig) } return configs, nil } func (f *FlowDefinitionService) UpdateDynamicStepConfig(ctx context.Context, flowID int64, stepID int64, config *DynamicApprovalStepConfig) error { return f.handlerStep(ctx, flowID, stepID, func(ctx context.Context, flow *ApprovalFlow, step *ApprovalStep) error { dynamicConfig := step.DynamicConfig // Update the fields of the existing dynamicConfig dynamicConfig.Name = config.Name dynamicConfig.Action = config.Action dynamicConfig.Priority = config.Priority dynamicConfig.ConditionExpression = config.ConditionExpression return nil }) } func (f *FlowDefinitionService) DeleteDynamicStepConfig(ctx context.Context, flowID int64, stepID int64) error { return f.handlerStep(ctx, flowID, stepID, func(ctx context.Context, flow *ApprovalFlow, step *ApprovalStep) error { step.DynamicConfig.Delete() return nil }) } func (f *FlowDefinitionService) AddPathConfig(ctx context.Context, flowID int64, stepID int64, config *ApprovalPathConfig) error { return f.handlerStep(ctx, flowID, stepID, func(ctx context.Context, flow *ApprovalFlow, step *ApprovalStep) error { return step.AddPathConfig(config) }) } func (f *FlowDefinitionService) GetPathConfigs(ctx context.Context, flowID int64) ([]*ApprovalPathConfig, error) { // Retrieve dynamic configurations for the flow flowByID, err := f.GetFlowRepository().GetFlowByID(ctx, flowID) if err != nil { return nil, err } // Extract PathConfigs from each step in the flow var configs []*ApprovalPathConfig for _, step := range flowByID.Steps { configs = append(configs, step.PathConfigs...) } return configs, nil } func (f *FlowDefinitionService) UpdatePathConfig(ctx context.Context, flowID int64, stepID int64, config *ApprovalPathConfig) error { return f.handlerStep(ctx, flowID, stepID, func(ctx context.Context, flow *ApprovalFlow, step *ApprovalStep) error { pathById, err := step.GetPathById(config.ID) if err != nil { return err } pathById.ToNodeKey = config.ToNodeKey pathById.IsParallel = config.IsParallel pathById.ConditionExpression = config.ConditionExpression return nil }) } func (f *FlowDefinitionService) DeletePathConfig(ctx context.Context, flowID int64, stepID int64, pathID int64) error { return f.handlerStep(ctx, flowID, stepID, func(ctx context.Context, flow *ApprovalFlow, step *ApprovalStep) error { pathById, err := step.GetPathById(pathID) if err != nil { return err } pathById.Delete() return nil }) } func (f *FlowDefinitionService) handlerStep( ctx context.Context, flowID int64, stepID int64, handler func(ctx context.Context, flow *ApprovalFlow, step *ApprovalStep) error, ) error { flowById, step, err := f.findStepByStepId(ctx, flowID, stepID) if err != nil { return err } if step == nil { return fmt.Errorf("step with ID %d not found in flow %d", stepID, flowID) } err = handler(ctx, flowById, step) if err != nil { return err } return f.GetFlowRepository().SaveFlow(ctx, flowById) } func (f *FlowDefinitionService) handlerFlow(ctx context.Context, flowID int64, handler func(ctx context.Context, flow *ApprovalFlow) error, ) error { flowById, err := f.GetFlowRepository().GetFlowByID(ctx, flowID) if err != nil { return err } err = handler(ctx, flowById) if err != nil { return err } return f.GetFlowRepository().SaveFlow(ctx, flowById) } func (f *FlowDefinitionService) findStepByStepId(ctx context.Context, flowID int64, stepID int64) (*ApprovalFlow, *ApprovalStep, error) { // Retrieve the flow to confirm it exists flowByID, err := f.GetFlowRepository().GetFlowByID(ctx, flowID) if err != nil { return nil, nil, err } var step *ApprovalStep for _, s := range flowByID.Steps { if s.ID == stepID { step = s break } } if step == nil { return nil, nil, errors.New("step not found") } return flowByID, step, nil } func NewFlowDefinitionService(params ...interface{}) (interface{}, error) { container := params[0].(framework.Container) return &FlowDefinitionService{container: container}, nil } func (f *FlowDefinitionService) GetFlowRepository() FlowRepository { infrastructureService := f.container.MustMake(contract.InfrastructureKey).(contract.InfrastructureService) return infrastructureService.GetModuleOrmRepository(FlowRepositoryKey).(FlowRepository) }