houdini/lib/insert/insert_payout.rb

98 lines
4.6 KiB
Ruby
Raw Normal View History

# frozen_string_literal: true
2020-06-12 20:03:43 +00:00
# License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later
# Full license explanation at https://github.com/houdiniproject/houdini/blob/master/LICENSE
# Create a new payout
require 'psql'
require 'qexpr'
require 'query/query_payments'
require 'update/update_charges'
require 'update/update_refunds'
require 'update/update_disputes'
require 'param_validation'
module InsertPayout
# Pass in the following inside the data hash:
# - stripe_account_id
# - email
# - user_ip
# - bank_name
# options hash can have a :date (before date) for only paying out funds before a certain date (useful for only disbursing the prev month)
def self.with_stripe(np_id, data, options = {})
bigger_data = (data || {}).merge(np_id: np_id)
ParamValidation.new(bigger_data,
np_id: { required: true, is_integer: true },
stripe_account_id: { not_blank: true, required: true },
email: { not_blank: true, required: true },
user_ip: { not_blank: true, required: true },
bank_name: { not_blank: true, required: true })
options ||= {}
entities = RetrieveActiveRecordItems.retrieve_from_keys(bigger_data, Nonprofit => :np_id)
payment_ids = QueryPayments.ids_for_payout(np_id, options)
if payment_ids.count < 1
raise ArgumentError, 'No payments are available for disbursal on this account.'
end
totals = QueryPayments.get_payout_totals(payment_ids)
nonprofit_currency = entities[:np_id].currency
now = Time.current
begin
stripe_transfer = StripeUtils.create_transfer(totals['net_amount'], data[:stripe_account_id], nonprofit_currency)
Psql.transaction do
# Create the Transfer on Stripe
# Retrieve all payments with available charges and undisbursed refunds
# Mark all the above payments as disbursed
UpdateCharges.disburse_all_with_payments(payment_ids)
# Mark all the above refunds as disbursed
UpdateRefunds.disburse_all_with_payments(payment_ids)
# Mark all disputes as lost_and_paid
UpdateDisputes.disburse_all_with_payments(payment_ids)
# Get gross total, total fees, net total, and total count
# Create the payout record (whether it succeeded on Stripe or not)
payout = Psql.execute(
Qexpr.new.insert(:payouts, [{
net_amount: totals['net_amount'],
nonprofit_id: np_id,
failure_message: stripe_transfer['failure_message'],
status: stripe_transfer.status,
fee_total: totals['fee_total'],
gross_amount: totals['gross_amount'],
email: data[:email],
count: totals['count'],
stripe_transfer_id: stripe_transfer.id,
user_ip: data[:user_ip],
ach_fee: 0,
bank_name: data[:bank_name]
}])
.returning('id', 'net_amount', 'nonprofit_id', 'created_at', 'updated_at', 'status', 'fee_total', 'gross_amount', 'email', 'count', 'stripe_transfer_id', 'user_ip', 'ach_fee', 'bank_name')
).first
# Create PaymentPayout records linking all the payments to the payout
pps = Psql.execute(Qexpr.new.insert('payment_payouts', payment_ids.map { |id| { payment_id: id.to_i } }, common_data: { payout_id: payout['id'].to_i }))
2019-11-07 19:00:10 +00:00
PayoutPendingJob.perform_later(Payout.find(payout['id'].to_i))
return payout
end
rescue Stripe::StripeError => e
payout = Psql.execute(
Qexpr.new.insert(:payouts, [{
net_amount: totals['net_amount'],
nonprofit_id: np_id,
failure_message: e.message,
status: 'failed',
fee_total: totals['fee_total'],
gross_amount: totals['gross_amount'],
email: data[:email],
count: totals['count'],
stripe_transfer_id: nil,
user_ip: data[:user_ip],
ach_fee: 0,
bank_name: data[:bank_name]
}])
.returning('id', 'net_amount', 'nonprofit_id', 'created_at', 'updated_at', 'status', 'fee_total', 'gross_amount', 'email', 'count', 'stripe_transfer_id', 'user_ip', 'ach_fee', 'bank_name')
).first
return payout
end
end
end