This commit is contained in:
Seth Call 2015-11-12 05:51:25 -06:00
parent 9d66717f90
commit fa7eceec9b
29 changed files with 827 additions and 91 deletions

View File

@ -0,0 +1,41 @@
ActiveAdmin.register_page "Giftcards" do
menu :label => 'Gift Cards', :parent => 'JamTracks'
page_action :upload_giftcards, :method => :post do
GiftCard.transaction do
puts params
file = params[:jam_ruby_gift_card][:csv]
array_of_arrays = CSV.read(file.tempfile.path)
array_of_arrays.each do |row|
if row.length != 1
raise "UKNONWN CSV FORMAT! Must be 1 column"
end
code = row[0]
gift_card = GiftCard.new
gift_card.code = code
gift_card.card_type = params[:jam_ruby_gift_card][:card_type]
gift_card.origin = file .original_filename
gift_card.save!
end
redirect_to admin_giftcards_path, :notice => "Created #{array_of_arrays.length} gift cards!"
end
end
content do
semantic_form_for GiftCard.new, :url => admin_giftcards_upload_giftcards_path, :builder => ActiveAdmin::FormBuilder do |f|
f.inputs "Upload Gift Cards" do
f.input :csv, as: :file, required: true, :label => "A single column CSV that contains ONE type of gift card (5 JamTrack, 10 JamTrack, etc)"
f.input :card_type, required:true, as: :select, :collection => JamRuby::GiftCard::CARD_TYPES
end
f.actions
end
end
end

View File

@ -0,0 +1,9 @@
class JamRuby::GiftCard
attr_accessor :csv
def process_csv
end
end

View File

@ -1,13 +1,13 @@
CREATE TABLE gift_card ( CREATE TABLE gift_cards (
id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4(), id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4(),
code VARCHAR(64) UNIQUE NOT NULL, code VARCHAR(64) UNIQUE NOT NULL,
user_id VARCHAR (64) REFERENCES users(id) ON DELETE CASCADE, user_id VARCHAR (64) REFERENCES users(id) ON DELETE CASCADE,
card_type VARCHAR(64) NOT NULL, card_type VARCHAR(64) NOT NULL,
used BOOLEAN NOT NULL DEFAULT FALSE, origin VARCHAR(200),
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
); );
CREATE INDEX gift_card_user_id_idx ON gift_card(user_id); CREATE INDEX gift_card_user_id_idx ON gift_cards(user_id);
ALTER TABLE users ADD COLUMN gifted_jamtracks INTEGER DEFAULT 0; ALTER TABLE users ADD COLUMN gifted_jamtracks INTEGER DEFAULT 0;

View File

@ -253,6 +253,7 @@ require "jam_ruby/models/musician_search"
require "jam_ruby/models/band_search" require "jam_ruby/models/band_search"
require "jam_ruby/import/tency_stem_mapping" require "jam_ruby/import/tency_stem_mapping"
require "jam_ruby/models/jam_track_search" require "jam_ruby/models/jam_track_search"
require "jam_ruby/models/gift_card"
include Jampb include Jampb

View File

@ -19,6 +19,8 @@ module ValidationMessages
# sessions # sessions
SESSION_NOT_FOUND = "Session not found." SESSION_NOT_FOUND = "Session not found."
NOT_FOUND = 'not found'
# genres # genres
RECORDING_GENRE_LIMIT_EXCEEDED = "No more than 1 genre is allowed." RECORDING_GENRE_LIMIT_EXCEEDED = "No more than 1 genre is allowed."
BAND_GENRE_LIMIT_EXCEEDED = "No more than 3 genres are allowed." BAND_GENRE_LIMIT_EXCEEDED = "No more than 3 genres are allowed."

View File

@ -24,6 +24,8 @@ module JamRuby
end end
def has_redeemable_jamtrack def has_redeemable_jamtrack
raise "not a cookied anonymous user" if @cookies.nil?
APP_CONFIG.one_free_jamtrack_per_user && !@cookies[:redeemed_jamtrack] APP_CONFIG.one_free_jamtrack_per_user && !@cookies[:redeemed_jamtrack]
end end
@ -46,5 +48,9 @@ module JamRuby
def signup_hint def signup_hint
SignupHint.where(anonymous_user_id: @id).where('expires_at > ?', Time.now).first SignupHint.where(anonymous_user_id: @id).where('expires_at > ?', Time.now).first
end end
def reload
end
end end
end end

View File

@ -3,34 +3,33 @@ module JamRuby
@@log = Logging.logger[GiftCard] @@log = Logging.logger[GiftCard]
FIVE_JAM_TRACKS = 'five_jam_tracks' JAM_TRACKS_10 = 'jam_tracks_10'
TEN_JAM_TRACKS = 'ten_jam_tracks' JAM_TRACKS_20 = 'jam_tracks_20'
CARD_TYPES = CARD_TYPES =
[ [
FIVE_JAM_TRACKS, JAM_TRACKS_10,
TEN_JAM_TRACKS JAM_TRACKS_20
] ]
belongs_to :user, class_name: "JamRuby::User" belongs_to :user, class_name: "JamRuby::User"
validates :card_type, presence: true, inclusion: {in: CARD_TYPES} validates :card_type, presence: true, inclusion: {in: CARD_TYPES}
validates :redeemed, inclusion: {in: [true, false]}
validates :code, presence: true, uniqueness: true validates :code, presence: true, uniqueness: true
def redeem(user) after_save :check_gifted
transaction do def check_gifted
update({redeemed: true, user: user}) if user && user_id_changed?
if card_type == JAM_TRACKS_10
if card_type == FIVE_JAM_TRACK user.gifted_jamtracks += 10
user.red elsif card_type == JAM_TRACKS_20
elsif card_type == TEN_JAM_TRACK user.gifted_jamtracks += 20
else else
raise 'unknown type' raise "unknown card type #{card_type}"
end end
user.save!
end end
end end
end end
end end

View File

@ -129,7 +129,29 @@ module JamRuby
end end
def self.is_only_freebie(shopping_carts_jam_tracks) def self.is_only_freebie(shopping_carts_jam_tracks)
shopping_carts_jam_tracks.length == 1 && shopping_carts_jam_tracks[0].product_info[:free] free = true
shopping_carts_jam_tracks.each do |cart|
free = cart.product_info[:free]
if !free
break
end
end
free
end
# we don't allow mixed shopping carts :/
def self.is_mixed(shopping_carts)
free = false
non_free = false
shopping_carts.each do |cart|
if cart.product_info[:free]
free = true
else
non_free = true
end
end
free && non_free
end end
# this method will either return a valid sale, or throw a RecurlyClientError or ActiveRecord validation error (save! failed) # this method will either return a valid sale, or throw a RecurlyClientError or ActiveRecord validation error (save! failed)

View File

@ -12,6 +12,8 @@ module JamRuby
attr_accessible :quantity, :cart_type, :product_info attr_accessible :quantity, :cart_type, :product_info
attr_accessor :skip_mix_check
validates_uniqueness_of :cart_id, scope: [:cart_type, :user_id, :anonymous_user_id] validates_uniqueness_of :cart_id, scope: [:cart_type, :user_id, :anonymous_user_id]
belongs_to :user, :inverse_of => :shopping_carts, :class_name => "JamRuby::User", :foreign_key => "user_id" belongs_to :user, :inverse_of => :shopping_carts, :class_name => "JamRuby::User", :foreign_key => "user_id"
@ -20,6 +22,7 @@ module JamRuby
validates :cart_type, presence: true validates :cart_type, presence: true
validates :cart_class_name, presence: true validates :cart_class_name, presence: true
validates :marked_for_redeem, numericality: {only_integer: true} validates :marked_for_redeem, numericality: {only_integer: true}
validate :not_mixed
default_scope order('created_at DESC') default_scope order('created_at DESC')
@ -38,6 +41,31 @@ module JamRuby
(quantity - marked_for_redeem) * product.price (quantity - marked_for_redeem) * product.price
end end
def not_mixed
return if @skip_mix_check
existing_carts = []
this_user = any_user()
if this_user
existing_carts = this_user.shopping_carts
end
existing_carts = existing_carts.to_a
existing_carts << self
if Sale.is_mixed(existing_carts)
if free?
errors.add(:base, "You can not add a free JamTrack to a cart with non-free items. Please clear out your cart.")
return false
else
errors.add(:base, "You can not add a non-free JamTrack to a cart containing free items. Please clear out your cart.")
return false
end
end
false
end
def cart_product def cart_product
self.cart_class_name.classify.constantize.find_by_id(self.cart_id) unless self.cart_class_name.blank? self.cart_class_name.classify.constantize.find_by_id(self.cart_id) unless self.cart_class_name.blank?
@ -51,6 +79,16 @@ module JamRuby
marked_for_redeem == quantity marked_for_redeem == quantity
end end
def any_user
if user
user
elsif anonymous_user_id
AnonymousUser.new(anonymous_user_id, nil)
else
nil
end
end
def self.create user, product, quantity = 1, mark_redeem = false def self.create user, product, quantity = 1, mark_redeem = false
cart = ShoppingCart.new cart = ShoppingCart.new
if user.is_a?(User) if user.is_a?(User)
@ -81,6 +119,7 @@ module JamRuby
if free? if free?
puts "GOT A FREEBIE!"
# create the credit, then the pseudo charge # create the credit, then the pseudo charge
[ [
{ {
@ -197,6 +236,22 @@ module JamRuby
end end
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)
if jam_track_carts.count > user.gifted_jamtracks
# can't do anything automatically
return
end
jam_track_carts.each do |cart|
cart.skip_mix_check = true
cart.marked_for_redeem = 1
cart.save!
end
end
def port(user, anonymous_user) def port(user, anonymous_user)
ShoppingCart.transaction do ShoppingCart.transaction do

View File

@ -40,7 +40,7 @@ module JamRuby
attr_accessible :first_name, :last_name, :email, :city, :password, :password_confirmation, :state, :country, :birth_date, :subscribe_email, :terms_of_service, :original_fpfile, :cropped_fpfile, :cropped_large_fpfile, :cropped_s3_path, :cropped_large_s3_path, :photo_url, :large_photo_url, :crop_selection attr_accessible :first_name, :last_name, :email, :city, :password, :password_confirmation, :state, :country, :birth_date, :subscribe_email, :terms_of_service, :original_fpfile, :cropped_fpfile, :cropped_large_fpfile, :cropped_s3_path, :cropped_large_s3_path, :photo_url, :large_photo_url, :crop_selection
# updating_password corresponds to a lost_password # updating_password corresponds to a lost_password
attr_accessor :updating_password, :updating_email, :updated_email, :update_email_confirmation_url, :administratively_created, :current_password, :setting_password, :confirm_current_password, :updating_avatar, :updating_progression_field, :mods_json attr_accessor :updating_password, :updating_email, :updated_email, :update_email_confirmation_url, :administratively_created, :current_password, :setting_password, :confirm_current_password, :updating_avatar, :updating_progression_field, :mods_json, :expecting_gift_card
belongs_to :icecast_server_group, class_name: "JamRuby::IcecastServerGroup", inverse_of: :users, foreign_key: 'icecast_server_group_id' belongs_to :icecast_server_group, class_name: "JamRuby::IcecastServerGroup", inverse_of: :users, foreign_key: 'icecast_server_group_id'
@ -148,6 +148,9 @@ module JamRuby
# events # events
has_many :event_sessions, :class_name => "JamRuby::EventSession" has_many :event_sessions, :class_name => "JamRuby::EventSession"
# gift cards
has_many :gift_cards, :class_name=> "JamRuby::GiftCard"
# affiliate_partner # affiliate_partner
has_one :affiliate_partner, :class_name => "JamRuby::AffiliatePartner", :foreign_key => :partner_user_id, inverse_of: :partner_user has_one :affiliate_partner, :class_name => "JamRuby::AffiliatePartner", :foreign_key => :partner_user_id, inverse_of: :partner_user
belongs_to :affiliate_referral, :class_name => "JamRuby::AffiliatePartner", :foreign_key => :affiliate_referral_id, :counter_cache => :referral_user_count belongs_to :affiliate_referral, :class_name => "JamRuby::AffiliatePartner", :foreign_key => :affiliate_referral_id, :counter_cache => :referral_user_count
@ -215,6 +218,7 @@ module JamRuby
validate :email_case_insensitive_uniqueness validate :email_case_insensitive_uniqueness
validate :update_email_case_insensitive_uniqueness, :if => :updating_email validate :update_email_case_insensitive_uniqueness, :if => :updating_email
validate :validate_mods validate :validate_mods
validate :presence_gift_card, :if => :expecting_gift_card
scope :musicians, where(:musician => true) scope :musicians, where(:musician => true)
scope :fans, where(:musician => false) scope :fans, where(:musician => false)
@ -268,6 +272,12 @@ module JamRuby
end end
end end
def presence_gift_card
if self.gift_cards.length == 0
errors.add(:gift_card, ValidationMessages::NOT_FOUND)
end
end
def validate_current_password def validate_current_password
# checks if the user put in their current password (used when changing your email, for instance) # checks if the user put in their current password (used when changing your email, for instance)
errors.add(:current_password, ValidationMessages::NOT_YOUR_PASSWORD) if should_confirm_existing_password? && !valid_password?(self.current_password) errors.add(:current_password, ValidationMessages::NOT_YOUR_PASSWORD) if should_confirm_existing_password? && !valid_password?(self.current_password)
@ -1038,6 +1048,7 @@ module JamRuby
reuse_card = options[:reuse_card] reuse_card = options[:reuse_card]
signup_hint = options[:signup_hint] signup_hint = options[:signup_hint]
affiliate_partner = options[:affiliate_partner] affiliate_partner = options[:affiliate_partner]
gift_card = options[:gift_card]
user = User.new user = User.new
@ -1049,12 +1060,8 @@ module JamRuby
user.terms_of_service = terms_of_service user.terms_of_service = terms_of_service
user.musician = musician user.musician = musician
user.reuse_card unless reuse_card.nil? user.reuse_card unless reuse_card.nil?
user.gifted_jamtracks = 0
if APP_CONFIG.one_free_jamtrack_per_user user.has_redeemable_jamtrack = true
user.free_jamtracks = 1
else
user.free_jamtracks = 0
end
# FIXME: Setting random password for social network logins. This # FIXME: Setting random password for social network logins. This
@ -1160,6 +1167,13 @@ module JamRuby
end end
end end
# if a gift card value was passed in, then try to find that gift card and apply it to user
if gift_card
user.expecting_gift_card = true
found_gift_card = GiftCard.where(code:gift_card).where(user_id:nil).first
user.gift_cards << found_gift_card if found_gift_card
end
user.save user.save
# if the user has just one, free jamtrack in their shopping cart, and it matches the signup hint, then auto-buy it # if the user has just one, free jamtrack in their shopping cart, and it matches the signup hint, then auto-buy it
@ -1201,6 +1215,7 @@ module JamRuby
end end
end end
end end
user.reload if user.id# gift card adding gifted_jamtracks doesn't reflect here until reload
user user
end # def signup end # def signup

View File

@ -860,4 +860,9 @@ FactoryGirl.define do
legalese Faker::Lorem.paragraphs(6).join("\n\n") legalese Faker::Lorem.paragraphs(6).join("\n\n")
end end
factory :gift_card, class: 'JamRuby::GiftCard' do
sequence(:code) {n.to_s}
card_type = JamRuby::GiftCard::JAM_TRACKS_10
end
end end

View File

@ -5,6 +5,23 @@ describe Sale do
let(:user) {FactoryGirl.create(:user)} let(:user) {FactoryGirl.create(:user)}
let(:user2) {FactoryGirl.create(:user)} let(:user2) {FactoryGirl.create(:user)}
let(:jam_track) {FactoryGirl.create(:jam_track)} let(:jam_track) {FactoryGirl.create(:jam_track)}
let(:jam_track2) {FactoryGirl.create(:jam_track)}
let(:jam_track3) {FactoryGirl.create(:jam_track)}
def assert_free_line_item(sale_line_item, jamtrack)
sale_line_item.recurly_tax_in_cents.should be_nil
sale_line_item.recurly_total_in_cents.should be_nil
sale_line_item.recurly_currency.should be_nil
sale_line_item.recurly_discount_in_cents.should be_nil
sale_line_item.product_type.should eq(JamTrack::PRODUCT_TYPE)
sale_line_item.unit_price.should eq(jamtrack.price)
sale_line_item.quantity.should eq(1)
sale_line_item.free.should eq(1)
sale_line_item.sales_tax.should be_nil
sale_line_item.shipping_handling.should eq(0)
sale_line_item.recurly_plan_code.should eq(jamtrack.plan_code)
sale_line_item.product_id.should eq(jamtrack.id)
end
describe "index" do describe "index" do
it "empty" do it "empty" do
@ -47,6 +64,9 @@ describe Sale do
let(:user) {FactoryGirl.create(:user)} let(:user) {FactoryGirl.create(:user)}
let(:jamtrack) { FactoryGirl.create(:jam_track) } let(:jamtrack) { FactoryGirl.create(:jam_track) }
let(:jamtrack2) { FactoryGirl.create(:jam_track) }
let(:jamtrack3) { FactoryGirl.create(:jam_track) }
let(:jamtrack4) { FactoryGirl.create(:jam_track) }
let(:jam_track_price_in_cents) { (jamtrack.price * 100).to_i } let(:jam_track_price_in_cents) { (jamtrack.price * 100).to_i }
let(:client) { RecurlyClient.new } let(:client) { RecurlyClient.new }
let(:billing_info) { let(:billing_info) {
@ -87,6 +107,7 @@ describe Sale do
sales.should eq(user.sales) sales.should eq(user.sales)
sale = sales[0] sale = sales[0]
sale.recurly_invoice_id.should be_nil sale.recurly_invoice_id.should be_nil
sale.recurly_subtotal_in_cents.should eq(0) sale.recurly_subtotal_in_cents.should eq(0)
@ -132,6 +153,92 @@ describe Sale do
user.has_redeemable_jamtrack.should be_false user.has_redeemable_jamtrack.should be_false
end end
it "for two jam tracks (1 freebie, 1 gifted), then 1 gifted/1 pay" do
user.gifted_jamtracks = 2
user.save!
shopping_cart1 = ShoppingCart.create user, jamtrack, 1, true
shopping_cart2 = ShoppingCart.create user, jamtrack2, 1, true
client.find_or_create_account(user, billing_info)
sales = Sale.place_order(user, [shopping_cart1, shopping_cart2])
user.reload
user.sales.length.should eq(1)
sale = sales[0]
sale.reload
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
assert_free_line_item(sale.sale_line_items[0], jamtrack)
assert_free_line_item(sale.sale_line_items[1], jamtrack2)
# verify jam_track_rights data
right1 = JamTrackRight.where(user_id: user.id).where(jam_track_id: jamtrack.id).first
right2 = JamTrackRight.where(user_id: user.id).where(jam_track_id: jamtrack2.id).first
user.jam_track_rights.should have(2).items
right1.redeemed.should be_true
right2.redeemed.should be_true
user.has_redeemable_jamtrack.should be_false
user.gifted_jamtracks.should eq(1)
# 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])
user.reload
user.sales.length.should eq(2)
sale = sales[0]
sale.reload
sale.recurly_invoice_id.should_not 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
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 it "for a free jam track with an affiliate association" do
partner = FactoryGirl.create(:affiliate_partner) partner = FactoryGirl.create(:affiliate_partner)
user.affiliate_referral = partner user.affiliate_referral = partner

View File

@ -18,6 +18,9 @@ describe ShoppingCart do
it "can reference a shopping cart" do it "can reference a shopping cart" do
shopping_cart = ShoppingCart.create user, jam_track, 1 shopping_cart = ShoppingCart.create user, jam_track, 1
shopping_cart.errors.any?.should be_false
shopping_cart.valid?.should be_true
user.reload
ShoppingCart.count.should == 1 ShoppingCart.count.should == 1
user.shopping_carts.count.should == 1 user.shopping_carts.count.should == 1
user.shopping_carts[0].product_info[:name].should == jam_track.name user.shopping_carts[0].product_info[:name].should == jam_track.name
@ -86,7 +89,7 @@ describe ShoppingCart do
user.save! user.save!
end end
it "user can add and remove jamtracks without issue" do it "user can add and remove jamtracks without issue, until 'mixed' free/non-free is hit" do
cart1 = ShoppingCart.add_jam_track_to_cart(user, jam_track) cart1 = ShoppingCart.add_jam_track_to_cart(user, jam_track)
cart1.should_not be_nil cart1.should_not be_nil
cart1.errors.any?.should be_false cart1.errors.any?.should be_false
@ -138,48 +141,51 @@ describe ShoppingCart do
cart6.marked_for_redeem.should eq(1) cart6.marked_for_redeem.should eq(1)
cart7 = ShoppingCart.add_jam_track_to_cart(user, jam_track7) cart7 = ShoppingCart.add_jam_track_to_cart(user, jam_track7)
cart7.errors.any?.should be_false cart7.errors.any?.should be_true
user.reload user.reload
user.shopping_carts.length.should eq(7) user.shopping_carts.length.should eq(6)
cart1.marked_for_redeem.should eq(1) cart1.marked_for_redeem.should eq(1)
cart2.marked_for_redeem.should eq(1) cart2.marked_for_redeem.should eq(1)
cart3.marked_for_redeem.should eq(1) cart3.marked_for_redeem.should eq(1)
cart4.marked_for_redeem.should eq(1) cart4.marked_for_redeem.should eq(1)
cart5.marked_for_redeem.should eq(1) cart5.marked_for_redeem.should eq(1)
cart6.marked_for_redeem.should eq(1) cart6.marked_for_redeem.should eq(1)
# finally, a non-free one end
cart7.marked_for_redeem.should eq(0) end
describe "mixed" do
# Now remove one of the free jamtracks, and we should see the one-non free jamtrack (jam_track6) become free it "non-free then free" do
ShoppingCart.remove_jam_track_from_cart(user, cart1) # you shouldn't be able to add a free after a non-free
user.has_redeemable_jamtrack = false
cart1.destroyed?.should be true user.save!
user.reload
user.shopping_carts.length.should eq(6)
cart1.destroyed?.should be true
cart2.reload
cart3.reload
cart4.reload
cart5.reload
cart6.reload
cart7.reload
cart2.marked_for_redeem.should eq(1)
cart3.marked_for_redeem.should eq(1)
cart4.marked_for_redeem.should eq(1)
cart5.marked_for_redeem.should eq(1)
cart6.marked_for_redeem.should eq(1)
# cart7 should have changed to free automatically
cart7.marked_for_redeem.should eq(1)
cart1 = ShoppingCart.add_jam_track_to_cart(user, jam_track) cart1 = ShoppingCart.add_jam_track_to_cart(user, jam_track)
cart1.should_not be_nil cart1.should_not be_nil
cart1.errors.any?.should be_false cart1.errors.any?.should be_false
cart1.marked_for_redeem.should eq(0)
user.has_redeemable_jamtrack = true
user.save!
user.reload
cart2 = ShoppingCart.add_jam_track_to_cart(user, jam_track2)
cart2.errors.any?.should be_true
cart2.errors[:base].should eq(["You can not add a free JamTrack to a cart with non-free items. Please clear out your cart."])
user.shopping_carts.length.should eq(1)
end
it "free then non-free" do
cart1 = ShoppingCart.add_jam_track_to_cart(user, jam_track)
cart1.should_not be_nil
cart1.errors.any?.should be_false
user.reload
cart2 = ShoppingCart.add_jam_track_to_cart(user, jam_track2)
cart2.errors.any?.should be_true
cart2.errors[:base].should eq(["You can not add a non-free JamTrack to a cart containing free items. Please clear out your cart."])
user.shopping_carts.length.should eq(1)
end end
end end
end end

View File

@ -1800,7 +1800,7 @@
}); });
deferred.done(function(response) { deferred.done(function(response) {
window.UserActions.modify({response}) window.UserActions.modify(response)
}) })
return deferred return deferred
} }
@ -1824,7 +1824,7 @@
}) })
deferred.done(function(response) { deferred.done(function(response) {
window.UserActions.modify({response}) window.UserActions.modify(response)
}) })
return deferred return deferred
} }
@ -1997,6 +1997,17 @@
}); });
} }
function redeemGiftCard(data) {
var id = getId(data);
return $.ajax({
type: "POST",
url: '/api/users/' + id + '/gift_cards',
dataType: "json",
contentType: 'application/json',
data: JSON.stringify(data),
});
}
function portOverCarts() { function portOverCarts() {
return $.ajax({ return $.ajax({
type: "POST", type: "POST",
@ -2201,6 +2212,7 @@
this.playJamTrack = playJamTrack; this.playJamTrack = playJamTrack;
this.createSignupHint = createSignupHint; this.createSignupHint = createSignupHint;
this.createAlert = createAlert; this.createAlert = createAlert;
this.redeemGiftCard = redeemGiftCard;
this.signup = signup; this.signup = signup;
this.portOverCarts = portOverCarts; this.portOverCarts = portOverCarts;
return this; return this;

View File

@ -1,32 +1,159 @@
context = window context = window
rest = context.JK.Rest() rest = context.JK.Rest()
ReactCSSTransitionGroup = React.addons.CSSTransitionGroup;
@RedeemGiftCardPage = React.createClass({ @RedeemGiftCardPage = React.createClass({
render: () -> render: () ->
if this.state.formErrors?
for key, value of this.state.formErrors
break
errorText = context.JK.getFullFirstError(key, @state.formErrors, {email: 'Email', password: 'Password', gift_card: 'Gift Card Code', 'terms_of_service' : 'The terms of service'})
buttonClassnames = classNames({'redeem-giftcard': true, 'button-orange': true, disabled: @state.processing || @state.done })
if @state.done
button =
`<div key="done" className="done-action">
<div>You have {this.state.gifted_jamtracks} free JamTracks on your account!</div>
<div>You can now <a className="go-browse" href="/client#/jamtrack">browse our collection</a> and redeem them.</div>
</div>`
else
button = `<button key="button" className={buttonClassnames} onClick={this.action}>REDEEM GIFT CARD</button>`
action = `<ReactCSSTransitionGroup transitionName="session-track-list">
{button}
</ReactCSSTransitionGroup>`
if context.JK.currentUserId? if context.JK.currentUserId?
form = form =
`<form> `<form onSubmit={this.submit}>
<label>Gift Card Code:</label><input type="text" name="code"/> <label>Gift Card Code:</label><input type="text" name="code"/>
<button className="button-orange" onClick={this.redeem}>REDEEM GIFT CARD</button> {action}
</form>` </form>`
instruments = `<p className="instructions">Enter the code from the back of your gift card to associate it with your account.</p>` instruments = `<p className="instructions">Enter the code from the back of your gift card to associate it with your account.</p>`
else else
form = form =
`<form> `<form onSubmit={this.submit}>
<label>Gift Card Code:</label><input type="text" name="code"/> <label>Gift Card Code:</label><input type="text" name="code"/>
<label>Email:</label><input type="text" name="email"/> <label>Email:</label><input type="text" name="email"/>
<label>Password:</label><input type="password" name="password"/> <label>Password:</label><input type="password" name="password"/>
<button className="button-orange" onClick={this.redeem}>REDEEM GIFT CARD</button> <div className="clearall"/>
<input className="terms-checkbox" type="checkbox" name="terms" /><label className="terms-help">I have read and agree to the JamKazam <a href="/corp/terms" onClick={this.termsClicked}>terms of service</a></label>
<div className="clearall"/>
{action}
</form>` </form>`
instruments = `<p className="instructions">Enter the code from the back of your gift card to associate it with your new JamKazam account.</p>` instruments = `<p className="instructions">Enter the code from the back of your gift card to associate it with your new JamKazam account.</p>`
`<div className={classNames({'redeem-container': true, 'not-logged-in': !context.JK.currentUserId?})}> classes = classNames({'redeem-container': true, 'not-logged-in': !context.JK.currentUserId?, 'logged-in': context.JK.currentUserId? })
`<div className={classes}>
<div className="redeem-content"> <div className="redeem-content">
<h2>Redeem Your Gift Card</h2> <h2>Redeem Your Gift Card</h2>
{instruments} {instruments}
{form} {form}
<div className={classNames({'errors': true, 'active': this.state.formErrors})}>
{errorText}
</div>
</div> </div>
</div>` </div>`
getInitialState: () ->
{formErrors: null, processing:false, gifted_jamtracks: null}
privacyPolicy: (e) ->
e.preventDefault()
context.JK.popExternalLink('/corp/privacy')
termsClicked: (e) ->
e.preventDefault()
context.JK.popExternalLink('/corp/terms')
componentDidMount:() ->
$root = $(this.getDOMNode())
$checkbox = $root.find('.terms-checkbox')
console.log("$checkbox", $checkbox)
context.JK.checkbox($checkbox)
submit: (e) ->
@action(e)
action: (e) ->
if @state.done || @state.processing
e.preventDefault()
return
if context.JK.currentUserId?
@redeem(e)
else
@signup(e)
redeem: (e) ->
e.preventDefault()
return if @state.done || @state.processing
$root = $(@getDOMNode())
$code = $root.find('input[name="code"]')
code = $code.val()
rest.redeemGiftCard({gift_card: code})
.done((response) =>
@setState({formErrors: null, processing:false, done: true, gifted_jamtracks: response.gifted_jamtracks})
).fail((jqXHR) =>
@setState({processing:false})
if jqXHR.status == 422
response = JSON.parse(jqXHR.responseText)
if response.errors
@setState({formErrors: response.errors})
else
context.JK.app.notify({title: 'Unknown Error', text: jqXHR.responseText})
else
context.JK.app.notifyServerError(jqXHR, "Unable to Redeem Giftcard")
)
signup: (e) ->
e.preventDefault()
return if @state.done || @state.processing
$root = $(@getDOMNode())
$email = $root.find('input[name="email"]')
$code = $root.find('input[name="code"]')
$password = $root.find('input[name="password"]')
terms = $root.find('input[name="terms"]').is(':checked')
@setState({processing:true})
email = $email.val()
password = $password.val()
code = $code.val()
if !code
# must pass up non-null value to indicate user is trying to redeem giftcard while creating account
code = ''
rest.signup({email: email, password: password, gift_card: code, terms: terms})
.done((response) =>
@setState({formErrors: null, processing:false, done: true, gifted_jamtracks: response.gifted_jamtracks})
).fail((jqXHR) =>
@setState({processing:false})
if jqXHR.status == 422
response = JSON.parse(jqXHR.responseText)
if response.errors
@setState({formErrors: response.errors})
else
context.JK.app.notify({title: 'Unknown Signup Error', text: jqXHR.responseText})
else
context.JK.app.notifyServerError(jqXHR, "Unable to Sign Up")
)
}) })

View File

@ -702,4 +702,23 @@ $ReactSelectVerticalPadding: 3px;
.Select-search-prompt { .Select-search-prompt {
padding:3px 0 !important; padding:3px 0 !important;
} }
.session-track-list-enter {
opacity: 0.01;
transition: opacity .5s ease-in;
&.session-track-list-enter-active {
opacity: 1;
}
}
.session-track-list-leave {
opacity:1;
transition: opacity .5s ease-in;
&.session-track-list-leave-active {
opacity: 0.01;
}
}

View File

@ -386,22 +386,3 @@ $session-screen-divider: 1190px;
} }
} }
} }
.session-track-list-enter {
opacity: 0.01;
transition: opacity .5s ease-in;
&.session-track-list-enter-active {
opacity: 1;
}
}
.session-track-list-leave {
opacity:1;
transition: opacity .5s ease-in;
&.session-track-list-leave-active {
opacity: 0.01;
}
}

View File

@ -21,11 +21,15 @@ body.web.redeem_giftcard {
width:400px; width:400px;
padding-top:20px; padding-top:20px;
&.not-logged-in { &.logged-in {
button { button {
margin-top:10px !important; margin-top:10px !important;
} }
} }
&.not-logged-in {
}
} }
.redeem-content { .redeem-content {
@ -45,8 +49,42 @@ body.web.redeem_giftcard {
padding: 7px 3px !important; padding: 7px 3px !important;
line-height:inherit !important; line-height:inherit !important;
margin-left:2px !important; margin-left:2px !important;
margin-top:30px; margin-top:15px;
} }
.icheckbox_minimal {
float: left;
top: -2px;
margin-left: 0;
margin-right:10px;
}
.errors {
font-size:14px;
height:20px;
margin:0;
visibility: hidden;
color: red;
font-weight: bold;
&.active {
visibility: visible;
}
}
form {
margin-bottom:20px;
}
.terms-help {
float:left;
margin-top:-5px;
font-size:12px;
width:178px;
}
.done-action {
margin-top: 20px;
line-height: 125%;
}
} }

View File

@ -126,8 +126,15 @@ class ApiRecurlyController < ApiController
error=nil error=nil
response = {jam_tracks: []} response = {jam_tracks: []}
if Sale.is_mixed(current_user.shopping_carts)
msg = "has free and non-free items. Try removing non-free items."
render json: {message: "Cart " + msg, errors: {cart: [msg]}}, :status => 404
return
end
sales = Sale.place_order(current_user, current_user.shopping_carts) sales = Sale.place_order(current_user, current_user.shopping_carts)
sales.each do |sale| sales.each do |sale|
if sale.is_jam_track_sale? if sale.is_jam_track_sale?
sale.sale_line_items.each do |line_item| sale.sale_line_items.each do |line_item|

View File

@ -14,8 +14,8 @@ ApiUsersController < ApiController
:band_invitation_index, :band_invitation_show, :band_invitation_update, # band invitations :band_invitation_index, :band_invitation_show, :band_invitation_update, # band invitations
:set_password, :begin_update_email, :update_avatar, :delete_avatar, :generate_filepicker_policy, :set_password, :begin_update_email, :update_avatar, :delete_avatar, :generate_filepicker_policy,
:share_session, :share_recording, :share_session, :share_recording,
:affiliate_report, :audio_latency, :broadcast_notification] :affiliate_report, :audio_latency, :broadcast_notification, :redeem_giftcard]
before_filter :ip_blacklist, :only => [:create] before_filter :ip_blacklist, :only => [:create, :redeem_giftcard]
respond_to :json, :except => :calendar respond_to :json, :except => :calendar
respond_to :ics, :only => :calendar respond_to :ics, :only => :calendar
@ -81,6 +81,7 @@ ApiUsersController < ApiController
terms_of_service: params[:terms], terms_of_service: params[:terms],
location: {:country => nil, :state => nil, :city => nil}, location: {:country => nil, :state => nil, :city => nil},
signup_hint: signup_hint, signup_hint: signup_hint,
gift_card: params[:gift_card],
affiliate_referral_id: cookies[:affiliate_visitor] affiliate_referral_id: cookies[:affiliate_visitor]
} }
@ -919,6 +920,45 @@ ApiUsersController < ApiController
.find(params[:id]) .find(params[:id])
end end
def redeem_giftcard
@gift_card = GiftCard.find_by_code(params[:gift_card])
if @gift_card.nil?
render json: {errors:{gift_card: ['does not exist']}}, status: 422
return
end
if current_user.gift_cards.count >= 5
render json: {errors:{gift_card: ['has too many on account']}}, status: 422
return
end
if @gift_card.user
if @gift_card.user == current_user
render json: {errors:{gift_card: ['already redeemed by you']}}, status: 422
return
else
render json: {errors:{gift_card: ['already redeemed by another']}}, status: 422
return
end
end
@gift_card.user = current_user
@gift_card.save
if @gift_card.errors.any?
respond_with_model(@gift_card)
return
else
# apply gift card items to everything in shopping cart
current_user.reload
ShoppingCart.apply_gifted_jamtracks(current_user)
render json: {gifted_jamtracks:current_user.gifted_jamtracks}, status: 200
end
end
###################### RECORDINGS ####################### ###################### RECORDINGS #######################
# def recording_index # def recording_index
# @recordings = User.recording_index(current_user, params[:id]) # @recordings = User.recording_index(current_user, params[:id])

View File

@ -1,3 +1,3 @@
node :show_free_jamtrack do node :show_free_jamtrack do
any_user.user.show_free_jamtrack? any_user.show_free_jamtrack?
end end

View File

@ -48,7 +48,6 @@
<%= render "checkout_complete" %> <%= render "checkout_complete" %>
<%= render "redeem_signup" %> <%= render "redeem_signup" %>
<%= render "redeem_complete" %> <%= render "redeem_complete" %>
<%= render "order" %>
<%= render "feed" %> <%= render "feed" %>
<%= render "bands" %> <%= render "bands" %>
<%= render "musicians" %> <%= render "musicians" %>

View File

@ -454,6 +454,9 @@ SampleApp::Application.routes.draw do
match '/users/:id/syncs/:user_sync_id' => 'api_user_syncs#show', :via => :get match '/users/:id/syncs/:user_sync_id' => 'api_user_syncs#show', :via => :get
match '/users/:id/syncs/deletables' => 'api_user_syncs#deletables', :via => :post match '/users/:id/syncs/deletables' => 'api_user_syncs#deletables', :via => :post
# giftcards
match '/users/:id/gift_cards' => 'api_users#redeem_giftcard', :via => :post
# bands # bands

View File

@ -29,6 +29,7 @@ class UserManager < BaseManager
any_user = options[:any_user] any_user = options[:any_user]
signup_hint = options[:signup_hint] signup_hint = options[:signup_hint]
affiliate_partner = options[:affiliate_partner] affiliate_partner = options[:affiliate_partner]
gift_card = options[:gift_card]
recaptcha_failed = false recaptcha_failed = false
unless options[:skip_recaptcha] # allow callers to opt-of recaptcha unless options[:skip_recaptcha] # allow callers to opt-of recaptcha
@ -72,7 +73,8 @@ class UserManager < BaseManager
affiliate_referral_id: affiliate_referral_id, affiliate_referral_id: affiliate_referral_id,
any_user: any_user, any_user: any_user,
signup_hint: signup_hint, signup_hint: signup_hint,
affiliate_partner: affiliate_partner) affiliate_partner: affiliate_partner,
gift_card: gift_card)
user user
end end

View File

@ -25,11 +25,14 @@ describe ApiShoppingCartsController do
it "add_jamtrack" do it "add_jamtrack" do
post :add_jamtrack, {:format => 'json', id: jam_track.id} post :add_jamtrack, {:format => 'json', id: jam_track.id}
response.status.should == 201 response.status.should == 200
end end
it "index" do it "index" do
cart = ShoppingCart.create(user, jam_track) cart = ShoppingCart.create(user, jam_track)
cart.errors.any?.should be_false
user.reload
user.shopping_carts.count.should eq(1)
get :index, {:format => 'json'} get :index, {:format => 'json'}
response.status.should == 200 response.status.should == 200
@ -41,7 +44,7 @@ describe ApiShoppingCartsController do
it "remove_cart" do it "remove_cart" do
cart = ShoppingCart.create(user, jam_track) cart = ShoppingCart.create(user, jam_track)
delete :remove_cart, {:format => 'json', id: cart.id} delete :remove_cart, {:format => 'json', id: cart.id}
response.status.should == 204 response.status.should == 200
ShoppingCart.find_by_id(cart.id).should be_nil ShoppingCart.find_by_id(cart.id).should be_nil
end end
@ -64,7 +67,9 @@ describe ApiShoppingCartsController do
it "add_jamtrack" do it "add_jamtrack" do
post :add_jamtrack, {:format => 'json', id: jam_track.id} post :add_jamtrack, {:format => 'json', id: jam_track.id}
response.status.should == 201 response.status.should == 200
user.reload
user.shopping_carts.count.should eql(1)
end end
it "index" do it "index" do
@ -80,7 +85,7 @@ describe ApiShoppingCartsController do
it "remove_cart" do it "remove_cart" do
cart = ShoppingCart.create(user, jam_track) cart = ShoppingCart.create(user, jam_track)
delete :remove_cart, {:format => 'json', id: cart.id} delete :remove_cart, {:format => 'json', id: cart.id}
response.status.should == 204 response.status.should == 200
ShoppingCart.find_by_id(cart.id).should be_nil ShoppingCart.find_by_id(cart.id).should be_nil
end end

View File

@ -5,12 +5,134 @@ describe ApiUsersController do
let (:user) { FactoryGirl.create(:user) } let (:user) { FactoryGirl.create(:user) }
let (:conn) { FactoryGirl.create(:connection, user: user, last_jam_audio_latency: 5) } let (:conn) { FactoryGirl.create(:connection, user: user, last_jam_audio_latency: 5) }
let (:jam_track) { FactoryGirl.create(:jam_track)}
before(:each) do before(:each) do
controller.current_user = user controller.current_user = user
end end
describe "redeem_giftcard" do
let!(:gift_card) {FactoryGirl.create(:gift_card)}
it "can succeed" do
post :redeem_giftcard, id:user.id, gift_card: gift_card.code, format:'json'
response.should be_success
user.reload
gift_card.reload
user.gift_cards.should eq([gift_card])
user.gifted_jamtracks.should eq(10)
gift_card.user.should eq(user)
end
it "indicates if you've redeemed it" do
gift_card.user = user
gift_card.save!
post :redeem_giftcard, id:user.id, gift_card: gift_card.code, format:'json'
response.status.should eq(422)
error_data = JSON.parse(response.body)
error_data['errors']['gift_card'].should eq(["already redeemed by you"])
user.reload
gift_card.reload
user.gift_cards.should eq([gift_card])
user.gifted_jamtracks.should eq(10)
gift_card.user.should eq(user)
end
it "indicates if someone else has redeemed it" do
user2 = FactoryGirl.create(:user)
gift_card.user = user2
gift_card.save!
post :redeem_giftcard, id:user.id, gift_card: gift_card.code, format:'json'
response.status.should eq(422)
error_data = JSON.parse(response.body)
error_data['errors']['gift_card'].should eq(["already redeemed by another"])
user.reload
gift_card.reload
user.gift_cards.should eq([])
user.gifted_jamtracks.should eq(0)
gift_card.user.should eq(user2)
end
it "marks free shopping cart item as free" do
# sort of a 'do nothing' really
cart1 = ShoppingCart.add_jam_track_to_cart(user, jam_track)
cart1.marked_for_redeem.should eq(1)
post :redeem_giftcard, id:user.id, gift_card: gift_card.code, format:'json'
response.should be_success
user.reload
gift_card.reload
user.gift_cards.should eq([gift_card])
user.gifted_jamtracks.should eq(10)
gift_card.user.should eq(user)
cart1.reload
cart1.marked_for_redeem.should eq(1)
end
it "marks non-free shopping cart item as free" do
# sort of a 'do nothing' really
user.has_redeemable_jamtrack = false
user.save!
cart1 = ShoppingCart.add_jam_track_to_cart(user, jam_track)
cart1.marked_for_redeem.should eq(0)
post :redeem_giftcard, id:user.id, gift_card: gift_card.code, format:'json'
response.should be_success
user.reload
gift_card.reload
user.gift_cards.should eq([gift_card])
user.gifted_jamtracks.should eq(10)
gift_card.user.should eq(user)
cart1.reload
cart1.marked_for_redeem.should eq(1)
end
it "leaves shopping cart alone if too many items in it for size of new gift card" do
# sort of a 'do nothing' really
user.has_redeemable_jamtrack = false
user.save!
11.times do |i|
jamtrack = FactoryGirl.create(:jam_track)
cart1 = ShoppingCart.add_jam_track_to_cart(user, jamtrack)
cart1.marked_for_redeem.should eq(0)
end
post :redeem_giftcard, id:user.id, gift_card: gift_card.code, format:'json'
response.should be_success
user.reload
gift_card.reload
user.gift_cards.should eq([gift_card])
user.gifted_jamtracks.should eq(10)
gift_card.user.should eq(user)
user.shopping_carts.each do |cart|
cart.marked_for_redeem.should eq(0)
end
end
end
describe "create" do describe "create" do
it "successful" do it "successful" do
email = 'user_create1@jamkazam.com' email = 'user_create1@jamkazam.com'

View File

@ -839,4 +839,9 @@ FactoryGirl.define do
factory :affiliate_legalese, class: 'JamRuby::AffiliateLegalese' do factory :affiliate_legalese, class: 'JamRuby::AffiliateLegalese' do
legalese Faker::Lorem.paragraphs(6).join("\n\n") legalese Faker::Lorem.paragraphs(6).join("\n\n")
end end
factory :gift_card, class: 'JamRuby::GiftCard' do
sequence(:code) {n.to_s}
card_type GiftCard::JAM_TRACKS_10
end
end end

View File

@ -0,0 +1,35 @@
require 'spec_helper'
# tests what happens when the websocket connection goes away
describe "Redeem Gift Card", :js => true, :type => :feature, :capybara_feature => true do
subject { page }
let(:user1) { FactoryGirl.create(:user) }
let(:user2) { FactoryGirl.create(:user) }
before(:all) do
User.delete_all
end
describe "not logged in" do
it "suceeeds" do
visit '/redeem_giftcard'
find('h2', text:'Redeem Your Gift Card')
fill_in "email", with: "gifter1@jamkazam.com"
fill_in "password", with: "jam123"
find('.redeem-container ins').trigger(:click)
find('button.redeem-giftcard').trigger(:click)
find('.done-action a.go-browse').trigger(:click)
find('.no-free-jamtrack')
end
it "validates correctly" do
end
end
end

View File

@ -707,4 +707,77 @@ describe UserManager do
user.errors.any?.should be_false user.errors.any?.should be_false
end # it "passes when facebook signup" end # it "passes when facebook signup"
end # describe "with nocaptcha" end # describe "with nocaptcha"
describe "gift_card" do
let(:gift_card) {FactoryGirl.create(:gift_card)}
it "can succeed when specified" do
user = @user_manager.signup(remote_ip: "1.2.3.4",
first_name: "bob",
last_name: "smith",
email: "giftcard1@jamkazam.com",
password: "foobar",
password_confirmation: "foobar",
terms_of_service: true,
instruments: @instruments,
musician: true,
location: @loca,
signup_confirm_url: "http://localhost:3000/confirm",
gift_card: gift_card.code)
user.errors.any?.should be_false
gift_card.reload
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.gift_cards[0].should eq(gift_card)
end
it "will fail if invalid gift card code" do
user = @user_manager.signup(remote_ip: "1.2.3.4",
first_name: "bob",
last_name: "smith",
email: "giftcard2@jamkazam.com",
password: "foobar",
password_confirmation: "foobar",
terms_of_service: true,
instruments: @instruments,
musician: true,
location: @loca,
signup_confirm_url: "http://localhost:3000/confirm",
gift_card: '')
user.errors.any?.should be_true
user.errors["gift_card"].should eq(["not found"])
user.gifted_jamtracks.should eq(0)
gift_card.reload
gift_card.user.should be_nil
user.gift_cards.length.should eq(0)
end
it "will fail if used gift card" do
gift_card.user = FactoryGirl.create(:user)
user = @user_manager.signup(remote_ip: "1.2.3.4",
first_name: "bob",
last_name: "smith",
email: "giftcard2@jamkazam.com",
password: "foobar",
password_confirmation: "foobar",
terms_of_service: true,
instruments: @instruments,
musician: true,
location: @loca,
signup_confirm_url: "http://localhost:3000/confirm",
gift_card: '')
user.errors.any?.should be_true
user.errors["gift_card"].should eq(["not found"])
user.gifted_jamtracks.should eq(0)
gift_card.reload
gift_card.user.should be_nil
user.gift_cards.length.should eq(0)
end
end
end # test end # test