jam-cloud/ruby/lib/jam_ruby/models/sale_line_item.rb

205 lines
7.9 KiB
Ruby

module JamRuby
class SaleLineItem < ActiveRecord::Base
JAMBLASTER = 'JamBlaster'
JAMCLOUD = 'JamCloud'
JAMTRACK = 'JamTrack'
GIFTCARD = 'GiftCardType'
LESSON = 'LessonPackageType'
POSACARD = 'PosaCard'
belongs_to :sale, class_name: 'JamRuby::Sale'
belongs_to :jam_track, class_name: 'JamRuby::JamTrack'
belongs_to :jam_track_right, class_name: 'JamRuby::JamTrackRight'
belongs_to :gift_card, class_name: 'JamRuby::GiftCard'
belongs_to :lesson_package_purchase, class_name: 'JamRuby::LessonPackagePurchase'
belongs_to :retailer, class_name: 'JamRuby::Retailer'
# deprecated; use affiliate_distribution !!
belongs_to :affiliate_referral, class_name: 'JamRuby::AffiliatePartner', foreign_key: :affiliate_referral_id
has_many :affiliate_distributions, class_name: 'JamRuby::AffiliateDistribution'
has_many :recurly_transactions, class_name: 'JamRuby::RecurlyTransactionWebHook', inverse_of: :sale_line_item, foreign_key: 'subscription_id', primary_key: 'recurly_subscription_uuid'
validates :product_type, inclusion: {in: [JAMBLASTER, JAMCLOUD, JAMTRACK, GIFTCARD, LESSON, POSACARD]}
validates :unit_price, numericality: {only_integer: false}
validates :quantity, numericality: {only_integer: true}
validates :free, numericality: {only_integer: true}
validates :sales_tax, numericality: {only_integer: false}, allow_nil: true
validates :shipping_handling, numericality: {only_integer: false}
validates :affiliate_referral_fee_in_cents, numericality: {only_integer: false}, allow_nil: true
validates :recurly_plan_code, presence:true
validates :sale, presence:true
def is_jam_track?
product_type == JAMTRACK
end
def is_gift_card?
product_type == GIFTCARD
end
def product
if product_type == JAMTRACK
JamTrack.find_by_id(product_id)
elsif product_type == GIFTCARD
GiftCardType.find_by_id(product_id)
elsif product_type == LESSON
lesson_package_purchase
elsif product_type == POSACARD
PosaCard.find(product_id)
else
raise 'unsupported product type'
end
end
def product_info
item = product
{ name: product.name, product_type: product_type } if item
end
def state
voided = false
refunded = false
failed = false
succeeded = false
recurly_transactions.each do |transaction|
if transaction.transaction_type == RecurlyTransactionWebHook::VOID
voided = true
elsif transaction.transaction_type == RecurlyTransactionWebHook::REFUND
refunded = true
elsif transaction.transaction_type == RecurlyTransactionWebHook::FAILED_PAYMENT
failed = true
elsif transaction.transaction_type == RecurlyTransactionWebHook::SUCCESSFUL_PAYMENT
succeeded = true
end
end
{
void: voided,
refund: refunded,
fail: failed,
success: succeeded
}
end
# in a shopping-cart less world (ios purchase), let's reuse as much logic as possible
def self.create_from_jam_track(current_user, sale, jam_track, mark_redeem)
shopping_cart = ShoppingCart.create(current_user, jam_track, 1, mark_redeem)
line_item = create_from_shopping_cart(sale, shopping_cart, nil, nil, nil)
shopping_cart.destroy
line_item
end
def add_referral_if_needed(user, shopping_cart, lesson_booking)
# if the teacher came from an affiliate, this is our chance to account for that (the student's affiliate status was accounted for in create_from_shopping_cart)
referral_info = user.should_attribute_sale?(shopping_cart, lesson_booking)
if referral_info
self.affiliate_distributions << AffiliateDistribution.create(user.affiliate_referral, referral_info[:fee_in_cents], self)
self.save!
end
end
# in a shopping-cart less world (ios purchase), let's reuse as much logic as possible
def self.create_from_lesson_package(current_user, sale, lesson_package_type, lesson_booking)
teacher = lesson_booking.teacher if lesson_booking
shopping_cart = ShoppingCart.create(current_user, lesson_package_type, 1)
line_item = create_from_shopping_cart(sale, shopping_cart, nil, nil, nil, lesson_booking)
if lesson_booking
teacher = lesson_booking.teacher
student = lesson_booking.student
if lesson_booking.is_test_drive?
# no referral for test drives
elsif lesson_booking.school_on_school?
# no referral; we don't make money on school-on-school
else
line_item.add_referral_if_needed(student, shopping_cart, lesson_booking)
if lesson_booking.school.nil?
line_item.add_referral_if_needed(teacher, shopping_cart, lesson_booking)
end
end
end
shopping_cart.destroy
line_item
end
def self.associate_user_for_posa(posa_card, user)
sale_line_item = SaleLineItem.where(product_type: POSACARD).where(product_id: posa_card.id).first
if sale_line_item
sale_line_item.sale.user = user
sale_line_item.sale.save!
end
end
def self.create_from_posa_card(sale, retailer, posa_card)
product_info = posa_card.product_info
sale_line_item = SaleLineItem.new
sale_line_item.retailer = retailer
sale_line_item.product_type = POSACARD
sale_line_item.product_id = posa_card.id
sale_line_item.unit_price = product_info[:price]
sale_line_item.quantity = product_info[:quantity]
sale_line_item.free = product_info[:marked_for_redeem]
sale_line_item.sales_tax = nil
sale_line_item.shipping_handling = 0
sale_line_item.recurly_plan_code = product_info[:plan_code]
#referral_info = retailer.referral_info
#if referral_info
# sale_line_item.affiliate_distributions << AffiliateDistribution.create(retailer.affiliate_partner, referral_info[:fee_in_cents], sale_line_item)
# sale_line_item.affiliate_referral = retailer.affiliate_partner
# sale_line_item.affiliate_referral_fee_in_cents = referral_info[:fee_in_cents]
#end
sale.sale_line_items << sale_line_item
sale_line_item.save
sale_line_item
end
def self.create_from_shopping_cart(sale, shopping_cart, recurly_subscription_uuid, recurly_adjustment_uuid, recurly_adjustment_credit_uuid, instance = nil)
product_info = shopping_cart.product_info(instance)
sale.order_total = sale.order_total + product_info[:real_price]
sale_line_item = SaleLineItem.new
sale_line_item.product_type = shopping_cart.cart_type
sale_line_item.variant = shopping_cart.variant
sale_line_item.unit_price = product_info[:price]
sale_line_item.quantity = product_info[:quantity]
sale_line_item.free = product_info[:marked_for_redeem]
sale_line_item.sales_tax = nil
sale_line_item.shipping_handling = 0
sale_line_item.recurly_plan_code = product_info[:plan_code]
sale_line_item.product_id = shopping_cart.cart_id
sale_line_item.recurly_subscription_uuid = recurly_subscription_uuid
sale_line_item.recurly_adjustment_uuid = recurly_adjustment_uuid
sale_line_item.recurly_adjustment_credit_uuid = recurly_adjustment_credit_uuid
# determine if we need to associate this sale with a partner
user = shopping_cart.user
referral_info = user.should_attribute_sale?(shopping_cart, instance) if !instance || !instance.is_a?(LessonBooking) # all affiliate stuff is handled elsewhere
if referral_info
sale_line_item.affiliate_distributions << AffiliateDistribution.create(user.affiliate_referral, referral_info[:fee_in_cents], sale_line_item)
sale_line_item.affiliate_referral = user.affiliate_referral
sale_line_item.affiliate_referral_fee_in_cents = referral_info[:fee_in_cents]
end
sale.sale_line_items << sale_line_item
sale_line_item.save
sale_line_item
end
end
end