GiftCards are purchable
This commit is contained in:
parent
6d514c3df2
commit
bd02774db9
|
|
@ -312,4 +312,5 @@ track_downloads.sql
|
|||
jam_track_lang_idx.sql
|
||||
giftcard.sql
|
||||
add_description_to_crash_dumps.sql
|
||||
acappella.sql
|
||||
acappella.sql
|
||||
purchasable_gift_cards.sql
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
|
||||
|
||||
CREATE TABLE gift_card_types (
|
||||
id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||
card_type VARCHAR(64) NOT NULL,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
INSERT INTO gift_card_types (id, card_type) VALUES ('jam_tracks_5', 'jam_tracks_5');
|
||||
INSERT INTO gift_card_types (id, card_type) VALUES ('jam_tracks_10', 'jam_tracks_10');
|
||||
|
||||
CREATE TABLE gift_card_purchases (
|
||||
id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||
user_id VARCHAR(64) NOT NULL REFERENCES users(id) ON DELETE SET NULL,
|
||||
gift_card_type_id VARCHAR(64) REFERENCES gift_card_types(id) ON DELETE SET NULL,
|
||||
recurly_adjustment_uuid VARCHAR(500),
|
||||
recurly_adjustment_credit_uuid VARCHAR(500),
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
|
||||
ALTER TABLE sale_line_items ADD COLUMN gift_card_purchase_id VARCHAR(64) REFERENCES gift_card_purchases(id);
|
||||
|
|
@ -254,6 +254,8 @@ require "jam_ruby/models/band_search"
|
|||
require "jam_ruby/import/tency_stem_mapping"
|
||||
require "jam_ruby/models/jam_track_search"
|
||||
require "jam_ruby/models/gift_card"
|
||||
require "jam_ruby/models/gift_card_purchase"
|
||||
require "jam_ruby/models/gift_card_type"
|
||||
|
||||
include Jampb
|
||||
|
||||
|
|
|
|||
|
|
@ -119,18 +119,16 @@ class JamRuby::AffiliatePartner < ActiveRecord::Base
|
|||
end
|
||||
|
||||
def should_attribute_sale?(shopping_cart)
|
||||
if shopping_cart.is_jam_track?
|
||||
if created_within_affiliate_window(shopping_cart.user, Time.now)
|
||||
product_info = shopping_cart.product_info
|
||||
# subtract the total quantity from the freebie quantity, to see how much we should attribute to them
|
||||
real_quantity = product_info[:quantity].to_i - product_info[:marked_for_redeem].to_i
|
||||
{fee_in_cents: (1.99 * 100 * real_quantity * rate.to_f).round}
|
||||
else
|
||||
false
|
||||
end
|
||||
|
||||
if created_within_affiliate_window(shopping_cart.user, Time.now)
|
||||
product_info = shopping_cart.product_info
|
||||
# subtract the total quantity from the freebie quantity, to see how much we should attribute to them
|
||||
real_quantity = product_info[:quantity].to_i - product_info[:marked_for_redeem].to_i
|
||||
{fee_in_cents: (product_info[:price] * 100 * real_quantity * rate.to_f).round}
|
||||
else
|
||||
raise 'shopping cart type not implemented yet'
|
||||
false
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def cumulative_earnings_in_dollars
|
||||
|
|
|
|||
|
|
@ -15,10 +15,15 @@ module JamRuby
|
|||
ShoppingCart.where(anonymous_user_id: @id).order('created_at DESC')
|
||||
end
|
||||
|
||||
|
||||
def destroy_all_shopping_carts
|
||||
ShoppingCart.destroy_all(anonymous_user_id: @id)
|
||||
end
|
||||
|
||||
def destroy_jam_track_shopping_carts
|
||||
ShoppingCart.destroy_all(anonymous_user_id: @id, cart_type: JamTrack::PRODUCT_TYPE)
|
||||
end
|
||||
|
||||
def admin
|
||||
false
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,14 +1,15 @@
|
|||
# represents the gift card you hold in your hand
|
||||
module JamRuby
|
||||
class GiftCard < ActiveRecord::Base
|
||||
|
||||
@@log = Logging.logger[GiftCard]
|
||||
|
||||
JAM_TRACKS_5 = 'jam_tracks_5'
|
||||
JAM_TRACKS_10 = 'jam_tracks_10'
|
||||
JAM_TRACKS_20 = 'jam_tracks_20'
|
||||
CARD_TYPES =
|
||||
[
|
||||
JAM_TRACKS_10,
|
||||
JAM_TRACKS_20
|
||||
JAM_TRACKS_5,
|
||||
JAM_TRACKS_10
|
||||
]
|
||||
|
||||
|
||||
|
|
@ -21,10 +22,10 @@ module JamRuby
|
|||
|
||||
def check_gifted
|
||||
if user && user_id_changed?
|
||||
if card_type == JAM_TRACKS_10
|
||||
if card_type == JAM_TRACKS_5
|
||||
user.gifted_jamtracks += 5
|
||||
elsif card_type == JAM_TRACKS_10
|
||||
user.gifted_jamtracks += 10
|
||||
elsif card_type == JAM_TRACKS_20
|
||||
user.gifted_jamtracks += 20
|
||||
else
|
||||
raise "unknown card type #{card_type}"
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,17 @@
|
|||
# reperesents the gift card you buy from the site (but physical gift card is modeled by GiftCard)
|
||||
module JamRuby
|
||||
class GiftCardPurchase < ActiveRecord::Base
|
||||
|
||||
@@log = Logging.logger[GiftCardPurchase]
|
||||
|
||||
attr_accessible :user, :gift_card_type
|
||||
|
||||
def name
|
||||
gift_card_type.sale_display
|
||||
end
|
||||
|
||||
# who purchased the card?
|
||||
belongs_to :user, class_name: "JamRuby::User"
|
||||
belongs_to :gift_card_type, class_name: "JamRuby::GiftCardType"
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
# reperesents the gift card you buy from the site (but physical gift card is modeled by GiftCard)
|
||||
module JamRuby
|
||||
class GiftCardType < ActiveRecord::Base
|
||||
|
||||
@@log = Logging.logger[GiftCardType]
|
||||
|
||||
PRODUCT_TYPE = 'GiftCardType'
|
||||
|
||||
JAM_TRACKS_5 = 'jam_tracks_5'
|
||||
JAM_TRACKS_10 = 'jam_tracks_10'
|
||||
CARD_TYPES =
|
||||
[
|
||||
JAM_TRACKS_5,
|
||||
JAM_TRACKS_10
|
||||
]
|
||||
|
||||
validates :card_type, presence: true, inclusion: {in: CARD_TYPES}
|
||||
|
||||
def self.jam_track_5
|
||||
GiftCardType.find(JAM_TRACKS_5)
|
||||
end
|
||||
|
||||
def self.jam_track_10
|
||||
GiftCardType.find(JAM_TRACKS_10)
|
||||
end
|
||||
|
||||
def name
|
||||
sale_display
|
||||
end
|
||||
|
||||
def price
|
||||
if card_type == JAM_TRACKS_5
|
||||
10.00
|
||||
elsif card_type == JAM_TRACKS_10
|
||||
20.00
|
||||
else
|
||||
raise "unknown card type #{card_type}"
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def sale_display
|
||||
if card_type == JAM_TRACKS_5
|
||||
'JamTracks Gift Card (5)'
|
||||
elsif card_type == JAM_TRACKS_10
|
||||
'JamTracks Gift Card (10)'
|
||||
else
|
||||
raise "unknown card type #{card_type}"
|
||||
end
|
||||
end
|
||||
|
||||
def plan_code
|
||||
if card_type == JAM_TRACKS_5
|
||||
"jamtrack-giftcard-5"
|
||||
elsif card_type == JAM_TRACKS_10
|
||||
"jamtrack-giftcard-10"
|
||||
else
|
||||
raise "unknown card type #{card_type}"
|
||||
end
|
||||
end
|
||||
|
||||
def sales_region
|
||||
'Worldwide'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -155,6 +155,9 @@ module JamRuby
|
|||
true
|
||||
end
|
||||
|
||||
def sale_display
|
||||
"JamTrack: " + name
|
||||
end
|
||||
def duplicate_positions?
|
||||
counter = {}
|
||||
jam_track_tracks.each do |track|
|
||||
|
|
|
|||
|
|
@ -92,53 +92,15 @@ module JamRuby
|
|||
transaction.save!
|
||||
|
||||
# now that we have the transaction saved, we also need to delete the jam_track_right if this is a refund, or voided
|
||||
|
||||
|
||||
if transaction.transaction_type == 'refund' || transaction.transaction_type == 'void'
|
||||
sale = Sale.find_by_recurly_invoice_id(transaction.invoice_id)
|
||||
|
||||
if sale && sale.is_jam_track_sale?
|
||||
if sale.sale_line_items.length == 1
|
||||
if sale.recurly_total_in_cents == transaction.amount_in_cents
|
||||
line_item = sale.sale_line_items[0]
|
||||
jam_track = line_item.product
|
||||
jam_track_right = jam_track.right_for_user(transaction.user) if jam_track
|
||||
if jam_track_right
|
||||
line_item.affiliate_refunded = true
|
||||
line_item.affiliate_refunded_at = Time.now
|
||||
line_item.save!
|
||||
if sale
|
||||
AdminMailer.recurly_alerts(transaction.user, {
|
||||
subject: "ACTION REQUIRED: #{transaction.user.email} has refund on invoice",
|
||||
body: "You will have to manually revoke any JamTrackRights in our database for the appropriate JamTracks"
|
||||
}).deliver
|
||||
|
||||
jam_track_right.destroy
|
||||
|
||||
# associate which JamTrack we assume this is related to in this one success case
|
||||
transaction.jam_track = jam_track
|
||||
transaction.save!
|
||||
|
||||
AdminMailer.recurly_alerts(transaction.user, {
|
||||
subject: "NOTICE: #{transaction.user.email} has had JamTrack: #{jam_track.name} revoked",
|
||||
body: "A #{transaction.transaction_type} event came from Recurly for sale with Recurly invoice ID #{sale.recurly_invoice_id}. We deleted their right to the track in our own database as a result."
|
||||
}).deliver
|
||||
else
|
||||
AdminMailer.recurly_alerts(transaction.user, {
|
||||
subject: "NOTICE: #{transaction.user.email} got a refund, but unable to find JamTrackRight to delete",
|
||||
body: "This should just mean the user already has no rights to the JamTrackRight when the refund came in. Not a big deal, but sort of weird..."
|
||||
}).deliver
|
||||
end
|
||||
|
||||
else
|
||||
AdminMailer.recurly_alerts(transaction.user, {
|
||||
subject: "ACTION REQUIRED: #{transaction.user.email} got a refund it was not for total value of a JamTrack sale",
|
||||
body: "We received a #{transaction.transaction_type} notice for an amount that was not the same as the original sale. So, no action was taken in the database. sale total: #{sale.recurly_total_in_cents}, refund amount: #{transaction.amount_in_cents}"
|
||||
}).deliver
|
||||
end
|
||||
|
||||
|
||||
else
|
||||
AdminMailer.recurly_alerts(transaction.user, {
|
||||
subject: "ACTION REQUIRED: #{transaction.user.email} has refund on invoice with multiple JamTracks",
|
||||
body: "You will have to manually revoke any JamTrackRights in our database for the appropriate JamTracks"
|
||||
}).deliver
|
||||
end
|
||||
else
|
||||
AdminMailer.recurly_alerts(transaction.user, {
|
||||
subject: "ACTION REQUIRED: #{transaction.user.email} has refund with no correlator to sales",
|
||||
|
|
|
|||
|
|
@ -69,28 +69,6 @@ module JamRuby
|
|||
}
|
||||
end
|
||||
|
||||
def self.preview_invoice(current_user, shopping_carts)
|
||||
|
||||
line_items = {jam_tracks: []}
|
||||
shopping_carts_jam_tracks = []
|
||||
shopping_carts_subscriptions = []
|
||||
shopping_carts.each do |shopping_cart|
|
||||
|
||||
if shopping_cart.is_jam_track?
|
||||
shopping_carts_jam_tracks << shopping_cart
|
||||
else
|
||||
# XXX: this may have to be revisited when we actually have something other than JamTracks for puchase
|
||||
shopping_carts_subscriptions << shopping_cart
|
||||
end
|
||||
end
|
||||
|
||||
jam_track_items = preview_invoice_jam_tracks(current_user, shopping_carts_jam_tracks)
|
||||
line_items[:jam_tracks] = jam_track_items if jam_track_items
|
||||
|
||||
# TODO: process shopping_carts_subscriptions
|
||||
|
||||
line_items
|
||||
end
|
||||
|
||||
def self.ios_purchase(current_user, jam_track, receipt)
|
||||
jam_track_right = JamRuby::JamTrackRight.find_or_create_by_user_id_and_jam_track_id(current_user.id, jam_track.id) do |jam_track_right|
|
||||
|
|
@ -105,19 +83,14 @@ module JamRuby
|
|||
def self.place_order(current_user, shopping_carts)
|
||||
|
||||
sales = []
|
||||
shopping_carts_jam_tracks = []
|
||||
shopping_carts_subscriptions = []
|
||||
shopping_carts.each do |shopping_cart|
|
||||
|
||||
if shopping_cart.is_jam_track?
|
||||
shopping_carts_jam_tracks << shopping_cart
|
||||
else
|
||||
# XXX: this may have to be revisited when we actually have something other than JamTracks for puchase
|
||||
shopping_carts_subscriptions << shopping_cart
|
||||
end
|
||||
|
||||
if Sale.is_mixed(shopping_carts)
|
||||
# the controller checks this too; this is just an extra-level of sanity checking
|
||||
return sales
|
||||
end
|
||||
|
||||
jam_track_sale = order_jam_tracks(current_user, shopping_carts_jam_tracks)
|
||||
jam_track_sale = order_jam_tracks(current_user, shopping_carts)
|
||||
sales << jam_track_sale if jam_track_sale
|
||||
|
||||
# TODO: process shopping_carts_subscriptions
|
||||
|
|
@ -125,18 +98,10 @@ module JamRuby
|
|||
sales
|
||||
end
|
||||
|
||||
def self.preview_invoice_jam_tracks(current_user, shopping_carts_jam_tracks)
|
||||
### XXX TODO;
|
||||
|
||||
# we currently use a fake plan in Recurly to estimate taxes using the Pricing.Attach metod in Recurly.js
|
||||
|
||||
# if we were to implement this the right way (ensure adjustments are on the account as necessary), then it would be better (more correct)
|
||||
# just a pain to implement
|
||||
end
|
||||
|
||||
def self.is_only_freebie(shopping_carts_jam_tracks)
|
||||
def self.is_only_freebie(shopping_carts)
|
||||
free = true
|
||||
shopping_carts_jam_tracks.each do |cart|
|
||||
shopping_carts.each do |cart|
|
||||
free = cart.product_info[:free]
|
||||
|
||||
if !free
|
||||
|
|
@ -162,7 +127,23 @@ module JamRuby
|
|||
|
||||
# this method will either return a valid sale, or throw a RecurlyClientError or ActiveRecord validation error (save! failed)
|
||||
# it may return an nil sale if the JamTrack(s) specified by the shopping carts are already owned
|
||||
def self.order_jam_tracks(current_user, shopping_carts_jam_tracks)
|
||||
def self.order_jam_tracks(current_user, shopping_carts)
|
||||
|
||||
shopping_carts_jam_tracks = []
|
||||
shopping_carts_subscriptions = []
|
||||
shopping_carts_gift_cards = []
|
||||
|
||||
shopping_carts.each do |shopping_cart|
|
||||
if shopping_cart.is_jam_track?
|
||||
shopping_carts_jam_tracks << shopping_cart
|
||||
elsif shopping_cart.is_gift_card?
|
||||
shopping_carts_gift_cards << shopping_cart
|
||||
else
|
||||
# XXX: this may have to be revisited when we actually have something other than JamTracks for puchase
|
||||
raise "unknown shopping cart type #{shopping_cart.cart_type}"
|
||||
shopping_carts_subscriptions << shopping_cart
|
||||
end
|
||||
end
|
||||
|
||||
client = RecurlyClient.new
|
||||
|
||||
|
|
@ -171,8 +152,8 @@ module JamRuby
|
|||
sale = create_jam_track_sale(current_user)
|
||||
|
||||
if sale.valid?
|
||||
if is_only_freebie(shopping_carts_jam_tracks)
|
||||
sale.process_jam_tracks(current_user, shopping_carts_jam_tracks, nil)
|
||||
if is_only_freebie(shopping_carts)
|
||||
sale.process_shopping_carts(current_user, shopping_carts, nil)
|
||||
|
||||
sale.recurly_subtotal_in_cents = 0
|
||||
sale.recurly_tax_in_cents = 0
|
||||
|
|
@ -187,11 +168,13 @@ module JamRuby
|
|||
return sale
|
||||
end
|
||||
|
||||
sale_line_item = sale.sale_line_items[0]
|
||||
sale_line_item.recurly_tax_in_cents = 0
|
||||
sale_line_item.recurly_total_in_cents = 0
|
||||
sale_line_item.recurly_currency = 'USD'
|
||||
sale_line_item.recurly_discount_in_cents = 0
|
||||
sale.sale_line_items.each do |sale_line_item|
|
||||
sale_line_item = sale.sale_line_items[0]
|
||||
sale_line_item.recurly_tax_in_cents = 0
|
||||
sale_line_item.recurly_total_in_cents = 0
|
||||
sale_line_item.recurly_currency = 'USD'
|
||||
sale_line_item.recurly_discount_in_cents = 0
|
||||
end
|
||||
sale.save
|
||||
|
||||
else
|
||||
|
|
@ -201,7 +184,7 @@ module JamRuby
|
|||
|
||||
purge_pending_adjustments(account)
|
||||
|
||||
created_adjustments = sale.process_jam_tracks(current_user, shopping_carts_jam_tracks, account)
|
||||
created_adjustments = sale.process_shopping_carts(current_user, shopping_carts, account)
|
||||
|
||||
# now invoice the sale ... almost done
|
||||
|
||||
|
|
@ -257,13 +240,13 @@ module JamRuby
|
|||
sale
|
||||
end
|
||||
|
||||
def process_jam_tracks(current_user, shopping_carts_jam_tracks, account)
|
||||
def process_shopping_carts(current_user, shopping_carts, account)
|
||||
|
||||
created_adjustments = []
|
||||
|
||||
begin
|
||||
shopping_carts_jam_tracks.each do |shopping_cart|
|
||||
process_jam_track(current_user, shopping_cart, account, created_adjustments)
|
||||
shopping_carts.each do |shopping_cart|
|
||||
process_shopping_cart(current_user, shopping_cart, account, created_adjustments)
|
||||
end
|
||||
rescue Recurly::Error, NoMethodError => x
|
||||
# rollback any adjustments created if error
|
||||
|
|
@ -279,7 +262,7 @@ module JamRuby
|
|||
end
|
||||
|
||||
|
||||
def process_jam_track(current_user, shopping_cart, account, created_adjustments)
|
||||
def process_shopping_cart(current_user, shopping_cart, account, created_adjustments)
|
||||
recurly_adjustment_uuid = nil
|
||||
recurly_adjustment_credit_uuid = nil
|
||||
|
||||
|
|
@ -287,15 +270,20 @@ module JamRuby
|
|||
shopping_cart.reload
|
||||
|
||||
# get the JamTrack in this shopping cart
|
||||
jam_track = shopping_cart.cart_product
|
||||
cart_product = shopping_cart.cart_product
|
||||
|
||||
if jam_track.right_for_user(current_user)
|
||||
# if the user already owns the JamTrack, we should just skip this cart item, and destroy it
|
||||
# if this occurs, we have to reload every shopping_cart as we iterate. so, we do at the top of the loop
|
||||
ShoppingCart.remove_jam_track_from_cart(current_user, shopping_cart)
|
||||
return
|
||||
if shopping_cart.is_jam_track?
|
||||
jam_track = cart_product
|
||||
if jam_track.right_for_user(current_user)
|
||||
# if the user already owns the JamTrack, we should just skip this cart item, and destroy it
|
||||
# if this occurs, we have to reload every shopping_cart as we iterate. so, we do at the top of the loop
|
||||
ShoppingCart.remove_jam_track_from_cart(current_user, shopping_cart)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
if account
|
||||
# ask the shopping cart to create the correct Recurly adjustment attributes for a JamTrack
|
||||
adjustments = shopping_cart.create_adjustment_attributes(current_user)
|
||||
|
|
@ -328,45 +316,69 @@ module JamRuby
|
|||
|
||||
# if the sale line item is invalid, blow up the transaction
|
||||
unless sale_line_item.valid?
|
||||
@log.error("sale item invalid! #{sale_line_item.errors.inspect}")
|
||||
@@log.error("sale item invalid! #{sale_line_item.errors.inspect}")
|
||||
puts("sale item invalid! #{sale_line_item.errors.inspect}")
|
||||
Stats.write('web.recurly.purchase.sale_invalid', {message: sale_line_item.errors.to_s, value: 1})
|
||||
raise RecurlyClientError.new(sale_line_item.errors)
|
||||
end
|
||||
|
||||
# create a JamTrackRight (this needs to be in a transaction too to make sure we don't make these by accident)
|
||||
jam_track_right = JamRuby::JamTrackRight.find_or_create_by_user_id_and_jam_track_id(current_user.id, jam_track.id) do |jam_track_right|
|
||||
jam_track_right.redeemed = shopping_cart.free?
|
||||
end
|
||||
if shopping_cart.is_jam_track?
|
||||
jam_track = cart_product
|
||||
|
||||
# also if the purchase was a free one, then:
|
||||
# first, mark the free has_redeemable_jamtrack field if that's still true
|
||||
# and if still they have more free things, then redeem the giftable_jamtracks
|
||||
if shopping_cart.free?
|
||||
if user.has_redeemable_jamtrack
|
||||
User.where(id: current_user.id).update_all(has_redeemable_jamtrack: false)
|
||||
current_user.has_redeemable_jamtrack = false
|
||||
else
|
||||
User.where(id: current_user.id).update_all(gifted_jamtracks: current_user.gifted_jamtracks - 1)
|
||||
current_user.gifted_jamtracks = current_user.gifted_jamtracks - 1
|
||||
# create a JamTrackRight (this needs to be in a transaction too to make sure we don't make these by accident)
|
||||
jam_track_right = JamRuby::JamTrackRight.find_or_create_by_user_id_and_jam_track_id(current_user.id, jam_track.id) do |jam_track_right|
|
||||
jam_track_right.redeemed = shopping_cart.free?
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
# this can't go in the block above, as it's here to fix bad subscription UUIDs in an update path
|
||||
if jam_track_right.recurly_adjustment_uuid != recurly_adjustment_uuid
|
||||
jam_track_right.recurly_adjustment_uuid = recurly_adjustment_uuid
|
||||
jam_track_right.recurly_adjustment_credit_uuid = recurly_adjustment_credit_uuid
|
||||
unless jam_track_right.save
|
||||
raise RecurlyClientError.new(jam_track_right.errors)
|
||||
# also if the purchase was a free one, then:
|
||||
# first, mark the free has_redeemable_jamtrack field if that's still true
|
||||
# and if still they have more free things, then redeem the giftable_jamtracks
|
||||
if shopping_cart.free?
|
||||
if user.has_redeemable_jamtrack
|
||||
User.where(id: current_user.id).update_all(has_redeemable_jamtrack: false)
|
||||
current_user.has_redeemable_jamtrack = false
|
||||
else
|
||||
User.where(id: current_user.id).update_all(gifted_jamtracks: current_user.gifted_jamtracks - 1)
|
||||
current_user.gifted_jamtracks = current_user.gifted_jamtracks - 1
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
# this can't go in the block above, as it's here to fix bad subscription UUIDs in an update path
|
||||
if jam_track_right.recurly_adjustment_uuid != recurly_adjustment_uuid
|
||||
jam_track_right.recurly_adjustment_uuid = recurly_adjustment_uuid
|
||||
jam_track_right.recurly_adjustment_credit_uuid = recurly_adjustment_credit_uuid
|
||||
unless jam_track_right.save
|
||||
raise RecurlyClientError.new(jam_track_right.errors)
|
||||
end
|
||||
end
|
||||
|
||||
# blow up the transaction if the JamTrackRight did not get created
|
||||
raise RecurlyClientError.new(jam_track_right.errors) if jam_track_right.errors.any?
|
||||
|
||||
elsif shopping_cart.is_gift_card?
|
||||
gift_card_type = cart_product
|
||||
raise "gift card is null" if gift_card_type.nil?
|
||||
raise if current_user.nil?
|
||||
|
||||
shopping_cart.quantity.times do |item|
|
||||
gift_card_purchase = GiftCardPurchase.new(
|
||||
{
|
||||
user: current_user,
|
||||
gift_card_type: gift_card_type
|
||||
})
|
||||
|
||||
unless gift_card_purchase.save
|
||||
raise RecurlyClientError.new(gift_card_purchase.errors)
|
||||
end
|
||||
end
|
||||
|
||||
else
|
||||
raise 'unknown shopping cart type: ' + shopping_cart.cart_type
|
||||
end
|
||||
|
||||
# delete the shopping cart; it's been dealt with
|
||||
shopping_cart.destroy if shopping_cart
|
||||
|
||||
# blow up the transaction if the JamTrackRight did not get created
|
||||
raise RecurlyClientError.new(jam_track_right.errors) if jam_track_right.errors.any?
|
||||
end
|
||||
|
||||
|
||||
|
|
@ -396,7 +408,7 @@ module JamRuby
|
|||
def self.create_jam_track_sale(user)
|
||||
sale = Sale.new
|
||||
sale.user = user
|
||||
sale.sale_type = JAMTRACK_SALE
|
||||
sale.sale_type = JAMTRACK_SALE # gift cards and jam tracks are sold with this type of sale
|
||||
sale.order_total = 0
|
||||
sale.save
|
||||
sale
|
||||
|
|
|
|||
|
|
@ -4,14 +4,16 @@ module JamRuby
|
|||
JAMBLASTER = 'JamBlaster'
|
||||
JAMCLOUD = 'JamCloud'
|
||||
JAMTRACK = 'JamTrack'
|
||||
GIFTCARD = 'GiftCardType'
|
||||
|
||||
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 :affiliate_referral, class_name: 'JamRuby::AffiliatePartner', foreign_key: :affiliate_referral_id
|
||||
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]}
|
||||
validates :product_type, inclusion: {in: [JAMBLASTER, JAMCLOUD, JAMTRACK, GIFTCARD]}
|
||||
validates :unit_price, numericality: {only_integer: false}
|
||||
validates :quantity, numericality: {only_integer: true}
|
||||
validates :free, numericality: {only_integer: true}
|
||||
|
|
@ -21,9 +23,19 @@ module JamRuby
|
|||
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)
|
||||
else
|
||||
raise 'unsupported product type'
|
||||
end
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ module JamRuby
|
|||
|
||||
def product_info
|
||||
product = self.cart_product
|
||||
{name: product.name, price: product.price, product_id: cart_id, plan_code: product.plan_code, real_price: real_price(product), total_price: total_price(product), quantity: quantity, marked_for_redeem: marked_for_redeem, free: free?, sales_region: product.sales_region} unless product.nil?
|
||||
{type: cart_type, name: product.name, price: product.price, product_id: cart_id, plan_code: product.plan_code, real_price: real_price(product), total_price: total_price(product), quantity: quantity, marked_for_redeem: marked_for_redeem, free: free?, sales_region: product.sales_region, sale_display:product.sale_display} unless product.nil?
|
||||
end
|
||||
|
||||
# multiply quantity by price
|
||||
|
|
@ -90,6 +90,7 @@ module JamRuby
|
|||
end
|
||||
|
||||
def self.create user, product, quantity = 1, mark_redeem = false
|
||||
|
||||
cart = ShoppingCart.new
|
||||
if user.is_a?(User)
|
||||
cart.user = user
|
||||
|
|
@ -110,40 +111,42 @@ module JamRuby
|
|||
cart_type == JamTrack::PRODUCT_TYPE
|
||||
end
|
||||
|
||||
def is_gift_card?
|
||||
cart_type == GiftCardType::PRODUCT_TYPE
|
||||
end
|
||||
|
||||
# returns an array of adjustments for the shopping cart
|
||||
def create_adjustment_attributes(current_user)
|
||||
raise "not a jam track" unless is_jam_track?
|
||||
raise "not a jam track or gift card" unless is_jam_track? || is_gift_card?
|
||||
|
||||
info = self.product_info
|
||||
|
||||
if free?
|
||||
|
||||
puts "GOT A FREEBIE!"
|
||||
# create the credit, then the pseudo charge
|
||||
[
|
||||
{
|
||||
accounting_code: PURCHASE_FREE_CREDIT,
|
||||
currency: 'USD',
|
||||
unit_amount_in_cents: -(info[:total_price] * 100).to_i,
|
||||
description: "JamTrack: " + info[:name] + " (Credit)",
|
||||
description: info[:sale_display] + " (Credit)",
|
||||
tax_exempt: true
|
||||
},
|
||||
{
|
||||
accounting_code: PURCHASE_FREE,
|
||||
currency: 'USD',
|
||||
unit_amount_in_cents: (info[:total_price] * 100).to_i,
|
||||
description: "JamTrack: " + info[:name],
|
||||
description: info[:sale_display],
|
||||
tax_exempt: true
|
||||
}
|
||||
]
|
||||
else
|
||||
|
||||
[
|
||||
{
|
||||
accounting_code: PURCHASE_NORMAL,
|
||||
currency: 'USD',
|
||||
unit_amount_in_cents: (info[:total_price] * 100).to_i,
|
||||
description: "JamTrack: " + info[:name],
|
||||
description: info[:sale_display],
|
||||
tax_exempt: false
|
||||
}
|
||||
]
|
||||
|
|
@ -152,8 +155,13 @@ module JamRuby
|
|||
|
||||
def self.move_to_user(user, anonymous_user, shopping_carts)
|
||||
shopping_carts.each do |shopping_cart|
|
||||
mark_redeem = ShoppingCart.user_has_redeemable_jam_track?(user)
|
||||
cart = ShoppingCart.create(user, shopping_cart.cart_product, shopping_cart.quantity, mark_redeem)
|
||||
if shopping_cart.is_jam_track?
|
||||
mark_redeem = ShoppingCart.user_has_redeemable_jam_track?(user)
|
||||
cart = ShoppingCart.create(user, shopping_cart.cart_product, shopping_cart.quantity, mark_redeem)
|
||||
else
|
||||
cart = ShoppingCart.create(user, shopping_cart.cart_product, shopping_cart.quantity, false)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
anonymous_user.destroy_all_shopping_carts
|
||||
|
|
@ -197,7 +205,7 @@ module JamRuby
|
|||
|
||||
if clear
|
||||
# if you are an anonymous user, we make sure there is nothing else in your shopping cart ... keep it clean for the 'new user rummaging around for a freebie scenario'
|
||||
any_user.destroy_all_shopping_carts
|
||||
any_user.destroy_jam_track_shopping_carts
|
||||
any_user.reload
|
||||
end
|
||||
|
||||
|
|
@ -207,6 +215,14 @@ module JamRuby
|
|||
cart
|
||||
end
|
||||
|
||||
def self.add_item_to_cart(any_user, item)
|
||||
cart = nil
|
||||
ShoppingCart.transaction do
|
||||
cart = ShoppingCart.create(any_user, item, 1, false)
|
||||
end
|
||||
cart
|
||||
end
|
||||
|
||||
# deletes a jam track from the shopping cart, updating redeem flag as necessary
|
||||
def self.remove_jam_track_from_cart(any_user, cart)
|
||||
ShoppingCart.transaction do
|
||||
|
|
@ -236,6 +252,12 @@ module JamRuby
|
|||
end
|
||||
end
|
||||
|
||||
def self.remove_item_from_cart(any_user, cart)
|
||||
ShoppingCart.transaction do
|
||||
cart.destroy
|
||||
end
|
||||
end
|
||||
|
||||
# if the number of items in the shopping cart is less than gifted_jamtracks on the user, then fix them all up
|
||||
def self.apply_gifted_jamtracks(user)
|
||||
jam_track_carts = user.shopping_carts.where(cart_type:JamTrack::PRODUCT_TYPE)
|
||||
|
|
|
|||
|
|
@ -150,6 +150,8 @@ module JamRuby
|
|||
|
||||
# gift cards
|
||||
has_many :gift_cards, :class_name=> "JamRuby::GiftCard"
|
||||
has_many :gift_card_purchases, :class_name=> "JamRuby::GiftCardPurchase"
|
||||
|
||||
|
||||
# affiliate_partner
|
||||
has_one :affiliate_partner, :class_name => "JamRuby::AffiliatePartner", :foreign_key => :partner_user_id, inverse_of: :partner_user
|
||||
|
|
@ -1678,6 +1680,11 @@ module JamRuby
|
|||
ShoppingCart.where("user_id=?", self).destroy_all
|
||||
end
|
||||
|
||||
def destroy_jam_track_shopping_carts
|
||||
ShoppingCart.destroy_all(anonymous_user_id: @id, cart_type: JamTrack::PRODUCT_TYPE)
|
||||
end
|
||||
|
||||
|
||||
def unsubscribe_token
|
||||
self.class.create_access_token(self)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -862,7 +862,16 @@ FactoryGirl.define do
|
|||
|
||||
factory :gift_card, class: 'JamRuby::GiftCard' do
|
||||
sequence(:code) {n.to_s}
|
||||
card_type = JamRuby::GiftCard::JAM_TRACKS_10
|
||||
card_type JamRuby::GiftCardType::JAM_TRACKS_5
|
||||
end
|
||||
|
||||
factory :gift_card_type, class: 'JamRuby::GiftCardType' do
|
||||
card_type JamRuby::GiftCardType::JAM_TRACKS_5
|
||||
end
|
||||
|
||||
factory :gift_card_purchase, class: 'JamRuby::GiftCardPurchase' do
|
||||
|
||||
association :user, factory: :user
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -135,7 +135,7 @@ describe RecurlyTransactionWebHook do
|
|||
|
||||
RecurlyTransactionWebHook.create_from_xml(document)
|
||||
|
||||
JamTrackRight.find_by_id(jam_track_right.id).should be_nil
|
||||
JamTrackRight.find_by_id(jam_track_right.id).should_not be_nil
|
||||
end
|
||||
|
||||
it "deletes jam_track_right when voided" do
|
||||
|
|
@ -154,7 +154,7 @@ describe RecurlyTransactionWebHook do
|
|||
|
||||
RecurlyTransactionWebHook.create_from_xml(document)
|
||||
|
||||
JamTrackRight.find_by_id(jam_track_right.id).should be_nil
|
||||
JamTrackRight.find_by_id(jam_track_right.id).should_not be_nil
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ describe SaleLineItem do
|
|||
let(:user) {FactoryGirl.create(:user)}
|
||||
let(:user2) {FactoryGirl.create(:user)}
|
||||
let(:jam_track) {FactoryGirl.create(:jam_track)}
|
||||
let(:gift_card) {FactoryGirl.create(:gift_card_type, card_type: GiftCardType::JAM_TRACKS_10)}
|
||||
|
||||
describe "associations" do
|
||||
|
||||
|
|
@ -23,7 +24,7 @@ describe SaleLineItem do
|
|||
|
||||
describe "state" do
|
||||
|
||||
it "success" do
|
||||
it "jam track success" do
|
||||
sale = Sale.create_jam_track_sale(user)
|
||||
shopping_cart = ShoppingCart.create(user, jam_track)
|
||||
sale_line_item = SaleLineItem.create_from_shopping_cart(sale, shopping_cart, 'some_recurly_uuid', nil, nil)
|
||||
|
|
@ -37,5 +38,20 @@ describe SaleLineItem do
|
|||
success: true
|
||||
})
|
||||
end
|
||||
|
||||
it "gift card success" do
|
||||
sale = Sale.create_jam_track_sale(user)
|
||||
shopping_cart = ShoppingCart.create(user, gift_card)
|
||||
sale_line_item = SaleLineItem.create_from_shopping_cart(sale, shopping_cart, 'some_recurly_uuid', nil, nil)
|
||||
transaction = FactoryGirl.create(:recurly_transaction_web_hook, subscription_id: 'some_recurly_uuid')
|
||||
|
||||
sale_line_item.reload
|
||||
sale_line_item.state.should eq({
|
||||
void: false,
|
||||
refund: false,
|
||||
fail: false,
|
||||
success: true
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ describe Sale do
|
|||
let(:jam_track) {FactoryGirl.create(:jam_track)}
|
||||
let(:jam_track2) {FactoryGirl.create(:jam_track)}
|
||||
let(:jam_track3) {FactoryGirl.create(:jam_track)}
|
||||
let(:gift_card) {GiftCardType.jam_track_5}
|
||||
|
||||
def assert_free_line_item(sale_line_item, jamtrack)
|
||||
sale_line_item.recurly_tax_in_cents.should be_nil
|
||||
|
|
@ -68,6 +69,7 @@ describe Sale do
|
|||
let(:jamtrack3) { FactoryGirl.create(:jam_track) }
|
||||
let(:jamtrack4) { FactoryGirl.create(:jam_track) }
|
||||
let(:jam_track_price_in_cents) { (jamtrack.price * 100).to_i }
|
||||
let(:gift_card_price_in_cents) { (gift_card.price * 100).to_i }
|
||||
let(:client) { RecurlyClient.new }
|
||||
let(:billing_info) {
|
||||
info = {}
|
||||
|
|
@ -95,6 +97,77 @@ describe Sale do
|
|||
end
|
||||
end
|
||||
|
||||
it "for a gift card" do
|
||||
shopping_cart = ShoppingCart.create user, gift_card, 1, false
|
||||
client.find_or_create_account(user, billing_info)
|
||||
|
||||
sales = Sale.place_order(user, [shopping_cart])
|
||||
|
||||
user.reload
|
||||
user.sales.length.should eq(1)
|
||||
|
||||
sales.should eq(user.sales)
|
||||
sale = sales[0]
|
||||
sale.recurly_invoice_id.should_not be_nil
|
||||
|
||||
sale.recurly_subtotal_in_cents.should eq(gift_card_price_in_cents)
|
||||
sale.recurly_tax_in_cents.should eq(0)
|
||||
sale.recurly_total_in_cents.should eq(gift_card_price_in_cents)
|
||||
sale.recurly_currency.should eq('USD')
|
||||
|
||||
sale.order_total.should eq(gift_card.price)
|
||||
sale.sale_line_items.length.should == 1
|
||||
sale_line_item = sale.sale_line_items[0]
|
||||
# validate we are storing pricing info from recurly
|
||||
sale_line_item.recurly_tax_in_cents.should eq(0)
|
||||
sale_line_item.recurly_total_in_cents.should eq(gift_card_price_in_cents)
|
||||
sale_line_item.recurly_currency.should eq('USD')
|
||||
sale_line_item.recurly_discount_in_cents.should eq(0)
|
||||
sale_line_item.product_type.should eq(GiftCardType::PRODUCT_TYPE)
|
||||
sale_line_item.unit_price.should eq(gift_card.price)
|
||||
sale_line_item.quantity.should eq(1)
|
||||
sale_line_item.free.should eq(0)
|
||||
sale_line_item.sales_tax.should be_nil
|
||||
sale_line_item.shipping_handling.should eq(0)
|
||||
sale_line_item.recurly_plan_code.should eq(gift_card.plan_code)
|
||||
sale_line_item.product_id.should eq(gift_card.id)
|
||||
sale_line_item.recurly_subscription_uuid.should be_nil
|
||||
sale_line_item.recurly_adjustment_uuid.should_not be_nil
|
||||
sale_line_item.recurly_adjustment_credit_uuid.should be_nil
|
||||
sale_line_item.recurly_adjustment_uuid.should_not be_nil
|
||||
|
||||
# verify subscription is in Recurly
|
||||
recurly_account = client.get_account(user)
|
||||
adjustments = recurly_account.adjustments
|
||||
adjustments.should_not be_nil
|
||||
adjustments.should have(1).items
|
||||
purchase= adjustments[0]
|
||||
purchase.unit_amount_in_cents.should eq((gift_card.price * 100).to_i)
|
||||
purchase.accounting_code.should eq(ShoppingCart::PURCHASE_NORMAL)
|
||||
purchase.description.should eq("JamTracks Gift Card (5)")
|
||||
purchase.state.should eq('invoiced')
|
||||
purchase.uuid.should eq(sale_line_item.recurly_adjustment_uuid)
|
||||
|
||||
invoices = recurly_account.invoices
|
||||
invoices.should have(1).items
|
||||
invoice = invoices[0]
|
||||
invoice.uuid.should eq(sale.recurly_invoice_id)
|
||||
invoice.line_items.should have(1).items # should have single adjustment associated
|
||||
invoice.line_items[0].should eq(purchase)
|
||||
invoice.subtotal_in_cents.should eq((gift_card.price * 100).to_i)
|
||||
invoice.total_in_cents.should eq((gift_card.price * 100).to_i)
|
||||
invoice.state.should eq('collected')
|
||||
|
||||
# verify jam_track_rights data
|
||||
user.gift_card_purchases.should_not be_nil
|
||||
user.gift_card_purchases.should have(1).items
|
||||
user.gift_card_purchases.last.gift_card_type.should eq(GiftCardType.jam_track_5)
|
||||
user.has_redeemable_jamtrack.should be_true
|
||||
|
||||
sale_line_item.affiliate_referral.should be_nil
|
||||
sale_line_item.affiliate_referral_fee_in_cents.should be_nil
|
||||
end
|
||||
|
||||
|
||||
it "for a free jam track" do
|
||||
shopping_cart = ShoppingCart.create user, jamtrack, 1, true
|
||||
|
|
@ -195,48 +268,25 @@ describe Sale do
|
|||
|
||||
# OK! Now make a second purchase; this time, buy one free, one not free
|
||||
shopping_cart3 = ShoppingCart.create user, jamtrack3, 1, true
|
||||
shopping_cart4 = ShoppingCart.create user, jamtrack4, 1, false
|
||||
|
||||
client.find_or_create_account(user, billing_info)
|
||||
|
||||
sales = Sale.place_order(user, [shopping_cart3, shopping_cart4])
|
||||
sales = Sale.place_order(user, [shopping_cart3])
|
||||
|
||||
user.reload
|
||||
user.sales.length.should eq(2)
|
||||
sale = sales[0]
|
||||
sale.reload
|
||||
|
||||
sale.recurly_invoice_id.should_not be_nil
|
||||
sale.recurly_invoice_id.should be_nil
|
||||
sale.recurly_subtotal_in_cents.should eq(0)
|
||||
sale.recurly_tax_in_cents.should eq(0)
|
||||
sale.recurly_total_in_cents.should eq(0)
|
||||
sale.recurly_currency.should eq('USD')
|
||||
sale.order_total.should eq(0)
|
||||
sale.sale_line_items.length.should == 2
|
||||
sale.sale_line_items.length.should == 1
|
||||
|
||||
assert_free_line_item(sale.sale_line_items[0], jamtrack3)
|
||||
|
||||
paid_right = JamTrackRight.where(user_id:user.id).where(jam_track_id: jamtrack4.id).first
|
||||
|
||||
sale_line_item.recurly_total_in_cents.should eq(jam_track_price_in_cents)
|
||||
sale_line_item.recurly_currency.should eq('USD')
|
||||
sale_line_item.recurly_discount_in_cents.should eq(0)
|
||||
sale_line_item.product_type.should eq(JamTrack::PRODUCT_TYPE)
|
||||
sale_line_item.unit_price.should eq(jamtrack4.price)
|
||||
sale_line_item.quantity.should eq(1)
|
||||
sale_line_item.free.should eq(0)
|
||||
sale_line_item.sales_tax.should be_nil
|
||||
sale_line_item.shipping_handling.should eq(0)
|
||||
sale_line_item.recurly_plan_code.should eq(jamtrack4.plan_code)
|
||||
sale_line_item.product_id.should eq(jamtrack.id)
|
||||
sale_line_item.recurly_subscription_uuid.should be_nil
|
||||
sale_line_item.recurly_adjustment_uuid.should_not be_nil
|
||||
sale_line_item.recurly_adjustment_credit_uuid.should be_nil
|
||||
sale_line_item.recurly_adjustment_uuid.should eq(paid_right.recurly_adjustment_uuid)
|
||||
|
||||
user.has_redeemable_jamtrack.should be_false
|
||||
user.gifted_jamtracks.should eq(0)
|
||||
|
||||
end
|
||||
|
||||
it "for a free jam track with an affiliate association" do
|
||||
|
|
|
|||
|
|
@ -10,6 +10,8 @@ describe ShoppingCart do
|
|||
let(:jam_track5) { FactoryGirl.create(:jam_track) }
|
||||
let(:jam_track6) { FactoryGirl.create(:jam_track) }
|
||||
let(:jam_track7) { FactoryGirl.create(:jam_track) }
|
||||
let(:gift_card) {FactoryGirl.create(:gift_card_type)}
|
||||
let(:gift_card2) {FactoryGirl.create(:gift_card_type)}
|
||||
|
||||
before(:each) do
|
||||
ShoppingCart.delete_all
|
||||
|
|
@ -29,7 +31,6 @@ describe ShoppingCart do
|
|||
user.shopping_carts[0].quantity.should == 1
|
||||
end
|
||||
|
||||
|
||||
it "maintains only one free JamTrack in ShoppingCart" do
|
||||
cart1 = ShoppingCart.add_jam_track_to_cart(user, jam_track, clear: true)
|
||||
cart1.should_not be_nil
|
||||
|
|
@ -39,8 +40,12 @@ describe ShoppingCart do
|
|||
cart2.errors.any?.should be_false
|
||||
user.reload
|
||||
user.shopping_carts.length.should eq(1)
|
||||
cart3 = ShoppingCart.add_jam_track_to_cart(user, jam_track2, clear: true)
|
||||
cart3.errors.any?.should be_false
|
||||
cart3 = ShoppingCart.add_item_to_cart(user, gift_card)
|
||||
cart3.errors.any?.should be_true
|
||||
user.reload
|
||||
user.shopping_carts.length.should eq(1)
|
||||
cart4 = ShoppingCart.add_jam_track_to_cart(user, jam_track2, clear: true)
|
||||
cart4.errors.any?.should be_false
|
||||
user.reload
|
||||
user.shopping_carts.length.should eq(1)
|
||||
end
|
||||
|
|
@ -56,6 +61,10 @@ describe ShoppingCart do
|
|||
cart2.errors.any?.should be_true
|
||||
end
|
||||
|
||||
it "a second giftcard just adds quantity" do
|
||||
|
||||
end
|
||||
|
||||
describe "redeemable behavior" do
|
||||
|
||||
it "removes redeemable item to shopping cart (maintains only one in cart)" do
|
||||
|
|
@ -153,6 +162,25 @@ describe ShoppingCart do
|
|||
end
|
||||
end
|
||||
|
||||
describe "gift cards" do
|
||||
it "can not add multiple of same type" do
|
||||
cart1 = ShoppingCart.add_item_to_cart(user, gift_card)
|
||||
cart1.should_not be_nil
|
||||
cart1.errors.any?.should be_false
|
||||
|
||||
user.reload
|
||||
user.has_redeemable_jamtrack = true
|
||||
user.shopping_carts.length.should eq(1)
|
||||
user.shopping_carts[0].quantity.should eql(1)
|
||||
|
||||
cart2 = ShoppingCart.add_item_to_cart(user, gift_card)
|
||||
cart2.should_not be_nil
|
||||
# it's the same type, so it's blocked
|
||||
cart2.errors.any?.should be_true
|
||||
cart2.errors[:cart_id].should eq(["has already been taken"])
|
||||
end
|
||||
end
|
||||
|
||||
describe "mixed" do
|
||||
it "non-free then free" do
|
||||
# you shouldn't be able to add a free after a non-free
|
||||
|
|
|
|||
|
|
@ -95,13 +95,13 @@ end
|
|||
|
||||
config.before(:suite) do
|
||||
DatabaseCleaner.strategy = :transaction
|
||||
DatabaseCleaner.clean_with(:deletion, {pre_count: true, reset_ids:false, :except => %w[instruments genres icecast_server_groups jamcompany jamisp geoipblocks geoipisp geoiplocations cities regions countries generic_state spatial_ref_sys] })
|
||||
DatabaseCleaner.clean_with(:deletion, {pre_count: true, reset_ids:false, :except => %w[gift_card_types instruments genres icecast_server_groups jamcompany jamisp geoipblocks geoipisp geoiplocations cities regions countries generic_state spatial_ref_sys] })
|
||||
end
|
||||
|
||||
config.around(:each) do |example|
|
||||
# set no_transaction: true as metadata on your test to use deletion strategy instead
|
||||
if example.metadata[:no_transaction]
|
||||
DatabaseCleaner.strategy = :deletion, {pre_count: true, reset_ids:false, :except => %w[instruments genres icecast_server_groups jamcompany jamisp geoipblocks geoipisp geoiplocations cities regions countries generic_state spatial_ref_sys] }
|
||||
DatabaseCleaner.strategy = :deletion, {pre_count: true, reset_ids:false, :except => %w[gift_card_types instruments genres icecast_server_groups jamcompany jamisp geoipblocks geoipisp geoiplocations cities regions countries generic_state spatial_ref_sys] }
|
||||
else
|
||||
DatabaseCleaner.strategy = :transaction
|
||||
end
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
var $templatePurchasedJamTrack = null;
|
||||
var $thanksPanel = null;
|
||||
var $jamTrackInBrowser = null;
|
||||
var $giftCardPurchased = null;
|
||||
var $purchasedJamTrack = null;
|
||||
var $purchasedJamTrackHeader = null;
|
||||
var $purchasedJamTracks = null;
|
||||
|
|
@ -75,9 +76,17 @@
|
|||
else {
|
||||
$thanksPanel.removeClass('hidden')
|
||||
handleJamTracksPurchased(purchaseResponse.jam_tracks)
|
||||
handleGiftCardsPurchased(purchaseResponse.gift_cards)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function handleGiftCardsPurchased(gift_cards) {
|
||||
// were any GiftCards purchased?
|
||||
if(gift_cards && gift_cards.length > 0) {
|
||||
$giftCardPurchased.removeClass('hidden')
|
||||
}
|
||||
}
|
||||
function handleJamTracksPurchased(jamTracks) {
|
||||
// were any JamTracks purchased?
|
||||
var jamTracksPurchased = jamTracks && jamTracks.length > 0;
|
||||
|
|
@ -194,6 +203,7 @@
|
|||
$templatePurchasedJamTrack = $('#template-purchased-jam-track');
|
||||
$thanksPanel = $screen.find(".thanks-panel");
|
||||
$jamTrackInBrowser = $screen.find(".thanks-detail.jam-tracks-in-browser");
|
||||
$giftCardPurchased = $screen.find('.thanks-detail.gift-card')
|
||||
$purchasedJamTrack = $thanksPanel.find(".thanks-detail.purchased-jam-track");
|
||||
$purchasedJamTrackHeader = $purchasedJamTrack.find(".purchased-jam-track-header");
|
||||
$purchasedJamTracks = $purchasedJamTrack.find(".purchased-list")
|
||||
|
|
|
|||
|
|
@ -135,15 +135,7 @@
|
|||
}
|
||||
}
|
||||
|
||||
function displayTax(effectiveQuantity, item_tax, total_with_tax) {
|
||||
var totalTax = 0;
|
||||
var totalPrice = 0;
|
||||
|
||||
var unitTax = item_tax * effectiveQuantity;
|
||||
totalTax += unitTax;
|
||||
|
||||
var totalUnitPrice = total_with_tax * effectiveQuantity;
|
||||
totalPrice += totalUnitPrice;
|
||||
function displayTax(totalTax, totalPrice) {
|
||||
|
||||
$screen.find('.order-right-page .order-items-value.taxes').text('$' + totalTax.toFixed(2))
|
||||
$screen.find('.order-right-page .order-items-value.grand-total').text('$' + totalPrice.toFixed(2))
|
||||
|
|
@ -181,8 +173,16 @@
|
|||
taxRate = 0.0825;
|
||||
}
|
||||
|
||||
var unitTax = 1.99 * taxRate;
|
||||
displayTax(effectiveQuantity, unitTax, 1.99 + unitTax)
|
||||
var estimatedTax = 0;
|
||||
var estimatedTotal = 0;
|
||||
|
||||
context._.each(carts, function(cart) {
|
||||
var cart_quantity = cart.product_info.quantity - cart.product_info.marked_for_redeem
|
||||
estimatedTax += cart.product_info.price * cart_quantity * taxRate;
|
||||
estimatedTotal += cart.product_info.price * cart_quantity;
|
||||
})
|
||||
|
||||
displayTax(Math.round(estimatedTax*100)/100, Math.round((estimatedTotal + estimatedTax)*100)/100)
|
||||
}
|
||||
else {
|
||||
checkoutUtils.configureRecurly()
|
||||
|
|
|
|||
|
|
@ -1805,6 +1805,17 @@
|
|||
return deferred
|
||||
}
|
||||
|
||||
function addGiftCardToShoppingCart(options) {
|
||||
var deferred = $.ajax({
|
||||
type: "POST",
|
||||
url: '/api/shopping_carts/add_gift_card?' + $.param(options),
|
||||
dataType: "json",
|
||||
contentType: 'application/json'
|
||||
});
|
||||
|
||||
return deferred
|
||||
}
|
||||
|
||||
function getShoppingCarts() {
|
||||
// the need for the time de-duplicator indicates we are doing something wrong on the server
|
||||
return $.ajax({
|
||||
|
|
@ -2188,6 +2199,7 @@
|
|||
this.enqueueJamTrack = enqueueJamTrack;
|
||||
this.getBackingTracks = getBackingTracks;
|
||||
this.addJamtrackToShoppingCart = addJamtrackToShoppingCart;
|
||||
this.addGiftCardToShoppingCart = addGiftCardToShoppingCart;
|
||||
this.getShoppingCarts = getShoppingCarts;
|
||||
this.removeShoppingCart = removeShoppingCart;
|
||||
this.clearShoppingCart = clearShoppingCart;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,93 @@
|
|||
context = window
|
||||
rest = context.JK.Rest()
|
||||
|
||||
@GiftCardLandingPage = React.createClass({
|
||||
|
||||
render: () ->
|
||||
|
||||
if this.state.done
|
||||
ctaButtonText10 = 'sending you in...'
|
||||
ctaButtonText20 = 'sending you in...'
|
||||
else if this.state.processing
|
||||
ctaButtonText10 = 'hold on...'
|
||||
ctaButtonText20 = 'hold on...'
|
||||
else
|
||||
ctaButtonText10 = `<span>ADD $10 CARD<br/>TO CART</span>`
|
||||
ctaButtonText20 = `<span>ADD $20 CARD<br/>TO CART</span>`
|
||||
|
||||
|
||||
ctaButtons =
|
||||
`<div className="cta-buttons">
|
||||
<button className={classNames({'five-jt': true, 'gift-card': true, 'cta-button' : true, 'processing': this.state.processing})} onClick={this.ctaClick.bind(this, 5)}>{ctaButtonText10}</button>
|
||||
<button className={classNames({'ten-jt': true, 'gift-card': true, 'cta-button' : true, 'processing': this.state.processing})} onClick={this.ctaClick.bind(this, 10)}>{ctaButtonText20}</button>
|
||||
</div>`
|
||||
|
||||
|
||||
`<div className="top-container">
|
||||
<div className="full-row name-and-artist">
|
||||
<div>
|
||||
<img className="gift-card-preview" width="300" height="191" src="/assets/landing/gift_card.png" alt="gift card "/>
|
||||
<h1 className="jam-track-name">$10 or $20 JAMTRACKS GIFT CARDS</h1>
|
||||
<h2 className="original-artist">A PERFECT GIFT FOR THE HOLIDAYS</h2>
|
||||
<div className="clearall"/>
|
||||
</div>
|
||||
<div className="preview-and-action-box">
|
||||
<img src="/assets/landing/jamtrack_landing_arrow_1.png" className="arrow1" />
|
||||
<img src="/assets/landing/jamtrack_landing_arrow_2.png" className="arrow2" />
|
||||
<div className="preview-jamtrack-header">
|
||||
Preview JamTrack
|
||||
</div>
|
||||
<div className={classNames({'preview-area': true, 'gift-card': true})}>
|
||||
<p>Click the play buttons below to preview the master mix and 20-second samples of all the isolated tracks.</p>
|
||||
<div className="tracks previews">
|
||||
|
||||
</div>
|
||||
<p className="gift-getter">
|
||||
Get a $10 gift card (good for 5 songs) or a $20 gift card (good for 10 songs), and your happy
|
||||
gift card getter can choose their favorites from our catalog of 3,700+ popular songs.
|
||||
</p>
|
||||
{ctaButtons}
|
||||
<a className="browse-all" href="/client?search=#/jamtrack/search">or browse our catalog of 3,700+ songs</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="row summary-text">
|
||||
<p className="top-summary">
|
||||
JamTracks by JamKazam are the best way to play along with your favorite songs. Far better and different than traditional
|
||||
backing tracks, our JamTracks are complete multi-track professional recordings, with fully isolated tracks for each part of the music.
|
||||
And our free app and Internet service are packed with features that give you unmatched creative freedom to learn, practice, record, play with others, and share your performances.
|
||||
</p>
|
||||
</div>
|
||||
</div>`
|
||||
|
||||
getInitialState: () ->
|
||||
{processing:false}
|
||||
|
||||
componentDidMount:() ->
|
||||
$root = $(this.getDOMNode())
|
||||
|
||||
# add item to cart, create the user if necessary, and then place the order to get the free JamTrack.
|
||||
ctaClick: (card_type, e) ->
|
||||
e.preventDefault()
|
||||
|
||||
return if @state.processing
|
||||
|
||||
loggedIn = context.JK.currentUserId?
|
||||
|
||||
rest.addGiftCardToShoppingCart({id: card_type}).done((response) =>
|
||||
|
||||
if loggedIn
|
||||
@setState({done: true})
|
||||
context.location = '/client#/shoppingCart'
|
||||
else
|
||||
@setState({done: true})
|
||||
context.location = '/client#/checkoutPayment'
|
||||
|
||||
).fail((jqXHR, textStatus, errorMessage) =>
|
||||
if jqXHR.status == 422
|
||||
errors = JSON.parse(jqXHR.responseText)
|
||||
cart_errors = errors?.errors?.cart_id
|
||||
context.JK.app.ajaxError(jqXHR, textStatus, errorMessage)
|
||||
@setState({processing:false})
|
||||
)
|
||||
})
|
||||
|
|
@ -24,8 +24,8 @@ logger = context.JK.logger
|
|||
|
||||
onModify: (changes) ->
|
||||
@user = $.extend({}, @user, changes)
|
||||
@changed(
|
||||
)
|
||||
@changed()
|
||||
|
||||
changed:() ->
|
||||
@trigger({user: @user})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -73,6 +73,10 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
.thanks-detail.gift-card{
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.thanks-detail.purchased-jam-track {
|
||||
|
||||
margin-top:20px;
|
||||
|
|
|
|||
|
|
@ -162,6 +162,18 @@ body.web.individual_jamtrack {
|
|||
text-align: center;
|
||||
}
|
||||
|
||||
img.gift-card-preview {
|
||||
width:300px;
|
||||
float: left;
|
||||
margin-left: -15px; // because image has black on the left, which you can't see on back background
|
||||
margin-right: 20px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
p.gift-getter {
|
||||
margin-top:20px;
|
||||
line-height:125%;
|
||||
}
|
||||
|
||||
img.app-preview {
|
||||
width: 340px;
|
||||
float: left;
|
||||
|
|
@ -205,6 +217,9 @@ body.web.individual_jamtrack {
|
|||
|
||||
.browse-all {
|
||||
color: #ffb800;
|
||||
text-decoration: underline;
|
||||
text-align: center;
|
||||
display: block;
|
||||
}
|
||||
|
||||
p {
|
||||
|
|
@ -320,6 +335,11 @@ body.web.individual_jamtrack {
|
|||
padding: 10px;
|
||||
|
||||
border-width: 0 0 $chunkyBorderWidth;
|
||||
|
||||
&.gift-card {
|
||||
border-width: 0 0 2px;
|
||||
}
|
||||
|
||||
border-style: solid;
|
||||
border-color: $copy-color-on-dark;
|
||||
|
||||
|
|
@ -338,6 +358,9 @@ body.web.individual_jamtrack {
|
|||
margin-bottom:10px;
|
||||
}
|
||||
|
||||
.cta-buttons {
|
||||
text-align:center;
|
||||
}
|
||||
.cta-button {
|
||||
font-size: 24px;
|
||||
color: white;
|
||||
|
|
@ -348,6 +371,13 @@ body.web.individual_jamtrack {
|
|||
width: 100%;
|
||||
border: 1px outset buttonface;
|
||||
font-family: Raleway, Arial, Helvetica, sans-serif;
|
||||
|
||||
&.gift-card {
|
||||
font-size:16px;
|
||||
width:138px;
|
||||
margin:15px 5px;
|
||||
display:inline-block;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -385,12 +415,7 @@ body.web.individual_jamtrack {
|
|||
border: 1px outset buttonface;
|
||||
font-family: Raleway, Arial, Helvetica, sans-serif;
|
||||
}
|
||||
.browse-all {
|
||||
text-decoration: underline;
|
||||
text-align: center;
|
||||
display: block;
|
||||
|
||||
}
|
||||
.privacy-policy {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -124,7 +124,7 @@ class ApiRecurlyController < ApiController
|
|||
|
||||
def place_order
|
||||
error=nil
|
||||
response = {jam_tracks: []}
|
||||
response = {jam_tracks: [], gift_cards: []}
|
||||
|
||||
if Sale.is_mixed(current_user.shopping_carts)
|
||||
msg = "has free and non-free items. Try removing non-free items."
|
||||
|
|
@ -136,11 +136,16 @@ class ApiRecurlyController < ApiController
|
|||
|
||||
|
||||
sales.each do |sale|
|
||||
if sale.is_jam_track_sale?
|
||||
sale.sale_line_items.each do |line_item|
|
||||
sale.sale_line_items.each do |line_item|
|
||||
if line_item.is_jam_track?
|
||||
jam_track = line_item.product
|
||||
jam_track_right = jam_track.right_for_user(current_user)
|
||||
response[:jam_tracks] << {name: jam_track.name, id: jam_track.id, jam_track_right_id: jam_track_right.id, version: jam_track.version}
|
||||
elsif line_item.is_gift_card?
|
||||
gift_card = line_item.product
|
||||
response[:gift_cards] << {name: gift_card.name, id: gift_card.id}
|
||||
else
|
||||
raise 'unknown sale line item type: ' + line_item.product_type
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -30,6 +30,34 @@ class ApiShoppingCartsController < ApiController
|
|||
end
|
||||
end
|
||||
|
||||
def add_gift_card
|
||||
gift_card_type = nil
|
||||
|
||||
id = params[:id]
|
||||
|
||||
if id && id.to_i == 5
|
||||
gift_card_type = 'jam_tracks_5'
|
||||
elsif id && id.to_i == 10
|
||||
gift_card_type = 'jam_tracks_10'
|
||||
end
|
||||
|
||||
gift_card = GiftCardType.find_by_id(gift_card_type)
|
||||
|
||||
# verify GiftCard exists
|
||||
if gift_card.nil?
|
||||
raise StateError, "Invalid JamTrack."
|
||||
end
|
||||
|
||||
@cart = ShoppingCart.add_item_to_cart(any_user, gift_card)
|
||||
|
||||
if @cart.errors.any?
|
||||
response.status = :unprocessable_entity
|
||||
respond_with @cart
|
||||
else
|
||||
# let add_gift_card.rabl take over
|
||||
end
|
||||
end
|
||||
|
||||
def update_cart
|
||||
@cart = ShoppingCart.find_by_id params[:id]
|
||||
|
||||
|
|
|
|||
|
|
@ -213,5 +213,28 @@ class LandingsController < ApplicationController
|
|||
@landing_tag_play_learn_earn = true
|
||||
render 'redeem_giftcard', layout: 'web'
|
||||
end
|
||||
|
||||
def buy_gift_card
|
||||
@no_landing_tag = true
|
||||
@landing_tag_play_learn_earn = true
|
||||
@show_after_black_bar_border = true
|
||||
@jam_track = JamTrack.find_by_slug('elton-john-rocket-man')
|
||||
@jam_track = JamTrack.first unless @jam_track
|
||||
|
||||
instrument_id = nil
|
||||
instrument_name = nil
|
||||
instrument_count = 0
|
||||
|
||||
band_jam_track_count = @jam_track.band_jam_track_count
|
||||
jam_track_count = JamTrack.count
|
||||
@title = individual_jamtrack_title(false, params[:generic], @jam_track)
|
||||
@description = individual_jamtrack_desc(false, params[:generic], @jam_track)
|
||||
@page_data = {jam_track: @jam_track, all_track_count: jam_track_count, band_track_count: band_jam_track_count, band: false, generic: params[:generic], instrument: instrument_name, instrument_id: instrument_id, instrument_count: instrument_count}
|
||||
gon.jam_track_plan_code = @jam_track.plan_code if @jam_track
|
||||
gon.generic = params[:generic]
|
||||
gon.instrument_id = instrument_id
|
||||
|
||||
render 'buy_gift_card', layout: 'web'
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
extends "api_shopping_carts/show"
|
||||
|
||||
node :show_free_jamtrack do
|
||||
any_user.show_free_jamtrack?
|
||||
end
|
||||
|
|
@ -19,6 +19,8 @@ div layout="screen" layout-id="checkoutComplete" id="checkoutCompleteScreen" cla
|
|||
br
|
||||
.thanks-detail We'll send you an email confirming your order shortly.
|
||||
br
|
||||
.thanks-detail.gift-card.hidden
|
||||
p Thank you for purchasing a JamTrack Gift Card! It will be mailed to you.
|
||||
.thanks-detail.jam-tracks-in-browser.hidden
|
||||
p To play your purchased JamTrack, launch the JamKazam application and open the JamTrack while in a session.
|
||||
a.download-jamkazam-wrapper.hidden href="/downloads" rel="external"
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@ script type='text/template' id='template-order-content'
|
|||
= "{% _.each(data.carts, function(cart) { %}"
|
||||
.cart-item cart-id="{{cart.id}}"
|
||||
.cart-item-caption
|
||||
= "{{cart.cart_type}}: {{cart.product_info.name}}"
|
||||
= "{{cart.product_info.sale_display}}"
|
||||
= "{% if (cart.product_info.free) { %}"
|
||||
span.first-one-free
|
||||
| (first one free)
|
||||
|
|
|
|||
|
|
@ -10,8 +10,7 @@ div layout="screen" layout-id="checkoutPayment" id="checkoutPaymentScreen" class
|
|||
.checkout-navigation-bar
|
||||
.payment-wrapper
|
||||
p.payment-prompt.free-jamtrack.hidden
|
||||
| Please enter your billing address and payment information below. You will not be billed for your first JamTrack, which is 100% free.
|
||||
| But we need this data to prevent fraud/abuse of those who would create multiple accounts to collect multiple free JamTracks.
|
||||
| Please enter your billing address and payment information below.
|
||||
| You will not be billed for any charges of any kind without your explicit authorization.
|
||||
| There are no "hidden" charges or fees, thank you!
|
||||
p.payment-prompt.no-free-jamtrack.hidden
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@
|
|||
= "{% _.each(data.carts, function(cart, index) { %}"
|
||||
%tr.cart-item{"cart-id" => "{{cart.id}}"}
|
||||
%td.cart-item-caption
|
||||
{{cart.cart_type}}: {{cart.product_info.name}}
|
||||
{{cart.product_info.sale_display}}
|
||||
%td.cart-item-price
|
||||
$ {{Number(cart.product_info.real_price).toFixed(2)}}
|
||||
= "{% if(index == data.carts.length - 1) { %}"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,24 @@
|
|||
- provide(:page_name, 'landing_page full individual_jamtrack')
|
||||
- provide(:description, @description)
|
||||
- provide(:title, @title)
|
||||
|
||||
= react_component 'GiftCardLandingPage', @page_data.to_json
|
||||
|
||||
- content_for :after_black_bar do
|
||||
.row.cta-row
|
||||
h2 GET YOUR GIFT CARD NOW!
|
||||
p And join 20,000+ other musicians who love our JamTracks.
|
||||
p.cta-text Not sure if JamTracks are for you? Scroll down to learn more.
|
||||
|
||||
- content_for :white_bar do
|
||||
= react_component 'JamTrackLandingBottomPage', @page_data.to_json
|
||||
|
||||
- content_for :red_bar do
|
||||
.full-row
|
||||
| Get your free JamTrack and start playing today!
|
||||
|
||||
javascript:
|
||||
$(document).on('JAMKAZAM_READY', function(e, data) {
|
||||
var song = new JK.IndividualJamTrack(data.app, true);
|
||||
song.initialize();
|
||||
})
|
||||
|
|
@ -41,6 +41,7 @@ SampleApp::Application.routes.draw do
|
|||
match '/landing/jamtracks/:plan_code', to: 'landings#individual_jamtrack', via: :get, as: 'individual_jamtrack'
|
||||
match '/landing/jamtracks/band/:plan_code', to: 'landings#individual_jamtrack_band', via: :get, as: 'individual_jamtrack_band'
|
||||
match '/landing/jamtracks/:instrument/:plan_code', to: 'landings#individual_jamtrack', via: :get, as: 'individual_jamtrack_instrument'
|
||||
match '/landing/gift-card', to: 'landings#buy_gift_card', via: :get, as: 'buy_gift_card'
|
||||
|
||||
match '/affiliateProgram', to: 'landings#affiliate_program', via: :get, as: 'affiliate_program'
|
||||
|
||||
|
|
@ -276,6 +277,7 @@ SampleApp::Application.routes.draw do
|
|||
match '/shopping_carts' => 'api_shopping_carts#index', :via => :get
|
||||
match '/shopping_carts' => 'api_shopping_carts#remove_cart', :via => :delete
|
||||
match '/shopping_carts/clear_all' => 'api_shopping_carts#clear_all', :via => :delete
|
||||
match '/shopping_carts/add_gift_card' => 'api_shopping_carts#add_gift_card', :via => :post
|
||||
|
||||
# RSVP requests
|
||||
match '/rsvp_requests' => 'api_rsvp_requests#index', :via => :get
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ describe ApiUsersController do
|
|||
gift_card.reload
|
||||
|
||||
user.gift_cards.should eq([gift_card])
|
||||
user.gifted_jamtracks.should eq(10)
|
||||
user.gifted_jamtracks.should eq(5)
|
||||
gift_card.user.should eq(user)
|
||||
end
|
||||
|
||||
|
|
@ -42,7 +42,7 @@ describe ApiUsersController do
|
|||
gift_card.reload
|
||||
|
||||
user.gift_cards.should eq([gift_card])
|
||||
user.gifted_jamtracks.should eq(10)
|
||||
user.gifted_jamtracks.should eq(5)
|
||||
gift_card.user.should eq(user)
|
||||
end
|
||||
|
||||
|
|
@ -78,7 +78,7 @@ describe ApiUsersController do
|
|||
gift_card.reload
|
||||
|
||||
user.gift_cards.should eq([gift_card])
|
||||
user.gifted_jamtracks.should eq(10)
|
||||
user.gifted_jamtracks.should eq(5)
|
||||
gift_card.user.should eq(user)
|
||||
cart1.reload
|
||||
cart1.marked_for_redeem.should eq(1)
|
||||
|
|
@ -100,7 +100,7 @@ describe ApiUsersController do
|
|||
gift_card.reload
|
||||
|
||||
user.gift_cards.should eq([gift_card])
|
||||
user.gifted_jamtracks.should eq(10)
|
||||
user.gifted_jamtracks.should eq(5)
|
||||
gift_card.user.should eq(user)
|
||||
cart1.reload
|
||||
cart1.marked_for_redeem.should eq(1)
|
||||
|
|
@ -125,7 +125,7 @@ describe ApiUsersController do
|
|||
gift_card.reload
|
||||
|
||||
user.gift_cards.should eq([gift_card])
|
||||
user.gifted_jamtracks.should eq(10)
|
||||
user.gifted_jamtracks.should eq(5)
|
||||
gift_card.user.should eq(user)
|
||||
user.shopping_carts.each do |cart|
|
||||
cart.marked_for_redeem.should eq(0)
|
||||
|
|
|
|||
|
|
@ -842,6 +842,6 @@ FactoryGirl.define do
|
|||
|
||||
factory :gift_card, class: 'JamRuby::GiftCard' do
|
||||
sequence(:code) {|n| n.to_s}
|
||||
card_type GiftCard::JAM_TRACKS_10
|
||||
card_type GiftCard::JAM_TRACKS_5
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -827,8 +827,6 @@ describe "Checkout", :js => true, :type => :feature, :capybara_feature => true d
|
|||
acdc_sale.free.should eq(0)
|
||||
acdc_sale.unit_price.should eq(1.99)
|
||||
acdc_sale.sale.should eq(sale)
|
||||
|
||||
|
||||
end
|
||||
|
||||
it "for anonymous user with referral" do
|
||||
|
|
|
|||
|
|
@ -0,0 +1,245 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe "Gift Card Landing", :js => true, :type => :feature, :capybara_feature => true do
|
||||
|
||||
subject { page }
|
||||
|
||||
before(:all) do
|
||||
ShoppingCart.delete_all
|
||||
JamTrackRight.delete_all
|
||||
JamTrack.delete_all
|
||||
JamTrackTrack.delete_all
|
||||
JamTrackLicensor.delete_all
|
||||
GiftCardPurchase.delete_all
|
||||
GiftCard.delete_all
|
||||
end
|
||||
|
||||
before(:all) do
|
||||
@jamtrack_rocketman = FactoryGirl.create(:jam_track, slug: 'elton-john-rocket-man', name: 'Rocket Man', original_artist: 'Elton John', sales_region: 'United States', make_track: true, plan_code: 'jamtrack-acdc-backinblack')
|
||||
end
|
||||
|
||||
|
||||
let(:jamtrack_rocketman) {@jamtrack_rocketman}
|
||||
let(:user) { FactoryGirl.create(:user, country: 'US') }
|
||||
|
||||
let(:billing_info) {
|
||||
{
|
||||
first_name: 'Seth',
|
||||
last_name: 'Call',
|
||||
address1: '10704 Buckthorn Drive',
|
||||
city: 'Austin',
|
||||
state: 'Texas',
|
||||
country: 'US',
|
||||
zip: '78759',
|
||||
number: '4111111111111111',
|
||||
month: '08',
|
||||
year: '2017',
|
||||
verification_value: '012'
|
||||
}
|
||||
}
|
||||
|
||||
it "logged out (5) and affiliate" do
|
||||
partner = FactoryGirl.create(:affiliate_partner)
|
||||
affiliate_params = partner.affiliate_query_params
|
||||
visit "/landing/gift-card?" + affiliate_params
|
||||
|
||||
find('h1.jam-track-name', '$10 or $20 JAMTRACKS GIFT CARDS')
|
||||
find('h2.original-artist', 'A PERFECT GIFT FOR THE HOLIDAYS')
|
||||
jamtrack_rocketman.jam_track_tracks.each do |track|
|
||||
if track.master?
|
||||
find('.tracks.previews[data-id="' + track.id + '"] img.instrument-icon[data-instrument-id="other"]')
|
||||
find('.tracks.previews[data-id="' + track.id + '"] .instrument-name', text: 'Master Mix')
|
||||
else
|
||||
find('.tracks.previews[data-id="' + track.id + '"] img.instrument-icon[data-instrument-id="' + track.instrument.id + '"]')
|
||||
find('.tracks.previews[data-id="' + track.id + '"] .instrument-name', text: track.instrument.description)
|
||||
end
|
||||
end
|
||||
find('a.browse-all')['href'].should eq("/client?search=#/jamtrack/search")
|
||||
find('button.five-jt', text: 'ADD $10 CARD TO CART').trigger(:click)
|
||||
|
||||
|
||||
find('h1', text: 'check out')
|
||||
|
||||
# fill out all billing info and account info
|
||||
fill_in 'billing-first-name', with: 'Seth'
|
||||
fill_in 'billing-last-name', with: 'Call'
|
||||
fill_in 'billing-address1', with: '10704 Buckthorn Drive'
|
||||
fill_in 'billing-city', with: 'Austin'
|
||||
fill_in 'billing-state', with: 'Texas'
|
||||
fill_in 'billing-zip', with: '78759'
|
||||
fill_in 'card-number', with: '4111111111111111'
|
||||
fill_in 'card-verify', with: '012'
|
||||
|
||||
# fill in user/email/tos
|
||||
fill_in 'email', with: 'bogus+gc1@jamkazam.com'
|
||||
fill_in 'password', with: 'jam123'
|
||||
find('#divJamKazamTos ins.iCheck-helper').trigger(:click) # accept TOS
|
||||
|
||||
# try to submit, and see order page
|
||||
find('#payment-info-next').trigger(:click)
|
||||
|
||||
find('.order-items-value.sub-total', text:'10.00')
|
||||
find('.order-items-value.taxes', text:'0.83')
|
||||
find('.order-items-value.order-total', text:'$10.00')
|
||||
find('.order-items-value.grand-total', text:'$10.83')
|
||||
|
||||
# click the ORDER button
|
||||
find('.place-order-center a.button-orange.place-order').trigger(:click)
|
||||
|
||||
# and now we should see confirmation, and a notice that we are in a normal browser
|
||||
find('.thanks-detail.gift-card')
|
||||
|
||||
created_user = User.find_by_email('bogus+gc1@jamkazam.com')
|
||||
|
||||
sleep 3 # challenge to all comers! WHY DO I HAVE TO SLEEP FOR THIS ASSERTION TO BE TRUE! GAH . and 1 second won't do it
|
||||
|
||||
created_user.reload
|
||||
created_user.has_redeemable_jamtrack.should be_true
|
||||
created_user.gifted_jamtracks.should eq(0)
|
||||
created_user.gift_card_purchases.length.should eq(1)
|
||||
|
||||
# verify sales data
|
||||
created_user.sales.length.should eq(1)
|
||||
sale = created_user.sales.last
|
||||
sale.sale_line_items.length.should eq(1)
|
||||
line_item = sale.sale_line_items[0]
|
||||
line_item.product_type.should eq('GiftCardType')
|
||||
line_item.product_id.should eq('jam_tracks_5')
|
||||
line_item.quantity.should eq(1)
|
||||
line_item.free.should eq(0)
|
||||
line_item.unit_price.should eq(10.00)
|
||||
line_item.sale.should eq(sale)
|
||||
line_item.affiliate_referral.should eq(partner)
|
||||
line_item.affiliate_refunded.should be_false
|
||||
line_item.affiliate_refunded_at.should be_nil
|
||||
line_item.affiliate_referral_fee_in_cents.should eq(10.00 * partner.rate * 100)
|
||||
end
|
||||
|
||||
it "logged out (10)" do
|
||||
visit "/landing/gift-card"
|
||||
|
||||
find('h1.jam-track-name', '$10 or $20 JAMTRACKS GIFT CARDS')
|
||||
find('h2.original-artist', 'A PERFECT GIFT FOR THE HOLIDAYS')
|
||||
jamtrack_rocketman.jam_track_tracks.each do |track|
|
||||
if track.master?
|
||||
find('.tracks.previews[data-id="' + track.id + '"] img.instrument-icon[data-instrument-id="other"]')
|
||||
find('.tracks.previews[data-id="' + track.id + '"] .instrument-name', text: 'Master Mix')
|
||||
else
|
||||
find('.tracks.previews[data-id="' + track.id + '"] img.instrument-icon[data-instrument-id="' + track.instrument.id + '"]')
|
||||
find('.tracks.previews[data-id="' + track.id + '"] .instrument-name', text: track.instrument.description)
|
||||
end
|
||||
end
|
||||
find('a.browse-all')['href'].should eq("/client?search=#/jamtrack/search")
|
||||
find('button.ten-jt', text: 'ADD $20 CARD TO CART').trigger(:click)
|
||||
|
||||
|
||||
find('h1', text: 'check out')
|
||||
|
||||
# fill out all billing info and account info
|
||||
fill_in 'billing-first-name', with: 'Seth'
|
||||
fill_in 'billing-last-name', with: 'Call'
|
||||
fill_in 'billing-address1', with: '10704 Buckthorn Drive'
|
||||
fill_in 'billing-city', with: 'Austin'
|
||||
fill_in 'billing-state', with: 'Texas'
|
||||
fill_in 'billing-zip', with: '78759'
|
||||
fill_in 'card-number', with: '4111111111111111'
|
||||
fill_in 'card-verify', with: '012'
|
||||
|
||||
# fill in user/email/tos
|
||||
fill_in 'email', with: 'bogus+gc2@jamkazam.com'
|
||||
fill_in 'password', with: 'jam123'
|
||||
find('#divJamKazamTos ins.iCheck-helper').trigger(:click) # accept TOS
|
||||
|
||||
# try to submit, and see order page
|
||||
find('#payment-info-next').trigger(:click)
|
||||
|
||||
find('.order-items-value.sub-total', text:'20.00')
|
||||
find('.order-items-value.taxes', text:'1.65')
|
||||
find('.order-items-value.order-total', text:'$20.00')
|
||||
find('.order-items-value.grand-total', text:'$21.65')
|
||||
|
||||
# click the ORDER button
|
||||
find('.place-order-center a.button-orange.place-order').trigger(:click)
|
||||
|
||||
# and now we should see confirmation, and a notice that we are in a normal browser
|
||||
find('.thanks-detail.gift-card')
|
||||
|
||||
created_user = User.find_by_email('bogus+gc2@jamkazam.com')
|
||||
|
||||
sleep 3 # challenge to all comers! WHY DO I HAVE TO SLEEP FOR THIS ASSERTION TO BE TRUE! GAH . and 1 second won't do it
|
||||
|
||||
created_user.reload
|
||||
created_user.has_redeemable_jamtrack.should be_true
|
||||
created_user.gifted_jamtracks.should eq(0)
|
||||
created_user.gift_card_purchases.length.should eq(1)
|
||||
|
||||
# verify sales data
|
||||
created_user.sales.length.should eq(1)
|
||||
sale = created_user.sales.last
|
||||
sale.sale_line_items.length.should eq(1)
|
||||
line_item = sale.sale_line_items[0]
|
||||
line_item.product_type.should eq('GiftCardType')
|
||||
line_item.product_id.should eq('jam_tracks_10')
|
||||
line_item.quantity.should eq(1)
|
||||
line_item.free.should eq(0)
|
||||
line_item.unit_price.should eq(20.00)
|
||||
line_item.sale.should eq(sale)
|
||||
end
|
||||
|
||||
it "logged in (5)" do
|
||||
fast_signin(user,"/landing/gift-card")
|
||||
|
||||
find('h1.jam-track-name', '$10 or $20 JAMTRACKS GIFT CARDS')
|
||||
find('h2.original-artist', 'A PERFECT GIFT FOR THE HOLIDAYS')
|
||||
jamtrack_rocketman.jam_track_tracks.each do |track|
|
||||
if track.master?
|
||||
find('.tracks.previews[data-id="' + track.id + '"] img.instrument-icon[data-instrument-id="other"]')
|
||||
find('.tracks.previews[data-id="' + track.id + '"] .instrument-name', text: 'Master Mix')
|
||||
else
|
||||
find('.tracks.previews[data-id="' + track.id + '"] img.instrument-icon[data-instrument-id="' + track.instrument.id + '"]')
|
||||
find('.tracks.previews[data-id="' + track.id + '"] .instrument-name', text: track.instrument.description)
|
||||
end
|
||||
end
|
||||
find('a.browse-all')['href'].should eq("/client?search=#/jamtrack/search")
|
||||
find('button.five-jt', text: 'ADD $10 CARD TO CART').trigger(:click)
|
||||
|
||||
# land in shopping cart because we are a user; log in
|
||||
find('.proceed-checkout').trigger(:click)
|
||||
|
||||
find('h1', text: 'check out')
|
||||
|
||||
# fill out all billing info and account info
|
||||
fill_in 'billing-first-name', with: 'Seth'
|
||||
fill_in 'billing-last-name', with: 'Call'
|
||||
fill_in 'billing-address1', with: '10704 Buckthorn Drive'
|
||||
fill_in 'billing-city', with: 'Austin'
|
||||
fill_in 'billing-state', with: 'Texas'
|
||||
fill_in 'billing-zip', with: '78759'
|
||||
fill_in 'card-number', with: '4111111111111111'
|
||||
fill_in 'card-verify', with: '012'
|
||||
|
||||
# try to submit, and see order page
|
||||
find('#payment-info-next').trigger(:click)
|
||||
|
||||
find('.order-items-value.sub-total', text:'10.00')
|
||||
find('.order-items-value.taxes', text:'0.83')
|
||||
find('.order-items-value.order-total', text:'$10.00')
|
||||
find('.order-items-value.grand-total', text:'$10.83')
|
||||
|
||||
# click the ORDER button
|
||||
find('.place-order-center a.button-orange.place-order').trigger(:click)
|
||||
|
||||
# and now we should see confirmation, and a notice that we are in a normal browser
|
||||
find('.thanks-detail.gift-card')
|
||||
|
||||
user.reload
|
||||
|
||||
sleep 3 # challenge to all comers! WHY DO I HAVE TO SLEEP FOR THIS ASSERTION TO BE TRUE! GAH . and 1 second won't do it
|
||||
|
||||
user.reload
|
||||
user.has_redeemable_jamtrack.should be_true
|
||||
user.gifted_jamtracks.should eq(0)
|
||||
user.gift_card_purchases.length.should eq(1)
|
||||
end
|
||||
|
||||
end
|
||||
|
|
@ -30,13 +30,13 @@ describe "Redeem Gift Card", :js => true, :type => :feature, :capybara_feature =
|
|||
|
||||
find('.done-action a.go-browse').trigger(:click)
|
||||
|
||||
find('.no-free-jamtrack')
|
||||
find('.free-jamtrack')
|
||||
|
||||
user = User.find_by_email("gifter1@jamkazam.com")
|
||||
gift_card.reload
|
||||
gift_card.user.should eq(user)
|
||||
user.reload
|
||||
user.gifted_jamtracks.should eq(10)
|
||||
user.gifted_jamtracks.should eq(5)
|
||||
end
|
||||
|
||||
it "validates correctly" do
|
||||
|
|
@ -58,13 +58,13 @@ describe "Redeem Gift Card", :js => true, :type => :feature, :capybara_feature =
|
|||
|
||||
find('.done-action a.go-browse').trigger(:click)
|
||||
|
||||
find('.no-free-jamtrack')
|
||||
find('.free-jamtrack')
|
||||
|
||||
user = User.find_by_email("gifter2@jamkazam.com")
|
||||
gift_card.reload
|
||||
gift_card.user.should eq(user)
|
||||
user.reload
|
||||
user.gifted_jamtracks.should eq(10)
|
||||
user.gifted_jamtracks.should eq(5)
|
||||
end
|
||||
|
||||
it "converts shopping cart items to free" do
|
||||
|
|
@ -89,7 +89,7 @@ describe "Redeem Gift Card", :js => true, :type => :feature, :capybara_feature =
|
|||
|
||||
find('.done-action a.go-browse').trigger(:click)
|
||||
|
||||
find('.no-free-jamtrack')
|
||||
find('.free-jamtrack')
|
||||
|
||||
cart.reload
|
||||
cart.marked_for_redeem.should eq(1)
|
||||
|
|
@ -108,12 +108,12 @@ describe "Redeem Gift Card", :js => true, :type => :feature, :capybara_feature =
|
|||
|
||||
find('.done-action a.go-browse').trigger(:click)
|
||||
|
||||
find('.no-free-jamtrack')
|
||||
find('.free-jamtrack')
|
||||
|
||||
gift_card.reload
|
||||
gift_card.user.should eq(user1)
|
||||
user1.reload
|
||||
user1.gifted_jamtracks.should eq(10)
|
||||
user1.gifted_jamtracks.should eq(5)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -133,12 +133,12 @@ describe "Redeem Gift Card", :js => true, :type => :feature, :capybara_feature =
|
|||
|
||||
find('.done-action a.go-browse').trigger(:click)
|
||||
|
||||
find('.no-free-jamtrack')
|
||||
find('.free-jamtrack')
|
||||
|
||||
gift_card.reload
|
||||
gift_card.user.should eq(user1)
|
||||
user1.reload
|
||||
user1.gifted_jamtracks.should eq(10)
|
||||
user1.gifted_jamtracks.should eq(5)
|
||||
end
|
||||
|
||||
it "converts shopping cart items to free" do
|
||||
|
|
@ -156,12 +156,12 @@ describe "Redeem Gift Card", :js => true, :type => :feature, :capybara_feature =
|
|||
fill_in "code", with: gift_card.code
|
||||
find('button.redeem-giftcard').trigger(:click)
|
||||
find('.done-action a.go-browse').trigger(:click)
|
||||
find('.no-free-jamtrack')
|
||||
find('.free-jamtrack')
|
||||
|
||||
gift_card.reload
|
||||
gift_card.user.should eq(user1)
|
||||
user1.reload
|
||||
user1.gifted_jamtracks.should eq(10)
|
||||
user1.gifted_jamtracks.should eq(5)
|
||||
cart.reload
|
||||
cart.marked_for_redeem.should eq(1)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -730,7 +730,7 @@ describe UserManager do
|
|||
gift_card.user.should eq(user)
|
||||
user = User.find(user.id)
|
||||
user.has_redeemable_jamtrack.should be_true
|
||||
user.gifted_jamtracks.should eq(10)
|
||||
user.gifted_jamtracks.should eq(5)
|
||||
user.gift_cards[0].should eq(gift_card)
|
||||
end
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue