We're in the process of migrating all of our rules into one place, with one format. Lets start by migrating merchant rules to use these new data formats and APIs
Data storage
- We have added a new onyx collection:
rules_<ruleID>
- Each rule has the following structure:
{
// For merchant rules, lets hard code this to 'policy'
"scope": "policy" | "account",
"scopeID": "<relevant ID based on the scope, so either the policyID, accountID, or domainAccountID>"
// The triggers for a rule are when the relevant rules run. There must always be 1 trigger, but there can be more. For now, lets just worry
// about CreateTransaction
"triggers": {
"0": "CreateTransaction",
},
// Filters follow the exact same AST format as search. They are infinitely extendable, however, for merchant rules, all we care about right now
// is the 'merchant' filter
"filters": {
"left": {
"left": "merchant",
"operator": "eq" | "neq" | "contains" | "notContains" | "gt" | "gte" | "lt" | "lte",
"right": ["Hello world"],
}
"operator": "and"
"right": {
"left": "category",
"operator": "eq" | "neq" | "contains" | "notContains" | "gt" | "gte" | "lt" | "lte",
"right": ["Hello world"],
},
// The actions that are taken on any expenses that match the filters object above
"actions": {
"0": { "name": "Set", "field": "billable", "value": true},
"1": { "name": "Set", "field": "merchant", "value": "modified merchant"},
"2": { "name": "Set", "field": "category", "value": "category"},
"3": { "name": "Set", "field": "tag", "value": "tag"},
"4": { "name": "Set", "field": "reimbursable", "value": true},
"5": { "name": "Set", "field": "vendorID", "value": "vendorid"},
"6": { "name": "Set", "field": "comment", "value": "mycomment"},
"7": { "name": "Set", "field": "tax", "value": { "field_id_TAX": {"externalID": "taxCode"}}},
}
}
When a user creates a merchant rule, we should modify the filters to meet the request of the user, and we should modify the actions to include the fields the user wants to set. The triggers should always be just CreateTransaction for now
API Commands
GetRules - Gets all of the rules that a user has access to. This command takes no params. We return the rules_ collection, which SETs the value.
Note: Any rule that has a CreateTransaction trigger, and at least one Set action is an Expense Default Rule. Lets use that to determine where the rule shows up
SetRule - Sets a new rule in the database
Params
scope - The scope of the rule. For merchant rules, this should be policy
scopeID - The ID for the scope of the rule. For merchant rules, this should be the policyID
ruleID - A random rand64() value for the ID of the rule
priority - This determines which order the rules should apply in. For expense defaults, lets hard code this to 10000
value - The value of the rule. This will be an object that looks like:
{
"filters": // ...
"triggers": //...
"actions": // ...
}
DeleteRule - Deletes a rule in the database
Params
ruleID - The ID of the rule
Issue Owner
Current Issue Owner: @Krishna2323
We're in the process of migrating all of our rules into one place, with one format. Lets start by migrating merchant rules to use these new data formats and APIs
Data storage
rules_<ruleID>{ // For merchant rules, lets hard code this to 'policy' "scope": "policy" | "account", "scopeID": "<relevant ID based on the scope, so either the policyID, accountID, or domainAccountID>" // The triggers for a rule are when the relevant rules run. There must always be 1 trigger, but there can be more. For now, lets just worry // about CreateTransaction "triggers": { "0": "CreateTransaction", }, // Filters follow the exact same AST format as search. They are infinitely extendable, however, for merchant rules, all we care about right now // is the 'merchant' filter "filters": { "left": { "left": "merchant", "operator": "eq" | "neq" | "contains" | "notContains" | "gt" | "gte" | "lt" | "lte", "right": ["Hello world"], } "operator": "and" "right": { "left": "category", "operator": "eq" | "neq" | "contains" | "notContains" | "gt" | "gte" | "lt" | "lte", "right": ["Hello world"], }, // The actions that are taken on any expenses that match the filters object above "actions": { "0": { "name": "Set", "field": "billable", "value": true}, "1": { "name": "Set", "field": "merchant", "value": "modified merchant"}, "2": { "name": "Set", "field": "category", "value": "category"}, "3": { "name": "Set", "field": "tag", "value": "tag"}, "4": { "name": "Set", "field": "reimbursable", "value": true}, "5": { "name": "Set", "field": "vendorID", "value": "vendorid"}, "6": { "name": "Set", "field": "comment", "value": "mycomment"}, "7": { "name": "Set", "field": "tax", "value": { "field_id_TAX": {"externalID": "taxCode"}}}, } }When a user creates a merchant rule, we should modify the
filtersto meet the request of the user, and we should modify theactionsto include the fields the user wants to set. Thetriggersshould always be justCreateTransactionfor nowAPI Commands
GetRules - Gets all of the rules that a user has access to. This command takes no params. We return the
rules_collection, whichSETs the value.Note: Any rule that has a
CreateTransactiontrigger, and at least oneSetaction is an Expense Default Rule. Lets use that to determine where the rule shows upSetRule - Sets a new rule in the database
Params
scope- The scope of the rule. For merchant rules, this should bepolicyscopeID- The ID for the scope of the rule. For merchant rules, this should be the policyIDruleID- A randomrand64()value for the ID of the rulepriority- This determines which order the rules should apply in. For expense defaults, lets hard code this to10000value- The value of the rule. This will be an object that looks like:DeleteRule - Deletes a rule in the database
Params
ruleID- The ID of the ruleIssue Owner
Current Issue Owner: @Krishna2323