diff --git a/app/models/plaid_account/importer.rb b/app/models/plaid_account/importer.rb index 1306278f..10ae1084 100644 --- a/app/models/plaid_account/importer.rb +++ b/app/models/plaid_account/importer.rb @@ -5,12 +5,10 @@ class PlaidAccount::Importer end def import - PlaidAccount.transaction do - import_account_info - import_transactions if account_snapshot.transactions_data.present? - import_investments if account_snapshot.investments_data.present? - import_liabilities if account_snapshot.liabilities_data.present? - end + import_account_info + import_transactions if account_snapshot.transactions_data.present? + import_investments if account_snapshot.investments_data.present? + import_liabilities if account_snapshot.liabilities_data.present? end private diff --git a/app/models/plaid_item/accounts_snapshot.rb b/app/models/plaid_item/accounts_snapshot.rb index fee02a76..dcf5957a 100644 --- a/app/models/plaid_item/accounts_snapshot.rb +++ b/app/models/plaid_item/accounts_snapshot.rb @@ -20,6 +20,11 @@ class PlaidItem::AccountsSnapshot ) end + def transactions_cursor + return nil unless transactions_data + transactions_data.cursor + end + private attr_reader :plaid_item, :plaid_provider @@ -68,7 +73,11 @@ class PlaidItem::AccountsSnapshot def transactions_data return nil unless can_fetch_transactions? - @transactions_data ||= plaid_provider.get_transactions(plaid_item.access_token) + + @transactions_data ||= plaid_provider.get_transactions( + plaid_item.access_token, + next_cursor: plaid_item.next_cursor + ) end def can_fetch_investments? diff --git a/app/models/plaid_item/importer.rb b/app/models/plaid_item/importer.rb index 9a4b295e..f1431d6c 100644 --- a/app/models/plaid_item/importer.rb +++ b/app/models/plaid_item/importer.rb @@ -39,15 +39,20 @@ class PlaidItem::Importer def fetch_and_import_accounts_data snapshot = PlaidItem::AccountsSnapshot.new(plaid_item, plaid_provider: plaid_provider) - snapshot.accounts.each do |raw_account| - plaid_account = plaid_item.plaid_accounts.find_or_initialize_by( - plaid_id: raw_account.account_id - ) + PlaidItem.transaction do + snapshot.accounts.each do |raw_account| + plaid_account = plaid_item.plaid_accounts.find_or_initialize_by( + plaid_id: raw_account.account_id + ) - PlaidAccount::Importer.new( - plaid_account, - account_snapshot: snapshot.get_account_data(raw_account.account_id) - ).import + PlaidAccount::Importer.new( + plaid_account, + account_snapshot: snapshot.get_account_data(raw_account.account_id) + ).import + end + + # Once we know all data has been imported, save the cursor to avoid re-fetching the same data next time + plaid_item.update!(next_cursor: snapshot.transactions_cursor) end end end diff --git a/app/views/shared/notifications/_cta.html.erb b/app/views/shared/notifications/_cta.html.erb index 6b38ff53..456cae73 100644 --- a/app/views/shared/notifications/_cta.html.erb +++ b/app/views/shared/notifications/_cta.html.erb @@ -1,10 +1,10 @@ <%# locals: (message:, description:) %>
- <%= tag.div class: "relative flex gap-3 rounded-lg bg-container-inset p-4 group w-full md:max-w-80 shadow-border-xs", data: { controller: "element-removal" } do %> + <%= tag.div class: "relative flex gap-3 rounded-lg bg-container p-4 group w-full md:max-w-80 shadow-border-xs", data: { controller: "element-removal" } do %>
-
- <%= icon "check", size: "xs" %> +
+ <%= icon "check", size: "xs", color: "current" %>
diff --git a/test/models/plaid_item/accounts_snapshot_test.rb b/test/models/plaid_item/accounts_snapshot_test.rb index a08b0e1e..467497f7 100644 --- a/test/models/plaid_item/accounts_snapshot_test.rb +++ b/test/models/plaid_item/accounts_snapshot_test.rb @@ -26,7 +26,14 @@ class PlaidItem::AccountsSnapshotTest < ActiveSupport::TestCase ) ]).at_least_once - @plaid_provider.expects(:get_transactions).with(@plaid_item.access_token).once + @plaid_provider.expects(:get_transactions).with(@plaid_item.access_token, next_cursor: nil).returns( + OpenStruct.new( + added: [], + modified: [], + removed: [], + cursor: "test_cursor_1" + ) + ).once @plaid_provider.expects(:get_item_investments).never @plaid_provider.expects(:get_item_liabilities).never @@ -45,6 +52,31 @@ class PlaidItem::AccountsSnapshotTest < ActiveSupport::TestCase @snapshot.get_account_data("123") end + test "updates next_cursor when fetching transactions" do + @plaid_item.update!(available_products: [ "transactions" ], billed_products: [], next_cursor: "test_cursor_1") + + @snapshot.expects(:accounts).returns([ + OpenStruct.new( + account_id: "123", + type: "depository" + ) + ]).at_least_once + + @plaid_provider.expects(:get_transactions).with(@plaid_item.access_token, next_cursor: "test_cursor_1").returns( + OpenStruct.new( + added: [], + modified: [], + removed: [], + cursor: "test_cursor_2" + ) + ).once + + @plaid_provider.expects(:get_item_investments).never + @plaid_provider.expects(:get_item_liabilities).never + + @snapshot.get_account_data("123") + end + test "fetches investments data if item supports investments and investment accounts present" do @plaid_item.update!(available_products: [ "investments" ], billed_products: []) diff --git a/test/models/plaid_item/importer_test.rb b/test/models/plaid_item/importer_test.rb index cce355fa..421b34fd 100644 --- a/test/models/plaid_item/importer_test.rb +++ b/test/models/plaid_item/importer_test.rb @@ -33,14 +33,17 @@ class PlaidItem::ImporterTest < ActiveSupport::TestCase PlaidItem::AccountsSnapshot.any_instance.expects(:accounts).returns([ OpenStruct.new( account_id: "acc_1", - type: "depository" + type: "depository", ) ]).at_least_once + PlaidItem::AccountsSnapshot.any_instance.expects(:transactions_cursor).returns("test_cursor_1") + PlaidItem::AccountsSnapshot.any_instance.expects(:get_account_data).with("acc_1").once PlaidAccount::Importer.any_instance.expects(:import).once + @plaid_item.expects(:update!).with(next_cursor: "test_cursor_1") @plaid_item.expects(:upsert_plaid_snapshot!).with(item_data) @plaid_item.expects(:upsert_plaid_institution_snapshot!).with(institution_data)