mirror of
https://github.com/maybe-finance/maybe.git
synced 2025-07-24 23:59:40 +02:00
* Transfer data model migration * Transfers and payment modeling and UI improvements * Fix CI * Transfer matching flow * Better UI for transfers * Auto transfer matching, approve, reject flow * Mark transfers created from form as confirmed * Account filtering * Excluded rejected transfers from calculations * Calculation tweaks with transfer exclusions * Clean up migration
75 lines
3 KiB
Ruby
75 lines
3 KiB
Ruby
class ReverseTransferRelations < ActiveRecord::Migration[7.2]
|
|
def change
|
|
create_table :transfers, id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
|
|
t.references :inflow_transaction, null: false, foreign_key: { to_table: :account_transactions }, type: :uuid
|
|
t.references :outflow_transaction, null: false, foreign_key: { to_table: :account_transactions }, type: :uuid
|
|
t.string :status, null: false, default: "pending"
|
|
t.text :notes
|
|
|
|
t.index [ :inflow_transaction_id, :outflow_transaction_id ], unique: true
|
|
t.timestamps
|
|
end
|
|
|
|
reversible do |dir|
|
|
dir.up do
|
|
execute <<~SQL
|
|
INSERT INTO transfers (inflow_transaction_id, outflow_transaction_id, status, created_at, updated_at)
|
|
SELECT
|
|
CASE WHEN e1.amount <= 0 THEN e1.entryable_id ELSE e2.entryable_id END as inflow_transaction_id,
|
|
CASE WHEN e1.amount <= 0 THEN e2.entryable_id ELSE e1.entryable_id END as outflow_transaction_id,
|
|
'confirmed' as status,
|
|
e1.created_at,
|
|
e1.updated_at
|
|
FROM account_entries e1
|
|
JOIN account_entries e2 ON
|
|
e1.transfer_id = e2.transfer_id AND
|
|
e1.id != e2.id AND
|
|
e1.id < e2.id -- Ensures we don't duplicate transfers from both sides
|
|
JOIN accounts a1 ON e1.account_id = a1.id
|
|
JOIN accounts a2 ON e2.account_id = a2.id
|
|
WHERE
|
|
e1.entryable_type = 'Account::Transaction' AND
|
|
e2.entryable_type = 'Account::Transaction' AND
|
|
e1.transfer_id IS NOT NULL AND
|
|
a1.family_id = a2.family_id;
|
|
SQL
|
|
end
|
|
|
|
dir.down do
|
|
execute <<~SQL
|
|
WITH new_transfers AS (
|
|
INSERT INTO account_transfers (created_at, updated_at)
|
|
SELECT created_at, updated_at
|
|
FROM transfers
|
|
RETURNING id, created_at
|
|
),
|
|
transfer_pairs AS (
|
|
SELECT
|
|
nt.id as transfer_id,
|
|
ae_in.id as inflow_entry_id,
|
|
ae_out.id as outflow_entry_id
|
|
FROM transfers t
|
|
JOIN new_transfers nt ON nt.created_at = t.created_at
|
|
JOIN account_entries ae_in ON ae_in.entryable_id = t.inflow_transaction_id
|
|
JOIN account_entries ae_out ON ae_out.entryable_id = t.outflow_transaction_id
|
|
WHERE
|
|
ae_in.entryable_type = 'Account::Transaction' AND
|
|
ae_out.entryable_type = 'Account::Transaction'
|
|
)
|
|
UPDATE account_entries ae
|
|
SET transfer_id = tp.transfer_id
|
|
FROM transfer_pairs tp
|
|
WHERE ae.id IN (tp.inflow_entry_id, tp.outflow_entry_id);
|
|
SQL
|
|
end
|
|
end
|
|
|
|
remove_foreign_key :account_entries, :account_transfers, column: :transfer_id
|
|
remove_column :account_entries, :transfer_id, :uuid
|
|
remove_column :account_entries, :marked_as_transfer, :boolean
|
|
|
|
drop_table :account_transfers, id: :uuid, default: -> { "gen_random_uuid()" } do |t|
|
|
t.timestamps
|
|
end
|
|
end
|
|
end
|