90 lines
2.6 KiB
Go
90 lines
2.6 KiB
Go
package run
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
|
|
"git.iwork-ai.com/xdc/iqudo-top1/internal/model"
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
func deriveForScenario(db *gorm.DB, tenantID, scenarioID uint64, input map[string]interface{}) (map[string]interface{}, []string, error) {
|
|
rules := make([]model.ScenarioRule, 0)
|
|
if err := db.Where("tenant_id = ? AND scenario_id = ? AND status = ?", tenantID, scenarioID, "active").Order("priority, id").Find(&rules).Error; err != nil {
|
|
return nil, nil, err
|
|
}
|
|
return applyScenarioRules(rules, input)
|
|
}
|
|
|
|
type ruleAction struct {
|
|
Operation string `json:"operation"`
|
|
Field string `json:"field"`
|
|
Value interface{} `json:"value"`
|
|
ValueFrom string `json:"value_from"`
|
|
}
|
|
|
|
func applyScenarioRules(rules []model.ScenarioRule, input map[string]interface{}) (map[string]interface{}, []string, error) {
|
|
derived := map[string]interface{}{}
|
|
matched := make([]string, 0)
|
|
context := runtimeContext(input, derived, nil)
|
|
for _, rule := range rules {
|
|
ok, err := matchCondition(json.RawMessage(rule.Condition), context)
|
|
if err != nil {
|
|
return nil, nil, fmt.Errorf("规则 %s 条件不正确: %w", rule.RuleKey, err)
|
|
}
|
|
if !ok {
|
|
continue
|
|
}
|
|
var actions []ruleAction
|
|
if err := json.Unmarshal(rule.Actions, &actions); err != nil {
|
|
return nil, nil, fmt.Errorf("规则 %s 动作不正确", rule.RuleKey)
|
|
}
|
|
for _, action := range actions {
|
|
resolvedValues := []interface{}{action.Value}
|
|
valueFromList := false
|
|
if action.ValueFrom != "" {
|
|
resolved, exists := lookupContextValue(context, action.ValueFrom)
|
|
if !exists {
|
|
continue
|
|
}
|
|
if list, ok := resolved.([]interface{}); ok {
|
|
resolvedValues = list
|
|
valueFromList = true
|
|
} else {
|
|
resolvedValues = []interface{}{resolved}
|
|
}
|
|
}
|
|
switch action.Operation {
|
|
case "set":
|
|
if valueFromList {
|
|
derived[action.Field] = resolvedValues
|
|
} else if len(resolvedValues) == 1 {
|
|
derived[action.Field] = resolvedValues[0]
|
|
} else {
|
|
derived[action.Field] = resolvedValues
|
|
}
|
|
case "append":
|
|
targetValues, _ := derived[action.Field].([]interface{})
|
|
for _, value := range resolvedValues {
|
|
duplicate := false
|
|
for _, existing := range targetValues {
|
|
if fmt.Sprint(existing) == fmt.Sprint(value) {
|
|
duplicate = true
|
|
break
|
|
}
|
|
}
|
|
if !duplicate {
|
|
targetValues = append(targetValues, value)
|
|
}
|
|
}
|
|
derived[action.Field] = targetValues
|
|
default:
|
|
return nil, nil, fmt.Errorf("规则 %s 使用了不支持的动作", rule.RuleKey)
|
|
}
|
|
}
|
|
matched = append(matched, rule.RuleKey)
|
|
context = runtimeContext(input, derived, nil)
|
|
}
|
|
return derived, matched, nil
|
|
}
|