Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions app/controllers/column/webhooks_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@ def webhook
type = params[:type]
if type == "ach.incoming_transfer.scheduled"
handle_ach_incoming_transfer_scheduled
elsif type == "ach.incoming_transfer.settled"
handle_as_raw_pending_column_transaction
elsif type == "wire.incoming_transfer.completed"
handle_as_raw_pending_column_transaction
elsif type == "swift.incoming_transfer.completed"
handle_as_raw_pending_column_transaction
elsif type == "ach.outgoing_transfer.returned"
handle_ach_outgoing_transfer_returned
elsif type == "check.outgoing_debit.settled"
Expand Down Expand Up @@ -50,6 +56,20 @@ def handle_ach_incoming_transfer_scheduled
# at this point, the ACH is approved!
end

def handle_as_raw_pending_column_transaction(column_event_type:)
account_number = AccountNumber.find_by(column_id: @object[:account_number_id])
# we only create RawPendingColumnTransaction for transactions to
# event-specific account numbers.
return if account_number.nil?

Comment on lines +62 to +64
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# event-specific account numbers.
return if account_number.nil?
# event-specific account numbers.
return if account_number.nil?

RawPendingColumnTransaction.create!(
amount_cents: @object["available_amount"],
date_posted: @object["effective_at_utc"],
column_transaction: @object,
column_event_type:
)
end

def handle_ach_outgoing_transfer_returned
AchTransfer.find_by(column_id: @object[:id])&.mark_failed!(reason: @object[:return_details].pick(:description)&.gsub(/\(trace #: \d+\)\Z/, "")&.strip)
end
Expand Down
8 changes: 8 additions & 0 deletions app/models/canonical_pending_transaction.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
# increase_check_id :bigint
# paypal_transfer_id :bigint
# raw_pending_bank_fee_transaction_id :bigint
# raw_pending_column_transaction_id :bigint
# raw_pending_donation_transaction_id :bigint
# raw_pending_incoming_disbursement_transaction_id :bigint
# raw_pending_invoice_transaction_id :bigint
Expand All @@ -31,6 +32,7 @@
#
# Indexes
#
# idx_on_raw_pending_column_transaction_id_ceea9a99e1 (raw_pending_column_transaction_id) UNIQUE
# index_canonical_pending_transactions_on_check_deposit_id (check_deposit_id)
# index_canonical_pending_transactions_on_hcb_code (hcb_code)
# index_canonical_pending_transactions_on_increase_check_id (increase_check_id)
Expand All @@ -44,6 +46,7 @@
# index_canonical_pending_txs_on_raw_pending_stripe_tx_id (raw_pending_stripe_transaction_id)
# index_canonical_pending_txs_on_reimbursement_expense_payout_id (reimbursement_expense_payout_id)
# index_canonical_pending_txs_on_reimbursement_payout_holding_id (reimbursement_payout_holding_id)
# index_canonical_pending_txs_on_rpct_id (raw_pending_column_transaction_id)
# index_cpts_on_raw_pending_incoming_disbursement_transaction_id (raw_pending_incoming_disbursement_transaction_id)
# index_cpts_on_raw_pending_outgoing_disbursement_transaction_id (raw_pending_outgoing_disbursement_transaction_id)
#
Expand All @@ -66,6 +69,7 @@ class CanonicalPendingTransaction < ApplicationRecord
belongs_to :raw_pending_donation_transaction, optional: true
belongs_to :raw_pending_invoice_transaction, optional: true
belongs_to :raw_pending_bank_fee_transaction, optional: true
belongs_to :raw_pending_column_transaction, optional: true
belongs_to :raw_pending_incoming_disbursement_transaction, optional: true
belongs_to :raw_pending_outgoing_disbursement_transaction, optional: true
belongs_to :increase_check, optional: true
Expand Down Expand Up @@ -363,6 +367,10 @@ def stripe_card
end
end

def column_transaction_id
raw_pending_column_transaction&.column_id
end

private

def write_hcb_code
Expand Down
11 changes: 10 additions & 1 deletion app/models/raw_column_transaction.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,20 @@ class RawColumnTransaction < ApplicationRecord
after_create :canonize, if: -> { canonical_transaction.nil? }

def canonize
create_canonical_transaction!(
ct = create_canonical_transaction!(
amount_cents:,
memo:,
date: date_posted,
)

raw_pending_column_transaction = RawPendingColumnTransaction.find_by(column_id: column_transaction["transaction_id"])

if raw_pending_column_transaction&.canonical_pending_transaction
CanonicalPendingTransactionService::Settle.new(
canonical_transaction: ct,
canonical_pending_transaction: raw_pending_column_transaction.canonical_pending_transaction
).run!
end
end

def memo
Expand Down
53 changes: 53 additions & 0 deletions app/models/raw_pending_column_transaction.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# frozen_string_literal: true

# == Schema Information
#
# Table name: raw_pending_column_transactions
#
# id :bigint not null, primary key
# amount_cents :integer not null
# column_event_type :integer not null
# column_transaction :jsonb not null
# date_posted :date not null
# description :text not null
# created_at :datetime not null
# updated_at :datetime not null
# column_id :string not null
#
# Indexes
#
# index_raw_pending_column_transactions_on_column_id (column_id) UNIQUE
#
class RawPendingColumnTransaction < ApplicationRecord
has_one :canonical_pending_transaction

after_create :create_canonical_pending_transaction, if: -> { canonical_pending_transaction.nil? }

enum :column_event_type, {
"swift.incoming_transfer.completed": 0,
"wire.incoming_transfer.completed": 1,
"ach.incoming_transfer.settled": 2
}

def create_canonical_pending_transaction
column_account_number = Column::AccountNumber.find_by(column_id: column_transaction["account_number_id"])
return unless column_account_number
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question: When might we run into this scenario? Should we fail louder?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is common and we shouldn't fail for this - this is any time a transaction hits our main account number and can't be matched to an event. Examples include internal book transfers and all Stripe transactions.


# create_canonical_pending_transaction!(
# amount_cents:,
# memo:,
# date: date_posted,
# event: column_account_number.event,
# fronted: true
# )
end

def memo
if column_id.start_with? "acht"
return "#{column_transaction.fetch("company_name")} #{column_transaction["company_entry_description"]}"
elsif column_id.start_with?("wire") || column_id.start_with?("swft_")
return column_transaction.fetch("originator_name")
end
end

end
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,7 @@ def unknown_hcb_code
[
HCB_CODE,
UNKNOWN_CODE,
@ct_or_cp.id
@ct_or_cp.column_transaction_id || @ct_or_cp.id
].join(SEPARATOR)
end

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
class CreateRawPendingColumnTransactions < ActiveRecord::Migration[7.2]
def change
create_table :raw_pending_column_transactions do |t|
t.string :column_id, null: false
t.integer :column_event_type, null: false
t.jsonb :column_transaction, null: false
t.text :description, null: false
t.date :date_posted, null: false
t.integer :amount_cents, null: false
t.timestamps
end
add_index :raw_pending_column_transactions, :column_id, unique: true
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
class AddRawPendingColumnTransactionIdToCanonicalPendingTransaction < ActiveRecord::Migration[7.2]
disable_ddl_transaction!

def change
add_reference :canonical_pending_transactions, :raw_pending_column_transaction, index: { algorithm: :concurrently, name: "index_canonical_pending_txs_on_rpct_id" }
add_index :canonical_pending_transactions, :raw_pending_column_transaction_id, unique: true, algorithm: :concurrently
end
end
15 changes: 15 additions & 0 deletions db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -398,11 +398,14 @@
t.bigint "paypal_transfer_id"
t.bigint "reimbursement_payout_holding_id"
t.bigint "wire_id"
t.bigint "raw_pending_column_transaction_id"
t.index ["check_deposit_id"], name: "index_canonical_pending_transactions_on_check_deposit_id"
t.index ["hcb_code"], name: "index_canonical_pending_transactions_on_hcb_code"
t.index ["increase_check_id"], name: "index_canonical_pending_transactions_on_increase_check_id"
t.index ["paypal_transfer_id"], name: "index_canonical_pending_transactions_on_paypal_transfer_id"
t.index ["raw_pending_bank_fee_transaction_id"], name: "index_canonical_pending_txs_on_raw_pending_bank_fee_tx_id"
t.index ["raw_pending_column_transaction_id"], name: "idx_on_raw_pending_column_transaction_id_ceea9a99e1", unique: true
t.index ["raw_pending_column_transaction_id"], name: "index_canonical_pending_txs_on_rpct_id"
t.index ["raw_pending_donation_transaction_id"], name: "index_canonical_pending_txs_on_raw_pending_donation_tx_id"
t.index ["raw_pending_incoming_disbursement_transaction_id"], name: "index_cpts_on_raw_pending_incoming_disbursement_transaction_id"
t.index ["raw_pending_invoice_transaction_id"], name: "index_canonical_pending_txs_on_raw_pending_invoice_tx_id"
Expand Down Expand Up @@ -1632,6 +1635,18 @@
t.datetime "updated_at", null: false
end

create_table "raw_pending_column_transactions", force: :cascade do |t|
t.string "column_id", null: false
t.integer "column_event_type", null: false
t.jsonb "column_transaction", null: false
t.text "description", null: false
t.date "date_posted", null: false
t.integer "amount_cents", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["column_id"], name: "index_raw_pending_column_transactions_on_column_id", unique: true
end

create_table "raw_pending_donation_transactions", force: :cascade do |t|
t.integer "amount_cents"
t.date "date_posted"
Expand Down