137 lines
4.3 KiB
Ruby
137 lines
4.3 KiB
Ruby
module JamRuby
|
|
class TeacherPayment < ActiveRecord::Base
|
|
|
|
belongs_to :teacher, class_name: "JamRuby::User", foreign_key: :teacher_id
|
|
belongs_to :teacher_payment_charge, class_name: "JamRuby::TeacherPaymentCharge", foreign_key: :charge_id
|
|
has_one :teacher_distribution, class_name: "JamRuby::TeacherDistribution"
|
|
belongs_to :school, class_name: "JamRuby::School"
|
|
belongs_to :retailer, class_name: "JamRuby::Retailer"
|
|
|
|
|
|
def self.hourly_check
|
|
teacher_payments
|
|
end
|
|
|
|
# pay the school if the payment owns the school; otherwise default to the teacher
|
|
def payable_teacher
|
|
if school
|
|
if school.education
|
|
teacher
|
|
else
|
|
school.owner
|
|
end
|
|
else
|
|
teacher
|
|
end
|
|
end
|
|
|
|
def teacher_distributions
|
|
[teacher_distribution]
|
|
end
|
|
|
|
def self.pending_teacher_payments
|
|
User.select(['users.id']).joins(:teacher).joins(:user_authorizations).joins(:teacher_distributions).where("user_authorizations.provider = 'stripe_connect' AND user_authorizations.token_expiration > NOW()").where('teacher_distributions.distributed = false').where('teacher_distributions.ready = true').uniq
|
|
end
|
|
|
|
def self.teacher_payments
|
|
pending_teacher_payments.each do |row|
|
|
teacher = User.find(row['id'])
|
|
|
|
TeacherDistribution.where(teacher_id: teacher.id).where(ready: true).where(distributed: false).each do |distribution|
|
|
payment = TeacherPayment.charge(teacher)
|
|
if payment.nil? || !payment.teacher_payment_charge.billed
|
|
break
|
|
end
|
|
end
|
|
|
|
end
|
|
end
|
|
|
|
def amount
|
|
amount_in_cents / 100.0
|
|
end
|
|
|
|
def is_card_declined?
|
|
teacher_payment_charge.is_card_declined?
|
|
end
|
|
|
|
def is_card_expired?
|
|
teacher_payment_charge.is_card_expired?
|
|
end
|
|
|
|
def last_billed_at_date
|
|
teacher_payment_charge.last_billed_at_date
|
|
end
|
|
|
|
def charge_retry_hours
|
|
24
|
|
end
|
|
|
|
def real_distribution_in_cents
|
|
amount_in_cents - fee_in_cents
|
|
end
|
|
|
|
# will find, for a given teacher, an outstading unsuccessful payment or make a new one.
|
|
# it will then associate a charge with it, and then execute the charge.
|
|
def self.charge(teacher)
|
|
payment = TeacherPayment.joins(:teacher_payment_charge).where('teacher_payments.teacher_id = ?', teacher.id).where('charges.billed = false').order(:created_at).first
|
|
if payment.nil?
|
|
payment = TeacherPayment.new
|
|
payment.teacher = teacher
|
|
else
|
|
payment = TeacherPayment.find(payment.id)
|
|
end
|
|
|
|
if payment.teacher_distribution.nil?
|
|
teacher_distribution = TeacherDistribution.where(teacher_id: teacher.id).where(ready: true).where(distributed: false).order(:created_at).first
|
|
if teacher_distribution.nil?
|
|
return
|
|
end
|
|
payment.teacher_distribution = teacher_distribution
|
|
end
|
|
|
|
payment.school = payment.teacher_distribution.school
|
|
payment.amount_in_cents = payment.teacher_distribution.amount_in_cents
|
|
payment.fee_in_cents = payment.teacher_distribution.calculate_teacher_fee
|
|
|
|
if payment.teacher_distribution.amount_in_cents > 0
|
|
|
|
effective_in_cents = payment.real_distribution_in_cents
|
|
|
|
if payment.teacher_payment_charge.nil?
|
|
charge = TeacherPaymentCharge.new
|
|
charge.user = payment.payable_teacher
|
|
charge.amount_in_cents = (effective_in_cents / (1 - APP_CONFIG.stripe[:ach_pct])).round
|
|
charge.fee_in_cents = payment.fee_in_cents
|
|
charge.teacher_payment = payment
|
|
payment.teacher_payment_charge = charge
|
|
# charge.save!
|
|
else
|
|
charge = payment.teacher_payment_charge
|
|
charge.amount_in_cents = (effective_in_cents / (1 - APP_CONFIG.stripe[:ach_pct])).round
|
|
charge.fee_in_cents = payment.fee_in_cents
|
|
charge.save!
|
|
end
|
|
|
|
payment.save!
|
|
|
|
payment.teacher_payment_charge.charge
|
|
|
|
if payment.teacher_payment_charge.billed
|
|
payment.teacher_distribution.distributed = true
|
|
payment.teacher_distribution.save!
|
|
end
|
|
else
|
|
|
|
# 0 amount distribution; these occur in 100% roll forward scenarios (previous month was completely missed)
|
|
payment.save!
|
|
payment.teacher_distribution.distributed = true
|
|
payment.teacher_distribution.save!
|
|
|
|
end
|
|
|
|
payment
|
|
end
|
|
end
|
|
|
|
end |