96 lines
4.6 KiB
Ruby
96 lines
4.6 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
# License: AGPL-3.0-or-later WITH Web-Template-Output-Additional-Permission-3.0-or-later
|
|
# 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 }))
|
|
NonprofitMailer.delay.pending_payout_notification(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
|