mirror of
https://github.com/maybe-finance/maybe.git
synced 2025-07-24 15:49:39 +02:00
Breaks our Plaid sync process out into more manageable classes. Notably, this moves the sync process to a distinct, 2-step flow: 1. Import stage - we first make API calls and import Plaid data to "mirror" tables 2. Processing stage - read the raw data, apply business rules, build internal domain models and sync balances This provides several benefits: - Plaid syncs can now be "replayed" without fetching API data again - Mirror tables provide better audit and debugging capabilities - Eliminates the "all or nothing" sync behavior that is currently in place, which is brittle
63 lines
2.1 KiB
Ruby
63 lines
2.1 KiB
Ruby
require "test_helper"
|
|
|
|
class PlaidAccount::Transactions::ProcessorTest < ActiveSupport::TestCase
|
|
setup do
|
|
@plaid_account = plaid_accounts(:one)
|
|
end
|
|
|
|
test "processes added and modified plaid transactions" do
|
|
added_transactions = [ { "transaction_id" => "123" } ]
|
|
modified_transactions = [ { "transaction_id" => "456" } ]
|
|
|
|
@plaid_account.update!(raw_transactions_payload: {
|
|
added: added_transactions,
|
|
modified: modified_transactions,
|
|
removed: []
|
|
})
|
|
|
|
mock_processor = mock("PlaidEntry::Processor")
|
|
category_matcher_mock = mock("PlaidAccount::Transactions::CategoryMatcher")
|
|
|
|
PlaidAccount::Transactions::CategoryMatcher.stubs(:new).returns(category_matcher_mock)
|
|
PlaidEntry::Processor.expects(:new)
|
|
.with(added_transactions.first, plaid_account: @plaid_account, category_matcher: category_matcher_mock)
|
|
.returns(mock_processor)
|
|
.once
|
|
|
|
PlaidEntry::Processor.expects(:new)
|
|
.with(modified_transactions.first, plaid_account: @plaid_account, category_matcher: category_matcher_mock)
|
|
.returns(mock_processor)
|
|
.once
|
|
|
|
mock_processor.expects(:process).twice
|
|
|
|
processor = PlaidAccount::Transactions::Processor.new(@plaid_account)
|
|
processor.process
|
|
end
|
|
|
|
test "removes transactions no longer in plaid" do
|
|
destroyable_transaction_id = "destroy_me"
|
|
@plaid_account.account.entries.create!(
|
|
plaid_id: destroyable_transaction_id,
|
|
date: Date.current,
|
|
amount: 100,
|
|
name: "Destroy me",
|
|
currency: "USD",
|
|
entryable: Transaction.new
|
|
)
|
|
|
|
@plaid_account.update!(raw_transactions_payload: {
|
|
added: [],
|
|
modified: [],
|
|
removed: [ { "transaction_id" => destroyable_transaction_id } ]
|
|
})
|
|
|
|
processor = PlaidAccount::Transactions::Processor.new(@plaid_account)
|
|
|
|
assert_difference [ "Entry.count", "Transaction.count" ], -1 do
|
|
processor.process
|
|
end
|
|
|
|
assert_nil Entry.find_by(plaid_id: destroyable_transaction_id)
|
|
end
|
|
end
|