mirror of
https://github.com/we-promise/sure
synced 2026-04-25 17:15:07 +02:00
FIX schema drift and snaptrade and mercury issues (#1232)
This commit is contained in:
@@ -17,7 +17,6 @@ class SnaptradeAccount < ApplicationRecord
|
||||
has_one :linked_account, through: :account_provider, source: :account
|
||||
|
||||
validates :name, :currency, presence: true
|
||||
validates :account_id, uniqueness: { scope: :snaptrade_item_id, allow_nil: true }
|
||||
validates :snaptrade_account_id, uniqueness: { scope: :snaptrade_item_id, allow_nil: true }
|
||||
|
||||
# Enqueue cleanup job after destruction to avoid blocking transaction with API call
|
||||
|
||||
@@ -4,16 +4,8 @@
|
||||
# account can be linked in multiple families. See: https://github.com/we-promise/sure/issues/740
|
||||
class ScopeSnaptradeAccountUniquenessToItem < ActiveRecord::Migration[7.2]
|
||||
def up
|
||||
remove_index :snaptrade_accounts, name: "index_snaptrade_accounts_on_account_id", if_exists: true
|
||||
remove_index :snaptrade_accounts, name: "index_snaptrade_accounts_on_snaptrade_account_id", if_exists: true
|
||||
|
||||
unless index_exists?(:snaptrade_accounts, [ :snaptrade_item_id, :account_id ], unique: true, name: "index_snaptrade_accounts_on_item_and_account_id")
|
||||
add_index :snaptrade_accounts,
|
||||
[ :snaptrade_item_id, :account_id ],
|
||||
unique: true,
|
||||
name: "index_snaptrade_accounts_on_item_and_account_id",
|
||||
where: "account_id IS NOT NULL"
|
||||
end
|
||||
unless index_exists?(:snaptrade_accounts, [ :snaptrade_item_id, :snaptrade_account_id ], unique: true, name: "index_snaptrade_accounts_on_item_and_snaptrade_account_id")
|
||||
add_index :snaptrade_accounts,
|
||||
[ :snaptrade_item_id, :snaptrade_account_id ],
|
||||
@@ -24,20 +16,12 @@ class ScopeSnaptradeAccountUniquenessToItem < ActiveRecord::Migration[7.2]
|
||||
end
|
||||
|
||||
def down
|
||||
if execute("SELECT 1 FROM snaptrade_accounts WHERE account_id IS NOT NULL GROUP BY account_id HAVING COUNT(DISTINCT snaptrade_item_id) > 1 LIMIT 1").any? ||
|
||||
execute("SELECT 1 FROM snaptrade_accounts WHERE snaptrade_account_id IS NOT NULL GROUP BY snaptrade_account_id HAVING COUNT(DISTINCT snaptrade_item_id) > 1 LIMIT 1").any?
|
||||
if execute("SELECT 1 FROM snaptrade_accounts WHERE snaptrade_account_id IS NOT NULL GROUP BY snaptrade_account_id HAVING COUNT(DISTINCT snaptrade_item_id) > 1 LIMIT 1").any?
|
||||
raise ActiveRecord::IrreversibleMigration,
|
||||
"Cannot rollback: cross-item duplicates exist in snaptrade_accounts. Remove duplicates first."
|
||||
end
|
||||
|
||||
remove_index :snaptrade_accounts, name: "index_snaptrade_accounts_on_item_and_account_id", if_exists: true
|
||||
remove_index :snaptrade_accounts, name: "index_snaptrade_accounts_on_item_and_snaptrade_account_id", if_exists: true
|
||||
unless index_exists?(:snaptrade_accounts, :account_id, name: "index_snaptrade_accounts_on_account_id")
|
||||
add_index :snaptrade_accounts, :account_id,
|
||||
name: "index_snaptrade_accounts_on_account_id",
|
||||
unique: true,
|
||||
where: "account_id IS NOT NULL"
|
||||
end
|
||||
unless index_exists?(:snaptrade_accounts, :snaptrade_account_id, name: "index_snaptrade_accounts_on_snaptrade_account_id")
|
||||
add_index :snaptrade_accounts, :snaptrade_account_id,
|
||||
name: "index_snaptrade_accounts_on_snaptrade_account_id",
|
||||
|
||||
11
db/schema.rb
generated
11
db/schema.rb
generated
@@ -49,8 +49,6 @@ ActiveRecord::Schema[7.2].define(version: 2026_03_14_131357) do
|
||||
t.string "institution_name"
|
||||
t.string "institution_domain"
|
||||
t.text "notes"
|
||||
t.jsonb "holdings_snapshot_data"
|
||||
t.datetime "holdings_snapshot_at"
|
||||
t.index ["accountable_id", "accountable_type"], name: "index_accounts_on_accountable_id_and_accountable_type"
|
||||
t.index ["accountable_type"], name: "index_accounts_on_accountable_type"
|
||||
t.index ["currency"], name: "index_accounts_on_currency"
|
||||
@@ -1243,7 +1241,6 @@ ActiveRecord::Schema[7.2].define(version: 2026_03_14_131357) do
|
||||
create_table "snaptrade_accounts", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
|
||||
t.uuid "snaptrade_item_id", null: false
|
||||
t.string "name"
|
||||
t.string "account_id"
|
||||
t.string "snaptrade_account_id"
|
||||
t.string "snaptrade_authorization_id"
|
||||
t.string "account_number"
|
||||
@@ -1265,7 +1262,6 @@ ActiveRecord::Schema[7.2].define(version: 2026_03_14_131357) do
|
||||
t.datetime "updated_at", null: false
|
||||
t.boolean "activities_fetch_pending", default: false
|
||||
t.date "sync_start_date"
|
||||
t.index ["snaptrade_item_id", "account_id"], name: "index_snaptrade_accounts_on_item_and_account_id", unique: true, where: "(account_id IS NOT NULL)"
|
||||
t.index ["snaptrade_item_id", "snaptrade_account_id"], name: "index_snaptrade_accounts_on_item_and_snaptrade_account_id", unique: true, where: "(snaptrade_account_id IS NOT NULL)"
|
||||
t.index ["snaptrade_item_id"], name: "index_snaptrade_accounts_on_snaptrade_item_id"
|
||||
end
|
||||
@@ -1403,15 +1399,8 @@ ActiveRecord::Schema[7.2].define(version: 2026_03_14_131357) do
|
||||
t.datetime "updated_at", null: false
|
||||
t.string "currency"
|
||||
t.jsonb "locked_attributes", default: {}
|
||||
t.decimal "realized_gain", precision: 19, scale: 4
|
||||
t.decimal "cost_basis_amount", precision: 19, scale: 4
|
||||
t.string "cost_basis_currency"
|
||||
t.integer "holding_period_days"
|
||||
t.string "realized_gain_confidence"
|
||||
t.string "realized_gain_currency"
|
||||
t.string "investment_activity_label"
|
||||
t.index ["investment_activity_label"], name: "index_trades_on_investment_activity_label"
|
||||
t.index ["realized_gain"], name: "index_trades_on_realized_gain_not_null", where: "(realized_gain IS NOT NULL)"
|
||||
t.index ["security_id"], name: "index_trades_on_security_id"
|
||||
end
|
||||
|
||||
|
||||
@@ -22,32 +22,9 @@ class SnaptradeAccountTest < ActiveSupport::TestCase
|
||||
)
|
||||
end
|
||||
|
||||
test "same account_id can be linked under different snaptrade_items" do
|
||||
SnaptradeAccount.create!(
|
||||
snaptrade_item: @item_a,
|
||||
account_id: "shared_snap_acc_1",
|
||||
snaptrade_account_id: "snap_uuid_a_1",
|
||||
name: "Brokerage",
|
||||
currency: "USD",
|
||||
current_balance: 10_000
|
||||
)
|
||||
|
||||
assert_difference "SnaptradeAccount.count", 1 do
|
||||
SnaptradeAccount.create!(
|
||||
snaptrade_item: @item_b,
|
||||
account_id: "shared_snap_acc_1",
|
||||
snaptrade_account_id: "snap_uuid_b_1",
|
||||
name: "Brokerage",
|
||||
currency: "USD",
|
||||
current_balance: 10_000
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
test "same snaptrade_account_id can be linked under different snaptrade_items" do
|
||||
SnaptradeAccount.create!(
|
||||
snaptrade_item: @item_a,
|
||||
account_id: "acc_a",
|
||||
snaptrade_account_id: "shared_snap_uuid_1",
|
||||
name: "IRA",
|
||||
currency: "USD",
|
||||
@@ -57,7 +34,6 @@ class SnaptradeAccountTest < ActiveSupport::TestCase
|
||||
assert_difference "SnaptradeAccount.count", 1 do
|
||||
SnaptradeAccount.create!(
|
||||
snaptrade_item: @item_b,
|
||||
account_id: "acc_b",
|
||||
snaptrade_account_id: "shared_snap_uuid_1",
|
||||
name: "IRA",
|
||||
currency: "USD",
|
||||
@@ -66,43 +42,9 @@ class SnaptradeAccountTest < ActiveSupport::TestCase
|
||||
end
|
||||
end
|
||||
|
||||
test "same account_id cannot appear twice under the same snaptrade_item" do
|
||||
SnaptradeAccount.create!(
|
||||
snaptrade_item: @item_a,
|
||||
account_id: "dup_acc",
|
||||
snaptrade_account_id: "snap_1",
|
||||
name: "Brokerage",
|
||||
currency: "USD",
|
||||
current_balance: 1000
|
||||
)
|
||||
|
||||
duplicate = SnaptradeAccount.new(
|
||||
snaptrade_item: @item_a,
|
||||
account_id: "dup_acc",
|
||||
snaptrade_account_id: "snap_2",
|
||||
name: "Brokerage",
|
||||
currency: "USD",
|
||||
current_balance: 1000
|
||||
)
|
||||
refute duplicate.valid?
|
||||
assert_includes duplicate.errors[:account_id], "has already been taken"
|
||||
|
||||
assert_raises(ActiveRecord::RecordInvalid) do
|
||||
SnaptradeAccount.create!(
|
||||
snaptrade_item: @item_a,
|
||||
account_id: "dup_acc",
|
||||
snaptrade_account_id: "snap_2",
|
||||
name: "Brokerage",
|
||||
currency: "USD",
|
||||
current_balance: 1000
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
test "same snaptrade_account_id cannot appear twice under the same snaptrade_item" do
|
||||
SnaptradeAccount.create!(
|
||||
snaptrade_item: @item_a,
|
||||
account_id: "acc_1",
|
||||
snaptrade_account_id: "dup_snap_uuid",
|
||||
name: "Brokerage",
|
||||
currency: "USD",
|
||||
@@ -111,7 +53,6 @@ class SnaptradeAccountTest < ActiveSupport::TestCase
|
||||
|
||||
duplicate = SnaptradeAccount.new(
|
||||
snaptrade_item: @item_a,
|
||||
account_id: "acc_2",
|
||||
snaptrade_account_id: "dup_snap_uuid",
|
||||
name: "Brokerage",
|
||||
currency: "USD",
|
||||
@@ -123,7 +64,6 @@ class SnaptradeAccountTest < ActiveSupport::TestCase
|
||||
assert_raises(ActiveRecord::RecordInvalid) do
|
||||
SnaptradeAccount.create!(
|
||||
snaptrade_item: @item_a,
|
||||
account_id: "acc_2",
|
||||
snaptrade_account_id: "dup_snap_uuid",
|
||||
name: "Brokerage",
|
||||
currency: "USD",
|
||||
|
||||
Reference in New Issue
Block a user