strategy

package
v0.32.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 30, 2026 License: Apache-2.0 Imports: 10 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	// Assignee resolver errors.
	ErrAssigneeServiceNil        = errors.New("assignee service is nil")
	ErrApplicantIDEmpty          = errors.New("applicant ID is empty")
	ErrFormFieldNameEmpty        = errors.New("form field name is empty")
	ErrUnsupportedFieldValueType = errors.New("unsupported form field value type")
	ErrAssigneeResolverNotFound  = errors.New("assignee resolver not found")

	// Registry lookup errors.
	ErrPassRuleNotFound           = errors.New("pass rule strategy not found")
	ErrConditionEvaluatorNotFound = errors.New("condition evaluator not found")

	// Condition evaluation errors.
	ErrExpressionReturnedNonBool = errors.New("expression returned non-bool type")
	ErrUnsupportedOperator       = errors.New("unsupported condition operator")
	ErrIncomparableValues        = errors.New("condition values are not comparable")
)
View Source
var Module = fx.Module(
	"vef:approval:strategy",

	fx.Provide(

		fx.Annotate(NewAllPassStrategy, fx.ResultTags(`group:"vef:approval:pass_rule_strategies"`)),
		fx.Annotate(NewOnePassStrategy, fx.ResultTags(`group:"vef:approval:pass_rule_strategies"`)),
		fx.Annotate(NewRatioPassStrategy, fx.ResultTags(`group:"vef:approval:pass_rule_strategies"`)),

		fx.Annotate(NewUserAssigneeResolver, fx.ResultTags(`group:"vef:approval:assignee_resolvers"`)),
		fx.Annotate(NewRoleAssigneeResolver, fx.ResultTags(`group:"vef:approval:assignee_resolvers"`)),
		fx.Annotate(NewDepartmentAssigneeResolver, fx.ResultTags(`group:"vef:approval:assignee_resolvers"`)),
		fx.Annotate(NewSelfAssigneeResolver, fx.ResultTags(`group:"vef:approval:assignee_resolvers"`)),
		fx.Annotate(NewSuperiorAssigneeResolver, fx.ResultTags(`group:"vef:approval:assignee_resolvers"`)),
		fx.Annotate(NewDepartmentLeaderAssigneeResolver, fx.ResultTags(`group:"vef:approval:assignee_resolvers"`)),
		fx.Annotate(NewFormFieldAssigneeResolver, fx.ResultTags(`group:"vef:approval:assignee_resolvers"`)),

		fx.Annotate(NewFieldConditionEvaluator, fx.ResultTags(`group:"vef:approval:condition_evaluators"`)),
		fx.Annotate(NewExpressionConditionEvaluator, fx.ResultTags(`group:"vef:approval:condition_evaluators"`)),

		fx.Annotate(
			NewStrategyRegistry,
			fx.ParamTags(
				`group:"vef:approval:pass_rule_strategies"`,
				`group:"vef:approval:assignee_resolvers"`,
				`group:"vef:approval:condition_evaluators"`,
			),
		),
	),

	fx.Invoke(func(r *StrategyRegistry) error { return r.ValidateBuiltins() }),
)

Module provides built-in strategies with FX group extensibility.

Functions

func NewAllPassStrategy

func NewAllPassStrategy() approval.PassRuleStrategy

NewAllPassStrategy creates a new AllPassStrategy.

func NewExpressionConditionEvaluator

func NewExpressionConditionEvaluator(engine expression.Engine) approval.ConditionEvaluator

NewExpressionConditionEvaluator creates the evaluator for free-form expression conditions backed by the framework expression engine.

func NewFieldConditionEvaluator

func NewFieldConditionEvaluator() approval.ConditionEvaluator

NewFieldConditionEvaluator creates the evaluator for structured field conditions.

func NewOnePassStrategy

func NewOnePassStrategy() approval.PassRuleStrategy

NewOnePassStrategy creates a new OnePassStrategy.

func NewRatioPassStrategy

func NewRatioPassStrategy() approval.PassRuleStrategy

NewRatioPassStrategy creates a new RatioPassStrategy.

Types

type AllPassStrategy

type AllPassStrategy struct{}

AllPassStrategy requires all assignees to approve; any single rejection fails the node, so "everyone must agree" and "one veto rejects" are the same rule under this strategy.

func (*AllPassStrategy) Evaluate

func (*AllPassStrategy) Rule

type AssigneeResolver

type AssigneeResolver interface {
	// Kind returns the assignee kind this resolver handles (user, role, department_leader, superior, etc.).
	Kind() approval.AssigneeKind
	// Resolve resolves concrete assignees from the assignee configuration in ResolveContext.
	Resolve(ctx context.Context, rc *ResolveContext) ([]approval.ResolvedAssignee, error)
}

AssigneeResolver resolves assignees for a specific kind.

func NewDepartmentAssigneeResolver added in v0.20.1

func NewDepartmentAssigneeResolver(svc approval.AssigneeService) AssigneeResolver

NewDepartmentAssigneeResolver creates a new DepartmentAssigneeResolver.

func NewDepartmentLeaderAssigneeResolver added in v0.20.1

func NewDepartmentLeaderAssigneeResolver(svc approval.AssigneeService) AssigneeResolver

NewDepartmentLeaderAssigneeResolver creates a new DepartmentLeaderAssigneeResolver.

func NewFormFieldAssigneeResolver

func NewFormFieldAssigneeResolver() AssigneeResolver

NewFormFieldAssigneeResolver creates a new FormFieldAssigneeResolver.

func NewRoleAssigneeResolver

func NewRoleAssigneeResolver(svc approval.AssigneeService) AssigneeResolver

NewRoleAssigneeResolver creates a new RoleAssigneeResolver.

func NewSelfAssigneeResolver

func NewSelfAssigneeResolver() AssigneeResolver

NewSelfAssigneeResolver creates a new SelfAssigneeResolver.

func NewSuperiorAssigneeResolver

func NewSuperiorAssigneeResolver(svc approval.AssigneeService) AssigneeResolver

NewSuperiorAssigneeResolver creates a new SuperiorAssigneeResolver.

func NewUserAssigneeResolver

func NewUserAssigneeResolver() AssigneeResolver

NewUserAssigneeResolver creates a new UserAssigneeResolver.

type CompositeAssigneeResolver

type CompositeAssigneeResolver struct {
	// contains filtered or unexported fields
}

CompositeAssigneeResolver chains multiple resolvers and resolves assignees based on config kind.

func NewCompositeAssigneeResolver

func NewCompositeAssigneeResolver(resolvers ...AssigneeResolver) *CompositeAssigneeResolver

NewCompositeAssigneeResolver creates a composite resolver from individual resolvers.

func (*CompositeAssigneeResolver) ResolveAll

ResolveAll resolves assignees from multiple configs.

type DepartmentAssigneeResolver added in v0.20.1

type DepartmentAssigneeResolver struct {
	// contains filtered or unexported fields
}

DepartmentAssigneeResolver resolves the leaders of the configured department IDs (rc.IDs) as assignees.

func (*DepartmentAssigneeResolver) Kind added in v0.20.1

func (*DepartmentAssigneeResolver) Resolve added in v0.20.1

type DepartmentLeaderAssigneeResolver added in v0.20.1

type DepartmentLeaderAssigneeResolver struct {
	// contains filtered or unexported fields
}

DepartmentLeaderAssigneeResolver resolves the leaders of the applicant's own department as assignees. This is a single-level lookup (GetDepartmentLeaders); it does not walk a multi-level supervisor chain.

func (*DepartmentLeaderAssigneeResolver) Kind added in v0.20.1

func (*DepartmentLeaderAssigneeResolver) Resolve added in v0.20.1

type ExpressionConditionEvaluator

type ExpressionConditionEvaluator struct {
	// contains filtered or unexported fields
}

ExpressionConditionEvaluator evaluates expression conditions through the framework's expression.Engine abstraction, so approval depends on the engine contract rather than any concrete backend. The expression reads a fixed environment: formData (the instance form), applicantId, and applicantDepartmentId.

func (*ExpressionConditionEvaluator) Evaluate

func (*ExpressionConditionEvaluator) Kind

type FieldConditionEvaluator

type FieldConditionEvaluator struct{}

FieldConditionEvaluator evaluates structured field conditions natively in Go. Field conditions are data, not code: comparing them directly keeps the operator semantics typed per field kind (no string templating, no injection surface, no expression-engine round-trip) and guarantees the operator set stays in lockstep with the approval.ConditionOperator contract — adding an operator there without handling it here fails loudly at evaluation.

func (*FieldConditionEvaluator) Evaluate

func (*FieldConditionEvaluator) Kind

type FormFieldAssigneeResolver

type FormFieldAssigneeResolver struct{}

FormFieldAssigneeResolver resolves assignees from a form field value.

func (*FormFieldAssigneeResolver) Kind

func (*FormFieldAssigneeResolver) Resolve

type OnePassStrategy

type OnePassStrategy struct{}

OnePassStrategy passes when at least one assignee approves.

func (*OnePassStrategy) Evaluate

func (*OnePassStrategy) Rule

type RatioPassStrategy

type RatioPassStrategy struct{}

RatioPassStrategy passes when approval ratio meets threshold.

func (*RatioPassStrategy) Evaluate

func (*RatioPassStrategy) Rule

type ResolveContext

type ResolveContext struct {
	ApplicantID           string
	ApplicantName         string
	ApplicantDepartmentID *string
	FormData              approval.FormData
	UserResolver          approval.UserInfoResolver

	IDs       []string
	FormField *string
}

ResolveContext provides context for assignee resolution.

type RoleAssigneeResolver

type RoleAssigneeResolver struct {
	// contains filtered or unexported fields
}

RoleAssigneeResolver resolves assignees from role IDs via AssigneeService.

func (*RoleAssigneeResolver) Kind

func (*RoleAssigneeResolver) Resolve

type SelfAssigneeResolver

type SelfAssigneeResolver struct{}

SelfAssigneeResolver resolves the applicant as assignee.

func (*SelfAssigneeResolver) Kind

func (*SelfAssigneeResolver) Resolve

type StrategyRegistry

type StrategyRegistry struct {
	// contains filtered or unexported fields
}

StrategyRegistry holds all strategy implementations indexed by their type.

func NewStrategyRegistry

func NewStrategyRegistry(
	passRules []approval.PassRuleStrategy,
	assignees []AssigneeResolver,
	conditions []approval.ConditionEvaluator,
) *StrategyRegistry

NewStrategyRegistry creates a registry from slices (designed for FX group injection). It does not validate completeness on construction so test suites can build registries with partial strategy sets. Production modules call ValidateBuiltins via fx.Invoke after construction.

func (*StrategyRegistry) CompositeAssigneeResolver

func (r *StrategyRegistry) CompositeAssigneeResolver() *CompositeAssigneeResolver

CompositeAssigneeResolver returns the cached CompositeAssigneeResolver.

func (*StrategyRegistry) GetConditionEvaluator

GetConditionEvaluator returns the condition evaluator for the given type.

func (*StrategyRegistry) GetPassRuleStrategy

func (r *StrategyRegistry) GetPassRuleStrategy(rule approval.PassRule) (approval.PassRuleStrategy, error)

GetPassRuleStrategy returns the pass rule strategy for the given rule.

func (*StrategyRegistry) ValidateBuiltins added in v0.24.0

func (r *StrategyRegistry) ValidateBuiltins() error

ValidateBuiltins asserts that every built-in enum value the framework guarantees has a registered strategy. The production strategy.Module invokes this during boot so misconfigurations surface immediately rather than as a runtime "strategy not found" error deep inside a flow.

type SuperiorAssigneeResolver

type SuperiorAssigneeResolver struct {
	// contains filtered or unexported fields
}

SuperiorAssigneeResolver resolves the direct superior as assignee.

func (*SuperiorAssigneeResolver) Kind

func (*SuperiorAssigneeResolver) Resolve

type UserAssigneeResolver

type UserAssigneeResolver struct{}

UserAssigneeResolver resolves assignees from fixed user IDs.

func (*UserAssigneeResolver) Kind

func (*UserAssigneeResolver) Resolve

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL