1
0
Fork 0
mirror of https://github.com/maybe-finance/maybe.git synced 2025-08-10 07:55:21 +02:00

Log data enrichments, only apply rules to unlocked attributes

This commit is contained in:
Zach Gollwitzer 2025-04-12 22:11:24 -04:00
parent 77b914150f
commit e8fb2a5d02
8 changed files with 49 additions and 14 deletions

View file

@ -1,3 +1,5 @@
class DataEnrichment < ApplicationRecord
belongs_to :enrichable, polymorphic: true
enum :source, { rule: "rule", plaid: "plaid", synth: "synth" }
end

View file

@ -3,8 +3,8 @@ class Rule::Action < ApplicationRecord
validates :action_type, presence: true
def apply(resource_scope)
executor.execute(resource_scope, value)
def apply(resource_scope, ignore_attribute_locks: false)
executor.execute(resource_scope, value: value, ignore_attribute_locks: ignore_attribute_locks)
end
def options

View file

@ -21,7 +21,7 @@ class Rule::ActionExecutor
nil
end
def execute(scope, value = nil)
def execute(scope, value: nil, ignore_attribute_locks: false)
raise NotImplementedError, "Action executor #{self.class.name} must implement #execute"
end

View file

@ -1,5 +1,5 @@
class Rule::ActionExecutor::AiAutoCategorize < Rule::ActionExecutor
def execute(transaction_scope, value = nil)
def execute(transaction_scope, value: nil, ignore_attribute_locks: false)
# TODO
end
end

View file

@ -1,5 +1,5 @@
class Rule::ActionExecutor::AiEnhanceTransactionName < Rule::ActionExecutor
def execute(transaction_scope, value = nil)
def execute(transaction_scope, value: nil, ignore_attribute_locks: false)
# TODO
end
end

View file

@ -7,12 +7,27 @@ class Rule::ActionExecutor::SetTransactionCategory < Rule::ActionExecutor
family.categories.pluck(:name, :id)
end
def execute(transaction_scope, value = nil)
def execute(transaction_scope, value: nil, ignore_attribute_locks: false)
category = family.categories.find_by_id(value)
transaction_scope.attributes_unlocked(:category_id).update_all(
category_id: category.id,
updated_at: Time.current
)
scope = transaction_scope
unless ignore_attribute_locks
scope = scope.enrichable(:category_id)
end
scope.each do |txn|
txn.update!(category: category)
de = DataEnrichment.find_or_create_by!(
enrichable: txn,
attribute_name: "category_id",
value: category.id,
source: "rule"
)
de.value = category.id
de.save!
end
end
end

View file

@ -7,11 +7,29 @@ class Rule::ActionExecutor::SetTransactionTags < Rule::ActionExecutor
family.tags.pluck(:name, :id)
end
def execute(transaction_scope, value = nil)
def execute(transaction_scope, value: nil, ignore_attribute_locks: false)
tag = family.tags.find_by_id(value)
transaction_scope.attributes_unlocked(:tags).each do |transaction|
transaction.update(tags: [ tag ])
scope = transaction_scope
unless ignore_attribute_locks
scope = scope.enrichable(:tag_ids)
end
rows = scope.each do |txn|
DataEnrichment.transaction do
txn.update!(tag_ids: [ tag.id ])
de = DataEnrichment.find_or_initialize_by(
enrichable_id: txn.id,
enrichable_type: "Account::Transaction",
attribute_name: "tag_ids",
source: "rule"
)
de.value = [ tag.id ]
de.save!
end
end
end
end

View file

@ -42,7 +42,7 @@ class Rule::ActionTest < ActiveSupport::TestCase
tag = @family.tags.create!(name: "Rule test tag")
# Does not modify transactions that are locked (user edited them)
@txn1.lock!(:tags)
@txn1.lock!(:tag_ids)
action = Rule::Action.new(
rule: @transaction_rule,