* affiliate program in place VRFS-3030

This commit is contained in:
Seth Call 2015-05-28 08:20:14 -05:00
parent 8a82f86e64
commit d959a17be4
96 changed files with 20968 additions and 124 deletions

View File

@ -2,48 +2,47 @@ ActiveAdmin.register JamRuby::AffiliatePartner, :as => 'Affiliates' do
menu :label => 'Partners', :parent => 'Affiliates' menu :label => 'Partners', :parent => 'Affiliates'
config.sort_order = 'created_at DESC' config.sort_order = 'referral_user_count DESC'
config.batch_actions = false config.batch_actions = false
# config.clear_action_items! # config.clear_action_items!
config.filters = false config.filters = false
form :partial => 'form' form :partial => 'form'
scope("Active", default: true) { |scope| scope.where('partner_user_id IS NOT NULL') }
scope("Unpaid") { |partner| partner.unpaid }
index do index do
column 'User' do |oo| link_to(oo.partner_user.name, "http://www.jamkazam.com/client#/profile/#{oo.partner_user.id}", {:title => oo.partner_user.name}) end
column 'Email' do |oo| oo.partner_user.email end # default_actions # use this for all view/edit/delete links
column 'User' do |oo| link_to(oo.partner_user.name, admin_user_path(oo.partner_user.id), {:title => oo.partner_user.name}) end
column 'Name' do |oo| oo.partner_name end column 'Name' do |oo| oo.partner_name end
column 'Code' do |oo| oo.partner_code end column 'Type' do |oo| oo.entity_type end
column 'Code' do |oo| oo.id end
column 'Referral Count' do |oo| oo.referral_user_count end column 'Referral Count' do |oo| oo.referral_user_count end
# column 'Referrals' do |oo| link_to('View', admin_referrals_path(AffiliatePartner::PARAM_REFERRAL => oo.id)) end column 'Earnings' do |oo| sprintf("$%.2f", oo.cumulative_earnings_in_dollars) end
column 'Amount Owed' do |oo| sprintf("$%.2f", oo.due_amount_in_cents.to_f / 100.to_f) end
column 'Pay Actions' do |oo|
link_to('Mark Paid', mark_paid_admin_affiliate_path(oo.id), :confirm => "Mark this affiliate as PAID?") if oo.unpaid
end
default_actions default_actions
end end
action_item :only => [:show] do
link_to("Mark Paid",
mark_paid_admin_affiliate_path(resource.id),
:confirm => "Mark this affiliate as PAID?") if resource.unpaid
end
member_action :mark_paid, :method => :get do
resource.mark_paid
redirect_to admin_affiliate_path(resource.id)
end
controller do controller do
def show
redirect_to admin_referrals_path(AffiliatePartner::PARAM_REFERRAL => resource.id)
end
def create
obj = AffiliatePartner.create_with_params(params[:jam_ruby_affiliate_partner])
if obj.errors.present?
set_resource_ivar(obj)
render active_admin_template('new')
else
redirect_to admin_affiliates_path
end
end
def update
obj = resource
vals = params[:jam_ruby_affiliate_partner]
obj.partner_name = vals[:partner_name]
obj.user_email = vals[:user_email] if vals[:user_email].present?
obj.save!
set_resource_ivar(obj)
render active_admin_template('show')
end
end end
end end

View File

@ -1,13 +1,7 @@
<%= semantic_form_for([:admin, resource], :url => resource.new_record? ? admin_affiliates_path : "/admin/affiliates/#{resource.id}") do |f| %> <%= semantic_form_for([:admin, resource], :url => resource.new_record? ? admin_affiliates_path : "/admin/affiliates/#{resource.id}") do |f| %>
<%= f.semantic_errors *f.object.errors.keys %> <%= f.semantic_errors *f.object.errors.keys %>
<%= f.inputs do %> <%= f.inputs do %>
<%= f.input(:user_email, :input_html => {:maxlength => 255}) %>
<%= f.input(:partner_name, :input_html => {:maxlength => 128}) %> <%= f.input(:partner_name, :input_html => {:maxlength => 128}) %>
<% if resource.new_record? %>
<%= f.input(:partner_code, :input_html => {:maxlength => 128}) %>
<% else %>
<%= f.input(:partner_code, :input_html => {:maxlength => 128, :readonly => 'readonly'}) %>
<% end %>
<% end %> <% end %>
<%= f.actions %> <%= f.actions %>
<% end %> <% end %>

View File

@ -284,4 +284,5 @@ jam_track_right_private_key.sql
first_downloaded_jamtrack_at.sql first_downloaded_jamtrack_at.sql
signing.sql signing.sql
optimized_redeemption.sql optimized_redeemption.sql
optimized_redemption_warn_mode.sql optimized_redemption_warn_mode.sql
affiliate_partners2.sql

View File

@ -0,0 +1,132 @@
CREATE TABLE affiliate_legalese (
id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4(),
legalese TEXT,
version INTEGER NOT NULL DEFAULT 1,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
ALTER TABLE users DROP CONSTRAINT users_affiliate_referral_id_fkey;
ALTER TABLE users DROP COLUMN affiliate_referral_id;
DROP TABLE affiliate_partners;
CREATE TABLE affiliate_partners (
id INTEGER PRIMARY KEY,
partner_name VARCHAR(1000),
partner_user_id VARCHAR(64) REFERENCES users(id) ON DELETE SET NULL,
entity_type VARCHAR(64),
legalese_id VARCHAR(64),
signed_at TIMESTAMP,
last_paid_at TIMESTAMP,
address JSON NOT NULL DEFAULT '{}',
tax_identifier VARCHAR(1000),
referral_user_count INTEGER NOT NULL DEFAULT 0,
cumulative_earnings_in_cents INTEGER NOT NULL DEFAULT 0,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE SEQUENCE partner_key_sequence;
ALTER SEQUENCE partner_key_sequence RESTART WITH 10000;
ALTER TABLE affiliate_partners ALTER COLUMN id SET DEFAULT nextval('partner_key_sequence');;
ALTER TABLE users ADD COLUMN affiliate_referral_id INTEGER REFERENCES affiliate_partners(id) ON DELETE SET NULL;
CREATE INDEX affiliate_partners_legalese_idx ON affiliate_partners(legalese_id);
CREATE UNLOGGED TABLE affiliate_referral_visits (
id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4(),
affiliate_partner_id INTEGER NOT NULL,
ip_address VARCHAR NOT NULL,
visited_url VARCHAR,
referral_url VARCHAR,
first_visit BOOLEAN NOT NULL DEFAULT TRUE,
user_id VARCHAR(64),
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX on affiliate_referral_visits (affiliate_partner_id, created_at);
CREATE TABLE affiliate_quarterly_payments (
id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4(),
quarter INTEGER NOT NULL,
year INTEGER NOT NULL,
affiliate_partner_id INTEGER NOT NULL REFERENCES affiliate_partners(id),
due_amount_in_cents INTEGER NOT NULL DEFAULT 0,
paid BOOLEAN NOT NULL DEFAULT FALSE,
closed BOOLEAN NOT NULL DEFAULT FALSE,
jamtracks_sold INTEGER NOT NULL DEFAULT 0,
closed_at TIMESTAMP,
paid_at TIMESTAMP,
last_updated TIMESTAMP,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE affiliate_monthly_payments (
id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4(),
month INTEGER NOT NULL,
year INTEGER NOT NULL,
affiliate_partner_id INTEGER NOT NULL REFERENCES affiliate_partners(id),
due_amount_in_cents INTEGER NOT NULL DEFAULT 0,
closed BOOLEAN NOT NULL DEFAULT FALSE,
jamtracks_sold INTEGER NOT NULL DEFAULT 0,
closed_at TIMESTAMP,
last_updated TIMESTAMP,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX ON affiliate_quarterly_payments (affiliate_partner_id, year, quarter);
CREATE UNIQUE INDEX ON affiliate_quarterly_payments (year, quarter, affiliate_partner_id);
CREATE UNIQUE INDEX ON affiliate_monthly_payments (year, month, affiliate_partner_id);
CREATE INDEX ON affiliate_monthly_payments (affiliate_partner_id, year, month);
ALTER TABLE sale_line_items ADD COLUMN affiliate_referral_id INTEGER REFERENCES affiliate_partners(id);
ALTER TABLE sale_line_items ADD COLUMN affiliate_referral_fee_in_cents INTEGER;
ALTER TABLE sale_line_items ADD COLUMN affiliate_refunded BOOLEAN NOT NULL DEFAULT FALSE;
ALTER TABLE sale_line_items ADD COLUMN affiliate_refunded_at TIMESTAMP;
ALTER TABLE generic_state ADD COLUMN affiliate_tallied_at TIMESTAMP;
CREATE TABLE affiliate_traffic_totals (
day DATE NOT NULL,
signups INTEGER NOT NULL DEFAULT 0,
visits INTEGER NOT NULL DEFAULT 0,
affiliate_partner_id INTEGER NOT NULL REFERENCES affiliate_partners(id),
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE UNIQUE INDEX ON affiliate_traffic_totals (day, affiliate_partner_id);
CREATE INDEX ON affiliate_traffic_totals (affiliate_partner_id, day);
CREATE VIEW affiliate_payments AS
SELECT id AS monthly_id,
CAST(NULL as VARCHAR) AS quarterly_id,
affiliate_partner_id,
due_amount_in_cents,
jamtracks_sold,
created_at,
closed,
CAST(NULL AS BOOLEAN) AS paid,
year,
month as month,
CAST(NULL AS INTEGER) as quarter,
month as time_sort,
'monthly' AS payment_type
FROM affiliate_monthly_payments
UNION ALL
SELECT CAST(NULL as VARCHAR) AS monthly_id,
id AS quarterly_id,
affiliate_partner_id,
due_amount_in_cents,
jamtracks_sold,
created_at,
closed,
paid,
year,
CAST(NULL AS INTEGER) as month,
quarter,
(quarter * 3) + 3 as time_sort,
'quarterly' AS payment_type
FROM affiliate_quarterly_payments;

View File

@ -59,8 +59,9 @@ require "jam_ruby/resque/scheduled/score_history_sweeper"
require "jam_ruby/resque/scheduled/scheduled_music_session_cleaner" require "jam_ruby/resque/scheduled/scheduled_music_session_cleaner"
require "jam_ruby/resque/scheduled/recordings_cleaner" require "jam_ruby/resque/scheduled/recordings_cleaner"
require "jam_ruby/resque/scheduled/jam_tracks_cleaner" require "jam_ruby/resque/scheduled/jam_tracks_cleaner"
require "jam_ruby/resque/jam_tracks_builder"
require "jam_ruby/resque/scheduled/stats_maker" require "jam_ruby/resque/scheduled/stats_maker"
require "jam_ruby/resque/scheduled/tally_affiliates"
require "jam_ruby/resque/jam_tracks_builder"
require "jam_ruby/resque/google_analytics_event" require "jam_ruby/resque/google_analytics_event"
require "jam_ruby/resque/batch_email_job" require "jam_ruby/resque/batch_email_job"
require "jam_ruby/resque/long_running" require "jam_ruby/resque/long_running"
@ -206,6 +207,12 @@ require "jam_ruby/app/mailers/async_mailer"
require "jam_ruby/app/mailers/batch_mailer" require "jam_ruby/app/mailers/batch_mailer"
require "jam_ruby/app/mailers/progress_mailer" require "jam_ruby/app/mailers/progress_mailer"
require "jam_ruby/models/affiliate_partner" require "jam_ruby/models/affiliate_partner"
require "jam_ruby/models/affiliate_legalese"
require "jam_ruby/models/affiliate_quarterly_payment"
require "jam_ruby/models/affiliate_monthly_payment"
require "jam_ruby/models/affiliate_traffic_total"
require "jam_ruby/models/affiliate_referral_visit"
require "jam_ruby/models/affiliate_payment"
require "jam_ruby/models/chat_message" require "jam_ruby/models/chat_message"
require "jam_ruby/models/shopping_cart" require "jam_ruby/models/shopping_cart"
require "jam_ruby/models/generic_state" require "jam_ruby/models/generic_state"

View File

@ -0,0 +1,6 @@
class JamRuby::AffiliateLegalese < ActiveRecord::Base
self.table_name = 'affiliate_legalese'
has_many :affiliate_partners, :class_name => "JamRuby::AffiliatePartner", :foreign_key => :legalese_id
end

View File

@ -0,0 +1,39 @@
class JamRuby::AffiliateMonthlyPayment < ActiveRecord::Base
belongs_to :affiliate_partner, class_name: 'JamRuby::AffiliatePartner', inverse_of: :months
def self.index(user, options)
unless user.affiliate_partner
return [[], nil]
end
page = options[:page].to_i
per_page = options[:per_page].to_i
if page == 0
page = 1
end
if per_page == 0
per_page = 50
end
start = (page -1 ) * per_page
limit = per_page
query = AffiliateMonthlyPayment
.paginate(page: page, per_page: per_page)
.where(affiliate_partner_id: user.affiliate_partner.id)
.order('year ASC, month ASC')
if query.length == 0
[query, nil]
elsif query.length < limit
[query, nil]
else
[query, start + limit]
end
end
end

View File

@ -1,25 +1,75 @@
class JamRuby::AffiliatePartner < ActiveRecord::Base class JamRuby::AffiliatePartner < ActiveRecord::Base
belongs_to :partner_user, :class_name => "JamRuby::User", :foreign_key => :partner_user_id self.table_name = 'affiliate_partners'
has_many :user_referrals, :class_name => "JamRuby::User", :foreign_key => :affiliate_referral_id
belongs_to :partner_user, :class_name => "JamRuby::User", :foreign_key => :partner_user_id, inverse_of: :affiliate_partner
has_many :user_referrals, :class_name => "JamRuby::User", :foreign_key => :affiliate_referral_id
belongs_to :affiliate_legalese, :class_name => "JamRuby::AffiliateLegalese", :foreign_key => :legalese_id
has_many :sale_line_items, :class_name => 'JamRuby::SaleLineItem', foreign_key: :affiliate_referral_id
has_many :quarters, :class_name => 'JamRuby::AffiliateQuarterlyPayment', foreign_key: :affiliate_partner_id, inverse_of: :affiliate_partner
has_many :months, :class_name => 'JamRuby::AffiliateMonthlyPayment', foreign_key: :affiliate_partner_id, inverse_of: :affiliate_partner
has_many :traffic_totals, :class_name => 'JamRuby::AffiliateTrafficTotal', foreign_key: :affiliate_partner_id, inverse_of: :affiliate_partner
has_many :visits, :class_name => 'JamRuby::AffiliateReferralVisit', foreign_key: :affiliate_partner_id, inverse_of: :affiliate_partner
attr_accessible :partner_name, :partner_code, :partner_user_id attr_accessible :partner_name, :partner_code, :partner_user_id
ENTITY_TYPES = %w{ Individual Sole\ Proprietor Limited\ Liability\ Company\ (LLC) Partnership Trust/Estate S\ Corporation C\ Corporation Other }
KEY_ADDR1 = 'address1'
KEY_ADDR2 = 'address2'
KEY_CITY = 'city'
KEY_STATE = 'state'
KEY_POSTAL = 'postal_code'
KEY_COUNTRY = 'country'
# ten dollars in cents
PAY_THRESHOLD = 10 * 100
AFFILIATE_PARAMS="utm_source=affiliate&utm_medium=affiliate&utm_campaign=2015-affiliate-custom&affiliate="
ADDRESS_SCHEMA = {
KEY_ADDR1 => '',
KEY_ADDR2 => '',
KEY_CITY => '',
KEY_STATE => '',
KEY_POSTAL => '',
KEY_COUNTRY => '',
}
PARAM_REFERRAL = :ref PARAM_REFERRAL = :ref
PARAM_COOKIE = :affiliate_ref PARAM_COOKIE = :affiliate_ref
PARTNER_CODE_REGEX = /^[#{Regexp.escape('abcdefghijklmnopqrstuvwxyz0123456789-._+,')}]+{2,128}$/i PARTNER_CODE_REGEX = /^[#{Regexp.escape('abcdefghijklmnopqrstuvwxyz0123456789-._+,')}]+{2,128}$/i
validates :user_email, format: {with: JamRuby::User::VALID_EMAIL_REGEX}, :if => :user_email #validates :user_email, format: {with: JamRuby::User::VALID_EMAIL_REGEX}, :if => :user_email
validates :partner_name, presence: true #validates :partner_code, format: { with: PARTNER_CODE_REGEX }, :allow_blank => true
validates :partner_code, presence: true, format: { with: PARTNER_CODE_REGEX } validates :entity_type, inclusion: {in: ENTITY_TYPES, message: "invalid entity type"}
validates :partner_user, presence: true
serialize :address, JSON
before_save do |record|
record.address ||= ADDRESS_SCHEMA.clone
record.entity_type ||= ENTITY_TYPES.first
end
# used by admin
def self.create_with_params(params={}) def self.create_with_params(params={})
raise 'not supported'
oo = self.new oo = self.new
oo.partner_name = params[:partner_name].try(:strip) oo.partner_name = params[:partner_name].try(:strip)
oo.partner_code = params[:partner_code].try(:strip).try(:downcase) oo.partner_code = params[:partner_code].try(:strip).try(:downcase)
oo.partner_user = User.where(:email => params[:user_email].try(:strip)).limit(1).first oo.partner_user = User.where(:email => params[:user_email].try(:strip)).limit(1).first
oo.partner_user_id = oo.partner_user.try(:id) oo.partner_user_id = oo.partner_user.try(:id)
oo.entity_type = params[:entity_type] || ENTITY_TYPES.first
oo.save
oo
end
# used by web
def self.create_with_web_params(user, params={})
oo = self.new
oo.partner_name = params[:partner_name].try(:strip)
oo.partner_user = user if user # user is not required
oo.entity_type = params[:entity_type] || ENTITY_TYPES.first
oo.signed_at = Time.now
oo.save oo.save
oo oo
end end
@ -29,16 +79,393 @@ class JamRuby::AffiliatePartner < ActiveRecord::Base
end end
def self.is_code?(code) def self.is_code?(code)
self.where(:partner_code => code).limit(1).pluck(:id).present? self.where(:partner_code => code).limit(1).pluck(:id).present?
end end
def referrals_by_date def referrals_by_date
by_date = User.where(:affiliate_referral_id => self.id) by_date = User.where(:affiliate_referral_id => self.id)
.group('DATE(created_at)') .group('DATE(created_at)')
.having("COUNT(*) > 0") .having("COUNT(*) > 0")
.order('date_created_at DESC') .order('date_created_at DESC')
.count .count
block_given? ? yield(by_date) : by_date block_given? ? yield(by_date) : by_date
end end
def signed_legalese(legalese)
self.affiliate_legalese = legalese
self.signed_at = Time.now
save!
end
def update_address_value(key, val)
self.address[key] = val
self.update_attribute(:address, self.address)
end
def address_value(key)
self.address[key]
end
def created_within_affiliate_window(user, sale_time)
sale_time - user.created_at < 2.years
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: real_quantity * 20}
else
false
end
else
raise 'shopping cart type not implemented yet'
end
end
def cumulative_earnings_in_dollars
cumulative_earnings_in_cents.to_f / 100.to_f
end
def self.quarter_info(date)
year = date.year
# which quarter?
quarter = -1
if date.month >= 1 && date.month <= 3
quarter = 0
elsif date.month >= 4 && date.month <= 6
quarter = 1
elsif date.month >= 7 && date.month <= 9
quarter = 2
elsif date.month >= 10 && date.month <= 12
quarter = 3
end
raise 'quarter should never be -1' if quarter == -1
previous_quarter = quarter - 1
previous_year = date.year
if previous_quarter == -1
previous_quarter = 3
previous_year = year - 1
end
raise 'previous quarter should never be -1' if previous_quarter == -1
{year: year, quarter: quarter, previous_quarter: previous_quarter, previous_year: previous_year}
end
def self.did_quarter_elapse?(quarter_info, last_tallied_info)
if last_tallied_info.nil?
true
else
quarter_info == last_tallied_info
end
end
# meant to be run regularly; this routine will make summarized counts in the
# AffiliateQuarterlyPayment table
# AffiliatePartner.cumulative_earnings_in_cents, AffiliatePartner.referral_user_count
def self.tally_up(day)
AffiliatePartner.transaction do
quarter_info = quarter_info(day)
last_tallied_info = quarter_info(GenericState.affiliate_tallied_at) if GenericState.affiliate_tallied_at
quarter_elapsed = did_quarter_elapse?(quarter_info, last_tallied_info)
if quarter_elapsed
tally_monthly_payments(quarter_info[:previous_year], quarter_info[:previous_quarter])
tally_quarterly_payments(quarter_info[:previous_year], quarter_info[:previous_quarter])
end
tally_monthly_payments(quarter_info[:year], quarter_info[:quarter])
tally_quarterly_payments(quarter_info[:year], quarter_info[:quarter])
tally_traffic_totals(GenericState.affiliate_tallied_at, day)
tally_partner_totals
state = GenericState.singleton
state.affiliate_tallied_at = day
state.save!
end
end
# this just makes sure that the quarter rows exist before later manipulations with UPDATEs
def self.ensure_quarters_exist(year, quarter)
sql = %{
INSERT INTO affiliate_quarterly_payments (quarter, year, affiliate_partner_id)
(SELECT #{quarter}, #{year}, affiliate_partners.id FROM affiliate_partners WHERE affiliate_partners.partner_user_id IS NOT NULL AND affiliate_partners.id NOT IN
(SELECT affiliate_partner_id FROM affiliate_quarterly_payments WHERE year = #{year} AND quarter = #{quarter}))
}
ActiveRecord::Base.connection.execute(sql)
end
# this just makes sure that the quarter rows exist before later manipulations with UPDATEs
def self.ensure_months_exist(year, quarter)
months = [1, 2, 3].collect! { |i| quarter * 3 + i }
months.each do |month|
sql = %{
INSERT INTO affiliate_monthly_payments (month, year, affiliate_partner_id)
(SELECT #{month}, #{year}, affiliate_partners.id FROM affiliate_partners WHERE affiliate_partners.partner_user_id IS NOT NULL AND affiliate_partners.id NOT IN
(SELECT affiliate_partner_id FROM affiliate_monthly_payments WHERE year = #{year} AND month = #{month}))
}
ActiveRecord::Base.connection.execute(sql)
end
end
def self.sale_items_subquery(start_date, end_date, table_name)
%{
FROM sale_line_items
WHERE
(DATE(sale_line_items.created_at) >= DATE('#{start_date}') AND DATE(sale_line_items.created_at) <= DATE('#{end_date}'))
AND
sale_line_items.affiliate_referral_id = #{table_name}.affiliate_partner_id
}
end
def self.sale_items_refunded_subquery(start_date, end_date, table_name)
%{
FROM sale_line_items
WHERE
(DATE(sale_line_items.affiliate_refunded_at) >= DATE('#{start_date}') AND DATE(sale_line_items.affiliate_refunded_at) <= DATE('#{end_date}'))
AND
sale_line_items.affiliate_referral_id = #{table_name}.affiliate_partner_id
AND
sale_line_items.affiliate_refunded = TRUE
}
end
# total up quarters by looking in sale_line_items for items that are marked as having a affiliate_referral_id
# don't forget to substract any sale_line_items that have a affiliate_refunded = TRUE
def self.total_months(year, quarter)
months = [1, 2, 3].collect! { |i| quarter * 3 + i }
months.each do |month|
start_date, end_date = boundary_dates_for_month(year, month)
sql = %{
UPDATE affiliate_monthly_payments
SET
last_updated = NOW(),
jamtracks_sold =
COALESCE(
(SELECT COUNT(CASE WHEN sale_line_items.product_type = 'JamTrack' AND sale_line_items.affiliate_referral_fee_in_cents > 0 THEN 1 ELSE NULL END)
#{sale_items_subquery(start_date, end_date, 'affiliate_monthly_payments')}
), 0)
+
COALESCE(
(SELECT -COUNT(CASE WHEN sale_line_items.product_type = 'JamTrack' AND sale_line_items.affiliate_referral_fee_in_cents > 0 THEN 1 ELSE NULL END)
#{sale_items_refunded_subquery(start_date, end_date, 'affiliate_monthly_payments')}
), 0),
due_amount_in_cents =
COALESCE(
(SELECT SUM(affiliate_referral_fee_in_cents)
#{sale_items_subquery(start_date, end_date, 'affiliate_monthly_payments')}
), 0)
+
COALESCE(
(SELECT -SUM(affiliate_referral_fee_in_cents)
#{sale_items_refunded_subquery(start_date, end_date, 'affiliate_monthly_payments')}
), 0)
WHERE closed = FALSE AND year = #{year} AND month = #{month}
}
ActiveRecord::Base.connection.execute(sql)
end
end
# close any quarters that are done, so we don't manipulate them again
def self.close_months(year, quarter)
# close any quarters that occurred before this quarter
month = quarter * 3 + 1
sql = %{
UPDATE affiliate_monthly_payments
SET
closed = TRUE, closed_at = NOW()
WHERE year < #{year} OR month < #{month}
}
ActiveRecord::Base.connection.execute(sql)
end
# total up quarters by looking in sale_line_items for items that are marked as having a affiliate_referral_id
# don't forget to substract any sale_line_items that have a affiliate_refunded = TRUE
def self.total_quarters(year, quarter)
start_date, end_date = boundary_dates(year, quarter)
sql = %{
UPDATE affiliate_quarterly_payments
SET
last_updated = NOW(),
jamtracks_sold =
COALESCE(
(SELECT COUNT(CASE WHEN sale_line_items.product_type = 'JamTrack' AND sale_line_items.affiliate_referral_fee_in_cents > 0 THEN 1 ELSE NULL END)
#{sale_items_subquery(start_date, end_date, 'affiliate_quarterly_payments')}
), 0)
+
COALESCE(
(SELECT -COUNT(CASE WHEN sale_line_items.product_type = 'JamTrack' AND sale_line_items.affiliate_referral_fee_in_cents > 0 THEN 1 ELSE NULL END)
#{sale_items_refunded_subquery(start_date, end_date, 'affiliate_quarterly_payments')}
), 0),
due_amount_in_cents =
COALESCE(
(SELECT SUM(affiliate_referral_fee_in_cents)
#{sale_items_subquery(start_date, end_date, 'affiliate_quarterly_payments')}
), 0)
+
COALESCE(
(SELECT -SUM(affiliate_referral_fee_in_cents)
#{sale_items_refunded_subquery(start_date, end_date, 'affiliate_quarterly_payments')}
), 0)
WHERE closed = FALSE AND paid = FALSE AND year = #{year} AND quarter = #{quarter}
}
ActiveRecord::Base.connection.execute(sql)
end
# close any quarters that are done, so we don't manipulate them again
def self.close_quarters(year, quarter)
# close any quarters that occurred before this quarter
sql = %{
UPDATE affiliate_quarterly_payments
SET
closed = TRUE, closed_at = NOW()
WHERE year < #{year} OR quarter < #{quarter}
}
ActiveRecord::Base.connection.execute(sql)
end
def self.tally_quarterly_payments(year, quarter)
ensure_quarters_exist(year, quarter)
total_quarters(year, quarter)
close_quarters(year, quarter)
end
def self.tally_monthly_payments(year, quarter)
ensure_months_exist(year, quarter)
total_months(year, quarter)
close_months(year, quarter)
end
def self.tally_partner_totals
sql = %{
UPDATE affiliate_partners SET
referral_user_count = (SELECT count(*) FROM users WHERE affiliate_partners.id = users.affiliate_referral_id),
cumulative_earnings_in_cents = (SELECT COALESCE(SUM(due_amount_in_cents), 0) FROM affiliate_quarterly_payments AS aqp WHERE aqp.affiliate_partner_id = affiliate_partners.id AND closed = TRUE and paid = TRUE)
}
ActiveRecord::Base.connection.execute(sql)
end
def self.tally_traffic_totals(last_tallied_at, target_day)
if last_tallied_at
start_date = last_tallied_at.to_date
end_date = target_day.to_date
else
start_date = target_day.to_date - 1
end_date = target_day.to_date
end
if start_date == end_date
return
end
sql = %{
INSERT INTO affiliate_traffic_totals(SELECT day, 0, 0, ap.id FROM affiliate_partners AS ap CROSS JOIN (select (generate_series('#{start_date}', '#{end_date - 1}', '1 day'::interval))::date as day) AS lurp)
}
ActiveRecord::Base.connection.execute(sql)
sql = %{
UPDATE affiliate_traffic_totals traffic SET visits = COALESCE((SELECT COALESCE(count(affiliate_partner_id), 0) FROM affiliate_referral_visits v WHERE DATE(v.created_at) >= DATE('#{start_date}') AND DATE(v.created_at) < DATE('#{end_date}') AND v.created_at::date = traffic.day AND v.affiliate_partner_id = traffic.affiliate_partner_id GROUP BY affiliate_partner_id, v.created_at::date ), 0) WHERE traffic.day >= DATE('#{start_date}') AND traffic.day < DATE('#{end_date}')
}
ActiveRecord::Base.connection.execute(sql)
sql = %{
UPDATE affiliate_traffic_totals traffic SET signups = COALESCE((SELECT COALESCE(count(v.id), 0) FROM users v WHERE DATE(v.created_at) >= DATE('#{start_date}') AND DATE(v.created_at) < DATE('#{end_date}') AND v.created_at::date = traffic.day AND v.affiliate_referral_id = traffic.affiliate_partner_id GROUP BY affiliate_referral_id, v.created_at::date ), 0) WHERE traffic.day >= DATE('#{start_date}') AND traffic.day < DATE('#{end_date}')
}
ActiveRecord::Base.connection.execute(sql)
end
def self.boundary_dates(year, quarter)
if quarter == 0
[Date.new(year, 1, 1), Date.new(year, 3, 31)]
elsif quarter == 1
[Date.new(year, 4, 1), Date.new(year, 6, 30)]
elsif quarter == 2
[Date.new(year, 7, 1), Date.new(year, 9, 30)]
elsif quarter == 3
[Date.new(year, 7, 1), Date.new(year, 9, 30)]
else
raise "invalid quarter #{quarter}"
end
end
def self.boundary_dates_for_month(year, month)
[Date.new(year, month, 1), Date.civil(year, month, -1)]
end
# Finds all affiliates that need to be paid
def self.unpaid
joins(:quarters)
.where('affiliate_quarterly_payments.paid = false').where('affiliate_quarterly_payments.closed = true')
.group('affiliate_partners.id')
.having('sum(due_amount_in_cents) >= ?', PAY_THRESHOLD)
.order('sum(due_amount_in_cents) DESC')
end
# does this one affiliate need to be paid?
def unpaid
due_amount_in_cents > PAY_THRESHOLD
end
# admin function: mark the affiliate paid
def mark_paid
if unpaid
transaction do
now = Time.now
quarters.where(paid:false, closed:true).update_all(paid:true, paid_at: now)
self.last_paid_at = now
self.save!
end
end
end
# how much is this affiliate due?
def due_amount_in_cents
total_in_cents = 0
quarters.where(paid:false, closed:true).each do |quarter|
total_in_cents = total_in_cents + quarter.due_amount_in_cents
end
total_in_cents
end
def affiliate_query_params
AffiliatePartner::AFFILIATE_PARAMS + self.id.to_s
end
end end

View File

@ -0,0 +1,49 @@
module JamRuby
class AffiliatePayment < ActiveRecord::Base
belongs_to :affiliate_monthly_payment
belongs_to :affiliate_quarterly_payment
def self.index(user, options)
unless user.affiliate_partner
return [[], nil]
end
affiliate_partner_id = user.affiliate_partner.id
page = options[:page].to_i
per_page = options[:per_page].to_i
if page == 0
page = 1
end
if per_page == 0
per_page = 50
end
start = (page -1 ) * per_page
limit = per_page
query = AffiliatePayment
.includes(affiliate_quarterly_payment: [], affiliate_monthly_payment:[])
.where(affiliate_partner_id: affiliate_partner_id)
.where("payment_type='quarterly' AND closed = true")
.where('(paid = TRUE or due_amount_in_cents < 10000 or paid is NULL)')
.paginate(:page => page, :per_page => limit)
.order('year ASC, time_sort ASC, payment_type ASC')
if query.length == 0
[query, nil]
elsif query.length < limit
[query, nil]
else
[query, start + limit]
end
end
end
end

View File

@ -0,0 +1,41 @@
class JamRuby::AffiliateQuarterlyPayment < ActiveRecord::Base
belongs_to :affiliate_partner, class_name: 'JamRuby::AffiliatePartner', inverse_of: :quarters
def self.index(user, options)
unless user.affiliate_partner
return [[], nil]
end
page = options[:page].to_i
per_page = options[:per_page].to_i
if page == 0
page = 1
end
if per_page == 0
per_page = 50
end
start = (page -1 ) * per_page
limit = per_page
query = AffiliateQuarterlyPayment
.paginate(page: page, per_page: per_page)
.where(affiliate_partner_id: user.affiliate_partner.id)
.where(closed:true)
.where(paid:true)
.order('year ASC, quarter ASC')
if query.length == 0
[query, nil]
elsif query.length < limit
[query, nil]
else
[query, start + limit]
end
end
end

View File

@ -0,0 +1,23 @@
class JamRuby::AffiliateReferralVisit < ActiveRecord::Base
belongs_to :affiliate_partner, class_name: 'JamRuby::AffiliatePartner', inverse_of: :visits
validates :affiliate_partner_id, numericality: {only_integer: true}, :allow_nil => true
validates :visited_url, length: {maximum: 1000}
validates :referral_url, length: {maximum: 1000}
validates :ip_address, presence: true, length: {maximum:1000}
validates :first_visit, inclusion: {in: [true, false]}
validates :user_id, length: {maximum:64}
def self.track(options = {})
visit = AffiliateReferralVisit.new
visit.affiliate_partner_id = options[:affiliate_id]
visit.ip_address = options[:remote_ip]
visit.visited_url = options[:visited_url]
visit.referral_url = options[:referral_url]
visit.first_visit = options[:visited].nil?
visit.user_id = options[:current_user].id if options[:current_user]
visit.save
visit
end
end

View File

@ -0,0 +1,39 @@
class JamRuby::AffiliateTrafficTotal < ActiveRecord::Base
belongs_to :affiliate_partner, class_name: 'JamRuby::AffiliatePartner', inverse_of: :traffic_totals
def self.index(user, options)
unless user.affiliate_partner
return [[], nil]
end
page = options[:page].to_i
per_page = options[:per_page].to_i
if page == 0
page = 1
end
if per_page == 0
per_page = 50
end
start = (page -1 ) * per_page
limit = per_page
query = AffiliateTrafficTotal
.paginate(page: page, per_page: per_page)
.where(affiliate_partner_id: user.affiliate_partner.id)
.where('visits != 0 OR signups != 0')
.order('day ASC')
if query.length == 0
[query, nil]
elsif query.length < limit
[query, nil]
else
[query, start + limit]
end
end
end

View File

@ -28,7 +28,7 @@ module JamRuby
end end
def signup_hint def signup_hint
SignupHint.find_by_anonymous_user_id(@id) SignupHint.where(anonymous_user_id: @id).where('expires_at > ?', Time.now).first
end end
end end
end end

View File

@ -23,9 +23,14 @@ module JamRuby
(database_environment == 'development' && Environment.mode == 'development') (database_environment == 'development' && Environment.mode == 'development')
end end
def self.affiliate_tallied_at
GenericState.singleton.affiliate_tallied_at
end
def self.singleton def self.singleton
GenericState.find('default') GenericState.find('default')
end end
end end
end end

View File

@ -263,5 +263,10 @@ module JamRuby
jam_track_rights.where("user_id=?", user).first jam_track_rights.where("user_id=?", user).first
end end
def short_plan_code
prefix = 'jamtrack-'
plan_code[prefix.length..-1]
end
end end
end end

View File

@ -282,7 +282,7 @@ module JamRuby
return query return query
end end
def self.scheduled user def self.scheduled user, only_public = false
# keep unstarted sessions around for 12 hours after scheduled_start # keep unstarted sessions around for 12 hours after scheduled_start
session_not_started = "(music_sessions.scheduled_start > NOW() - '12 hour'::INTERVAL AND music_sessions.started_at IS NULL)" session_not_started = "(music_sessions.scheduled_start > NOW() - '12 hour'::INTERVAL AND music_sessions.started_at IS NULL)"
@ -293,6 +293,7 @@ module JamRuby
session_finished = "(music_sessions.session_removed_at > NOW() - '2 hour'::INTERVAL)" session_finished = "(music_sessions.session_removed_at > NOW() - '2 hour'::INTERVAL)"
query = MusicSession.where("music_sessions.canceled = FALSE") query = MusicSession.where("music_sessions.canceled = FALSE")
query = query.where('music_sessions.fan_access = TRUE or music_sessions.musician_access = TRUE') if only_public
query = query.where("music_sessions.user_id = '#{user.id}'") query = query.where("music_sessions.user_id = '#{user.id}'")
query = query.where("music_sessions.scheduled_start IS NULL OR #{session_not_started} OR #{session_finished} OR #{session_started_not_finished}") query = query.where("music_sessions.scheduled_start IS NULL OR #{session_not_started} OR #{session_finished} OR #{session_started_not_finished}")
query = query.where("music_sessions.create_type IS NULL OR music_sessions.create_type != '#{CREATE_TYPE_QUICK_START}'") query = query.where("music_sessions.create_type IS NULL OR music_sessions.create_type != '#{CREATE_TYPE_QUICK_START}'")

View File

@ -100,9 +100,14 @@ module JamRuby
if sale && sale.is_jam_track_sale? if sale && sale.is_jam_track_sale?
if sale.sale_line_items.length == 1 if sale.sale_line_items.length == 1
if sale.recurly_total_in_cents == transaction.amount_in_cents if sale.recurly_total_in_cents == transaction.amount_in_cents
jam_track = sale.sale_line_items[0].product 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 jam_track_right = jam_track.right_for_user(transaction.user) if jam_track
if jam_track_right if jam_track_right
line_item.affiliate_refunded = true
line_item.affiliate_refunded_at = Time.now
line_item.save!
jam_track_right.destroy jam_track_right.destroy
# associate which JamTrack we assume this is related to in this one success case # associate which JamTrack we assume this is related to in this one success case

View File

@ -8,7 +8,8 @@ module JamRuby
belongs_to :sale, class_name: 'JamRuby::Sale' belongs_to :sale, class_name: 'JamRuby::Sale'
belongs_to :jam_track, class_name: 'JamRuby::JamTrack' belongs_to :jam_track, class_name: 'JamRuby::JamTrack'
belongs_to :jam_track_right, class_name: 'JamRuby::JamTrackRight' belongs_to :jam_track_right, class_name: 'JamRuby::JamTrackRight'
has_many :recurly_transactions, class_name: 'JamRuby::RecurlyTransactionWebHook', inverse_of: :sale_line_item, foreign_key: 'subscription_id', primary_key: 'recurly_subscription_uuid' 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]}
validates :unit_price, numericality: {only_integer: false} validates :unit_price, numericality: {only_integer: false}
@ -16,6 +17,7 @@ module JamRuby
validates :free, numericality: {only_integer: true} validates :free, numericality: {only_integer: true}
validates :sales_tax, numericality: {only_integer: false}, allow_nil: true validates :sales_tax, numericality: {only_integer: false}, allow_nil: true
validates :shipping_handling, numericality: {only_integer: false} validates :shipping_handling, numericality: {only_integer: false}
validates :affiliate_referral_fee_in_cents, numericality: {only_integer: false}, allow_nil: true
validates :recurly_plan_code, presence:true validates :recurly_plan_code, presence:true
validates :sale, presence:true validates :sale, presence:true
@ -76,6 +78,16 @@ module JamRuby
sale_line_item.recurly_subscription_uuid = recurly_subscription_uuid sale_line_item.recurly_subscription_uuid = recurly_subscription_uuid
sale_line_item.recurly_adjustment_uuid = recurly_adjustment_uuid sale_line_item.recurly_adjustment_uuid = recurly_adjustment_uuid
sale_line_item.recurly_adjustment_credit_uuid = recurly_adjustment_credit_uuid sale_line_item.recurly_adjustment_credit_uuid = recurly_adjustment_credit_uuid
# determine if we need to associate this sale with a partner
user = shopping_cart.user
referral_info = user.should_attribute_sale?(shopping_cart)
if referral_info
sale_line_item.affiliate_referral = user.affiliate_referral
sale_line_item.affiliate_referral_fee_in_cents = referral_info[:fee_in_cents]
end
sale.sale_line_items << sale_line_item sale.sale_line_items << sale_line_item
sale_line_item.save sale_line_item.save
sale_line_item sale_line_item

View File

@ -144,7 +144,7 @@ module JamRuby
has_many :event_sessions, :class_name => "JamRuby::EventSession" has_many :event_sessions, :class_name => "JamRuby::EventSession"
# affiliate_partner # affiliate_partner
has_one :affiliate_partner, :class_name => "JamRuby::AffiliatePartner", :foreign_key => :partner_user_id 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
# diagnostics # diagnostics
has_many :diagnostics, :class_name => "JamRuby::Diagnostic" has_many :diagnostics, :class_name => "JamRuby::Diagnostic"
@ -954,6 +954,7 @@ module JamRuby
any_user = options[:any_user] any_user = options[:any_user]
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]
user = User.new user = User.new
@ -1088,6 +1089,14 @@ module JamRuby
if user.errors.any? if user.errors.any?
raise ActiveRecord::Rollback raise ActiveRecord::Rollback
else else
# if the partner ID was present and the partner doesn't already have a user associated, associate this new user with the affiliate partner
if affiliate_partner && affiliate_partner.partner_user.nil?
affiliate_partner.partner_user = user
unless affiliate_partner.save
@@log.error("unable to associate #{user.to_s} with affiliate_partner #{affiliate_partner.id} / #{affiliate_partner.partner_name}")
end
end
if user.affiliate_referral = AffiliatePartner.find_by_id(affiliate_referral_id) if user.affiliate_referral = AffiliatePartner.find_by_id(affiliate_referral_id)
user.save user.save
end if affiliate_referral_id.present? end if affiliate_referral_id.present?
@ -1603,6 +1612,15 @@ module JamRuby
options options
end end
def should_attribute_sale?(shopping_cart)
if affiliate_referral
referral_info = affiliate_referral.should_attribute_sale?(shopping_cart)
else
false
end
end
private private
def create_remember_token def create_remember_token
self.remember_token = SecureRandom.urlsafe_base64 self.remember_token = SecureRandom.urlsafe_base64

View File

@ -0,0 +1,31 @@
require 'json'
require 'resque'
require 'resque-retry'
require 'net/http'
require 'digest/md5'
module JamRuby
# periodically scheduled to find jobs that need retrying
class TallyAffiliates
extend Resque::Plugins::JamLonelyJob
@queue = :tally_affiliates
@@log = Logging.logger[TallyAffiliates]
def self.lock_timeout
# this should be enough time to make sure the job has finished, but not so long that the system isn't recovering from a abandoned job
120
end
def self.perform
@@log.debug("waking up")
AffiliatePartner.tally_up(Date.today)
@@log.debug("done")
end
end
end

View File

@ -797,4 +797,33 @@ FactoryGirl.define do
transaction_type JamRuby::RecurlyTransactionWebHook::FAILED_PAYMENT transaction_type JamRuby::RecurlyTransactionWebHook::FAILED_PAYMENT
end end
end end
factory :affiliate_partner, class: 'JamRuby::AffiliatePartner' do
sequence(:partner_name) { |n| "partner-#{n}" }
entity_type 'Individual'
signed_at Time.now
association :partner_user, factory: :user
end
factory :affiliate_quarterly_payment, class: 'JamRuby::AffiliateQuarterlyPayment' do
year 2015
quarter 0
association :affiliate_partner, factory: :affiliate_partner
end
factory :affiliate_monthly_payment, class: 'JamRuby::AffiliateMonthlyPayment' do
year 2015
month 0
association :affiliate_partner, factory: :affiliate_partner
end
factory :affiliate_referral_visit, class: 'JamRuby::AffiliateReferralVisit' do
ip_address '1.1.1.1'
association :affiliate_partner, factory: :affiliate_partner
end
factory :affiliate_legalese, class: 'JamRuby::AffiliateLegalese' do
legalese Faker::Lorem.paragraphs(6).join("\n\n")
end
end end

View File

@ -3,47 +3,46 @@ require 'spec_helper'
describe AffiliatePartner do describe AffiliatePartner do
let!(:user) { FactoryGirl.create(:user) } let!(:user) { FactoryGirl.create(:user) }
let!(:partner) { let(:partner) { FactoryGirl.create(:affiliate_partner) }
AffiliatePartner.create_with_params({:partner_name => 'partner', let!(:legalese) { FactoryGirl.create(:affiliate_legalese) }
:partner_code => 'code', let(:jam_track) {FactoryGirl.create(:jam_track) }
:user_email => user.email})
}
# Faker::Lorem.word is tripping up the PARTNER_CODE_REGEX. We should not use it. describe "unpaid" do
it 'validates required fields' do it "succeeds with no data" do
pending AffiliatePartner.unpaid.length.should eq(0)
expect(partner.referral_user_count).to eq(0) end
expect(partner.partner_user).to eq(user)
user.reload
expect(user.affiliate_partner).to eq(partner)
oo = AffiliatePartner.create_with_params({:partner_name => Faker::Company.name, it "finds one unpaid partner" do
:partner_code => 'a', quarter = FactoryGirl.create(:affiliate_quarterly_payment, affiliate_partner: partner, closed:true, paid:false, due_amount_in_cents: AffiliatePartner::PAY_THRESHOLD)
:user_email => user.email}) AffiliatePartner.unpaid.should eq([partner])
expect(oo.errors.messages[:partner_code][0]).to eq('is invalid') end
oo = AffiliatePartner.create_with_params({:partner_name => Faker::Company.name,
:partner_code => 'foo bar',
:user_email => user.email})
expect(oo.errors.messages[:partner_code][0]).to eq('is invalid')
oo = AffiliatePartner.create_with_params({:partner_name => '',
:partner_code => Faker::Lorem.word,
:user_email => user.email})
expect(oo.errors.messages[:partner_name][0]).to eq("can't be blank")
oo = AffiliatePartner.create_with_params({:partner_name => '',
:partner_code => Faker::Lorem.word,
:user_email => Faker::Internet.email})
expect(oo.errors.messages[:partner_user][0]).to eq("can't be blank")
code = Faker::Lorem.word.upcase it "finds one unpaid partner with two quarters that exceed threshold" do
oo = AffiliatePartner.create_with_params({:partner_name => Faker::Company.name, # this $5 quarter is not enough to make the threshold
:partner_code => " #{code} ", quarter = FactoryGirl.create(:affiliate_quarterly_payment, affiliate_partner: partner, year:2016, closed:true, paid:false, due_amount_in_cents: AffiliatePartner::PAY_THRESHOLD / 2)
:user_email => user.email}) AffiliatePartner.unpaid.should eq([])
expect(oo.partner_code).to eq(code.downcase)
# this should get the user over the hump
quarter = FactoryGirl.create(:affiliate_quarterly_payment, affiliate_partner: partner, year:2015, closed:true, paid:false, due_amount_in_cents: AffiliatePartner::PAY_THRESHOLD / 2)
AffiliatePartner.unpaid.should eq([partner])
end
it "does not find paid or closed quarters" do
quarter = FactoryGirl.create(:affiliate_quarterly_payment, affiliate_partner: partner, year:2016, closed:true, paid:true, due_amount_in_cents: AffiliatePartner::PAY_THRESHOLD)
AffiliatePartner.unpaid.should eq([])
quarter = FactoryGirl.create(:affiliate_quarterly_payment, affiliate_partner: partner, year:2015, closed:false, paid:true, due_amount_in_cents: AffiliatePartner::PAY_THRESHOLD)
AffiliatePartner.unpaid.should eq([])
end
end
it "user-partner association" do
user_partner = FactoryGirl.create(:user, affiliate_partner: partner)
user_partner.affiliate_partner.should_not be_nil
user_partner.affiliate_partner.present?.should be_true
end end
it 'has user referrals' do it 'has user referrals' do
pending
expect(AffiliatePartner.coded_id(partner.partner_code)).to eq(partner.id)
expect(partner.referral_user_count).to eq(0) expect(partner.referral_user_count).to eq(0)
uu = FactoryGirl.create(:user) uu = FactoryGirl.create(:user)
uu.affiliate_referral = partner uu.affiliate_referral = partner
@ -73,4 +72,656 @@ describe AffiliatePartner do
expect(by_date[keys.last]).to eq(2) expect(by_date[keys.last]).to eq(2)
end end
it 'updates address correctly' do
addy = partner.address.clone
addy[AffiliatePartner::KEY_ADDR1] = Faker::Address.street_address
addy[AffiliatePartner::KEY_ADDR2] = Faker::Address.secondary_address
addy[AffiliatePartner::KEY_CITY] = Faker::Address.city
addy[AffiliatePartner::KEY_STATE] = Faker::Address.state_abbr
addy[AffiliatePartner::KEY_COUNTRY] = Faker::Address.country
partner.update_address_value(AffiliatePartner::KEY_ADDR1, addy[AffiliatePartner::KEY_ADDR1])
partner.update_address_value(AffiliatePartner::KEY_ADDR2, addy[AffiliatePartner::KEY_ADDR2])
partner.update_address_value(AffiliatePartner::KEY_CITY, addy[AffiliatePartner::KEY_CITY])
partner.update_address_value(AffiliatePartner::KEY_STATE, addy[AffiliatePartner::KEY_STATE])
partner.update_address_value(AffiliatePartner::KEY_COUNTRY, addy[AffiliatePartner::KEY_COUNTRY])
expect(partner.address[AffiliatePartner::KEY_ADDR1]).to eq(addy[AffiliatePartner::KEY_ADDR1])
expect(partner.address[AffiliatePartner::KEY_ADDR2]).to eq(addy[AffiliatePartner::KEY_ADDR2])
expect(partner.address[AffiliatePartner::KEY_CITY]).to eq(addy[AffiliatePartner::KEY_CITY])
expect(partner.address[AffiliatePartner::KEY_STATE]).to eq(addy[AffiliatePartner::KEY_STATE])
expect(partner.address[AffiliatePartner::KEY_COUNTRY]).to eq(addy[AffiliatePartner::KEY_COUNTRY])
end
it 'associates legalese' do
end
describe "should_attribute_sale?" do
it "user with no affiliate relationship" do
shopping_cart = ShoppingCart.create user, jam_track, 1
user.should_attribute_sale?(shopping_cart).should be_false
end
it "user with an affiliate relationship buying a jamtrack" do
user.affiliate_referral = partner
user.save!
shopping_cart = ShoppingCart.create user, jam_track, 1, false
user.should_attribute_sale?(shopping_cart).should eq({fee_in_cents:20})
end
it "user with an affiliate relationship redeeming a jamtrack" do
user.affiliate_referral = partner
user.save!
shopping_cart = ShoppingCart.create user, jam_track, 1, true
user.should_attribute_sale?(shopping_cart).should eq({fee_in_cents:0})
end
it "user with an expired affiliate relationship redeeming a jamtrack" do
user.affiliate_referral = partner
user.created_at = (365 * 2 + 1).days.ago
user.save!
shopping_cart = ShoppingCart.create user, jam_track, 1, false
user.should_attribute_sale?(shopping_cart).should be_false
end
end
describe "created_within_affiliate_window" do
it "user created very recently" do
partner.created_within_affiliate_window(user, Time.now).should be_true
end
it "user created 2 years, 1 day asgo" do
days_future = 365 * 2 + 1
partner.created_within_affiliate_window(user, days_future.days.from_now).should be_false
end
end
describe "tally_up" do
let(:partner1) {FactoryGirl.create(:affiliate_partner)}
let(:partner2) {FactoryGirl.create(:affiliate_partner)}
let(:payment1) {FactoryGirl.create(:affiliate_quarterly_payment, affiliate_partner: partner1)}
let(:user_partner1) { FactoryGirl.create(:user, affiliate_referral: partner1)}
let(:user_partner2) { FactoryGirl.create(:user, affiliate_referral: partner2)}
let(:sale) {Sale.create_jam_track_sale(user_partner1)}
describe "ensure_quarters_exist" do
it "runs OK with no data" do
AffiliatePartner.ensure_quarters_exist(2015, 0)
AffiliateQuarterlyPayment.count.should eq(0)
end
it "creates new slots" do
partner1.touch
partner2.touch
AffiliatePartner.ensure_quarters_exist(2015, 0)
AffiliateQuarterlyPayment.count.should eq(2)
quarter = partner1.quarters.first
quarter.year.should eq(2015)
quarter.quarter.should eq(0)
quarter = partner2.quarters.first
quarter.year.should eq(2015)
quarter.quarter.should eq(0)
end
it "creates one slot, ignoring other" do
partner1.touch
partner2.touch
payment1.touch
AffiliateQuarterlyPayment.count.should eq(1)
AffiliatePartner.ensure_quarters_exist(2015, 0)
AffiliateQuarterlyPayment.count.should eq(2)
quarter = partner1.quarters.first
quarter.year.should eq(2015)
quarter.quarter.should eq(0)
quarter = partner2.quarters.first
quarter.year.should eq(2015)
quarter.quarter.should eq(0)
end
end
describe "close_quarters" do
it "runs OK with no data" do
AffiliateQuarterlyPayment.count.should eq(0)
AffiliatePartner.close_quarters(2015, 1)
end
it "ignores current quarter" do
partner1.touch
partner2.touch
AffiliatePartner.ensure_quarters_exist(2015, 0)
AffiliateQuarterlyPayment.count.should eq(2)
AffiliatePartner.close_quarters(2015, 0)
AffiliateQuarterlyPayment.where(closed: true).count.should eq(0)
end
it "closes previous quarter" do
partner1.touch
partner2.touch
AffiliatePartner.ensure_quarters_exist(2015, 0)
AffiliateQuarterlyPayment.count.should eq(2)
AffiliatePartner.close_quarters(2015, 1)
AffiliateQuarterlyPayment.where(closed: true).count.should eq(2)
end
it "closes previous quarter (edge case)" do
partner1.touch
partner2.touch
AffiliatePartner.ensure_quarters_exist(2014, 3)
AffiliateQuarterlyPayment.count.should eq(2)
AffiliatePartner.close_quarters(2015, 0)
AffiliateQuarterlyPayment.where(closed: true).count.should eq(2)
end
end
describe "tally_partner_totals" do
it "runs OK with no data" do
AffiliatePartner.tally_partner_totals
AffiliatePartner.count.should eq(0)
end
it "updates partner when there is no data to tally" do
partner1.touch
partner1.cumulative_earnings_in_cents.should eq(0)
partner1.referral_user_count.should eq(0)
AffiliatePartner.tally_partner_totals
partner1.reload
partner1.cumulative_earnings_in_cents.should eq(0)
partner1.referral_user_count.should eq(0)
end
it "updates referral_user_count" do
FactoryGirl.create(:user, affiliate_referral: partner1)
AffiliatePartner.tally_partner_totals
partner1.reload
partner1.referral_user_count.should eq(1)
partner1.cumulative_earnings_in_cents.should eq(0)
FactoryGirl.create(:user, affiliate_referral: partner2)
AffiliatePartner.tally_partner_totals
partner1.reload
partner1.referral_user_count.should eq(1)
partner1.cumulative_earnings_in_cents.should eq(0)
partner2.reload
partner2.referral_user_count.should eq(1)
partner2.cumulative_earnings_in_cents.should eq(0)
FactoryGirl.create(:user, affiliate_referral: partner2)
AffiliatePartner.tally_partner_totals
partner1.reload
partner1.referral_user_count.should eq(1)
partner1.cumulative_earnings_in_cents.should eq(0)
partner2.reload
partner2.referral_user_count.should eq(2)
partner2.cumulative_earnings_in_cents.should eq(0)
end
it "updates cumulative_earnings_in_cents" do
FactoryGirl.create(:affiliate_quarterly_payment, affiliate_partner:partner1, year:2015, quarter:0, due_amount_in_cents: 0, closed:true, paid:true)
AffiliatePartner.tally_partner_totals
partner1.reload
partner1.referral_user_count.should eq(0)
partner1.cumulative_earnings_in_cents.should eq(0)
FactoryGirl.create(:affiliate_quarterly_payment, affiliate_partner:partner2, year:2015, quarter:0, due_amount_in_cents: 10, closed:true, paid:true)
AffiliatePartner.tally_partner_totals
partner1.reload
partner1.referral_user_count.should eq(0)
partner1.cumulative_earnings_in_cents.should eq(0)
partner2.reload
partner2.referral_user_count.should eq(0)
partner2.cumulative_earnings_in_cents.should eq(10)
FactoryGirl.create(:affiliate_quarterly_payment, affiliate_partner:partner2, year:2015, quarter:1, due_amount_in_cents: 100, closed:true, paid:true)
AffiliatePartner.tally_partner_totals
partner1.reload
partner1.referral_user_count.should eq(0)
partner1.cumulative_earnings_in_cents.should eq(0)
partner2.reload
partner2.referral_user_count.should eq(0)
partner2.cumulative_earnings_in_cents.should eq(110)
FactoryGirl.create(:affiliate_quarterly_payment, affiliate_partner:partner1, year:2015, quarter:1, due_amount_in_cents: 100, closed:true, paid:true)
AffiliatePartner.tally_partner_totals
partner1.reload
partner1.referral_user_count.should eq(0)
partner1.cumulative_earnings_in_cents.should eq(100)
partner2.reload
partner2.referral_user_count.should eq(0)
partner2.cumulative_earnings_in_cents.should eq(110)
# a paid=false quarterly payment does not yet reflect in cumulative earnings
FactoryGirl.create(:affiliate_quarterly_payment, affiliate_partner:partner1, year:2015, quarter:2, due_amount_in_cents: 1000, closed:false, paid:false)
AffiliatePartner.tally_partner_totals
partner1.reload
partner1.referral_user_count.should eq(0)
partner1.cumulative_earnings_in_cents.should eq(100)
partner2.reload
partner2.referral_user_count.should eq(0)
partner2.cumulative_earnings_in_cents.should eq(110)
end
end
describe "total_quarters" do
it "runs OK with no data" do
AffiliateQuarterlyPayment.count.should eq(0)
AffiliatePartner.total_quarters(2015, 0)
end
it "totals 0 with no sales data" do
partner1.touch
partner2.touch
AffiliatePartner.ensure_quarters_exist(2015, 0)
AffiliateQuarterlyPayment.count.should eq(2)
AffiliatePartner.total_quarters(2015, 0)
quarter = partner1.quarters.first
quarter.due_amount_in_cents.should eq(0)
quarter.last_updated.should_not be_nil
quarter = partner2.quarters.first
quarter.due_amount_in_cents.should eq(0)
quarter.last_updated.should_not be_nil
end
it "totals with sales data" do
partner1.touch
partner2.touch
# create a freebie for partner1
shopping_cart = ShoppingCart.create user_partner1, jam_track, 1, true
freebie_sale = SaleLineItem.create_from_shopping_cart(sale, shopping_cart, nil, nil, nil)
freebie_sale.affiliate_referral_fee_in_cents.should eq(0)
freebie_sale.created_at = Date.new(2015, 1, 1)
freebie_sale.save!
AffiliatePartner.ensure_quarters_exist(2015, 0)
AffiliateQuarterlyPayment.count.should eq(2)
AffiliatePartner.total_quarters(2015, 0)
quarter = partner1.quarters.first
quarter.due_amount_in_cents.should eq(0)
quarter.jamtracks_sold.should eq(0)
quarter = partner2.quarters.first
quarter.due_amount_in_cents.should eq(0)
quarter.jamtracks_sold.should eq(0)
# create a real sale for partner1
shopping_cart = ShoppingCart.create user_partner1, jam_track, 1, false
real_sale = SaleLineItem.create_from_shopping_cart(sale, shopping_cart, nil, nil, nil)
real_sale.affiliate_referral_fee_in_cents.should eq(20)
real_sale.created_at = Date.new(2015, 1, 1)
real_sale.save!
AffiliatePartner.ensure_quarters_exist(2015, 0)
AffiliatePartner.total_quarters(2015, 0)
quarter = partner1.quarters.first
quarter.due_amount_in_cents.should eq(20)
quarter.jamtracks_sold.should eq(1)
quarter = partner2.quarters.first
quarter.due_amount_in_cents.should eq(0)
quarter.jamtracks_sold.should eq(0)
# create a real sale for partner2
shopping_cart = ShoppingCart.create user_partner2, jam_track, 1, false
real_sale = SaleLineItem.create_from_shopping_cart(sale, shopping_cart, nil, nil, nil)
real_sale.affiliate_referral_fee_in_cents.should eq(20)
real_sale.created_at = Date.new(2015, 1, 1)
real_sale.save!
AffiliatePartner.ensure_quarters_exist(2015, 0)
AffiliatePartner.total_quarters(2015, 0)
quarter = partner1.quarters.first
quarter.due_amount_in_cents.should eq(20)
quarter.jamtracks_sold.should eq(1)
quarter = partner2.quarters.first
quarter.due_amount_in_cents.should eq(20)
quarter.jamtracks_sold.should eq(1)
# create a real sale for partner1
shopping_cart = ShoppingCart.create user_partner1, jam_track, 1, false
real_sale = SaleLineItem.create_from_shopping_cart(sale, shopping_cart, nil, nil, nil)
real_sale.affiliate_referral_fee_in_cents.should eq(20)
real_sale.created_at = Date.new(2015, 1, 1)
real_sale.save!
AffiliatePartner.ensure_quarters_exist(2015, 0)
AffiliatePartner.total_quarters(2015, 0)
quarter = partner1.quarters.first
quarter.due_amount_in_cents.should eq(40)
quarter.jamtracks_sold.should eq(2)
quarter = partner2.quarters.first
quarter.due_amount_in_cents.should eq(20)
quarter.jamtracks_sold.should eq(1)
# create a real sale for a non-affiliated user
shopping_cart = ShoppingCart.create user, jam_track, 1, false
real_sale = SaleLineItem.create_from_shopping_cart(sale, shopping_cart, nil, nil, nil)
real_sale.affiliate_referral_fee_in_cents.should be_nil
real_sale.created_at = Date.new(2015, 1, 1)
real_sale.save!
AffiliatePartner.ensure_quarters_exist(2015, 0)
AffiliatePartner.total_quarters(2015, 0)
quarter = partner1.quarters.first
quarter.due_amount_in_cents.should eq(40)
quarter.jamtracks_sold.should eq(2)
quarter = partner2.quarters.first
quarter.due_amount_in_cents.should eq(20)
quarter.jamtracks_sold.should eq(1)
# create a real sale but in previous quarter (should no have effect on the quarter being computed)
shopping_cart = ShoppingCart.create user_partner1, jam_track, 1, false
real_sale = SaleLineItem.create_from_shopping_cart(sale, shopping_cart, nil, nil, nil)
real_sale.affiliate_referral_fee_in_cents.should eq(20)
real_sale.created_at = Date.new(2014, 12, 31)
real_sale.save!
AffiliatePartner.ensure_quarters_exist(2015, 0)
AffiliatePartner.total_quarters(2015, 0)
quarter = partner1.quarters.first
quarter.due_amount_in_cents.should eq(40)
quarter.jamtracks_sold.should eq(2)
quarter = partner2.quarters.first
quarter.due_amount_in_cents.should eq(20)
quarter.jamtracks_sold.should eq(1)
# create a real sale but in later quarter (should no have effect on the quarter being computed)
shopping_cart = ShoppingCart.create user_partner1, jam_track, 1, false
real_sale = SaleLineItem.create_from_shopping_cart(sale, shopping_cart, nil, nil, nil)
real_sale.affiliate_referral_fee_in_cents.should eq(20)
real_sale.created_at = Date.new(2015, 4, 1)
real_sale.save!
real_sale_later = real_sale
AffiliatePartner.ensure_quarters_exist(2015, 0)
AffiliatePartner.total_quarters(2015, 0)
quarter = partner1.quarters.first
quarter.due_amount_in_cents.should eq(40)
quarter.jamtracks_sold.should eq(2)
quarter = partner2.quarters.first
quarter.due_amount_in_cents.should eq(20)
quarter.jamtracks_sold.should eq(1)
# create a real sale but then refund it
shopping_cart = ShoppingCart.create user_partner1, jam_track, 1, false
real_sale = SaleLineItem.create_from_shopping_cart(sale, shopping_cart, nil, nil, nil)
real_sale.affiliate_referral_fee_in_cents.should eq(20)
real_sale.created_at = Date.new(2015, 3, 31)
real_sale.save!
AffiliatePartner.ensure_quarters_exist(2015, 0)
AffiliatePartner.total_quarters(2015, 0)
quarter = partner1.quarters.first
quarter.due_amount_in_cents.should eq(60)
quarter.jamtracks_sold.should eq(3)
quarter = partner2.quarters.first
quarter.due_amount_in_cents.should eq(20)
# now refund it
real_sale.affiliate_refunded_at = Date.new(2015, 3, 1)
real_sale.affiliate_refunded = true
real_sale.save!
AffiliatePartner.ensure_quarters_exist(2015, 0)
AffiliatePartner.total_quarters(2015, 0)
quarter = partner1.quarters.first
quarter.due_amount_in_cents.should eq(40)
quarter = partner2.quarters.first
quarter.due_amount_in_cents.should eq(20)
quarter.jamtracks_sold.should eq(1)
# create the 2nd quarter, which should add up the sale created a few bits up
AffiliatePartner.ensure_quarters_exist(2015, 1)
AffiliatePartner.total_quarters(2015, 1)
payment = AffiliateQuarterlyPayment.find_by_quarter_and_year_and_affiliate_partner_id!(1, 2015, partner1.id)
payment.due_amount_in_cents.should eq(20)
# and now refund it in the 3rd quarter
real_sale_later.affiliate_refunded_at = Date.new(2015, 7, 1)
real_sale_later.affiliate_refunded = true
real_sale_later.save!
AffiliatePartner.total_quarters(2015, 1)
payment = AffiliateQuarterlyPayment.find_by_quarter_and_year_and_affiliate_partner_id!(1, 2015, partner1.id)
payment.due_amount_in_cents.should eq(20)
payment.jamtracks_sold.should eq(1)
# now catch the one refund in the 3rd quarter
AffiliatePartner.ensure_quarters_exist(2015, 2)
AffiliatePartner.total_quarters(2015, 2)
payment = AffiliateQuarterlyPayment.find_by_quarter_and_year_and_affiliate_partner_id!(2, 2015, partner1.id)
payment.due_amount_in_cents.should eq(-20)
payment.jamtracks_sold.should eq(-1)
end
end
describe "tally_up complete" do
it "runs OK with no data" do
AffiliatePartner.tally_up(Date.new(2015, 1, 1))
end
it "successive runs" do
GenericState.singleton.affiliate_tallied_at.should be_nil
AffiliatePartner.tally_up(Date.new(2015, 1, 1))
GenericState.singleton.affiliate_tallied_at.should_not be_nil
AffiliateQuarterlyPayment.count.should eq(0)
# partner is created
partner1.touch
AffiliatePartner.tally_up(Date.new(2015, 1, 1))
AffiliateQuarterlyPayment.count.should eq(2)
AffiliateMonthlyPayment.count.should eq(6)
quarter_previous = AffiliateQuarterlyPayment.find_by_quarter_and_year_and_affiliate_partner_id!(3, 2014, partner1.id)
quarter_previous.due_amount_in_cents.should eq(0)
quarter_previous.closed.should be_true
quarter = AffiliateQuarterlyPayment.find_by_quarter_and_year_and_affiliate_partner_id!(0, 2015, partner1.id)
quarter.due_amount_in_cents.should eq(0)
quarter.closed.should be_false
month_previous= AffiliateMonthlyPayment.find_by_month_and_year_and_affiliate_partner_id!(10, 2014, partner1.id)
month_previous.due_amount_in_cents.should eq(0)
month_previous.closed.should be_true
month_previous.jamtracks_sold.should eq(0)
month_previous= AffiliateMonthlyPayment.find_by_month_and_year_and_affiliate_partner_id!(11, 2014, partner1.id)
month_previous.due_amount_in_cents.should eq(0)
month_previous.closed.should be_true
month_previous.jamtracks_sold.should eq(0)
month_previous= AffiliateMonthlyPayment.find_by_month_and_year_and_affiliate_partner_id!(12, 2014, partner1.id)
month_previous.due_amount_in_cents.should eq(0)
month_previous.closed.should be_true
month_previous.jamtracks_sold.should eq(0)
month = AffiliateMonthlyPayment.find_by_month_and_year_and_affiliate_partner_id!(1, 2015, partner1.id)
month_previous.due_amount_in_cents.should eq(0)
month_previous.closed.should be_true
month_previous.jamtracks_sold.should eq(0)
month = AffiliateMonthlyPayment.find_by_month_and_year_and_affiliate_partner_id!(2, 2015, partner1.id)
month_previous.due_amount_in_cents.should eq(0)
month_previous.closed.should be_true
month.jamtracks_sold.should eq(0)
month = AffiliateMonthlyPayment.find_by_month_and_year_and_affiliate_partner_id!(3, 2015, partner1.id)
month_previous.due_amount_in_cents.should eq(0)
month_previous.closed.should be_true
month_previous.jamtracks_sold.should eq(0)
shopping_cart = ShoppingCart.create user_partner1, jam_track, 1, false
real_sale = SaleLineItem.create_from_shopping_cart(sale, shopping_cart, nil, nil, nil)
real_sale.affiliate_referral_fee_in_cents.should eq(20)
real_sale.created_at = Date.new(2015, 4, 1)
real_sale.save!
AffiliatePartner.tally_up(Date.new(2015, 4, 1))
AffiliateQuarterlyPayment.count.should eq(3)
quarter = AffiliateQuarterlyPayment.find_by_quarter_and_year_and_affiliate_partner_id!(0, 2015, partner1.id)
quarter.due_amount_in_cents.should eq(0)
quarter.jamtracks_sold.should eq(0)
quarter.closed.should be_true
quarter2 = AffiliateQuarterlyPayment.find_by_quarter_and_year_and_affiliate_partner_id!(1, 2015, partner1.id)
quarter2.due_amount_in_cents.should eq(20)
quarter2.jamtracks_sold.should eq(1)
quarter2.closed.should be_false
month = AffiliateMonthlyPayment.find_by_month_and_year_and_affiliate_partner_id!(1, 2015, partner1.id)
month.due_amount_in_cents.should eq(0)
month.jamtracks_sold.should eq(0)
month.closed.should be_true
month = AffiliateMonthlyPayment.find_by_month_and_year_and_affiliate_partner_id!(2, 2015, partner1.id)
month.due_amount_in_cents.should eq(0)
month.jamtracks_sold.should eq(0)
month.closed.should be_true
month = AffiliateMonthlyPayment.find_by_month_and_year_and_affiliate_partner_id!(3, 2015, partner1.id)
month.due_amount_in_cents.should eq(0)
month.jamtracks_sold.should eq(0)
month.closed.should be_true
month = AffiliateMonthlyPayment.find_by_month_and_year_and_affiliate_partner_id!(4, 2015, partner1.id)
month.due_amount_in_cents.should eq(20)
month.jamtracks_sold.should eq(1)
month.closed.should be_false
month = AffiliateMonthlyPayment.find_by_month_and_year_and_affiliate_partner_id!(5, 2015, partner1.id)
month.due_amount_in_cents.should eq(0)
month.jamtracks_sold.should eq(0)
month.closed.should be_false
month = AffiliateMonthlyPayment.find_by_month_and_year_and_affiliate_partner_id!(6, 2015, partner1.id)
month.due_amount_in_cents.should eq(0)
month.jamtracks_sold.should eq(0)
month.closed.should be_false
# now sneak in a purchase in the 1st quarter, which makes no sense, but proves that closed quarters are not touched
shopping_cart = ShoppingCart.create user_partner1, jam_track, 1, false
real_sale = SaleLineItem.create_from_shopping_cart(sale, shopping_cart, nil, nil, nil)
real_sale.affiliate_referral_fee_in_cents.should eq(20)
real_sale.created_at = Date.new(2015, 1, 1)
real_sale.save!
AffiliatePartner.tally_up(Date.new(2015, 4, 2))
quarter = AffiliateQuarterlyPayment.find_by_quarter_and_year_and_affiliate_partner_id!(0, 2015, partner1.id)
quarter.due_amount_in_cents.should eq(0)
quarter.jamtracks_sold.should eq(0)
quarter.closed.should be_true
month = AffiliateMonthlyPayment.find_by_month_and_year_and_affiliate_partner_id!(1, 2015, partner1.id)
month.due_amount_in_cents.should eq(0)
month.closed.should be_true
month = AffiliateMonthlyPayment.find_by_month_and_year_and_affiliate_partner_id!(2, 2015, partner1.id)
month.due_amount_in_cents.should eq(0)
month.jamtracks_sold.should eq(0)
month.closed.should be_true
month = AffiliateMonthlyPayment.find_by_month_and_year_and_affiliate_partner_id!(3, 2015, partner1.id)
month.due_amount_in_cents.should eq(0)
month.jamtracks_sold.should eq(0)
month.closed.should be_true
end
end
describe "tally_traffic_totals" do
it "runs OK with no data" do
AffiliatePartner.tally_traffic_totals(Date.yesterday, Date.today)
end
it "can deal with simple signup case" do
user_partner1.touch
day0 = user_partner1.created_at.to_date
# simulate what happens when this scheduled job first ever runs
AffiliatePartner.tally_traffic_totals(nil, day0)
AffiliateTrafficTotal.count.should eq(1)
traffic_total_day_before = AffiliateTrafficTotal.find_by_day_and_affiliate_partner_id(day0 - 1, user_partner1.affiliate_referral_id)
traffic_total_day_before.visits.should eq(0)
traffic_total_day_before.signups.should eq(0)
# then simulate when it runs on the same day as it ran on the day before
AffiliatePartner.tally_traffic_totals(day0, day0)
AffiliateTrafficTotal.count.should eq(1)
traffic_total_day_before = AffiliateTrafficTotal.find_by_day_and_affiliate_partner_id(day0 - 1, user_partner1.affiliate_referral_id)
traffic_total_day_before.visits.should eq(0)
traffic_total_day_before.signups.should eq(0)
# now run it on the next day, which should catch the signup event
day1 = day0 + 1
AffiliatePartner.tally_traffic_totals(day0, day1)
AffiliateTrafficTotal.count.should eq(2)
traffic_total_day_before = AffiliateTrafficTotal.find_by_day_and_affiliate_partner_id(day0 - 1, user_partner1.affiliate_referral_id)
traffic_total_day_before.visits.should eq(0)
traffic_total_day_before.signups.should eq(0)
traffic_total_day0 = AffiliateTrafficTotal.find_by_day_and_affiliate_partner_id(day0, user_partner1.affiliate_referral_id)
traffic_total_day0.visits.should eq(0)
traffic_total_day0.signups.should eq(1)
# add in a visit
visit = FactoryGirl.create(:affiliate_referral_visit, affiliate_partner: user_partner1.affiliate_referral)
# it won't get seen though because we've moved on
AffiliatePartner.tally_traffic_totals(day1, day1)
AffiliateTrafficTotal.count.should eq(2)
traffic_total_day_before = AffiliateTrafficTotal.find_by_day_and_affiliate_partner_id(day0 - 1, user_partner1.affiliate_referral_id)
traffic_total_day_before.visits.should eq(0)
traffic_total_day_before.signups.should eq(0)
traffic_total_day0 = AffiliateTrafficTotal.find_by_day_and_affiliate_partner_id(day0, user_partner1.affiliate_referral_id)
traffic_total_day0.visits.should eq(0)
traffic_total_day0.signups.should eq(1)
# manipulate the visit created_at so we can record it
visit.created_at = day1
visit.save!
day2 = day1 + 1
AffiliatePartner.tally_traffic_totals(day1, day2)
AffiliateTrafficTotal.count.should eq(3)
traffic_total_day_before = AffiliateTrafficTotal.find_by_day_and_affiliate_partner_id(day0 - 1, user_partner1.affiliate_referral_id)
traffic_total_day_before.visits.should eq(0)
traffic_total_day_before.signups.should eq(0)
traffic_total_day0 = AffiliateTrafficTotal.find_by_day_and_affiliate_partner_id(day0, user_partner1.affiliate_referral_id)
traffic_total_day0.visits.should eq(0)
traffic_total_day0.signups.should eq(1)
traffic_total_day1 = AffiliateTrafficTotal.find_by_day_and_affiliate_partner_id(day1, user_partner1.affiliate_referral_id)
traffic_total_day1.visits.should eq(1)
traffic_total_day1.signups.should eq(0)
# now create 2 records on day 2 for visits and signups both, and a partner with their own visit and signup, and do a final check
user_partner2.touch
visit2 = FactoryGirl.create(:affiliate_referral_visit, affiliate_partner: user_partner1.affiliate_referral)
visit3 = FactoryGirl.create(:affiliate_referral_visit, affiliate_partner: user_partner1.affiliate_referral)
visit_partner2 = FactoryGirl.create(:affiliate_referral_visit, affiliate_partner: user_partner2.affiliate_referral)
visit2.created_at = day2
visit3.created_at = day2
visit_partner2.created_at = day2
visit2.save!
visit3.save!
visit_partner2.save!
user2 = FactoryGirl.create(:user, affiliate_referral:user_partner1.affiliate_referral)
user3 = FactoryGirl.create(:user, affiliate_referral:user_partner1.affiliate_referral)
user2.created_at = day2
user3.created_at = day2
user_partner2.created_at = day2
user2.save!
user3.save!
user_partner2.save!
day3 = day2 + 1
AffiliatePartner.tally_traffic_totals(day2, day3)
AffiliateTrafficTotal.count.should eq(5)
traffic_total_day_before = AffiliateTrafficTotal.find_by_day_and_affiliate_partner_id(day0 - 1, user_partner1.affiliate_referral_id)
traffic_total_day_before.visits.should eq(0)
traffic_total_day_before.signups.should eq(0)
traffic_total_day0 = AffiliateTrafficTotal.find_by_day_and_affiliate_partner_id(day0, user_partner1.affiliate_referral_id)
traffic_total_day0.visits.should eq(0)
traffic_total_day0.signups.should eq(1)
traffic_total_day1 = AffiliateTrafficTotal.find_by_day_and_affiliate_partner_id(day1, user_partner1.affiliate_referral_id)
traffic_total_day1.visits.should eq(1)
traffic_total_day1.signups.should eq(0)
traffic_total_day2 = AffiliateTrafficTotal.find_by_day_and_affiliate_partner_id(day2, user_partner1.affiliate_referral_id)
traffic_total_day2.visits.should eq(2)
traffic_total_day2.signups.should eq(2)
traffic_total_day2 = AffiliateTrafficTotal.find_by_day_and_affiliate_partner_id(day2, user_partner2.affiliate_referral_id)
traffic_total_day2.visits.should eq(1)
traffic_total_day2.signups.should eq(1)
end
end
end
end end

View File

@ -0,0 +1,39 @@
require 'spec_helper'
describe AffiliatePayment do
let(:partner) { FactoryGirl.create(:affiliate_partner) }
let(:user_partner) { FactoryGirl.create(:user, affiliate_partner: partner) }
it "succeeds with no data" do
results, nex = AffiliatePayment.index(user_partner, {})
results.length.should eq(0)
end
it "sorts month and quarters correctly" do
monthly1 = FactoryGirl.create(:affiliate_monthly_payment, affiliate_partner: partner, closed: true, due_amount_in_cents: 10, month: 1, year: 2015)
monthly2 = FactoryGirl.create(:affiliate_monthly_payment, affiliate_partner: partner, closed: true, due_amount_in_cents: 20, month: 2, year: 2015)
monthly3 = FactoryGirl.create(:affiliate_monthly_payment, affiliate_partner: partner, closed: true, due_amount_in_cents: 30, month: 3, year: 2015)
monthly4 = FactoryGirl.create(:affiliate_monthly_payment, affiliate_partner: partner, closed: true, due_amount_in_cents: 40, month: 4, year: 2015)
quarterly = FactoryGirl.create(:affiliate_quarterly_payment, affiliate_partner: partner, closed: true, paid:true, due_amount_in_cents: 50, quarter: 0, year: 2015)
results, nex = AffiliatePayment.index(user_partner, {})
results.length.should eq(5)
result1 = results[0]
result2 = results[1]
result3 = results[2]
result4 = results[3]
result5 = results[4]
result1.payment_type.should eq('monthly')
result1.due_amount_in_cents.should eq(10)
result2.payment_type.should eq('monthly')
result2.due_amount_in_cents.should eq(20)
result3.payment_type.should eq('monthly')
result3.due_amount_in_cents.should eq(30)
result4.payment_type.should eq('quarterly')
result4.due_amount_in_cents.should eq(50)
result5.payment_type.should eq('monthly')
result5.due_amount_in_cents.should eq(40)
end
end

View File

@ -0,0 +1,40 @@
require 'spec_helper'
describe AffiliateReferralVisit do
let!(:user) { FactoryGirl.create(:user) }
let(:partner) { FactoryGirl.create(:affiliate_partner) }
let(:valid_track_options) {
{
affiliate_id: partner.id,
visited: false,
remote_ip: '1.2.2.1',
visited_url: '/',
referral_url: 'http://www.youtube.com',
current_user: nil
}
}
describe "track" do
it "succeeds" do
visit = AffiliateReferralVisit.track( valid_track_options )
visit.valid?.should be_true
end
it "never fails with error" do
visit = AffiliateReferralVisit.track( {})
visit.valid?.should be_false
options = valid_track_options
options[:affiliate_id] = 111
visit = AffiliateReferralVisit.track( options)
visit.valid?.should be_true
options = valid_track_options
options[:current_user] = user
visit = AffiliateReferralVisit.track( options)
visit.valid?.should be_true
end
end
end

View File

@ -132,6 +132,69 @@ describe Sale do
user.has_redeemable_jamtrack.should be_false user.has_redeemable_jamtrack.should be_false
end end
it "for a free jam track with an affiliate association" do
partner = FactoryGirl.create(:affiliate_partner)
user.affiliate_referral = partner
user.save!
shopping_cart = ShoppingCart.create user, jamtrack, 1, true
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 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 == 1
sale_line_item = sale.sale_line_items[0]
sale_line_item.recurly_tax_in_cents.should eq(0)
sale_line_item.recurly_total_in_cents.should eq(0)
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(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)
sale_line_item.recurly_subscription_uuid.should be_nil
sale_line_item.recurly_adjustment_uuid.should be_nil
sale_line_item.recurly_adjustment_credit_uuid.should be_nil
sale_line_item.recurly_adjustment_uuid.should eq(user.jam_track_rights.last.recurly_adjustment_uuid)
sale_line_item.recurly_adjustment_credit_uuid.should eq(user.jam_track_rights.last.recurly_adjustment_credit_uuid)
sale_line_item.affiliate_referral.should eq(partner)
sale_line_item.affiliate_referral_fee_in_cents.should eq(0)
# verify subscription is in Recurly
recurly_account = client.get_account(user)
adjustments = recurly_account.adjustments
adjustments.should_not be_nil
adjustments.should have(0).items
invoices = recurly_account.invoices
invoices.should have(0).items
# verify jam_track_rights data
user.jam_track_rights.should_not be_nil
user.jam_track_rights.should have(1).items
user.jam_track_rights.last.jam_track.id.should eq(jamtrack.id)
user.jam_track_rights.last.redeemed.should be_true
user.has_redeemable_jamtrack.should be_false
end
it "for a normally priced jam track" do it "for a normally priced jam track" do
user.has_redeemable_jamtrack = false user.has_redeemable_jamtrack = false
user.save! user.save!
@ -201,6 +264,85 @@ describe Sale do
user.jam_track_rights.last.jam_track.id.should eq(jamtrack.id) user.jam_track_rights.last.jam_track.id.should eq(jamtrack.id)
user.jam_track_rights.last.redeemed.should be_false user.jam_track_rights.last.redeemed.should be_false
user.has_redeemable_jamtrack.should be_false user.has_redeemable_jamtrack.should be_false
sale_line_item.affiliate_referral.should be_nil
sale_line_item.affiliate_referral_fee_in_cents.should be_nil
end
it "for a normally priced jam track with an affiliate association" do
user.has_redeemable_jamtrack = false
partner = FactoryGirl.create(:affiliate_partner)
user.affiliate_referral = partner
user.save!
shopping_cart = ShoppingCart.create user, jamtrack, 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(jam_track_price_in_cents)
sale.recurly_tax_in_cents.should eq(0)
sale.recurly_total_in_cents.should eq(jam_track_price_in_cents)
sale.recurly_currency.should eq('USD')
sale.order_total.should eq(jamtrack.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(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(jamtrack.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(jamtrack.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(user.jam_track_rights.last.recurly_adjustment_uuid)
sale_line_item.affiliate_referral.should eq(partner)
sale_line_item.affiliate_referral_fee_in_cents.should eq(20)
# 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((jamtrack.price * 100).to_i)
purchase.accounting_code.should eq(ShoppingCart::PURCHASE_NORMAL)
purchase.description.should eq("JamTrack: " + jamtrack.name)
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((jamtrack.price * 100).to_i)
invoice.total_in_cents.should eq((jamtrack.price * 100).to_i)
invoice.state.should eq('collected')
# verify jam_track_rights data
user.jam_track_rights.should_not be_nil
user.jam_track_rights.should have(1).items
user.jam_track_rights.last.jam_track.id.should eq(jamtrack.id)
user.jam_track_rights.last.redeemed.should be_false
user.has_redeemable_jamtrack.should be_false
end end
it "for a jamtrack already owned" do it "for a jamtrack already owned" do

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@ -8,10 +8,10 @@
var rest = context.JK.Rest(); var rest = context.JK.Rest();
var userId; var userId;
var user = {}; var user = {};
var screen = null;
var gearUtils = context.JK.GearUtilsInstance; var gearUtils = context.JK.GearUtilsInstance;
function beforeShow(data) { function beforeShow(data) {
console.log("beforeShow", data)
userId = data.id; userId = data.id;
} }
@ -71,8 +71,11 @@
invalidProfiles : invalidProfiles, invalidProfiles : invalidProfiles,
isNativeClient: gon.isNativeClient, isNativeClient: gon.isNativeClient,
musician: context.JK.currentUserMusician, musician: context.JK.currentUserMusician,
webcamName: webcamName, sales_count: userDetail.sales_count,
sales_count: userDetail.sales_count is_affiliate_partner: userDetail.is_affiliate_partner,
affiliate_earnings: (userDetail.affiliate_earnings / 100).toFixed(2),
affiliate_referral_count: userDetail.affiliate_referral_count,
webcamName: webcamName
} , { variable: 'data' })); } , { variable: 'data' }));
$('#account-content-scroller').html($template); $('#account-content-scroller').html($template);
@ -135,6 +138,7 @@
$('#account-content-scroller').on('avatar_changed', '#profile-avatar', function(evt, newAvatarUrl) { evt.stopPropagation(); updateAvatar(newAvatarUrl); return false; }) $('#account-content-scroller').on('avatar_changed', '#profile-avatar', function(evt, newAvatarUrl) { evt.stopPropagation(); updateAvatar(newAvatarUrl); return false; })
$("#account-content-scroller").on('click', '#account-payment-history-link', function(evt) {evt.stopPropagation(); navToPaymentHistory(); return false; } ); $("#account-content-scroller").on('click', '#account-payment-history-link', function(evt) {evt.stopPropagation(); navToPaymentHistory(); return false; } );
$("#account-content-scroller").on('click', '#account-affiliate-partner-link', function(evt) {evt.stopPropagation(); navToAffiliates(); return false; } );
} }
function renderAccount() { function renderAccount() {
@ -187,6 +191,11 @@
window.location = '/client#/account/paymentHistory' window.location = '/client#/account/paymentHistory'
} }
function navToAffiliates() {
resetForm()
window.location = '/client#/account/affiliatePartner'
}
// handle update avatar event // handle update avatar event
function updateAvatar(avatar_url) { function updateAvatar(avatar_url) {
var photoUrl = context.JK.resolveAvatarUrl(avatar_url); var photoUrl = context.JK.resolveAvatarUrl(avatar_url);
@ -203,7 +212,7 @@
} }
function initialize() { function initialize() {
screen = $('#account-content-scroller');
var screenBindings = { var screenBindings = {
'beforeShow': beforeShow, 'beforeShow': beforeShow,
'afterShow': afterShow 'afterShow': afterShow
@ -218,4 +227,4 @@
return this; return this;
}; };
})(window,jQuery); })(window,jQuery);

View File

@ -0,0 +1,324 @@
(function (context, $) {
"use strict";
context.JK = context.JK || {};
context.JK.AccountAffiliateScreen = function (app) {
var logger = context.JK.logger;
var rest = context.JK.Rest();
var userId;
var user = {};
var affiliatePartnerTabs = ['account', 'agreement', 'signups', 'earnings'];
var affiliatePartnerData = null;
var $screen = null;
function beforeShow(data) {
userId = data.id;
affiliatePartnerData = null;
}
function afterShow(data) {
rest.getAffiliatePartnerData(userId)
.done(function (response) {
affiliatePartnerData = response;
renderAffiliateTab('account')
})
.fail(app.ajaxError)
}
function events() {
// Affiliate Partner
$("#account-affiliate-partner-content-scroller").on('click', '#affiliate-partner-account-link', function (evt) {
evt.stopPropagation();
renderAffiliateTab('account');
return false;
});
$("#account-affiliate-partner-content-scroller").on('click', '#affiliate-partner-links-link', function (evt) {
evt.stopPropagation();
renderAffiliateTab('links');
return false;
});
$("#account-affiliate-partner-content-scroller").on('click', '#affiliate-partner-agreement-link', function (evt) {
evt.stopPropagation();
renderAffiliateTab('agreement');
return false;
});
$("#account-affiliate-partner-content-scroller").on('click', '#affiliate-partner-signups-link', function (evt) {
evt.stopPropagation();
renderAffiliateTab('signups');
return false;
});
$("#account-affiliate-partner-content-scroller").on('click', '#affiliate-partner-earnings-link', function (evt) {
evt.stopPropagation();
renderAffiliateTab('earnings');
return false;
});
$("#account-affiliate-partner-content-scroller").on('click', '#affiliate-profile-account-submit', function (evt) {
evt.stopPropagation();
handleUpdateAffiliateAccount();
return false;
});
}
function _renderAffiliateTableSignups(rows) {
rest.getAffiliateSignups()
.done(onAffiliateSignups)
.fail(app.ajaxError)
}
function _renderAffiliateTableEarnings(rows) {
rest.getAffiliatePayments()
.done(onAffiliatePayments)
.fail(app.ajaxError)
}
function _renderAffiliateTableLinks(rows) {
$screen.find('.affiliate-agreement').on('click', function () {
renderAffiliateTab('agreement');
return false;
})
$screen.find('.affiliate-link-page').attr('href', '/affiliate/links/' + affiliatePartnerData.account.id)
$screen.find('select.link_type').easyDropDown();
var $linkType = $screen.find('.link_type')
$linkType.on('change', function() {
logger.debug("link type changed")
updateLinks();
})
updateLinks();
}
function onAffiliateSignups(signups) {
var $table = $screen.find('table.traffic-table tbody')
$table.empty();
var template = $('#template-affiliate-partner-signups-row').html();
context._.each(signups.traffics, function(item) {
var $link = $(context._.template(template, item, {variable: 'data'}));
var $day = $link.find('td.day')
var day = $day.text();
var bits = day.split('-')
if(bits.length == 3) {
$day.text(context.JK.getMonth(new Number(bits[1]) - 1) + ' ' + new Number(bits[2]))
}
$table.append($link)
})
}
function onAffiliatePayments(payments) {
var $table = $screen.find('table.payment-table tbody')
$table.empty();
var template = $('#template-affiliate-partner-earnings-row').html();
context._.each(payments.payments, function(item) {
var data = {}
if(item.payment_type == 'quarterly') {
if(item.quarter == 0) {
data.time = '1st Quarter ' + item.year
}
else if(item.quarter == 1) {
data.time = '2nd Quarter ' + item.year
}
else if(item.quarter == 2) {
data.time = '3rd Quarter ' + item.year
}
else if(item.quarter == 3) {
data.time = '4th Quarter ' + item.year
}
data.sold = ''
if(item.paid) {
data.earnings = 'PAID $' + (item.due_amount_in_cents / 100).toFixed(2);
}
else {
data.earnings = 'No earning were paid, as the $10 minimum threshold was not reached.'
}
}
else {
data.time = context.JK.getMonth(item.month - 1) + ' ' + item.year;
if(item.jamtracks_sold == 1) {
data.sold = 'JamTracks: ' + item.jamtracks_sold + ' unit sold';
}
else {
data.sold = 'JamTracks: ' + item.jamtracks_sold + ' units sold';
}
data.earnings = '$' + (item.due_amount_in_cents / 100).toFixed(2);
}
var $earning = $(context._.template(template, data, {variable: 'data'}));
$table.append($earning)
})
}
function updateLinks() {
var $select = $screen.find('select.link_type')
var value = $select.val()
logger.debug("value: " + value)
var type = 'jamtrack_songs';
if(value == 'JamTrack Song') {
type = 'jamtrack_songs'
}
else if(value == 'JamTrack Band') {
type = 'jamtrack_bands'
}
else if(value == 'JamTrack General') {
type = 'jamtrack_general'
}
else if(value == 'JamKazam General') {
type = 'jamkazam'
}
else if(value == 'JamKazam Session') {
type = 'sessions'
}
else if(value == 'JamKazam Recording') {
type = 'recordings'
}
else if(value == 'Custom Link') {
type = 'custom_links'
}
$screen.find('.link-type-prompt').hide();
$screen.find('.link-type-prompt[data-type="' + type + '"]').show();
if(type == 'custom_links') {
$screen.find('table.links-table').hide();
$screen.find('.link-type-prompt[data-type="custom_links"] span.affiliate_id').text(affiliatePartnerData.account.id)
}
else {
rest.getLinks(type)
.done(populateLinkTable)
.fail(function() {
app.notify({message: 'Unable to fetch links. Please try again later.' })
})
}
}
function _renderAffiliateTab(theTab) {
affiliateTabRefresh(theTab);
var template = $('#template-affiliate-partner-' + theTab).html();
var tabHtml = context._.template(template, affiliatePartnerData[theTab], {variable: 'data'});
$('#affiliate-partner-tab-content').html(tabHtml);
if (theTab == 'signups') {
_renderAffiliateTableSignups(affiliatePartnerData[theTab]);
} else if (theTab == 'earnings') {
_renderAffiliateTableEarnings(affiliatePartnerData[theTab]);
} else if (theTab == 'links') {
_renderAffiliateTableLinks(affiliatePartnerData[theTab]);
}
}
function renderAffiliateTab(theTab) {
if (affiliatePartnerData) {
return _renderAffiliateTab(theTab);
}
rest.getAffiliatePartnerData(userId)
.done(function (response) {
affiliatePartnerData = response;
_renderAffiliateTab(theTab);
})
.fail(app.ajaxError)
}
function affiliateTabRefresh(selectedTab) {
var container = $('#account-affiliate-partner-content-scroller');
container.find('.affiliate-partner-nav a.active').removeClass('active');
if (selectedTab) {
container.find('.affiliate-partner-' + selectedTab).show();
$.each(affiliatePartnerTabs, function (index, val) {
if (val != selectedTab) {
container.find('.affiliate-partner-' + val).hide();
}
});
container.find('.affiliate-partner-nav a#affiliate-partner-' + selectedTab + '-link').addClass('active');
} else {
$.each(affiliatePartnerTabs, function (index, val) {
container.find('.affiliate-partner-' + val).hide();
});
container.find('.affiliate-partner-nav a#affiliate-partner-' + affiliatePartnerTabs[0] + '-link').addClass('active');
}
}
function handleUpdateAffiliateAccount() {
var tab_content = $('#affiliate-partner-tab-content');
var affiliate_partner_data = {
'address': {
'address1': tab_content.find('#affiliate_partner_address1').val(),
'address2': tab_content.find('#affiliate_partner_address2').val(),
'city': tab_content.find('#affiliate_partner_city').val(),
'state': tab_content.find('#affiliate_partner_state').val(),
'postal_code': tab_content.find('#affiliate_partner_postal_code').val(),
'country': tab_content.find('#affiliate_partner_country').val()
},
'tax_identifier': tab_content.find('#affiliate_partner_tax_identifier').val()
}
rest.postAffiliatePartnerData(userId, affiliate_partner_data)
.done(postUpdateAffiliateAccountSuccess);
}
function postUpdateAffiliateAccountSuccess(response) {
app.notify(
{
title: "Affiliate Account",
text: "You have updated your affiliate partner data successfully."
},
null, true);
}
function populateLinkTable(response) {
$screen.find('table.links-table').show();
var $linkTable = $screen.find('.links-table tbody')
$linkTable.empty();
var template = $('#template-affiliate-link-entry').html();
context._.each(response, function(item) {
var $link = $(context._.template(template, item, {variable: 'data'}));
$link.find('td.copy-link a').click(copyLink)
$linkTable.append($link)
})
}
function copyLink() {
var element = $(this);
var $url = element.closest('tr').find('td.url input')
$url.select()
return false;
}
function initialize() {
var screenBindings = {
'beforeShow': beforeShow,
'afterShow': afterShow
};
app.bindScreen('account/affiliatePartner', screenBindings);
$screen = $('#account-affiliate-partner')
events();
}
this.initialize = initialize;
this.beforeShow = beforeShow;
this.afterShow = afterShow;
return this;
};
})(window, jQuery);

View File

@ -133,20 +133,25 @@
if(options.buttons) { if(options.buttons) {
context._.each(options.buttons, function(button, i) { context._.each(options.buttons, function(button, i) {
if(!button.name) throw "button.name must be specified"; if(!button.name) throw "button.name must be specified";
if(!button.click) throw "button.click must be specified"; if(!button.click && !button.href) throw "button.click or button.href must be specified";
var buttonStyle = button.buttonStyle; var buttonStyle = button.buttonStyle;
if(!buttonStyle) { if(!buttonStyle) {
buttonStyle = options.buttons.length == i + 1 ? 'button-orange' : 'button-grey'; buttonStyle = options.buttons.length == i + 1 ? 'button-orange' : 'button-grey';
} }
var $btn = $('<a class="' + buttonStyle + ' user-btn">' + button.name + '</a>'); var $btn = $('<a class="' + buttonStyle + ' user-btn">' + button.name + '</a>');
$btn.click(function() {
button.click(); if(button.href) {
hide(); $btn.attr('href', button.href)
return false; }
}); else {
$btn.click(function() {
button.click();
hide();
return false;
});
}
$buttons.append($btn); $buttons.append($btn);
}); });
} }

View File

@ -485,6 +485,80 @@
return detail; return detail;
} }
function createAffiliatePartner(options) {
return $.ajax({
type: "POST",
url: '/api/affiliate_partners',
dataType: "json",
contentType: 'application/json',
data: JSON.stringify(options)
})
}
function getAffiliatePartnerData(userId) {
return $.ajax({
type: "GET",
dataType: "json",
url: "/api/users/"+userId+"/affiliate_partner"
});
}
function postAffiliatePartnerData(userId, data) {
return $.ajax({
type: "POST",
dataType: "json",
url: "/api/users/"+userId+"/affiliate_partner",
contentType: 'application/json',
processData:false,
data: JSON.stringify(data)
});
}
function getLinks(type, partner_id) {
var url = "/api/links/" + type;
if(partner_id) {
url += '?affiliate_id=' + partner_id;
}
return $.ajax({
type: "GET",
dataType: "json",
url: url
});
}
function getAffiliateSignups() {
return $.ajax({
type: "GET",
dataType: "json",
url: "/api/affiliate_partners/signups"
});
}
function getAffiliateMonthly() {
return $.ajax({
type: "GET",
dataType: "json",
url: "/api/affiliate_partners/monthly_earnings"
});
}
function getAffiliateQuarterly() {
return $.ajax({
type: "GET",
dataType: "json",
url: "/api/affiliate_partners/quarterly_earnings"
});
}
function getAffiliatePayments() {
return $.ajax({
type: "GET",
dataType: "json",
url: "/api/affiliate_partners/payments"
});
}
function getCities(options) { function getCities(options) {
var country = options['country'] var country = options['country']
var region = options['region'] var region = options['region']
@ -1711,6 +1785,14 @@
this.cancelSession = cancelSession; this.cancelSession = cancelSession;
this.updateScheduledSession = updateScheduledSession; this.updateScheduledSession = updateScheduledSession;
this.getUserDetail = getUserDetail; this.getUserDetail = getUserDetail;
this.getAffiliatePartnerData = getAffiliatePartnerData;
this.postAffiliatePartnerData = postAffiliatePartnerData;
this.createAffiliatePartner = createAffiliatePartner;
this.getLinks = getLinks;
this.getAffiliateSignups = getAffiliateSignups;
this.getAffiliateMonthly = getAffiliateMonthly;
this.getAffiliateQuarterly = getAffiliateQuarterly;
this.getAffiliatePayments = getAffiliatePayments;
this.getCities = getCities; this.getCities = getCities;
this.getRegions = getRegions; this.getRegions = getRegions;
this.getCountries = getCountries; this.getCountries = getCountries;
@ -1853,4 +1935,4 @@
}; };
})(window,jQuery); })(window,jQuery);

View File

@ -156,6 +156,9 @@
submit_data.city = $('#jam_ruby_user_city').val() submit_data.city = $('#jam_ruby_user_city').val()
submit_data.birth_date = gather_birth_date() submit_data.birth_date = gather_birth_date()
submit_data.instruments = gather_instruments() submit_data.instruments = gather_instruments()
if($.QueryString['affiliate_partner_id']) {
submit_data.affiliate_partner_id = $.QueryString['affiliate_partner_id'];
}
//submit_data.photo_url = $('#jam_ruby_user_instruments').val() //submit_data.photo_url = $('#jam_ruby_user_instruments').val()

View File

@ -627,6 +627,10 @@
return (suppressDay ? '' : (days[date.getDay()] + ' ')) + months[date.getMonth()] + ' ' + context.JK.padString(date.getDate(), 2) + ', ' + date.getFullYear(); return (suppressDay ? '' : (days[date.getDay()] + ' ')) + months[date.getMonth()] + ' ' + context.JK.padString(date.getDate(), 2) + ', ' + date.getFullYear();
} }
// returns June for months 0-11
context.JK.getMonth = function(monthNumber) {
return months[monthNumber];
}
context.JK.formatDateYYYYMMDD = function(dateString) { context.JK.formatDateYYYYMMDD = function(dateString) {
var date = new Date(dateString); var date = new Date(dateString);

View File

@ -0,0 +1,55 @@
$ = jQuery
context = window
context.JK ||= {};
class AffiliateLinks
constructor: (@app, @partner_id) ->
@logger = context.JK.logger
@rest = new context.JK.Rest();
initialize: () =>
@page = $('body')
@sections = ['jamtrack_songs', 'jamtrack_bands', 'jamtrack_general', 'jamkazam', 'sessions', 'recordings']
@jamtrack_songs = @page.find('table.jamtrack_songs tbody')
@jamtrack_bands = @page.find('table.jamtrack_bands tbody')
@jamtrack_general = @page.find('table.jamtrack_general tbody')
@jamkazam = @page.find('table.jamkazam tbody')
@sessions= @page.find('table.sessions tbody')
@recordings = @page.find('table.recordings tbody')
@iterate()
onGetLinks: (links) =>
$table = @page.find('table.' + @section + ' tbody')
template = $('#template-affiliate-link-row').html();
context._.each(links, (item) =>
$link = $(context._.template(template, item, {variable: 'data'}));
$link.find('td.copy-link a').click(@copyLink)
$table.append($link)
)
if @sections.length > 0
@iterate()
copyLink: () ->
$element = $(this)
$url = $element.closest('tr').find('td.url input')
$url.select()
return false;
iterate: () =>
@section = @sections.shift()
@rest.getLinks(@section, @partner_id)
.done(@onGetLinks)
context.JK.AffiliateLinks = AffiliateLinks

View File

@ -0,0 +1,119 @@
$ = jQuery
context = window
context.JK ||= {};
class AffiliateProgram
constructor: (@app) ->
@logger = context.JK.logger
@rest = new context.JK.Rest();
@agreeBtn = null
@disagreeBtn = null
@entityForm = null
@disagreeNotice = null
@entityName = null
@entityType = null
@entityRadio = null
@fieldEntityName = null
@fieldEntityType = null
@entityOptions = null
removeErrors: () =>
@fieldEntityName.removeClass('error').find('.error-info').remove();
@fieldEntityType.removeClass('error').find('.error-info').remove();
@entityOptions.removeClass('error').find('.error-info').remove();
onRadioChanged: () =>
@removeErrors()
value = @page.find('input:radio[name="entity"]:checked').val()
if value == 'individual'
@entityForm.slideUp()
else
@entityForm.slideDown()
return false
onCreatedAffiliatePartner:(response) =>
if response.partner_user_id?
# this was an existing user, so tell them to go on in
context.JK.Banner.show({buttons: [{name: 'GO TO AFFILIATE PAGE', href: '/client#/account/affiliatePartner'}], title: 'congratulations', html: 'Thank you for joining the JamKazam affiliate program!<br/><br/>You can visit the <a href="/client#/account/affiliatePartner">Affiliate Page</a> in your JamKazam Account any time to get links to share to refer users, and to view reports on affiliate activity levels.'})
else
context.JK.Banner.show({buttons: [{name: 'GO SIGNUP', href:'/signup?affiliate_partner_id=' + response.id}], title: 'congratulations', html: 'Thank you for joining the JamKazam affiliate program!<br/><br/>There is still one more step: you still need to create a user account on JamKazam, so that you can access your affiliate information.'})
onFailedCreateAffiliatePartner: (jqXHR) =>
if jqXHR.status == 422
body = JSON.parse(jqXHR.responseText)
if body.errors && body.errors.affiliate_partner && body.errors.affiliate_partner[0] == 'You are already an affiliate.'
@app.notify({title:'Error', text:'You are already an affiliate.'})
else
@app.notifyServerError(jqXHR, 'Unable to Create Affiliate')
else
@app.notifyServerError(jqXHR, 'Unable to Create Affiliate')
onAgreeClicked: () =>
@removeErrors()
value = @page.find('input:radio[name="entity"]:checked').val()
error = false
if value?
if value == 'individual'
entityType = 'Individual'
else
# insist that they fill out entity type info
entityName = @entityName.val()
entityType = @entityType.val()
entityNameNotEmpty = !!entityName
entityTypeNotEmpty = !!entityType
if !entityNameNotEmpty
@fieldEntityName.addClass('error').append('<div class="error-info">must be specified</div>')
error = true
if !entityTypeNotEmpty
@fieldEntityType.addClass('error').append('<div class="error-info">must be specified</div>')
error = true
else
@entityOptions.addClass('error')
error = true
unless error
@rest.createAffiliatePartner({partner_name: entityName, entity_type: entityType})
.done(@onCreatedAffiliatePartner)
.fail(@onFailedCreateAffiliatePartner)
@disagreeNotice.hide ('hidden')
return false
onDisagreeClicked: () =>
@removeErrors()
@disagreeNotice.slideDown('hidden')
return false
events:() =>
@entityRadio.on('change', @onRadioChanged)
@agreeBtn.on('click', @onAgreeClicked)
@disagreeBtn.on('click', @onDisagreeClicked)
initialize: () =>
@page = $('body')
@agreeBtn = @page.find('.agree-button')
@disagreeBtn = @page.find('.disagree-button')
@entityForm = @page.find('.entity-info')
@disagreeNotice = @page.find('.disagree-text')
@entityName = @page.find('input[name="entity-name"]')
@entityType = @page.find('select[name="entity-type"]')
@entityRadio = @page.find('input[name="entity"]')
@fieldEntityName = @page.find('.field.entity.name')
@fieldEntityType = @page.find('.field.entity.type')
@entityOptions = @page.find('.entity-options')
@events()
context.JK.AffiliateProgram = AffiliateProgram

View File

@ -65,6 +65,8 @@
//= require web/tracking //= require web/tracking
//= require web/individual_jamtrack //= require web/individual_jamtrack
//= require web/individual_jamtrack_band //= require web/individual_jamtrack_band
//= require web/affiliate_program
//= require web/affiliate_links
//= require fakeJamClient //= require fakeJamClient
//= require fakeJamClientMessages //= require fakeJamClientMessages
//= require fakeJamClientRecordings //= require fakeJamClientRecordings

View File

@ -21,6 +21,13 @@
} }
} }
hr {
height:0;
border-width: 1px 0 0 0;
border-style:solid;
border-color:$ColorTextTypical;
}
h4 { h4 {
margin-top:8px; margin-top:8px;
margin-bottom: 10px; margin-bottom: 10px;
@ -57,7 +64,7 @@
.subcaption { .subcaption {
margin-bottom: 4px; margin-bottom: 4px;
} }
} }
.webcam-container { .webcam-container {

View File

@ -0,0 +1,201 @@
@import 'common.css.scss';
#account-affiliate-partner {
p {
font-size: 15px;
line-height: 125%;
margin:0;
}
.affiliates-header {
float:left;
}
.affiliate-partner-nav {
width:85%;
position:relative;
float:right;
margin-bottom:20px;
}
.affiliate-partner-nav a {
width:19%;
text-align:center;
height: 27px;
display: block;
float:right;
margin-right:5px;
vertical-align:bottom;
padding-top:10px;
background-color:#535353;
color:#ccc;
font-size:17px;
text-decoration:none;
}
.affiliate-partner-nav a:hover {
background-color:#666;
color:#fff;
}
.affiliate-partner-nav a.active {
background-color:#ed3618;
color:#fff;
}
.affiliate-partner-nav a.active:hover {
background-color:#ed3618;
cursor:default;
}
.affiliate-partner-nav a.last {
margin-right:0px !important;
}
#affiliate-partner-tab-content {
.tab-account {
.left-col {
float: left;
width: 55%;
.affiliate-label {
text-align: left;
width: 130px;
float: left;
display: inline-block;
margin-right: 10px;
margin-top: 3px;
}
input {
margin-bottom: 5px;
@include border_box_sizing;
}
.button-orange {
margin-right:2px;
}
.spacer {
width:140px;
display:inline-block;
}
.input-buttons {
width:60%;
display:inline-block;
}
}
.right-col {
float: right;
width: 45%;
margin-top: 30px;
line-height:125%;
}
}
}
.links {
p.prompt {
margin-bottom:20px;
}
}
.link-type-section {
border-width:0 0 1px 0;
border-style:solid;
border-color:$ColorTextTypical;
padding-bottom:20px;
margin-bottom:20px;
label {
display:inline-block;
margin-right:20px;
}
select {
}
}
.link-type-prompt {
display:none;
p {
margin-bottom:20px;
}
.example-link {
font-weight:bold;
}
}
table.traffic-table {
width:400px;
.signups, .visits {
width:70px;
text-align:right;
}
}
table.links-table {
min-width:100%;
margin-top:20px;
th {
padding: 10px 0 20px;
white-space:nowrap;
}
td {
padding:3px 0;
white-space:nowrap;
}
.target {
width:45%;
white-space:normal;
}
.copy-link {
width:100px;
}
.url {
input {
background-color: transparent;
-webkit-box-shadow:none;
box-shadow:none;
color:#ccc;
}
}
}
.agreement {
#partner-agreement-v1 {
height:340px;
overflow:scroll;
padding:20px;
border:1px solid white;
@include border-box_sizing;
}
label.partner-agreement {
display:inline-block;
margin-right:40px;
}
h2 {
font-size:20px;
font-weight:bold;
margin:40px 30px 20px 0;
display:inline-block;
}
.execution-date {
display:inline-block;
}
.input-buttons {
margin-top:20px;
}
}
}

View File

@ -32,6 +32,7 @@
*= require ./session *= require ./session
*= require ./account *= require ./account
*= require ./accountPaymentHistory *= require ./accountPaymentHistory
*= require ./account_affiliate
*= require ./search *= require ./search
*= require ./ftue *= require ./ftue
*= require ./jamServer *= require ./jamServer
@ -78,4 +79,5 @@
*= require ./downloadJamTrack *= require ./downloadJamTrack
*= require ./jamTrackPreview *= require ./jamTrackPreview
*= require users/signinCommon *= require users/signinCommon
*= require landings/partner_agreement_v1
*/ */

View File

@ -1,7 +1,7 @@
@import "client/common"; @import "client/common";
table.findsession-table, table.local-recordings, table.open-jam-tracks, table.open-backing-tracks, table.cart-items, #account-session-detail, table.payment-table { table.findsession-table, table.local-recordings, table.open-jam-tracks, table.open-backing-tracks, table.cart-items, #account-session-detail, table.payment-table, table.jamtable {
.latency-unacceptable { .latency-unacceptable {
width: 50px; width: 50px;
@ -64,7 +64,7 @@ table.findsession-table, table.local-recordings, table.open-jam-tracks, table.op
text-align:center; text-align:center;
} }
} }
table.findsession-table, table.local-recordings, table.open-jam-tracks, table.open-backing-tracks, table.cart-items, table.payment-table { table.findsession-table, table.local-recordings, table.open-jam-tracks, table.open-backing-tracks, table.cart-items, table.payment-table, table.jamtable {
width:98%; width:98%;
height:10%; height:10%;
font-size:11px; font-size:11px;

View File

@ -0,0 +1,74 @@
@import "client/common.css.scss";
body.web.landing_page.full {
&.affiliate_program {
.agree-disagree-buttons {
margin-top:30px;
}
.agree-button {
margin-right:20px;
}
#partner-agreement-v1 {
height:340px;
overflow:scroll;
padding:20px;
border:1px solid white;
@include border-box_sizing;
}
.wrapper {
padding-top:20px;
}
.row {
text-align:left;
}
h1 {
display: inline-block;
}
.column {
@include border_box_sizing;
width:50% ! important;
float:left;
p {
margin-bottom:15px;
}
}
label {
display:inline-block;
color:#ccc;
}
p.agreement-notice {
color:white;
margin:20px 0 30px;
}
.field.radio {
margin-top:10px;
label {
margin-left:10px;
}
}
.field.entity {
&.name {
margin-top:30px;
}
margin-top:10px;
width:400px;
input, select {
width:300px;
@include border_box_sizing;
}
label {
width:100px;
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,65 @@
@import 'client/common.css.scss';
body.affiliate_links {
h2 {
color:white !important;
}
h2, h3 {
margin-bottom:2px;
}
.intro {
margin-bottom:30px;
}
.link-type-prompt {
color:$ColorTextTypical;
line-height:125%;
p {
margin-bottom:20px;
}
.example-link {
font-weight:bold;
}
}
table.links-table {
min-width:100%;
margin-top:20px;
margin-bottom:30px;
th {
padding: 10px 0 20px;
white-space:nowrap;
}
td {
padding:3px 0;
white-space:nowrap;
}
.target {
width:45%;
white-space:normal;
}
.copy-link {
width:100px;
}
.url {
input {
background-color: transparent;
-webkit-box-shadow:none;
box-shadow:none;
color:#ccc;
width:100%;
}
}
}
}

View File

@ -28,6 +28,8 @@
*= require users/signinCommon *= require users/signinCommon
*= require dialogs/dialog *= require dialogs/dialog
*= require client/help *= require client/help
*= require landings/partner_agreement_v1
*= require web/affiliate_links
*= require_directory ../landings *= require_directory ../landings
*= require icheck/minimal/minimal *= require icheck/minimal/minimal
*/ */

View File

@ -0,0 +1,12 @@
class AffiliatesController < ApplicationController
respond_to :html
def links
@partner = AffiliatePartner.find(params[:id])
render 'affiliate_links', layout: 'web'
end
end

View File

@ -0,0 +1,53 @@
class ApiAffiliateController < ApiController
before_filter :api_signed_in_user, :except => [ :create ]
include ErrorsHelper
respond_to :json
def log
@log || Logging.logger[ApiAffiliateController]
end
def create
if current_user
# is this user already an affiliate? Then kick this back
if current_user.affiliate_partner
render :json => simple_error('affiliate_partner', 'You are already an affiliate.'), status: 422
return
else
@partner = AffiliatePartner.create_with_web_params(current_user, params)
respond_with_model(@partner)
return
end
else
@partner = AffiliatePartner.create_with_web_params(nil, params)
respond_with_model(@partner)
end
end
def traffic_index
data = AffiliateTrafficTotal.index(current_user, params)
@traffics, @next = data[0], data[1]
render "api_affiliates/traffic_index", :layout => nil
end
def monthly_index
data = AffiliateMonthlyPayment.index(current_user, params)
@monthlies, @next = data[0], data[1]
render "api_affiliates/monthly_index", :layout => nil
end
def quarterly_index
data = AffiliateQuarterlyPayment.index(current_user, params)
@quarterlies, @next = data[0], data[1]
render "api_affiliates/quarterly_index", :layout => nil
end
def payment_index
data = AffiliatePayment.index(current_user, params)
@payments, @next = data[0], data[1]
render "api_affiliates/payment_index", :layout => nil
end
end

View File

@ -69,6 +69,18 @@ class ApiController < ApplicationController
else else
auth_user auth_user
end end
end end
end
def affiliate_partner
if params[:affiliate_id]
@partner = AffiliatePartner.find(params[:affiliate_id])
if @partner.partner_user.nil?
raise JamPermissionError, ValidationMessages::PERMISSION_VALIDATION_ERROR
end
elsif current_user
@partner = current_user.affiliate_partner
else
raise JamPermissionError, ValidationMessages::PERMISSION_VALIDATION_ERROR
end
end
end

View File

@ -0,0 +1,114 @@
class ApiLinksController < ApiController
respond_to :json
before_filter :api_any_user
before_filter :affiliate_partner
def log
@log || Logging.logger[ApiLinksController]
end
def jamtrack_song_index
@affiliate_params = affiliate_params('jamtrack-song')
results = []
@jamtracks, @next = JamTrack.index({offset: 0, limit:1000}, any_user)
@jamtracks.each do |jamtrack|
results << {url: individual_jamtrack_url(jamtrack.short_plan_code, @affiliate_params),
target: "#{jamtrack.original_artist} - #{jamtrack.name}" }
end
render json: results, status: 200
end
def jamtrack_band_index
@affiliate_params = affiliate_params('jamtrack-band')
results = []
@jamtracks, @next = JamTrack.index({offset: 0, limit:1000}, any_user)
@jamtracks.each do |jamtrack|
results << {url: individual_jamtrack_band_url(jamtrack.short_plan_code, @affiliate_params),
target: "#{jamtrack.original_artist} - #{jamtrack.name}" }
end
render json: results, status: 200
end
def jamtrack_general_index
@affiliate_params = affiliate_params('jamtrack-general')
@affiliate_params[:generic] = 1
results = []
@jamtracks, @next = JamTrack.index({offset: 0, limit:1000}, any_user)
@jamtracks.each do |jamtrack|
results << {url: individual_jamtrack_url(jamtrack.short_plan_code, @affiliate_params),
target: "#{jamtrack.original_artist} - #{jamtrack.name}" }
end
render json: results, status: 200
end
def jamkazam_general_index
results = []
@affiliate_params = affiliate_params('home')
results << {url: root_url(@affiliate_params), target: 'JamKazam Home'}
@affiliate_params = affiliate_params('products-jamblaster')
results << {url: product_jamblaster_url(@affiliate_params), target: 'JamBlaster'}
@affiliate_params = affiliate_params('products-jamtracks')
results << {url: product_jamtracks_url(@affiliate_params), target: 'JamTracks'}
render json: results, status: 200
end
def session_index
@affiliate_params = affiliate_params('session')
results = []
ActiveRecord::Base.transaction do
options = {offset:0, limit:50}
@music_sessions = MusicSession.scheduled(@partner.partner_user, true)
@music_sessions.each do |session|
results << {url: music_scheduled_session_detail_url(session.id, @affiliate_params), target: session.name}
end
end
render json: results, status: 200
end
def recording_index
@affiliate_params = affiliate_params('recording')
results = []
feeds, next_page = Feed.index(@partner.partner_user, :type => 'recording', time_range: 'all', limit:100, user: @partner.partner_user.id, )
feeds.each do |feed|
claim = feed.recording.candidate_claimed_recording
if claim
results << {url: share_token_url(claim.share_token.token, @affiliate_params), target: claim.name}
end
end
render json: results, status: 200
end
private
def affiliate_params(campaign)
{utm_source:'affiliate', utm_medium: 'affiliate', utm_campaign: "#{Date.today.year}-affiliate-#{campaign}", affiliate: @partner.id}
end
end

View File

@ -34,7 +34,8 @@ class ApiRecurlyController < ApiController
password_confirmation: params[:password], password_confirmation: params[:password],
terms_of_service: terms_of_service, terms_of_service: terms_of_service,
location: {:country => billing_info[:country], :state => billing_info[:state], :city => billing_info[:city]}, location: {:country => billing_info[:country], :state => billing_info[:state], :city => billing_info[:city]},
reuse_card: reuse_card_next_time reuse_card: reuse_card_next_time,
affiliate_referral_id: cookies[:affiliate_visitor]
} }
options = User.musician_defaults(request.remote_ip, ApplicationHelper.base_uri(request) + "/confirm", any_user, options) options = User.musician_defaults(request.remote_ip, ApplicationHelper.base_uri(request) + "/confirm", any_user, options)

View File

@ -26,7 +26,7 @@ class ApiUsersController < ApiController
@user = User.includes([{musician_instruments: :instrument}, @user = User.includes([{musician_instruments: :instrument},
{band_musicians: :user}, {band_musicians: :user},
{genre_players: :genre}, {genre_players: :genre},
:bands, :instruments, :genres, :jam_track_rights]) :bands, :instruments, :genres, :jam_track_rights, :affiliate_partner])
.find(params[:id]) .find(params[:id])
respond_with @user, responder: ApiResponder, :status => 200 respond_with @user, responder: ApiResponder, :status => 200
@ -53,7 +53,8 @@ class ApiUsersController < ApiController
password_confirmation: params[:password], password_confirmation: params[:password],
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,
affiliate_referral_id: cookies[:affiliate_visitor]
} }
options = User.musician_defaults(request.remote_ip, ApplicationHelper.base_uri(request) + "/confirm", any_user, options) options = User.musician_defaults(request.remote_ip, ApplicationHelper.base_uri(request) + "/confirm", any_user, options)
@ -670,6 +671,40 @@ class ApiUsersController < ApiController
end end
end end
def affiliate_partner
if oo = current_user.affiliate_partner
if request.post?
oo.address = params[:address]
oo.tax_identifier = params[:tax_identifier]
oo.save!
render nothing: true
elsif request.get?
result = {}
result['account'] = {
'address' => oo.address.clone,
'tax_identifier' => oo.tax_identifier,
'entity_type' => oo.entity_type,
'partner_name' => oo.partner_name,
'partner_id' => oo.partner_user_id,
'id' => oo.id
}
if txt = oo.affiliate_legalese.try(:legalese)
txt = ControllerHelp.instance.simple_format(txt)
end
result['agreement'] = {
'legalese' => txt,
'signed_at' => oo.signed_at
}
#result['signups'] = oo.referrals_by_date
#result['earnings'] = [['April 2015', '1000 units', '$100']]
render json: result.to_json, status: 200
end
else
render :json => { :message => 'user not affiliate partner' }, :status => 400
end
end
def affiliate_report def affiliate_report
begin begin
affiliate = User affiliate = User

View File

@ -15,6 +15,7 @@ class ApplicationController < ActionController::Base
end end
before_filter :set_tracking_cookie before_filter :set_tracking_cookie
before_filter :track_affiliate_visits
before_filter do before_filter do
if params[AffiliatePartner::PARAM_REFERRAL].present? && current_user.nil? if params[AffiliatePartner::PARAM_REFERRAL].present? && current_user.nil?
@ -35,6 +36,16 @@ class ApplicationController < ActionController::Base
cookies.permanent[:user_uuid] = SecureRandom.uuid unless cookies[:user_uuid] cookies.permanent[:user_uuid] = SecureRandom.uuid unless cookies[:user_uuid]
end end
def track_affiliate_visits
if params[:affiliate] && params[:utm_medium] == 'affiliate' && params[:utm_source] == 'affiliate'
visit_cookie = cookies[:affiliate_visitor]
AffiliateReferralVisit.track(affiliate_id: params[:affiliate], visited: visit_cookie, remote_ip: request.remote_ip, visited_url: request.fullpath, referral_url: request.referer, current_user: current_user)
# set a cookie with the ID of the partner, and expires in 24 hours
cookies[:affiliate_visitor] = { :value => params[:affiliate], :expires => Time.now + 3600 * 24} # 1 day from now
end
end
private private
def add_user_info_to_bugsnag(notif) def add_user_info_to_bugsnag(notif)
@ -49,3 +60,14 @@ class ApplicationController < ActionController::Base
end end
end end
end end
class ControllerHelp
include Singleton
include ActionView::Helpers::TextHelper
include ActionView::Helpers::UrlHelper
include ActionView::Helpers::SanitizeHelper
extend ActionView::Helpers::SanitizeHelper::ClassMethods
include ActionView::Helpers::JavaScriptHelper
include ActionView::Helpers::TagHelper
include ActionView::Helpers::AssetTagHelper
end

View File

@ -103,5 +103,10 @@ class LandingsController < ApplicationController
gon.jam_track_plan_code = jam_track.plan_code if jam_track gon.jam_track_plan_code = jam_track.plan_code if jam_track
render 'product_jamtracks', layout: 'web' render 'product_jamtracks', layout: 'web'
end end
def affiliate_program
render 'affiliate_program', layout: 'web'
end
end end

View File

@ -65,7 +65,8 @@ class SessionsController < ApplicationController
user = UserManager.new.signup(remote_ip: remote_ip(), user = UserManager.new.signup(remote_ip: remote_ip(),
first_name: auth_hash[:info][:first_name], first_name: auth_hash[:info][:first_name],
last_name: auth_hash[:info][:last_name], last_name: auth_hash[:info][:last_name],
email: auth_hash[:info][:email]) email: auth_hash[:info][:email],
affiliate_referral_id: cookies[:affiliate_visitor])
# Users who sign up using oauth are presumed to have valid email adddresses. # Users who sign up using oauth are presumed to have valid email adddresses.
user.confirm_email! user.confirm_email!
@ -132,6 +133,7 @@ class SessionsController < ApplicationController
email: email, email: email,
terms_of_service: true, terms_of_service: true,
location: {:country => nil, :state => nil, :city => nil}, location: {:country => nil, :state => nil, :city => nil},
affiliate_referral_id: cookies[:affiliate_visitor]
} }
options = User.musician_defaults(request.remote_ip, ApplicationHelper.base_uri(request) + "/confirm", any_user, options) options = User.musician_defaults(request.remote_ip, ApplicationHelper.base_uri(request) + "/confirm", any_user, options)

View File

@ -70,6 +70,7 @@ class UsersController < ApplicationController
end end
end end
@affiliate_partner = load_affiliate_partner(params)
@invited_user = load_invited_user(params) @invited_user = load_invited_user(params)
if !@invited_user.nil? && @invited_user.has_required_email? && @invited_user.accepted if !@invited_user.nil? && @invited_user.has_required_email? && @invited_user.accepted
@ -77,7 +78,7 @@ class UsersController < ApplicationController
render "already_signed_up", :layout => 'landing' render "already_signed_up", :layout => 'landing'
return return
end end
@signup_postback = load_postback(@invited_user, @fb_signup) @signup_postback = load_postback(@invited_user, @fb_signup, @affiliate_partner)
load_location(request.remote_ip) load_location(request.remote_ip)
@ -136,7 +137,8 @@ class UsersController < ApplicationController
end end
@invited_user = load_invited_user(params) @invited_user = load_invited_user(params)
@signup_postback = load_postback(@invited_user, @fb_signup) @affiliate_partner = load_affiliate_partner(params)
@signup_postback = load_postback(@invited_user, @fb_signup, @affiliate_partner)
instruments = fixup_instruments(params[:jam_ruby_user][:instruments]) instruments = fixup_instruments(params[:jam_ruby_user][:instruments])
@ -161,7 +163,8 @@ class UsersController < ApplicationController
invited_user: @invited_user, invited_user: @invited_user,
fb_signup: @fb_signup, fb_signup: @fb_signup,
signup_confirm_url: ApplicationHelper.base_uri(request) + "/confirm", signup_confirm_url: ApplicationHelper.base_uri(request) + "/confirm",
affiliate_referral_id: AffiliatePartner.coded_id(self.affiliate_code)) affiliate_referral_id: cookies[:affiliate_visitor],
affiliate_partner: @affiliate_partner)
# check for errors # check for errors
if @user.errors.any? if @user.errors.any?
@ -468,6 +471,12 @@ JS
return invited_user return invited_user
end end
def load_affiliate_partner(params)
partner_id = params[:affiliate_partner_id]
AffiliatePartner.find(partner_id) if partner_id
end
def load_location(remote_ip, location = nil) def load_location(remote_ip, location = nil)
# useful if you need to repro something on 127.0.0.1 # useful if you need to repro something on 127.0.0.1
# remote_ip = ' 23.119.29.89' # remote_ip = ' 23.119.29.89'
@ -486,10 +495,11 @@ JS
@cities = @location[:state].nil? ? [] : MaxMindManager.cities(@location[:country], @location[:state]) @cities = @location[:state].nil? ? [] : MaxMindManager.cities(@location[:country], @location[:state])
end end
def load_postback(invited_user, fb_signup) def load_postback(invited_user, fb_signup, affiliate_partner)
query = {} query = {}
query[:invitation_code] = invited_user.invitation_code if invited_user query[:invitation_code] = invited_user.invitation_code if invited_user
query[:facebook_signup] = fb_signup.lookup_id if fb_signup query[:facebook_signup] = fb_signup.lookup_id if fb_signup
query[:affiliate_partner_id] = affiliate_partner.id if affiliate_partner
if query.length > 0 if query.length > 0
signup_path + "?" + query.to_query signup_path + "?" + query.to_query
else else

View File

@ -0,0 +1,7 @@
module ErrorsHelper
def simple_error(field, error_msg)
{"errors" => {field => [error_msg]}}
end
end

View File

@ -22,7 +22,6 @@ module SessionsHelper
end end
end end
# should be set whenever a user logs in who has redeemed a free jamtrack, or whenever the user # should be set whenever a user logs in who has redeemed a free jamtrack, or whenever the user
def set_purchased_jamtrack_cookie def set_purchased_jamtrack_cookie
cookies.permanent[:redeemed_jamtrack] = true cookies.permanent[:redeemed_jamtrack] = true

View File

@ -0,0 +1,119 @@
- provide(:page_name, 'landing_page full landing_product affiliate_links')
- provide(:description, 'Affiliate Links')
h2 Affiliate Links
p.intro
| This page provides you with lists of ready-to-use links you can use to direct your followers to JamKazam.&nbsp;
| These links include your unique affiliate ID, and users who follow these links to JamKazam and register for an account will be&nbsp;
| tagged with your affiliate ID, so that you will be paid on their purchase per the terms of the affiliate agreement.
h3 Table of Contents
ul
li
a href='#header_jamtrack_songs' JamTrack Songs
li
a href='#header_jamtrack_bands' JamTrack Bands
li
a href='#header_jamtrack_general' JamTrack Generic
li
a href='#header_jamkazam' JamKazam General
li
a href='#header_sessions' Sessions
li
a href='#header_recordings' Recordings
li
a href='#header_custom_links' Custom Links
h3#header_jamtrack_songs JamTrack Songs
.link-type-prompt data-type='jamtrack_songs'
| These links take users directly to the "landing page" for a JamTrack - i.e. an individual piece of music. This would be a great fit, for example, if you have produced a YouTube tutorial on how to play a particular song, or if you have music notation for a particular song, etc.
table.links-table.jamtrack_songs
thead
tr
th.target TARGET PAGE
th.copy-link
th.url URL
tbody
h3#header_jamtrack_bands JamTrack Bands
.link-type-prompt data-type='jamtrack_bands'
| These links take users directly to the "landing page" for a band to promote all the JamTracks by that band, not just an individual song. This would be a great fit, for example, if you have music notation for several songs by a band, etc.
table.links-table.jamtrack_bands
thead
tr
th.target TARGET PAGE
th.copy-link
th.url URL
tbody
h3#header_jamtrack_general JamTrack General
.link-type-prompt data-type='jamtrack_general'
| These links take users directly to a"landing page" that promotes JamTracks in general. This page will feature the song listed in the link as an example of a JamTrack, but the landing page is built to promote JamTracks in general versus promoting just the one song. This is a good fit if you want to let your followers know about JamTracks in general.
table.links-table.jamtrack_general
thead
tr
th.target TARGET PAGE
th.copy-link
th.url URL
tbody
h3#header_jamkazam JamKazam Generic
.link-type-prompt data-type='jamkazam'
| These links take users directly to a product page that promotes JamKazam more generally. This is a good fit if you want to let your followers know about JamKazam or its products in general.
table.links-table.jamkazam
thead
tr
th.target TARGET PAGE
th.copy-link
th.url URL
tbody
h3#header_sessions Sessions
.link-type-prompt data-type='sessions'
| These links take users to a page where they can listen to a session you have organized, and in which you are scheduled to perform, either alone or with others. This is a good fit if you can perform either solo or in a group with other musicians in a JamKazam session, and draw an audience to listen to your session. During the session, you can recommend that your audience members sign up for JamKazam from this page. Below is a list of your currently scheduled JamKazam sessions for which you may share links.
table.links-table.sessions
thead
tr
th.target TARGET PAGE
th.copy-link
th.url URL
tbody
h3#header_recordings Recordings
.link-type-prompt data-type='recordings'
| These links take users to a page with a recording you have made in a JamKazam session. This is a good fit if you have made a nice recording in a JamKazam session and can share it with your followers via Facebook, Twitter, email, and so on. Below is a list of your most recent JamKazam recordings for which you may share links.
table.links-table.recordings
thead
tr
th.target TARGET PAGE
th.copy-link
th.url URL
tbody
h3#header_custom_links Custom Links
.link-type-prompt data-type='custom_links'
p You may also link to any page on the JamKazam website and append the following text to the URL of the page to which you are linking:
p.example-link
| ?utm_source=affiliate&utm_medium=affiliate&utm_campaign=2015-affiliate-custom&affiliate=
span.affiliate_id = @partner.id
p For example, if you were linking to the JamKazam home page, you would combine https://www.jamkazam.com with the text above, and the result would be:
p.example-link
| https://www.jamkazam.com?utm_source=affiliate&utm_medium=affiliate&utm_campaign=2015-affiliate-custom&affiliate=
span.affiliate_id = @partner.id
javascript:
$(document).on('JAMKAZAM_READY', function (e, data) {
var affiliateLinks = new JK.AffiliateLinks(data.app, '#{@partner.id}');
affiliateLinks.initialize();
})
script type="text/template" id="template-affiliate-link-row"
tr
td.target
| {{data.target}}
td.copy-link
a href='#' select link
td.url
input type="text" value="{{data.url}}"

View File

@ -0,0 +1,3 @@
object @partner
extends "api_affiliates/show"

View File

@ -0,0 +1,8 @@
node :next do |page|
@next
end
node :monthlies do |page|
partial "api_affiliates/monthly_show", object: @monthlies
end

View File

@ -0,0 +1,3 @@
object @monthly
attribute :closed, :due_amount_in_cents, :affiliate_partner_id, :month, :year

View File

@ -0,0 +1,8 @@
node :next do |page|
@next
end
node :payments do |page|
partial "api_affiliates/payment_show", object: @payments
end

View File

@ -0,0 +1,3 @@
object @quarterly
attribute :closed, :paid, :due_amount_in_cents, :affiliate_partner_id, :quarter, :month, :year, :payment_type, :jamtracks_sold

View File

@ -0,0 +1,8 @@
node :next do |page|
@next
end
node :quarterlies do |page|
partial "api_affiliates/quarterly_show", object: @quarterlies
end

View File

@ -0,0 +1,3 @@
object @quarterly
attribute :closed, :paid, :due_amount_in_cents, :affiliate_partner_id, :quarter, :year

View File

@ -0,0 +1,2 @@
attributes :id, :partner_user_id, :partner_name, :entity_type

View File

@ -0,0 +1,8 @@
node :next do |page|
@next
end
node :traffics do |page|
partial "api_affiliates/traffic_show", object: @traffics
end

View File

@ -0,0 +1,3 @@
object @traffic
attribute :day, :visits, :signups, :affiliate_partner_id

View File

@ -33,6 +33,18 @@ if @user == current_user
@user.recurly_code == @user.id @user.recurly_code == @user.id
end end
node :is_affiliate_partner do
@user.affiliate_partner.present?
end
node :affiliate_referral_count do
@user.affiliate_partner.try(:referral_user_count)
end
node :affiliate_earnings do
@user.affiliate_partner.try(:cumulative_earnings_in_cents)
end
elsif current_user elsif current_user
node :is_friend do |uu| node :is_friend do |uu|
current_user.friends?(@user) current_user.friends?(@user)

View File

@ -151,6 +151,35 @@
<br clear="all" /> <br clear="all" />
{% } %} {% } %}
<hr />
<div class="account-left">
<h2>affiliate:</h2>
</div>
{% if (data.is_affiliate_partner) { %}
<div class="account-mid affiliate">
<div class="whitespace">
<span class="user-referrals">You have referred {{ data.affiliate_referral_count }} users to date.</span>
<br />
<span class="affiliate-earnings">You have earned ${{ data.affiliate_earnings }} to date.</span>
</div>
</div>
<div class="right">
<a id="account-affiliate-partner-link" href="#" class="button-orange">VIEW</a>
</div>
{% } else { %}
<div class="account-mid affiliate">
<div class="whitespace">
<span class="not-affiliated">You are not currently a JamKazam affiliate.</span>
<br />
<a href="/affiliateProgram" rel="external" class="learn-affiliate">Learn how you can earn cash simply by telling your friends and followers about JamKazam.</a>
</div>
</div>
{% } %}
<br clear="all" />
</div> </div>
<!-- end content wrapper --> <!-- end content wrapper -->
</script> </script>

View File

@ -0,0 +1,193 @@
/! Account affiliates Dialog
#account-affiliate-partner.screen.secondary layout='screen' layout-id='account/affiliatePartner'
.content-head
.content-icon
= image_tag "content/icon_account.png", :width => 27, :height => 20
h1 my account
= render "screen_navigation"
/! affiliates scrolling area
.content-body
.content-body-scroller.account-content-scroller#account-affiliate-partner-content-scroller
.content-wrapper.account-affiliates
.affiliates-header
.left.affiliates-caption
h2 affiliate:
.clearall
.affiliate-partner-nav
a#affiliate-partner-agreement-link agreement
a#affiliate-partner-earnings-link earnings
a#affiliate-partner-signups-link signups
a#affiliate-partner-links-link links
a#affiliate-partner-account-link.active account
.clearall
.affiliate-partner-account
.clearall
.affiliate-partner-links
.clearall
.affiliate-partner-agreement
.clearall
.affiliate-partner-signups
.clearall
.affiliate-partner-earnings
.clearall
#affiliate-partner-tab-content
.clearall
script type="text/template" id="template-affiliate-partner-account"
.tab-account
.right-col
| We must have a complete mailing address and a valid tax ID in order to process and mail payments due to all affiliates.&nbsp;&nbsp;Per the terms of the affiliate agreement, if this information is not available within 90 days of the end of a calendar quarter, then any payment obligation due to the affiliate for such calendar quarter shall be considered fully and permanently discharged, and no further payment for such calendar quarter shall be due or payable to affiliate.
br
| So please provide this data, and be sure to keep it current!
.left-col
.affiliate-label Affiliate:
.w80= "{{ data.partner_name }} ({{data.entity_type}})"
br
.affiliate-label Street Address 1:
= text_field_tag('affiliate_partner_address1', "{{ data.address.address1 }}", {class: 'w60'})
br
.affiliate-label Street Address 2:
= text_field_tag('affiliate_partner_address2', "{{ data.address.address2 }}", {class: 'w60'})
br
.affiliate-label City:
= text_field_tag('affiliate_partner_city', "{{ data.address.city }}", {class: 'w60'})
br
.affiliate-label State/Region:
= text_field_tag('affiliate_partner_state', "{{ data.address.state }}", {class: 'w60'})
br
.affiliate-label Zip/Postal Code:
= text_field_tag('affiliate_partner_postal_code', "{{ data.address.postal_code }}", {class: 'w60'})
br
.affiliate-label Country:
= text_field_tag('affiliate_partner_country', "{{ data.address.country }}", {class: 'w60'})
br
br
.affiliate-label Tax ID:
= text_field_tag('affiliate_partner_tax_identifier', "{{ data.tax_identifier }}", {class: 'w60'})
br
.spacer
.input-buttons
.right
a.button-grey href="javascript:history.go(-1)" CANCEL
a.button-orange id="affiliate-profile-account-submit" href="#" UPDATE
.clearall
.clearall
script type="text/template" id="template-affiliate-partner-agreement"
.agreement
label.partner-agreement You are viewing:
select.easydropdown name='agreement'
option value="Current agreement in effect" Current agreement in effect
br
h2 JamKazam Affiliate Agreement
.execution-date
| (you executed this Agreement on {{ window.JK.formatDate(data.signed_at) }})
= render "legal/partner_agreement_v1"
.input-buttons
.right
a.button-orange href='/client#/account' BACK TO ACCOUNT
script type="text/template" id="template-affiliate-partner-signups"
table.traffic-table.jamtable
thead
tr
th.day DATE
th.signups SIGNUPS
th.visits VISITS
tbody
script type="text/template" id="template-affiliate-partner-links"
.links
p.prompt
| This page provides you with lists of ready-to-use links you can use to direct your followers to JamKazam.&nbsp;
| These links include your unique affiliate ID, and users who follow these links to JamKazam and register for an account will be&nbsp;
| tagged with your affiliate ID, so that you will be paid on their purchase per the terms of the&nbsp;
a.affiliate-agreement rel='#' affiliate agreement
| . You can also find a&nbsp;
a.affiliate-link-page href='#' rel="external" single page listing all affiliate links
| &nbsp;which you can share with others who may need to share out affiliate links on your behalf.
.link-type-section
label Link Type:
select.link_type.easydropdown name="link_type"
option value="JamTrack Song" JamTrack Song
option value="JamTrack Band" JamTrack Band
option value="JamTrack General" JamTrack General
option value="JamKazam General" JamKazam General
option value="JamKazam Session" JamKazam Session
option value="JamKazam Recording" JamKazam Recording
option value="Custom Link" Custom Link
.link-type-prompt data-type='jamtrack_songs'
| These links take users directly to the "landing page" for a JamTrack - i.e. an individual piece of music. This would be a great fit, for example, if you have produced a YouTube tutorial on how to play a particular song, or if you have music notation for a particular song, etc.
.link-type-prompt data-type='jamtrack_bands'
| These links take users directly to the "landing page" for a band to promote all the JamTracks by that band, not just an individual song. This would be a great fit, for example, if you have music notation for several songs by a band, etc.
.link-type-prompt data-type='jamtrack_general'
| These links take users directly to a"landing page" that promotes JamTracks in general. This page will feature the song listed in the link as an example of a JamTrack, but the landing page is built to promote JamTracks in general versus promoting just the one song. This is a good fit if you want to let your followers know about JamTracks in general.
.link-type-prompt data-type='jamkazam'
| These links take users directly to a product page that promotes JamKazam more generally. This is a good fit if you want to let your followers know about JamKazam or its products in general.
.link-type-prompt data-type='sessions'
| These links take users to a page where they can listen to a session you have organized, and in which you are scheduled to perform, either alone or with others. This is a good fit if you can perform either solo or in a group with other musicians in a JamKazam session, and draw an audience to listen to your session. During the session, you can recommend that your audience members sign up for JamKazam from this page. Below is a list of your currently scheduled JamKazam sessions for which you may share links.
.link-type-prompt data-type='recordings'
| These links take users to a page with a recording you have made in a JamKazam session. This is a good fit if you have made a nice recording in a JamKazam session and can share it with your followers via Facebook, Twitter, email, and so on. Below is a list of your most recent JamKazam recordings for which you may share links.
.link-type-prompt data-type='custom_links'
p You may also link to any page on the JamKazam website and append the following text to the URL of the page to which you are linking:
p.example-link
| ?utm_source=affiliate&utm_medium=affiliate&utm_campaign=2015-affiliate-custom&affiliate=
span.affiliate_id
p For example, if you were linking to the JamKazam home page, you would combine https://www.jamkazam.com with the text above, and the result would be:
p.example-link
| https://www.jamkazam.com?utm_source=affiliate&utm_medium=affiliate&utm_campaign=2015-affiliate-custom&affiliate=
span.affiliate_id
table.links-table
thead
tr
th.target TARGET PAGE
th.copy-link
th.url URL
tbody
script type="text/template" id="template-affiliate-partner-signups-row"
tr
td.day
| {{data.day}}
td.signups
| {{data.signups}}
td.visits
| {{data.visits}}
script type="text/template" id="template-affiliate-partner-earnings"
table.payment-table.jamtable
thead
tr
th.month MONTH
th.sales SALES
th.earnings AFFILIATE EARNINGS
tbody
script type="text/template" id="template-affiliate-partner-earnings-row"
tr data-type="{{data.payment_type}}"
td.month
| {{data.time}}
td.sales
| {{data.sold}}
td.earnings
| {{data.earnings}}
script type="text/template" id="template-affiliate-link-entry"
tr
td.target
| {{data.target}}
td.copy-link
a href='#' select link
td.url
input type="text" value="{{data.url}}"

View File

@ -60,6 +60,7 @@
<%= render "account_video_profile" %> <%= render "account_video_profile" %>
<%= render "account_sessions" %> <%= render "account_sessions" %>
<%= render "account_jamtracks" %> <%= render "account_jamtracks" %>
<%= render "account_affiliate_partner" %>
<%= render "account_session_detail" %> <%= render "account_session_detail" %>
<%= render "account_session_properties" %> <%= render "account_session_properties" %>
<%= render "account_payment_history" %> <%= render "account_payment_history" %>
@ -209,6 +210,9 @@
var accountSessionPropertiesScreen = new JK.AccountSessionProperties(JK.app); var accountSessionPropertiesScreen = new JK.AccountSessionProperties(JK.app);
accountSessionPropertiesScreen.initialize(); accountSessionPropertiesScreen.initialize();
var accountAffiliateScreen = new JK.AccountAffiliateScreen(JK.app);
accountAffiliateScreen.initialize();
var affiliateReportScreen = new JK.AffiliateReportScreen(JK.app); var affiliateReportScreen = new JK.AffiliateReportScreen(JK.app);
affiliateReportScreen.initialize(); affiliateReportScreen.initialize();

View File

@ -0,0 +1,56 @@
- provide(:page_name, 'landing_page full landing_product affiliate_program')
- provide(:description, 'Signup for JamKazam Affiliate Program')
.row
.column
h1.product-headline JamKazam Affiliate Program
p Do you have a following of musicians on Facebook, YouTube, Twitter or an email list? Generate income simply by letting them know about JamKazam.
p Let's say you make YouTube tutorial videos. You can link directly from a video on how to play "Back in Black" to our JamTrack for that song. Video watchers can get this first JamTrack free, and can buy others if they like. You get paid every time they buy something from us for 2 years.
p Or let's say you have a Facebook group for guitarist with 5,000 members. You can let them know they can play together free on JamKazam. For everyone who signs up, you get paid every time they buy something from us for 2 years.
p You don't have to sell anything. Just let your followers know about cool new stuff they'll like! To get started, simply review the affiliate agreement below, accept it (at the end of the agreement), and then start sharing links with your affiliate code. When referred users buy JamTracks, JamBlasters, JamLessons, and so on, you get paid!
.column
h1 Learn How to Make Money by Referring Users
.video-wrapper
.video-container
iframe src="//www.youtube.com/embed/ylYcvTY9CVo" frameborder="0" allowfullscreen
br clear="all"
.row
h1 JamKazam Affiliate Agreement
= render "legal/partner_agreement_v1"
p.agreement-notice By clicking the "I Agree" button below, I certify that I have the authority to enter into this Agreement on behalf of myself as an individual or on behalf of the entity I have listed below, and I further certify that I have read, understood, and agree to be bound by the terms above.
.entity-options
.field.radio
= radio_button_tag(:entity, 'individual')
label I am entering into this Agreement as an individual
.field.radio
= radio_button_tag(:entity, 'entity')
label I am executing this Agreement on behalf of the company or entity listed below
.entity-info.hidden
.field.entity.name
label Entity Name
input type="text" name="entity-name"
.field.entity.type
label Entity Type
select name="entity-type"
option value="" Choose Entity Type
option value="Sole Proprietor" Sole Proprietor
option value="Limited Liability Company (LLC)" Limited Liability Company (LLC)
option value="Partnership" Partnership
option value="Trust/Estate" Trust/Estate
option value="S Corporation" S Corporation
option value="C Corporation" C Corporation
option value="Other" Other
.agree-disagree-buttons
= link_to image_tag("content/agree_button.png", {:width => 213, :height => 50 }), '#', class: "agree-button"
= link_to image_tag("content/disagree_button.png", {:width => 213, :height => 50 }), '#', class: "disagree-button"
p.disagree-text.hidden
| Thank you for your interest in the JamKazam affiliate program. We are sorry, but you cannot join the program without consenting to the terms of this Agreement.
javascript:
$(document).on('JAMKAZAM_READY', function(e, data) {
var affiliateProgram = new JK.AffiliateProgram(data.app);
affiliateProgram.initialize();
})

View File

@ -0,0 +1,422 @@
<!-- this was created by taking docx into Google Docs and Downloading as HTML -->
<div id="partner-agreement-v1">
<p class="c2"><span class="c0">Updated: April 30, 2015.</span></p>
<p class="c2 c5"><span class="c0"></span></p>
<p class="c2">
<span class="c0">This Affiliate Agreement (this &ldquo;</span><span class="c0 c10">Agreement</span><span class="c0">&rdquo;) contains the terms and conditions that govern your participation in the JamKazam affiliate marketing program (the &ldquo;</span><span class="c0 c10">Program</span><span class="c0">&rdquo;). &ldquo;</span><span class="c0 c10">JamKazam</span><span class="c0">&rdquo;, &ldquo;</span><span class="c0 c10">we</span><span class="c0">,&rdquo; &ldquo;</span><span class="c0 c10">us</span><span class="c0">,&rdquo;
or &ldquo;</span><span class="c0 c10">our</span><span class="c0">&rdquo;
means JamKazam, Inc. &ldquo;</span><span class="c0 c10">You</span><span class="c0">&rdquo;
or &ldquo;</span><span class="c0 c10">your</span><span class="c0">&rdquo;
means the applicant. A &ldquo;</span><span class="c0 c10">site</span><span class="c0">&rdquo;
means a website. &ldquo;</span><span class="c0 c10">JamKazam Site</span><span class="c0">&rdquo; means the jamkazam.com website or a JamKazam applicaion or any other site that is owned or operated by or on behalf of us and which is identified as participating in the Program in the </span><span class="c0 c10 c17">Program Advertising Fee Schedule</span><span class="c0">&nbsp;in Section 10, as applicable. &ldquo;</span><span class="c0 c10">Your Site</span><span class="c0">&rdquo;
means any site(s), software application(s), or content that you create, own, or operate and link to the JamKazam Site. </span>
</p>
<p class="c2 c5"><span class="c0"></span></p>
<p class="c2"><span class="c0 c7">1. Description of the Program</span></p>
<p class="c2 c5"><span class="c0"></span></p>
<p class="c2">
<span class="c0">The purpose of the Program is to permit you to advertise Products on Your Site and to earn advertising fees for Qualifying Purchases (defined in Section 7) made by your Qualifying Customers (defined in Section 7). A &ldquo;</span><span class="c0 c10">Product</span><span class="c0">&rdquo;
is an item sold on the JamKazam Site and listed in the </span><span class="c0 c10 c17">Program Advertising Fee Schedule</span><span class="c0">&nbsp;in Section 10. In order to facilitate your advertisement of Products, we may make available to you data, images, text, link formats, widgets, links, and other linking tools, and other information in connection with the Program (&ldquo;Content&rdquo;). </span>
</p>
<p class="c2 c5"><span class="c0"></span></p>
<p class="c2"><span class="c0 c7">2. Enrollment, Suitability, and Communications</span></p>
<p class="c2 c5"><span class="c0"></span></p>
<p class="c2"><span class="c0">To enroll in the Program, you must execute this Agreement by clicking the &ldquo;I Agree&rdquo;
button at the end of this Agreement, after having thoroughly reviewed the Agreement.</span></p>
<p class="c2 c5"><span class="c0"></span></p>
<p class="c2">
<span class="c0">Your Site may be considered unsuitable for participation in the Program resulting in termination of this Agreement by JamKazam if Your Site:</span>
</p>
<p class="c2 c5"><span class="c0"></span></p>
<ul class="c6 lst-kix_list_47-0 start">
<li class="c3 c2"><span class="c0 c8">promotes or contains sexually explicit materials;</span></li>
<li class="c3 c2"><span class="c0 c8">promotes violence or contains violent materials;</span></li>
<li class="c3 c2"><span class="c0 c8">promotes or contains libelous or defamatory materials;</span></li>
<li class="c3 c2">
<span class="c0 c8">promotes discrimination, or employs discriminatory practices, based on race, sex, religion, nationality, disability, sexual orientation, or age;</span>
</li>
<li class="c3 c2"><span class="c0 c8">promotes or undertakes illegal activities;</span></li>
<li class="c3 c2">
<span class="c0 c8">is directed toward children under 13 years of age, as defined by the Children&rsquo;s Online Privacy Protection Act (15 U.S.C. &sect;&sect;
6501-6506) and any regulations promulgated thereunder;</span></li>
<li class="c3 c2">
<span class="c0 c8">includes any trademark of JamKazam or a variant or misspelling of a trademark of JamKazam in any domain name, subdomain name, or in any username, group name, or other identifier on any social networking site; or</span>
</li>
<li class="c3 c2"><span class="c0 c8">otherwise violates intellectual property rights.</span></li>
</ul>
<p class="c2 c5"><span class="c0"></span></p>
<p class="c2">
<span class="c0">You will ensure that the information you provide in executing this Agreement and otherwise associated with your account, including your name, email address, mailing address, tax ID, and other information, is at all times complete, accurate, and up-to-date. We may send notifications (if any), reports (if any), and other communications relating to the Program and this Agreement to the email address then-currently associated with your JamKazam account. You will be deemed to have received all notifications, reports, and other communications sent to that email address, even if the email address associated with your account is no longer current. We may mail checks (if any) payable to you for advertising fees earned under this Agreement to the mailing address then-currently associated with your JamKazam account. You will be deemed to have received all checks sent to that mailing address, even if the mailing address associated with your account is no longer current. If we send a check to a mailing address that is no longer valid, we may, in our sole discretion, choose to issue a stop payment order for such a check and send a new check to a new current address that your provide, but in such a case, we will charge a US$50.00 fee for this exception process.</span>
</p>
<p class="c2 c5"><span class="c0"></span></p>
<p class="c2">
<span class="c0">If you are a Non-US person participating in the Program, you agree that you will perform all services under the Agreement outside the United States. </span>
</p>
<p class="c2 c5"><span class="c0"></span></p>
<p class="c2"><span class="c0 c7">3. Links on Your Site</span></p>
<p class="c2 c5"><span class="c0"></span></p>
<p class="c2">
<span class="c0">After you have entered into this Agreement, you may display Special Links on Your Site. &ldquo;</span><span class="c0 c10">Special Links</span><span class="c0">&rdquo;
are links to the JamKazam Site that you place on Your Site in accordance with this Agreement, that properly utilize the special &ldquo;tagged&rdquo;
link formats we specify or provide. Special Links permit accurate tracking, reporting, and accrual of advertising fees. </span>
</p>
<p class="c2 c5"><span class="c0"></span></p>
<p class="c2">
<span class="c0">You may earn advertising fees only as described in Section 7 and only with respect to activity on the JamKazam Site occurring directly through Special Links. We will have no obligation to pay you advertising fees if you fail to properly format the links on Your Site to the JamKazam Site as Special Links, including to the extent that such failure may result in any reduction of advertising fee amounts that would otherwise be paid to you under this Agreement.</span>
</p>
<p class="c2 c5"><span class="c0"></span></p>
<p class="c2"><span class="c0 c7">4. Program Requirements</span></p>
<p class="c2 c5"><span class="c0"></span></p>
<p class="c2"><span class="c0">You hereby consent to us:</span></p>
<p class="c2 c5"><span class="c0"></span></p>
<ul class="c6 lst-kix_list_44-0 start">
<li class="c3 c2"><span class="c0 c8">sending you emails relating to the Program from time to time; and</span></li>
<li class="c3 c2">
<span class="c0 c8">monitoring, recording, using, and disclosing information about Your Site and visitors to Your Site that we obtain in connection with your display of Special Links in accordance with the </span><span class="c0 c10 c8 c17">JamKazam Privacy Policy</span><span class="c0 c8">.</span>
</li>
</ul>
<p class="c2 c5"><span class="c0"></span></p>
<p class="c2"><span class="c0 c7">5. Responsibility for Your Site</span></p>
<p class="c2 c5"><span class="c0"></span></p>
<p class="c2">
<span class="c0">You will be solely responsible for Your Site including its development, operation, and maintenance, and all materials that appear on or within it. For example, you will be solely responsible for:</span>
</p>
<p class="c2 c5"><span class="c0"></span></p>
<ul class="c6 lst-kix_list_45-0 start">
<li class="c3 c2"><span class="c0 c8">the technical operation of Your Site and all related equipment;</span></li>
<li class="c3 c2">
<span class="c0 c8">displaying Special Links and Content on Your Site in compliance with this Agreement and any agreement between you and any other person or entity (including any restrictions or requirements placed on you by any person or entity that hosts Your Site);</span>
</li>
<li class="c3 c2">
<span class="c0 c8">creating and posting, and ensuring the accuracy, completeness, and appropriateness of, materials posted on Your Site (including all Product descriptions and other Product-related materials and any information you include within or associate with Special Links);</span>
</li>
<li class="c3 c2">
<span class="c0 c8">using the Content, Your Site, and the materials on or within Your Site in a manner that does not infringe, violate, or misappropriate any of our rights or those of any other person or entity (including copyrights, trademarks, privacy, publicity or other intellectual property or proprietary rights);</span>
</li>
<li class="c3 c2">
<span class="c0 c8">disclosing on Your Site accurately and adequately, either through a privacy policy or otherwise, how you collect, use, store, and disclose data collected from visitors, including, where applicable, that third parties (including us and other advertisers) may serve content and advertisements, collect information directly from visitors, and place or recognize cookies on visitors&rsquo;
browsers; and</span></li>
<li class="c3 c2">
<span class="c0 c8">any use that you make of the Content and the JamKazam Marks, whether or not permitted under this Agreement.</span>
</li>
</ul>
<p class="c2 c5"><span class="c0"></span></p>
<p class="c2">
<span class="c0">We will have no liability for these matters or for any of your end users&rsquo; claims relating to these matters, and you agree to defend, indemnify, and hold us, our affiliates and licensors, and our and their respective employees, officers, directors, and representatives, harmless from and against all claims, damages, losses, liabilities, costs, and expenses (including attorneys&rsquo;
fees) relating to (a) Your Site or any materials that appear on Your Site, including the combination of Your Site or those materials with other applications, content, or processes; (b) the use, development, design, manufacture, production, advertising, promotion, or marketing of Your Site or any materials that appear on or within Your Site, and all other matters described in this Section 5; (c) your use of any Content, whether or not such use is authorized by or violates this Agreement or any applicable law; (d) your violation of any term or condition of this Agreement; or (e) your or your employees&#39; negligence or willful misconduct.</span>
</p>
<p class="c2 c5"><span class="c0"></span></p>
<p class="c2"><span class="c0 c7">6. Order Processing</span></p>
<p class="c2 c5"><span class="c0"></span></p>
<p class="c2">
<span class="c0">We will process Product orders placed by Qualifying Customers (defined in Section 7) on the JamKazam Site. We reserve the right to reject orders that do not comply with any requirements on the JamKazam Site, as they may be updated from time to time. We will track Qualifying Purchases (defined in Section 7) for reporting and advertising fee accrual purposes and will make available to you reports summarizing those Qualifying Purchases.</span>
</p>
<p class="c2 c5"><span class="c0"></span></p>
<p class="c2"><span class="c0 c7">7. Advertising Fees</span></p>
<p class="c2 c5"><span class="c0"></span></p>
<p class="c2">
<span class="c0">We will pay you advertising fees on Qualifying Purchases in accordance with Section 8 and the </span><span class="c0 c10 c17">Program Advertising Fee Schedule</span><span class="c0">&nbsp;in Section 10. Subject to the exclusions set forth below, a &ldquo;</span><span class="c0 c10">Qualifying Purchase</span><span class="c0">&rdquo;
occurs when a Qualifying Customer: (a) purchases a Product within two (2) years of the date on which such Qualifying Customer registered to create his/her JamKazam account; and (b) pays for such Product. A &ldquo;</span><span class="c0 c10">Qualifying Customer</span><span class="c0">&rdquo;
is an end user who: (a) clicks through a Special Link on Your Site to the JamKazam Site; and (b) during the single Session created by this click through, registers to create a new JamKazam account. A &ldquo;</span><span class="c0 c10">Session</span><span class="c0">&rdquo;
begins when an end user clicks through a Special Link on Your Site to the JamKazam Site and ends when such end user leaves the JamKazam Site.</span>
</p>
<p class="c2 c5"><span class="c0"></span></p>
<p class="c2">
<span class="c0">Qualifying Purchases exclude, and we will not pay advertising fees on any of, the following:</span>
</p>
<p class="c2 c5"><span class="c0"></span></p>
<ul class="c6 lst-kix_list_46-0 start">
<li class="c3 c2">
<span class="c0 c8">any Product purchase that is not correctly tracked or reported because the links from Your Site to the JamKazam Site are not properly formatted;</span>
</li>
<li class="c3 c2">
<span class="c0 c8">any Product purchased through a Special Link by you or on your behalf, including Products you purchase through Special Links for yourself, friends, relatives, or associates;</span>
</li>
<li class="c3 c2">
<span class="c0 c8">any Product purchased through a Special Link that violates the terms of this Agreement;</span>
</li>
<li class="c2 c3"><span class="c0 c8">any Product order that is canceled or returned; </span></li>
<li class="c3 c2"><span class="c0 c8">any Product purchase that becomes classified as bad debt; or</span></li>
<li class="c3 c2">
<span class="c0 c8">any Product purchase for which we process a promotional discount against the transaction that makes such Product free.</span>
</li>
</ul>
<p class="c2 c5"><span class="c0"></span></p>
<p class="c2"><span class="c0 c7">8. Advertising Fee Payment</span></p>
<p class="c2 c5"><span class="c0"></span></p>
<p class="c2">
<span class="c0">We will pay you advertising fees on a quarterly basis for Qualifying Purchases downloaded, shipped, or otherwise fulfilled (as applicable) in a given calendar quarter, subject to any applicable withholding or deduction described below. We will pay you approximately 30 days following the end of each calendar quarter by mailing a check in the amount of the advertising fees you earn to the mailing address then-currently associated with your JamKazam account, but we may accrue and withhold payment of advertising fees until the total amount due to you is at least US$50.00. If you do not have a valid mailing address associated with your JamKazam account within 30 days of the end of a calendar quarter, we will withhold any unpaid accrued advertising fees until you have associated a valid mailing address and notified us that you have done so.</span>
</p>
<p class="c2 c5"><span class="c0"></span></p>
<p class="c2">
<span class="c0">Further, any unpaid accrued advertising fees in your account may be subject to escheatment under state law. We may be obligated by law to obtain tax information from you if you are a U.S. citizen, U.S. resident, or U.S. corporation, or if your business is otherwise taxable in the U.S. If we request tax information from you and you do not provide it to us, we may (in addition to any other rights or remedies available to us) withhold your advertising fees until you provide this information or otherwise satisfy us that you are not a person from whom we are required to obtain tax information.</span>
</p>
<p class="c2 c5"><span class="c0"></span></p>
<p class="c2"><span class="c0 c7">9. Policies and Pricing</span></p>
<p class="c2 c5"><span class="c0"></span></p>
<p class="c2">
<span class="c0">Qualifying Customers who buy Products through this Program are our customers with respect to all activities they undertake in connection with the JamKazam Site. Accordingly, as between you and us, all pricing, terms of sale, rules, policies, and operating procedures concerning customer orders, customer service, and product sales set forth on the JamKazam Site will apply to such Qualifying Customers, and we may change them at any time in our sole discretion.</span>
</p>
<p class="c2 c5"><span class="c0"></span></p>
<p class="c2"><span class="c0 c7">10. Program Advertising Fee Schedule</span></p>
<p class="c2 c5"><span class="c0"></span></p>
<p class="c2">
<span class="c0">We will determine and calculate amounts payable to you as advertising fees for Qualifying Purchases as set forth in the table below (the &ldquo;</span><span class="c0 c10">Program Advertising Fee Schedule</span><span class="c0">&rdquo;).</span>
</p>
<p class="c2 c5"><span class="c0"></span></p>
<a href="#" name="fcab919a72a4bb6a7511330807c3ec6acfd219eb"></a><a href="#" name="0"></a>
<table cellpadding="0" cellspacing="0" class="c16">
<tbody>
<tr class="c19">
<td class="c1" colspan="1" rowspan="1"><p class="c4 c2"><span class="c12 c0 c7">Product</span></p></td>
<td class="c20" colspan="1" rowspan="1"><p class="c4 c2"><span class="c0 c7 c12">Advertising Fees</span></p></td>
</tr>
<tr class="c19">
<td class="c1" colspan="1" rowspan="1"><p class="c4 c2"><span class="c12 c0 c8">JamTracks</span></p></td>
<td class="c20" colspan="1" rowspan="1"><p class="c2 c4">
<span class="c12 c0 c8">We will pay advertising fees of US$0.20 per JamTrack sold as a Qualifying Purchase.</span>
</p></td>
</tr>
</tbody>
</table>
<p class="c2 c5"><span class="c0"></span></p>
<p class="c2">
<span class="c0">From time to time, we may modify this Program Advertising Fee Schedule as part of modifications made to this Agreement. </span>
</p>
<p class="c2 c5"><span class="c0 c7 c13"></span></p>
<p class="c2"><span class="c0 c7">11. Limited License</span></p>
<p class="c2 c5"><span class="c0"></span></p>
<p class="c2">
<span class="c0">Subject to the terms of this Agreement and solely for the limited purposes of advertising Products on, and directing end users to, the JamKazam Site in connection with the Program, we hereby grant you a limited, revocable, non-transferable, non-sublicensable, non-exclusive, royalty-free license to (a) copy and display the Content solely on Your Site; and (b) use only those of our trademarks and logos that we may make available to you as part of Content (those trademarks and logos, collectively, &ldquo;</span><span class="c0 c10">JamKazam Marks</span><span class="c0">&rdquo;) solely on Your Site.</span>
</p>
<p class="c2 c5"><a name="h.gjdgxs"></a></p>
<p class="c2">
<span class="c0">The license set forth in this Section 11 will immediately and automatically terminate if at any time you do not timely comply with any obligation under this Agreement, or otherwise upon termination of this Agreement. In addition, we may terminate the license set forth in this Section 11 in whole or in part upon written notice to you. You will promptly remove from Your Site and delete or otherwise destroy all of the Content and JamKazam Marks with respect to which the license set forth in this Section 11 is terminated or as we may otherwise request from time to time.</span>
</p>
<p class="c2 c5"><span class="c0"></span></p>
<p class="c2"><span class="c0 c7">12. Reservation of Rights; Submissions</span></p>
<p class="c2 c5"><span class="c0"></span></p>
<p class="c2">
<span class="c0">Other than the limited licenses expressly set forth in Section 11, we reserve all right, title and interest (including all intellectual property and proprietary rights) in and to, and you do not, by virtue of this Agreement or otherwise, acquire any ownership interest or rights in or to, the Program, Special Links, Content, Products, any domain name owned or operated by us, our trademarks and logos (including the JamKazam Marks), and any other intellectual property and technology that we provide or use in connection with the Program (including any application program interfaces, software development kits, libraries, sample code, and related materials). If you provide us with suggestions, reviews, modifications, data, images, text, or other information or content about a Product or in connection with this Agreement, any Content, or your participation in the Program, or if you modify any Content in any way, (collectively, &ldquo;</span><span class="c0 c10">Your Submission</span><span class="c0">&rdquo;), you hereby irrevocably assign to us all right, title, and interest in and to Your Submission and grant us (even if you have designated Your Submission as confidential) a perpetual, paid-up royalty-free, nonexclusive, worldwide, irrevocable, freely transferable right and license to (a) use, reproduce, perform, display, and distribute Your Submission in any manner; (b) adapt, modify, re-format, and create derivative works of Your Submission for any purpose; (c) use and publish your name in the form of a credit in conjunction with Your Submission (however, we will not have any obligation to do so); and (d) sublicense the foregoing rights to any other person or entity. Additionally, you hereby warrant that: (y) Your Submission is your original work, or you obtained Your Submission in a lawful manner; and (z) our and our sublicensees&rsquo;
exercise of rights under the license above will not violate any person&rsquo;s or entity&rsquo;s rights, including any copyright rights. You agree to provide us such assistance as we may require to document, perfect, or maintain our rights in and to Your Submission.</span>
</p>
<p class="c2 c5"><span class="c0"></span></p>
<p class="c2"><span class="c0 c7">13. Compliance with Laws</span></p>
<p class="c2 c5"><span class="c0"></span></p>
<p class="c2">
<span class="c0">In connection with your participation in the Program you will comply with all applicable laws, ordinances, rules, regulations, orders, licenses, permits, judgments, decisions, and other requirements of any governmental authority that has jurisdiction over you, including laws (federal, state, or otherwise) that govern marketing email (e.g., the CAN-SPAM Act of 2003).</span>
</p>
<p class="c2 c5"><span class="c0"></span></p>
<p class="c2"><span class="c0 c7">14. Term and Termination</span></p>
<p class="c2 c5"><span class="c0"></span></p>
<p class="c2">
<span class="c0">The term of this Agreement will begin upon your execution of this Agreement by clicking the &ldquo;I Agree&rdquo;
button at the end of this Agreement, only if such execution is processed and confirmed successfully by the JamKazam Site, and will end when terminated by either you or us. Either you or we may terminate this Agreement at any time, with or without cause, by giving the other party written notice of termination. Upon any termination of this Agreement, any and all licenses you have with respect to Content will automatically terminate, and you will immediately stop using the Content and JamKazam Marks and promptly remove from Your Site and delete or otherwise destroy all links to the JamKazam Site, all JamKazam Marks, all other Content, and any other materials provided or made available by or on behalf of us to you under this Agreement or otherwise in connection with the Program. We may withhold accrued unpaid advertising fees for a reasonable period of time following termination to ensure that the correct amount is paid (e.g., to account for any cancelations or returns). Upon any termination of this Agreement, all rights and obligations of the parties will be extinguished, except that the rights and obligations of the parties under Sections 5, 9, 12, 13, 14, 16, 17, 18, 19, and 20, together with any of our payment obligations that accrue in accordance with Sections 6, 7, 8, and 10 following the termination of this Agreement, will survive the termination of this Agreement. No termination of this Agreement will relieve either party for any liability for any breach of, or liability accruing under, this Agreement prior to termination.</span>
</p>
<p class="c2 c5"><span class="c0"></span></p>
<p class="c2"><span class="c0 c7">15. Modification</span></p>
<p class="c2 c5"><span class="c0"></span></p>
<p class="c2">
<span class="c0">We may modify any of the terms and conditions contained in this Agreement at any time and in our sole discretion by posting a change notice or revised agreement on the JamKazam Site or by sending notice of such modification to you by email to the email address then-currently associated with your JamKazam account (any such change by email will be effective on the date specified in such email and will in no event be less than two business days after the date the email is sent). Modifications may include, for example, changes to the Program Advertising Fee Schedule, payment procedures, and other Program requirements. IF ANY MODIFICATION IS UNACCEPTABLE TO YOU, YOUR ONLY RECOURSE IS TO TERMINATE THIS AGREEMENT. YOUR CONTINUED PARTICIPATION IN THE PROGRAM FOLLOWING THE EFFECTIVE DATE OF ANY MODIFICATION (E.G., THE DATE OF OUR POSTING OF A CHANGE NOTICE OR REVISED AGREEMENT ON THE JAMKAZAM SITE OR THE DATE SPECIFIED IN ANY EMAIL TO YOU REGARDING SUCH MODIFICATION) WILL CONSTITUTE YOUR BINDING ACCEPTANCE OF THE CHANGE.</span>
</p>
<p class="c2 c5"><span class="c0"></span></p>
<p class="c2"><span class="c0 c7">16. Relationship of Parties</span></p>
<p class="c2 c5"><span class="c0"></span></p>
<p class="c2">
<span class="c0">You and we are independent contractors, and nothing in this Agreement will create any partnership, joint venture, agency, franchise, sales representative, or employment relationship between you and us or our respective affiliates. You will have no authority to make or accept any offers or representations on our behalf. You will not make any statement, whether on Your Site or otherwise, that contradicts or may contradict anything in this section. If you authorize, assist, encourage, or facilitate another person or entity to take any action related to the subject matter of this Agreement, you will be deemed to have taken the action yourself.</span>
</p>
<p class="c2 c5"><span class="c0"></span></p>
<p class="c2"><span class="c0 c7">17. Limitation of Liability</span></p>
<p class="c2 c5"><span class="c0"></span></p>
<p class="c2">
<span class="c0">WE WILL NOT BE LIABLE FOR INDIRECT, INCIDENTAL, SPECIAL, CONSEQUENTIAL, OR EXEMPLARY DAMAGES (INCLUDING ANY LOSS OF REVENUE, PROFITS, GOODWILL, USE, OR DATA) ARISING IN CONNECTION WITH THIS AGREEMENT, THE PROGRAM, THE JAMKAZAM SITE, OR THE SERVICE OFFERINGS (DEFINED BELOW), EVEN IF WE HAVE BEEN ADVISED OF THE POSSIBILITY OF THOSE DAMAGES. FURTHER, OUR AGGREGATE LIABILITY ARISING IN CONNECTION WITH THIS AGREEMENT, THE PROGRAM, THE JAMKAZAM SITE, AND THE SERVICE OFFERINGS WILL NOT EXCEED THE TOTAL ADVERTISING FEES PAID OR PAYABLE TO YOU UNDER THIS AGREEMENT IN THE TWELVE MONTHS IMMEDIATELY PRECEDING THE DATE ON WHICH THE EVENT GIVING RISE TO THE MOST RECENT CLAIM OF LIABILITY OCCURRED.</span>
</p>
<p class="c2 c5"><span class="c0"></span></p>
<p class="c2"><span class="c0 c7">18. Disclaimers</span></p>
<p class="c2 c5"><span class="c0"></span></p>
<p class="c2">
<span class="c0">THE PROGRAM, THE JAMKAZAM SITE, ANY PRODUCTS AND SERVICES OFFERED ON THE JAMKAZAM SITE, ANY SPECIAL LINKS, LINK FORMATS, CONTENT, JAMKAZAM.COM DOMAIN NAME, OUR TRADEMARKS AND LOGOS (INCLUDING THE JAMKAZAM MARKS), AND ALL TECHNOLOGY, SOFTWARE, FUNCTIONS, MATERIALS, DATA, IMAGES, TEXT, AND OTHER INFORMATION AND CONTENT PROVIDED OR USED BY OR ON BEHALF OF US OR LICENSORS IN CONNECTION WITH THE PROGRAM (COLLECTIVELY THE &ldquo;SERVICE OFFERINGS&rdquo;) ARE PROVIDED &ldquo;AS IS.&rdquo;
NEITHER WE NOR ANY OF OUR LICENSORS MAKE ANY REPRESENTATION OR WARRANTY OF ANY KIND, WHETHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO THE SERVICE OFFERINGS. EXCEPT TO THE EXTENT PROHIBITED BY APPLICABLE LAW, WE AND OUR LICENSORS DISCLAIM ALL WARRANTIES WITH RESPECT TO THE SERVICE OFFERINGS, INCLUDING ANY IMPLIED WARRANTIES OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND QUIET ENJOYMENT, AND ANY WARRANTIES ARISING OUT OF ANY COURSE OF DEALING, PERFORMANCE, OR TRADE USAGE. WE MAY DISCONTINUE ANY SERVICE OFFERING, OR MAY CHANGE THE NATURE, FEATURES, FUNCTIONS, SCOPE, OR OPERATION OF ANY SERVICE OFFERING, AT ANY TIME AND FROM TIME TO TIME. NEITHER WE NOR ANY OF OUR LICENSORS WARRANT THAT THE SERVICE OFFERINGS WILL CONTINUE TO BE PROVIDED, WILL FUNCTION AS DESCRIBED, CONSISTENTLY OR IN ANY PARTICULAR MANNER, OR WILL BE UNINTERRUPTED, ACCURATE, ERROR FREE, OR FREE OF HARMFUL COMPONENTS. NEITHER WE NOR ANY OF OUR LICENSORS WILL BE RESPONSIBLE FOR (A) ANY ERRORS, INACCURACIES, OR SERVICE INTERRUPTIONS, INCLUDING POWER OUTAGES OR SYSTEM FAILURES; OR (B) ANY UNAUTHORIZED ACCESS TO OR ALTERATION OF, OR DELETION, DESTRUCTION, DAMAGE, OR LOSS OF, YOUR SITE OR ANY DATA, IMAGES, TEXT, OR OTHER INFORMATION OR CONTENT. NO ADVICE OR INFORMATION OBTAINED BY YOU FROM US OR FROM ANY OTHER PERSON OR ENTITY OR THROUGH THE PROGRAM, CONTENT, OR THE JAMKAZAM SITE WILL CREATE ANY WARRANTY NOT EXPRESSLY STATED IN THIS AGREEMENT. FURTHER, NEITHER WE NOR ANY OF OUR LICENSORS WILL BE RESPONSIBLE FOR ANY COMPENSATION, REIMBURSEMENT, OR DAMAGES ARISING IN CONNECTION WITH (X) ANY LOSS OF PROSPECTIVE PROFITS OR REVENUE, ANTICIPATED SALES, GOODWILL, OR OTHER BENEFITS, (Y) ANY INVESTMENTS, EXPENDITURES, OR COMMITMENTS BY YOU IN CONNECTION WITH THIS AGREEMENT OR YOUR PARTICIPATION IN THE PROGRAM, OR (Z) ANY TERMINATION OF THIS AGREEMENT OR YOUR PARTICIPATION IN THE PROGRAM.</span>
</p>
<p class="c2 c5"><span class="c0"></span></p>
<p class="c2"><span class="c0 c7">19. Disputes</span></p>
<p class="c2 c5"><span class="c0"></span></p>
<p class="c2">
<span class="c0">Any dispute relating in any way to the Program or this Agreement will be resolved by binding arbitration, rather than in court, except that you may assert claims in small claims court if your claims qualify. The Federal Arbitration Act and federal arbitration law and the laws of the state of Texas, without regard to principles of conflict of laws, will govern this Agreement and any dispute of any sort that might arise between you and us.</span>
</p>
<p class="c2 c5"><span class="c0"></span></p>
<p class="c2">
<span class="c0">There is no judge or jury in arbitration, and court review of an arbitration award is limited. However, an arbitrator can award on an individual basis the same damages and relief as a court (including injunctive and declaratory relief or statutory damages), and must follow the terms of this Agreement as a court would.</span>
</p>
<p class="c2 c5"><span class="c0"></span></p>
<p class="c2">
<span class="c0">To begin an arbitration proceeding, you must send a letter requesting arbitration and describing your claim to us at: JamKazam, Inc., Attn: Legal Department, 5813 Lookout Mountain Drive, Austin TX 78731. The arbitration will be conducted by the American Arbitration Association (&ldquo;AAA&rdquo;) under its rules, including the AAA&rsquo;s Supplementary Procedures for Consumer-Related Disputes. The AAA&rsquo;s rules are available at www.adr.org or by calling 1-800-778-7879. Payment of all filing, administration and arbitrator fees will be governed by the AAA&rsquo;s rules. We will reimburse those fees for claims totaling less than $10,000 unless the arbitrator determines the claims are frivolous. Likewise, we will not seek attorneys&rsquo;
fees and costs in arbitration unless the arbitrator determines the claims are frivolous. You may choose to have the arbitration conducted by telephone, based on written submissions, or in person in the county where you live or at another mutually agreed location.</span>
</p>
<p class="c2 c5"><span class="c0"></span></p>
<p class="c2">
<span class="c0">We each agree that any dispute resolution proceedings will be conducted only on an individual basis and not in a class, consolidated or representative action. If for any reason a claim proceeds in court rather than in arbitration, we each waive any right to a jury trial. We also both agree that you or we may bring suit in court to enjoin infringement or other misuse of intellectual property rights.</span>
</p>
<p class="c2 c5"><span class="c0"></span></p>
<p class="c2">
<span class="c0">Notwithstanding anything to the contrary in this Agreement, we may seek injunctive or other relief in any state, federal, or national court of competent jurisdiction for any actual or alleged infringement of our or any other person or entity&rsquo;s intellectual property or proprietary rights. You further acknowledge and agree that our rights in the Content are of a special, unique, extraordinary character, giving them peculiar value, the loss of which cannot be readily estimated or adequately compensated for in monetary damages.</span>
</p>
<p class="c2 c5"><span class="c0"></span></p>
<p class="c2"><span class="c0 c7">20. Miscellaneous</span></p>
<p class="c2 c5"><span class="c0"></span></p>
<p class="c2">
<span class="c0">You acknowledge and agree that we may at any time (directly or indirectly) solicit customer referrals on terms that may differ from those contained in this Agreement or operate sites that are similar to or compete with Your Site. You may not assign this Agreement, by operation of law or otherwise, without our express prior written approval. Subject to that restriction, this Agreement will be binding on, inure to the benefit of, and be enforceable against the parties and their respective successors and assigns. Our failure to enforce your strict performance of any provision of this Agreement will not constitute a waiver of our right to subsequently enforce such provision or any other provision of this Agreement. Whenever used in this Agreement, the terms &ldquo;include(s),&rdquo; &ldquo;including,&rdquo; &ldquo;e.g.,&rdquo;
and &ldquo;for example&rdquo; mean, respectively, &ldquo;include(s), without limitation,&rdquo; &ldquo;including, without limitation,&rdquo; &ldquo;e.g., without limitation,&rdquo;
and &ldquo;for example, without limitation.&rdquo; Any determinations or updates that may be made by us, any actions that may be taken by us, and any approvals that may be given by us under this Agreement, may be made, taken, or given in our sole discretion.</span>
</p>
<p class="c2 c5"><span class="c0"></span></p>
<p class="c2 c5"><span class="c0"></span></p>
<p class="c2">
<span class="c0">BY CLICKING THE &quot;I AGREE&quot; BUTTON BELOW, YOU AGREE TO THE TERMS AND CONDITIONS OF THIS AGREEMENT, OR BY CONTINUING TO PARTICIPATE IN THE PROGRAM FOLLOWING OUR POSTING OF A CHANGE NOTICE OR REVISED AGREEMENT ON THE JAMKAZAM.COM SITE, YOU (A) AGREE TO BE BOUND BY THIS AGREEMENT; (B) ACKNOWLEDGE AND AGREE THAT YOU HAVE INDEPENDENTLY EVALUATED THE DESIRABILITY OF PARTICIPATING IN THE PROGRAM AND ARE NOT RELYING ON ANY REPRESENTATION, GUARANTEE, OR STATEMENT OTHER THAN AS EXPRESSLY SET FORTH IN THIS AGREEMENT; AND (C) HEREBY REPRESENT AND WARRANT THAT YOU ARE LAWFULLY ABLE TO ENTER INTO CONTRACTS (E.G., YOU ARE NOT A MINOR) AND THAT YOU ARE AND WILL REMAIN IN COMPLIANCE WITH THIS AGREEMENT. IN ADDITION, IF THIS AGREEMENT IS BEING AGREED TO BY A COMPANY OR OTHER LEGAL ENTITY, THEN THE PERSON AGREEING TO THIS AGREEMENT ON BEHALF OF THAT COMPANY OR ENTITY HEREBY REPRESENTS AND WARRANTS THAT HE OR SHE IS AUTHORIZED AND LAWFULLY ABLE TO BIND THAT COMPANY OR ENTITY TO THIS AGREEMENT.</span>
</p>
<!--
<p class="c2 c5"><span class="c0"></span></p>
<p class="c2"><span class="c0">Radio buttons for:</span></p>
<ul class="c6 lst-kix_list_43-0 start">
<li class="c3 c2"><span class="c0 c8">I am entering into this Agreement as an individual</span></li>
<li class="c3 c2">
<span class="c0 c8">I am executing this Agreement on behalf of the company or entity listed below</span></li>
</ul>
<p class="c2 c5"><span class="c0"></span></p>
<p class="c2">
<span class="c0">If the user clicks the entity radio button above, we display an Entity Name label and associated text entry box, and an Entity Type label with a drop down list box with the following options: Sole Proprietorship, Limited Liability Company (LLC), S Corporation, C Corporation, Partnership, Trust/Estate, and Other.</span>
</p>
<p class="c2 c5"><span class="c0"></span></p>
<p class="c2">
<span class="c0">Green &ldquo;I Agree&rdquo; button on the left / centered. Red &ldquo;I Do Not Agree&rdquo; button on the right / centered.</span>
</p>
<p class="c2 c5"><span class="c0"></span></p>
<p class="c2 c5"><span class="c0"></span></p>
<p class="c2 c5"><span></span></p>
-->
<div><p class="c2 c21">
<span class="c8 c14">JamKazam Confidential&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="c14 c8">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4/17/2015</span>
</p></div>
</div>

File diff suppressed because it is too large Load Diff

View File

@ -145,7 +145,7 @@
<!--<a href="/auth/facebook" class="right"><img src="/fb-signup-button.png"></a> --> <!--<a href="/auth/facebook" class="right"><img src="/fb-signup-button.png"></a> -->
</div> </div>
<br clear="all" />
<!-- end right column --> <!-- end right column -->
<% end %> <% end %>

View File

@ -108,5 +108,6 @@ SampleApp::Application.configure do
config.jam_tracks_available = true config.jam_tracks_available = true
config.video_available = "full" config.video_available = "full"
config.guard_against_fraud = true config.guard_against_fraud = true
config.error_on_fraud = true
end end

View File

@ -32,6 +32,9 @@ SampleApp::Application.routes.draw do
match '/landing/kick4', to: 'landings#watch_overview_kick4', via: :get, as: 'landing_kick4' match '/landing/kick4', to: 'landings#watch_overview_kick4', via: :get, as: 'landing_kick4'
match '/landing/jamtracks/:plan_code', to: 'landings#individual_jamtrack', via: :get, as: 'individual_jamtrack' 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/band/:plan_code', to: 'landings#individual_jamtrack_band', via: :get, as: 'individual_jamtrack_band'
match '/affiliateProgram', to: 'landings#affiliate_program', via: :get, as: 'affiliate_program'
match '/affiliate/links/:id', to: 'affiliates#links', via: :get, as: 'affilate_links'
# redirect /jamtracks to jamtracks browse page # redirect /jamtracks to jamtracks browse page
get '/jamtracks', to: redirect('/client#/jamtrackBrowse') get '/jamtracks', to: redirect('/client#/jamtrackBrowse')
@ -384,6 +387,13 @@ SampleApp::Application.routes.draw do
match '/users/:id/plays' => 'api_users#add_play', :via => :post, :as => 'api_users_add_play' match '/users/:id/plays' => 'api_users#add_play', :via => :post, :as => 'api_users_add_play'
match '/users/:id/affiliate' => 'api_users#affiliate_report', :via => :get, :as => 'api_users_affiliate' match '/users/:id/affiliate' => 'api_users#affiliate_report', :via => :get, :as => 'api_users_affiliate'
match '/users/:id/affiliate_partner' => 'api_users#affiliate_partner', :via => [:get, :post], :as => 'api_users_affiliate_partner'
match '/affiliate_partners' => 'api_affiliate#create', :via => :post, :as => 'api_affiliates_create'
match '/affiliate_partners/signups' => 'api_affiliate#traffic_index', :via => :get, :as => 'api_affiliates_signups'
match '/affiliate_partners/monthly_earnings' => 'api_affiliate#monthly_index', :via => :get, :as => 'api_affiliates_monthly'
match '/affiliate_partners/quarterly_earnings' => 'api_affiliate#quarterly_index', :via => :get, :as => 'api_affiliates_quarterly'
match '/affiliate_partners/payments' => 'api_affiliate#payment_index', :via => :get, :as => 'api_affiliates_payment'
# downloads/uploads # downloads/uploads
match '/users/:id/syncs' => 'api_user_syncs#index', :via => :get match '/users/:id/syncs' => 'api_user_syncs#index', :via => :get
@ -569,5 +579,13 @@ SampleApp::Application.routes.draw do
match '/signup_hints/:id' => 'api_signup_hints#show', :via => :get, :as => :api_signup_hint_detail match '/signup_hints/:id' => 'api_signup_hints#show', :via => :get, :as => :api_signup_hint_detail
match '/alerts' => 'api_alerts#create', :via => :post match '/alerts' => 'api_alerts#create', :via => :post
# links generated to help affiliates share relevant links
match '/links/jamtrack_songs' => 'api_links#jamtrack_song_index'
match '/links/jamtrack_bands' => 'api_links#jamtrack_band_index'
match '/links/jamtrack_general' => 'api_links#jamtrack_general_index'
match '/links/jamkazam' => 'api_links#jamkazam_general_index'
match '/links/sessions' => 'api_links#session_index'
match '/links/recordings' => 'api_links#recording_index'
end end
end end

View File

@ -74,3 +74,8 @@ StatsMaker:
cron: "* * * * *" cron: "* * * * *"
class: "JamRuby::StatsMaker" class: "JamRuby::StatsMaker"
description: "Generates interesting stats from the database" description: "Generates interesting stats from the database"
TallyAffiliates:
cron: "0 0,4,8,12,16,20 * * *"
class: "JamRuby::TallyAffiliates"
description: "Tallies up affiliate totals"

1752
web/db/schema.rb Normal file

File diff suppressed because it is too large Load Diff

3862
web/db/structure.sql Normal file

File diff suppressed because it is too large Load Diff

13
web/lib/tasks/email.rake Normal file
View File

@ -0,0 +1,13 @@
namespace :emails do
task :test_progression_email => :environment do |task, args|
user = User.find_by_email('jonathan@jamkazam.com')
EmailBatchProgression::SUBTYPES.each do |stype|
ebatch = EmailBatchProgression.create
ebatch.update_attribute(:sub_type, stype)
ebatch.email_batch_sets << (bset = ebatch.make_set(user, 0))
ProgressMailer.send_reminder(bset).deliver
end
end
end

13
web/lib/tasks/google.rake Normal file
View File

@ -0,0 +1,13 @@
=begin
require 'google/api_client'
namespace :google do
task :youtube do |task, args|
client = Google::APIClient.new
yt = client.discovered_api('youtube', 'v3')
# google-api oauth-2-login --client-id='785931784279-gd0g8on6sc0tuesj7cu763pitaiv2la8.apps.googleusercontent.com' --client-secret='UwzIcvtErv9c2-GIsNfIo7bA' --scope="https://www.googleapis.com/auth/plus.me"
end
end
=end

View File

@ -85,6 +85,17 @@ namespace :db do
make_music_sessions_history make_music_sessions_history
make_music_sessions_user_history make_music_sessions_user_history
end end
task affiliate_traffic_earnings: :environment do
partner = FactoryGirl.create(:affiliate_partner)
user_partner = FactoryGirl.create(:user, affiliate_partner: partner)
puts "USER CREATED: u: #{user_partner.email}/p: foobar"
today = Date.today
quarter1 = FactoryGirl.create(:affiliate_quarterly_payment, affiliate_partner: partner, due_amount_in_cents: 10000, closed:true)
month1 = FactoryGirl.create(:affiliate_monthly_payment, affiliate_partner: partner, due_amount_in_cents: 10000, closed:true)
end
end end
def make_music_sessions_history def make_music_sessions_history

View File

@ -28,6 +28,7 @@ class UserManager < BaseManager
affiliate_referral_id = options[:affiliate_referral_id] affiliate_referral_id = options[:affiliate_referral_id]
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]
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
@ -70,7 +71,8 @@ class UserManager < BaseManager
signup_confirm_url: signup_confirm_url, signup_confirm_url: signup_confirm_url,
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)
user user
end end

7
web/loop.bash Executable file
View File

@ -0,0 +1,7 @@
#!/bin/bash
for i in {1..100}
do
echo "Loop $i "`date`
bundle exec rspec spec/features/music_sessions_spec.rb
done

919
web/ruby-bt.txt Normal file
View File

@ -0,0 +1,919 @@
$ bundle exec rake routes
/home/jam/.rvm/gems/ruby-2.0.0-p247/gems/json-1.8.1/lib/json/common.rb:67: [BUG] Segmentation fault
ruby 2.0.0p247 (2013-06-27 revision 41674) [x86_64-linux]
-- Control frame information -----------------------------------------------
c:0056 p:---- s:0192 e:000191 CFUNC :initialize
c:0055 p:---- s:0190 e:000189 CFUNC :new
c:0054 p:0075 s:0187 e:000184 METHOD /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/json-1.8.1/lib/json/common.rb:67
c:0053 p:0070 s:0176 e:000174 CLASS /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/json-1.8.1/lib/json/ext.rb:17
c:0052 p:0011 s:0173 e:000172 CLASS /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/json-1.8.1/lib/json/ext.rb:12
c:0051 p:0057 s:0171 e:000170 TOP /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/json-1.8.1/lib/json/ext.rb:9 [FINISH]
c:0050 p:---- s:0169 e:000168 CFUNC :require
c:0049 p:0010 s:0165 e:000164 BLOCK /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/dependencies.rb:251
c:0048 p:0054 s:0163 e:000162 METHOD /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/dependencies.rb:236
c:0047 p:0015 s:0158 e:000157 METHOD /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/dependencies.rb:251
c:0046 p:0019 s:0153 e:000152 CLASS /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/json-1.8.1/lib/json.rb:58
c:0045 p:0017 s:0151 e:000150 TOP /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/json-1.8.1/lib/json.rb:54 [FINISH]
c:0044 p:---- s:0149 e:000148 CFUNC :require
c:0043 p:0010 s:0145 e:000144 BLOCK /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/dependencies.rb:251
c:0042 p:0054 s:0143 e:000142 METHOD /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/dependencies.rb:236
c:0041 p:0015 s:0138 e:000137 METHOD /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/dependencies.rb:251
c:0040 p:0009 s:0133 e:000132 TOP /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/object/to_json.rb:3 [FINISH]
c:0039 p:---- s:0131 e:000130 CFUNC :require
c:0038 p:0010 s:0127 e:000126 BLOCK /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/dependencies.rb:251
c:0037 p:0054 s:0125 e:000124 METHOD /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/dependencies.rb:236
c:0036 p:0015 s:0120 e:000119 METHOD /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/dependencies.rb:251
c:0035 p:0007 s:0115 e:000114 TOP /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/json/encoding.rb:1 [FINISH]
c:0034 p:---- s:0113 e:000112 CFUNC :require
c:0033 p:0010 s:0109 e:000108 BLOCK /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/dependencies.rb:251
c:0032 p:0054 s:0107 e:000106 METHOD /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/dependencies.rb:236
c:0031 p:0015 s:0102 e:000101 METHOD /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/dependencies.rb:251
c:0030 p:0015 s:0097 e:000096 TOP /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/json.rb:2 [FINISH]
c:0029 p:---- s:0095 e:000094 CFUNC :require
c:0028 p:0010 s:0091 e:000090 BLOCK /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/dependencies.rb:251
c:0027 p:0054 s:0089 e:000088 METHOD /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/dependencies.rb:236
c:0026 p:0015 s:0084 e:000083 METHOD /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/dependencies.rb:251
c:0025 p:0007 s:0079 e:000078 TOP /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activemodel-3.2.15/lib/active_model/serializers/json.rb:1 [FINISH]
c:0024 p:0029 s:0077 e:000075 CLASS /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/serialization.rb:5
c:0023 p:0011 s:0074 e:000073 CLASS /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/serialization.rb:3
c:0022 p:0009 s:0072 e:000071 TOP /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/serialization.rb:1 [FINISH]
c:0021 p:0770 s:0070 e:000065 CLASS /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/base.rb:715
c:0020 p:0011 s:0064 e:000063 CLASS /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/base.rb:333
c:0019 p:0228 s:0062 e:000061 TOP /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/base.rb:33 [FINISH]
c:0018 p:0068 s:0060 e:000059 TOP /home/jam/workspace/jam-cloud/web/config/application.rb:13 [FINISH]
c:0017 p:---- s:0058 e:000057 CFUNC :require
c:0016 p:0018 s:0054 e:000053 TOP /home/jam/workspace/jam-cloud/web/Rakefile:5 [FINISH]
c:0015 p:---- s:0052 e:000051 CFUNC :load
c:0014 p:0009 s:0048 e:000047 METHOD /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/rake_module.rb:25
c:0013 p:0176 s:0044 e:000043 METHOD /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/application.rb:637
c:0012 p:0007 s:0039 e:000038 BLOCK /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/application.rb:94
c:0011 p:0006 s:0037 e:000036 METHOD /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/application.rb:165
c:0010 p:0007 s:0033 e:000032 METHOD /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/application.rb:93
c:0009 p:0013 s:0030 e:000029 BLOCK /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/application.rb:77
c:0008 p:0006 s:0028 e:000027 METHOD /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/application.rb:165
c:0007 p:0007 s:0024 e:000023 METHOD /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/application.rb:75
c:0006 p:0040 s:0021 e:000020 TOP /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/bin/rake:33 [FINISH]
c:0005 p:---- s:0019 e:000018 CFUNC :load
c:0004 p:0118 s:0015 E:000da8 EVAL /home/jam/.rvm/gems/ruby-2.0.0-p247@global/bin/rake:23 [FINISH]
c:0003 p:---- s:0011 e:000010 CFUNC :eval
c:0002 p:0118 s:0005 E:001d40 EVAL /home/jam/.rvm/gems/ruby-2.0.0-p247@global/bin/ruby_executable_hooks:15 [FINISH]
c:0001 p:0000 s:0002 E:000338 TOP [FINISH]
/home/jam/.rvm/gems/ruby-2.0.0-p247@global/bin/ruby_executable_hooks:15:in `<main>'
/home/jam/.rvm/gems/ruby-2.0.0-p247@global/bin/ruby_executable_hooks:15:in `eval'
/home/jam/.rvm/gems/ruby-2.0.0-p247@global/bin/rake:23:in `<main>'
/home/jam/.rvm/gems/ruby-2.0.0-p247@global/bin/rake:23:in `load'
/home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/bin/rake:33:in `<top (required)>'
/home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/application.rb:75:in `run'
/home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/application.rb:165:in `standard_exception_handling'
/home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/application.rb:77:in `block in run'
/home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/application.rb:93:in `load_rakefile'
/home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/application.rb:165:in `standard_exception_handling'
/home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/application.rb:94:in `block in load_rakefile'
/home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/application.rb:637:in `raw_load_rakefile'
/home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/rake_module.rb:25:in `load_rakefile'
/home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/rake_module.rb:25:in `load'
/home/jam/workspace/jam-cloud/web/Rakefile:5:in `<top (required)>'
/home/jam/workspace/jam-cloud/web/Rakefile:5:in `require'
/home/jam/workspace/jam-cloud/web/config/application.rb:13:in `<top (required)>'
/home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/base.rb:33:in `<top (required)>'
/home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/base.rb:333:in `<module:ActiveRecord>'
/home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/base.rb:715:in `<class:Base>'
/home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/serialization.rb:1:in `<top (required)>'
/home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/serialization.rb:3:in `<module:ActiveRecord>'
/home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/serialization.rb:5:in `<module:Serialization>'
/home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activemodel-3.2.15/lib/active_model/serializers/json.rb:1:in `<top (required)>'
/home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/dependencies.rb:251:in `require'
/home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/dependencies.rb:236:in `load_dependency'
/home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/dependencies.rb:251:in `block in require'
/home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/dependencies.rb:251:in `require'
/home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/json.rb:2:in `<top (required)>'
/home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/dependencies.rb:251:in `require'
/home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/dependencies.rb:236:in `load_dependency'
/home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/dependencies.rb:251:in `block in require'
/home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/dependencies.rb:251:in `require'
/home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/json/encoding.rb:1:in `<top (required)>'
/home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/dependencies.rb:251:in `require'
/home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/dependencies.rb:236:in `load_dependency'
/home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/dependencies.rb:251:in `block in require'
/home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/dependencies.rb:251:in `require'
/home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/object/to_json.rb:3:in `<top (required)>'
/home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/dependencies.rb:251:in `require'
/home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/dependencies.rb:236:in `load_dependency'
/home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/dependencies.rb:251:in `block in require'
/home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/dependencies.rb:251:in `require'
/home/jam/.rvm/gems/ruby-2.0.0-p247/gems/json-1.8.1/lib/json.rb:54:in `<top (required)>'
/home/jam/.rvm/gems/ruby-2.0.0-p247/gems/json-1.8.1/lib/json.rb:58:in `<module:JSON>'
/home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/dependencies.rb:251:in `require'
/home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/dependencies.rb:236:in `load_dependency'
/home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/dependencies.rb:251:in `block in require'
/home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/dependencies.rb:251:in `require'
/home/jam/.rvm/gems/ruby-2.0.0-p247/gems/json-1.8.1/lib/json/ext.rb:9:in `<top (required)>'
/home/jam/.rvm/gems/ruby-2.0.0-p247/gems/json-1.8.1/lib/json/ext.rb:12:in `<module:JSON>'
/home/jam/.rvm/gems/ruby-2.0.0-p247/gems/json-1.8.1/lib/json/ext.rb:17:in `<module:Ext>'
/home/jam/.rvm/gems/ruby-2.0.0-p247/gems/json-1.8.1/lib/json/common.rb:67:in `generator='
/home/jam/.rvm/gems/ruby-2.0.0-p247/gems/json-1.8.1/lib/json/common.rb:67:in `new'
/home/jam/.rvm/gems/ruby-2.0.0-p247/gems/json-1.8.1/lib/json/common.rb:67:in `initialize'
-- C level backtrace information -------------------------------------------
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x19d7f5) [0x7fd2a8a937f5] vm_dump.c:647
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x64dbc) [0x7fd2a895adbc] error.c:283
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(rb_bug+0xb7) [0x7fd2a895c2c7] error.c:302
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x129cee) [0x7fd2a8a1fcee] signal.c:672
/lib/x86_64-linux-gnu/libc.so.6(+0x364a0) [0x7fd2a856d4a0]
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(rb_hash_aref+0x11) [0x7fd2a897ce31] hash.c:561
/home/jam/.rvm/gems/ruby-2.0.0-p247/gems/json-1.8.1/lib/json/ext/generator.so(+0x3294) [0x7fd2a3f99294] generator.c:528
/home/jam/.rvm/gems/ruby-2.0.0-p247/gems/json-1.8.1/lib/json/ext/generator.so(+0x4d9f) [0x7fd2a3f9ad9f] generator.c:954
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x193440) [0x7fd2a8a89440] vm_eval.c:117
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x1939e3) [0x7fd2a8a899e3] vm_eval.c:49
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(rb_class_new_instance+0x30) [0x7fd2a89b5ae0] object.c:1761
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x187c06) [0x7fd2a8a7dc06] vm_insnhelper.c:1469
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x1965ff) [0x7fd2a8a8c5ff] vm_insnhelper.c:1559
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x18c2d2) [0x7fd2a8a822d2] insns.def:1017
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x192036) [0x7fd2a8a88036] vm.c:1201
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(rb_iseq_eval+0x176) [0x7fd2a8a8e8f6] vm.c:1436
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x6f784) [0x7fd2a8965784] load.c:599
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(rb_require_safe+0x4ff) [0x7fd2a896757f] load.c:959
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x187c06) [0x7fd2a8a7dc06] vm_insnhelper.c:1469
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x1965ff) [0x7fd2a8a8c5ff] vm_insnhelper.c:1559
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x18c45d) [0x7fd2a8a8245d] insns.def:1039
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x192036) [0x7fd2a8a88036] vm.c:1201
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(rb_iseq_eval+0x176) [0x7fd2a8a8e8f6] vm.c:1436
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x6f784) [0x7fd2a8965784] load.c:599
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(rb_require_safe+0x4ff) [0x7fd2a896757f] load.c:959
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x187c06) [0x7fd2a8a7dc06] vm_insnhelper.c:1469
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x1965ff) [0x7fd2a8a8c5ff] vm_insnhelper.c:1559
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x18c45d) [0x7fd2a8a8245d] insns.def:1039
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x192036) [0x7fd2a8a88036] vm.c:1201
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(rb_iseq_eval+0x176) [0x7fd2a8a8e8f6] vm.c:1436
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x6f784) [0x7fd2a8965784] load.c:599
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(rb_require_safe+0x4ff) [0x7fd2a896757f] load.c:959
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x187c06) [0x7fd2a8a7dc06] vm_insnhelper.c:1469
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x1965ff) [0x7fd2a8a8c5ff] vm_insnhelper.c:1559
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x18c45d) [0x7fd2a8a8245d] insns.def:1039
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x192036) [0x7fd2a8a88036] vm.c:1201
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(rb_iseq_eval+0x176) [0x7fd2a8a8e8f6] vm.c:1436
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x6f784) [0x7fd2a8965784] load.c:599
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(rb_require_safe+0x4ff) [0x7fd2a896757f] load.c:959
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x187c06) [0x7fd2a8a7dc06] vm_insnhelper.c:1469
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x1965ff) [0x7fd2a8a8c5ff] vm_insnhelper.c:1559
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x18c45d) [0x7fd2a8a8245d] insns.def:1039
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x192036) [0x7fd2a8a88036] vm.c:1201
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(rb_iseq_eval+0x176) [0x7fd2a8a8e8f6] vm.c:1436
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x6f784) [0x7fd2a8965784] load.c:599
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(rb_require_safe+0x4ff) [0x7fd2a896757f] load.c:959
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x187c06) [0x7fd2a8a7dc06] vm_insnhelper.c:1469
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x1965ff) [0x7fd2a8a8c5ff] vm_insnhelper.c:1559
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x18c45d) [0x7fd2a8a8245d] insns.def:1039
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x192036) [0x7fd2a8a88036] vm.c:1201
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(rb_iseq_eval+0x176) [0x7fd2a8a8e8f6] vm.c:1436
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x6f784) [0x7fd2a8965784] load.c:599
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(rb_require_safe+0x4ff) [0x7fd2a896757f] load.c:959
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(rb_protect+0xd7) [0x7fd2a8963307] eval.c:786
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(rb_autoload_load+0x10c) [0x7fd2a8a614fc] variable.c:1781
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x16b687) [0x7fd2a8a61687] variable.c:1841
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x189e48) [0x7fd2a8a7fe48] vm_insnhelper.c:450
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x192036) [0x7fd2a8a88036] vm.c:1201
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(rb_iseq_eval+0x176) [0x7fd2a8a8e8f6] vm.c:1436
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x6f784) [0x7fd2a8965784] load.c:599
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(rb_require_safe+0x4ff) [0x7fd2a896757f] load.c:959
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(rb_protect+0xd7) [0x7fd2a8963307] eval.c:786
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(rb_autoload_load+0x10c) [0x7fd2a8a614fc] variable.c:1781
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x18784f) [0x7fd2a8a7d84f] vm_insnhelper.c:414
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x18d92f) [0x7fd2a8a8392f] vm_insnhelper.c:383
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x192036) [0x7fd2a8a88036] vm.c:1201
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(rb_iseq_eval+0x176) [0x7fd2a8a8e8f6] vm.c:1436
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x6f784) [0x7fd2a8965784] load.c:599
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(rb_require_safe+0x4ff) [0x7fd2a896757f] load.c:959
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(rb_protect+0xd7) [0x7fd2a8963307] eval.c:786
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(rb_autoload_load+0x10c) [0x7fd2a8a614fc] variable.c:1781
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x16b687) [0x7fd2a8a61687] variable.c:1841
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x189e48) [0x7fd2a8a7fe48] vm_insnhelper.c:450
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x192036) [0x7fd2a8a88036] vm.c:1201
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(rb_iseq_eval+0x176) [0x7fd2a8a8e8f6] vm.c:1436
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x6f784) [0x7fd2a8965784] load.c:599
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(rb_require_safe+0x4ff) [0x7fd2a896757f] load.c:959
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x187c06) [0x7fd2a8a7dc06] vm_insnhelper.c:1469
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x1965ff) [0x7fd2a8a8c5ff] vm_insnhelper.c:1559
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x18c2d2) [0x7fd2a8a822d2] insns.def:1017
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x192036) [0x7fd2a8a88036] vm.c:1201
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(rb_iseq_eval+0x176) [0x7fd2a8a8e8f6] vm.c:1436
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x6f784) [0x7fd2a8965784] load.c:599
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x6f8e8) [0x7fd2a89658e8] load.c:680
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x187c06) [0x7fd2a8a7dc06] vm_insnhelper.c:1469
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x1965ff) [0x7fd2a8a8c5ff] vm_insnhelper.c:1559
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x18c2d2) [0x7fd2a8a822d2] insns.def:1017
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x192036) [0x7fd2a8a88036] vm.c:1201
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(rb_iseq_eval+0x176) [0x7fd2a8a8e8f6] vm.c:1436
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x6f784) [0x7fd2a8965784] load.c:599
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x6f8e8) [0x7fd2a89658e8] load.c:680
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x187c06) [0x7fd2a8a7dc06] vm_insnhelper.c:1469
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x1965ff) [0x7fd2a8a8c5ff] vm_insnhelper.c:1559
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x18c2d2) [0x7fd2a8a822d2] insns.def:1017
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x192036) [0x7fd2a8a88036] vm.c:1201
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x19259c) [0x7fd2a8a8859c] vm_eval.c:1251
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x192a1f) [0x7fd2a8a88a1f] vm_eval.c:1292
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x187c06) [0x7fd2a8a7dc06] vm_insnhelper.c:1469
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x1965ff) [0x7fd2a8a8c5ff] vm_insnhelper.c:1559
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x18c2d2) [0x7fd2a8a822d2] insns.def:1017
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x192036) [0x7fd2a8a88036] vm.c:1201
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(rb_iseq_eval_main+0x8a) [0x7fd2a8a8e9da] vm.c:1449
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(+0x6b8c2) [0x7fd2a89618c2] eval.c:250
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(ruby_exec_node+0x1d) [0x7fd2a8962bad] eval.c:315
/home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/../lib/libruby.so.2.0(ruby_run_node+0x1e) [0x7fd2a8964dae] eval.c:307
/home/jam/.rvm/gems/ruby-2.0.0-p247@global/bin/rake() [0x40080b]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xed) [0x7fd2a855876d]
/home/jam/.rvm/gems/ruby-2.0.0-p247@global/bin/rake() [0x400839]
-- Other runtime information -----------------------------------------------
* Loaded script: /home/jam/.rvm/gems/ruby-2.0.0-p247@global/bin/rake
* Loaded features:
0 enumerator.so
1 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/enc/encdb.so
2 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/enc/trans/transdb.so
3 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/rbconfig.rb
4 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/site_ruby/2.0.0/rubygems/compatibility.rb
5 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/site_ruby/2.0.0/rubygems/defaults.rb
6 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/site_ruby/2.0.0/rubygems/deprecate.rb
7 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/site_ruby/2.0.0/rubygems/errors.rb
8 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/site_ruby/2.0.0/rubygems/version.rb
9 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/site_ruby/2.0.0/rubygems/requirement.rb
10 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/site_ruby/2.0.0/rubygems/platform.rb
11 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/site_ruby/2.0.0/rubygems/specification.rb
12 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/site_ruby/2.0.0/rubygems/exceptions.rb
13 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/site_ruby/2.0.0/rubygems/core_ext/kernel_gem.rb
14 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/site_ruby/2.0.0/rubygems/core_ext/kernel_require.rb
15 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/site_ruby/2.0.0/rubygems.rb
16 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/pathname.so
17 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/pathname.rb
18 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/site_ruby/2.0.0/rubygems/user_interaction.rb
19 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/etc.so
20 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/site_ruby/2.0.0/rubygems/config_file.rb
21 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/bundler-1.3.5/lib/bundler/rubygems_integration.rb
22 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/site_ruby/2.0.0/rubygems/dependency.rb
23 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/bundler-1.3.5/lib/bundler/shared_helpers.rb
24 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/fileutils.rb
25 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/bundler-1.3.5/lib/bundler/gem_path_manipulation.rb
26 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/bundler-1.3.5/lib/bundler/gem_helpers.rb
27 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/bundler-1.3.5/lib/bundler/match_platform.rb
28 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/bundler-1.3.5/lib/bundler/rubygems_ext.rb
29 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/bundler-1.3.5/lib/bundler/version.rb
30 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/bundler-1.3.5/lib/bundler.rb
31 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/bundler-1.3.5/lib/bundler/settings.rb
32 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/site_ruby/2.0.0/rubygems/path_support.rb
33 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/digest.so
34 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/digest.rb
35 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/digest/sha1.so
36 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/set.rb
37 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/bundler-1.3.5/lib/bundler/definition.rb
38 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/bundler-1.3.5/lib/bundler/dependency.rb
39 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/bundler-1.3.5/lib/bundler/ruby_dsl.rb
40 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/bundler-1.3.5/lib/bundler/dsl.rb
41 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/bundler-1.3.5/lib/bundler/source.rb
42 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/common.rb
43 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/generic.rb
44 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/ftp.rb
45 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/http.rb
46 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/https.rb
47 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/ldap.rb
48 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/ldaps.rb
49 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri/mailto.rb
50 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/uri.rb
51 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/socket.so
52 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/socket.rb
53 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/fcntl.so
54 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/timeout.rb
55 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/thread.rb
56 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/openssl.so
57 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/openssl/bn.rb
58 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/openssl/cipher.rb
59 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/stringio.so
60 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/openssl/config.rb
61 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/openssl/digest.rb
62 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/openssl/x509.rb
63 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/openssl/buffering.rb
64 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/openssl/ssl.rb
65 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/openssl.rb
66 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/securerandom.rb
67 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/resolv.rb
68 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/site_ruby/2.0.0/rubygems/remote_fetcher.rb
69 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/site_ruby/2.0.0/rubygems/text.rb
70 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/site_ruby/2.0.0/rubygems/name_tuple.rb
71 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/site_ruby/2.0.0/rubygems/spec_fetcher.rb
72 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/bundler-1.3.5/lib/bundler/source/rubygems.rb
73 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/bundler-1.3.5/lib/bundler/source/path.rb
74 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/strscan.so
75 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/bundler-1.3.5/lib/bundler/source/git.rb
76 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/bundler-1.3.5/lib/bundler/lockfile_parser.rb
77 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/bundler-1.3.5/lib/bundler/lazy_specification.rb
78 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/tsort.rb
79 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/forwardable.rb
80 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/bundler-1.3.5/lib/bundler/spec_set.rb
81 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/bundler-1.3.5/lib/bundler/index.rb
82 /home/jam/workspace/jam-cloud/websocket-gateway/lib/jam_websockets/version.rb
83 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/bundler-1.3.5/lib/bundler/environment.rb
84 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/bundler-1.3.5/lib/bundler/runtime.rb
85 /home/jam/workspace/jam-cloud/db/target/ruby_package/lib/jam_db/version.rb
86 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/bundler-1.3.5/lib/bundler/remote_specification.rb
87 /home/jam/workspace/jam-cloud/ruby/lib/jam_ruby/version.rb
88 /home/jam/workspace/jam-cloud/pb/target/ruby/jampb/lib/jampb/version.rb
89 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/bundler-1.3.5/lib/bundler/dep_proxy.rb
90 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/bundler-1.3.5/lib/bundler/resolver.rb
91 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/bundler-1.3.5/lib/bundler/ui.rb
92 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/bundler-1.3.5/lib/bundler/endpoint_specification.rb
93 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/bundler-1.3.5/lib/bundler/setup.rb
94 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/version.rb
95 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/singleton.rb
96 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/monitor.rb
97 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/optparse.rb
98 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/ostruct.rb
99 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/ext/module.rb
100 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/ext/core.rb
101 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/ext/string.rb
102 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/early_time.rb
103 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/ext/time.rb
104 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/alt_system.rb
105 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/win32.rb
106 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/linked_list.rb
107 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/scope.rb
108 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/task_argument_error.rb
109 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/rule_recursion_overflow_error.rb
110 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/shellwords.rb
111 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/task_manager.rb
112 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/cloneable.rb
113 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/file_utils.rb
114 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/file_utils_ext.rb
115 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/pathmap.rb
116 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/file_list.rb
117 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/promise.rb
118 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/thread_pool.rb
119 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/private_reader.rb
120 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/thread_history_display.rb
121 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/trace_output.rb
122 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/application.rb
123 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/rake_module.rb
124 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/pseudo_status.rb
125 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/task_arguments.rb
126 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/invocation_chain.rb
127 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/invocation_exception_mixin.rb
128 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/task.rb
129 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/file_task.rb
130 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/file_creation_task.rb
131 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/multi_task.rb
132 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/dsl_definition.rb
133 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/default_loader.rb
134 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/name_space.rb
135 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake/backtrace.rb
136 /home/jam/.rvm/gems/ruby-2.0.0-p247@global/gems/rake-10.1.0/lib/rake.rb
137 /home/jam/workspace/jam-cloud/web/config/boot.rb
138 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/inflector/inflections.rb
139 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/inflections.rb
140 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/inflector/methods.rb
141 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/lazy_load_hooks.rb
142 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/dependencies/autoload.rb
143 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/version.rb
144 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support.rb
145 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/i18n-0.6.5/lib/i18n/version.rb
146 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/i18n-0.6.5/lib/i18n/exceptions.rb
147 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/i18n-0.6.5/lib/i18n/interpolate/ruby.rb
148 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/i18n-0.6.5/lib/i18n.rb
149 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/i18n-0.6.5/lib/i18n/config.rb
150 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/i18n.rb
151 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activemodel-3.2.15/lib/active_model/version.rb
152 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activemodel-3.2.15/lib/active_model.rb
153 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/crud.rb
154 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/factory_methods.rb
155 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/expressions.rb
156 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/predications.rb
157 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/math.rb
158 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/alias_predication.rb
159 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/order_predications.rb
160 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/table.rb
161 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/attributes/attribute.rb
162 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/attributes.rb
163 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/compatibility/wheres.rb
164 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/relation.rb
165 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/expression.rb
166 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/visitors/visitor.rb
167 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/visitors/depth_first.rb
168 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/bigdecimal.so
169 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/date_core.so
170 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/date/format.rb
171 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/date.rb
172 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/visitors/to_sql.rb
173 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/visitors/sqlite.rb
174 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/visitors/postgresql.rb
175 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/visitors/mysql.rb
176 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/visitors/mssql.rb
177 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/visitors/oracle.rb
178 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/visitors/join_sql.rb
179 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/visitors/where_sql.rb
180 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/visitors/order_clauses.rb
181 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/visitors/dot.rb
182 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/visitors/ibm_db.rb
183 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/visitors/informix.rb
184 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/visitors.rb
185 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/tree_manager.rb
186 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/insert_manager.rb
187 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/select_manager.rb
188 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/update_manager.rb
189 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/delete_manager.rb
190 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/nodes/node.rb
191 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/nodes/select_statement.rb
192 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/nodes/select_core.rb
193 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/nodes/insert_statement.rb
194 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/nodes/update_statement.rb
195 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/nodes/terminal.rb
196 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/nodes/true.rb
197 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/nodes/false.rb
198 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/nodes/unary.rb
199 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/nodes/ascending.rb
200 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/nodes/descending.rb
201 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/nodes/unqualified_column.rb
202 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/nodes/with.rb
203 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/nodes/binary.rb
204 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/nodes/equality.rb
205 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/nodes/in.rb
206 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/nodes/join_source.rb
207 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/nodes/delete_statement.rb
208 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/nodes/table_alias.rb
209 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/nodes/infix_operation.rb
210 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/nodes/and.rb
211 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/nodes/function.rb
212 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/nodes/count.rb
213 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/nodes/values.rb
214 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/nodes/named_function.rb
215 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/nodes/inner_join.rb
216 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/nodes/outer_join.rb
217 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/nodes/string_join.rb
218 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/nodes/sql_literal.rb
219 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/nodes.rb
220 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/deprecated.rb
221 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/sql/engine.rb
222 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel/sql_literal.rb
223 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/arel-3.0.2/lib/arel.rb
224 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/version.rb
225 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/psych/syntax_error.rb
226 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/psych.so
227 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/psych/nodes/node.rb
228 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/psych/nodes/stream.rb
229 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/psych/nodes/document.rb
230 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/psych/nodes/sequence.rb
231 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/psych/nodes/scalar.rb
232 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/psych/nodes/mapping.rb
233 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/psych/nodes/alias.rb
234 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/psych/nodes.rb
235 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/psych/streaming.rb
236 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/psych/visitors/visitor.rb
237 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/psych/scalar_scanner.rb
238 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/psych/visitors/to_ruby.rb
239 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/psych/visitors/emitter.rb
240 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/psych/visitors/yaml_tree.rb
241 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/psych/json/ruby_events.rb
242 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/psych/visitors/json_tree.rb
243 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/psych/visitors/depth_first.rb
244 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/psych/visitors.rb
245 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/psych/handler.rb
246 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/psych/tree_builder.rb
247 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/psych/parser.rb
248 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/psych/omap.rb
249 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/psych/set.rb
250 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/psych/coder.rb
251 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/psych/core_ext.rb
252 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/psych/deprecated.rb
253 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/psych/stream.rb
254 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/psych/json/yaml_events.rb
255 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/psych/json/tree_builder.rb
256 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/psych/json/stream.rb
257 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/psych/handlers/document_stream.rb
258 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/psych.rb
259 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/yaml.rb
260 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/ordered_hash.rb
261 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/enumerable.rb
262 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/notifications/fanout.rb
263 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/notifications.rb
264 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/array/wrap.rb
265 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/deprecation/behaviors.rb
266 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/deprecation/reporting.rb
267 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/module/deprecation.rb
268 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/module/aliasing.rb
269 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/array/extract_options.rb
270 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/deprecation/method_wrappers.rb
271 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/deprecation/proxy_wrappers.rb
272 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/deprecation.rb
273 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/concern.rb
274 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/hash/keys.rb
275 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/kernel/singleton_class.rb
276 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/module/remove_method.rb
277 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/class/attribute.rb
278 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activemodel-3.2.15/lib/active_model/attribute_methods.rb
279 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/attribute_methods.rb
280 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/bigdecimal/util.rb
281 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/benchmark.rb
282 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/benchmark.rb
283 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/connection_adapters/schema_cache.rb
284 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/big_decimal/conversions.rb
285 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/connection_adapters/abstract/quoting.rb
286 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/connection_adapters/abstract/database_statements.rb
287 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/connection_adapters/abstract/schema_statements.rb
288 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/connection_adapters/abstract/database_limits.rb
289 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/connection_adapters/abstract/query_cache.rb
290 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/descendants_tracker.rb
291 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/kernel/reporting.rb
292 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/object/inclusion.rb
293 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/callbacks.rb
294 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/connection_adapters/abstract_adapter.rb
295 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/scoping.rb
296 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record.rb
297 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/railties-3.2.15/lib/rails/ruby_version_check.rb
298 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/class/attribute_accessors.rb
299 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/logger.rb
300 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/logger.rb
301 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/hash/reverse_merge.rb
302 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/railties-3.2.15/lib/rails/initializable.rb
303 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/ordered_options.rb
304 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/hash/deep_dup.rb
305 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/railties-3.2.15/lib/rails/paths.rb
306 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/railties-3.2.15/lib/rails/rack.rb
307 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/railties-3.2.15/lib/rails/configuration.rb
308 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/module/attribute_accessors.rb
309 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/multibyte/utils.rb
310 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/multibyte.rb
311 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/string/multibyte.rb
312 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/inflector/transliterate.rb
313 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/string/inflections.rb
314 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/inflector.rb
315 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/module/introspection.rb
316 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/module/delegation.rb
317 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/railties-3.2.15/lib/rails/railtie.rb
318 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/railties-3.2.15/lib/rails/engine/railties.rb
319 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/railties-3.2.15/lib/rails/engine.rb
320 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/time.rb
321 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/base64.rb
322 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/base64.rb
323 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/string/encoding.rb
324 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/object/blank.rb
325 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/xml_mini/rexml.rb
326 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/xml_mini.rb
327 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/array/conversions.rb
328 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/railties-3.2.15/lib/rails/plugin.rb
329 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/railties-3.2.15/lib/rails/application.rb
330 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/railties-3.2.15/lib/rails/version.rb
331 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/file_update_checker.rb
332 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/railties-3.2.15/lib/rails/railtie/configurable.rb
333 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/railties-3.2.15/lib/rails/railtie/configuration.rb
334 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/i18n_railtie.rb
335 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/railtie.rb
336 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/actionpack-3.2.15/lib/action_pack/version.rb
337 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/actionpack-3.2.15/lib/action_pack.rb
338 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/rack-1.4.5/lib/rack.rb
339 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/actionpack-3.2.15/lib/action_dispatch.rb
340 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/actionpack-3.2.15/lib/action_dispatch/railtie.rb
341 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/railties-3.2.15/lib/rails.rb
342 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activemodel-3.2.15/lib/active_model/railtie.rb
343 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/basic_object.rb
344 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/object/acts_like.rb
345 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/duration.rb
346 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/object/try.rb
347 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/values/time_zone.rb
348 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/time_with_zone.rb
349 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/time/zones.rb
350 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/date/zones.rb
351 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/date/calculations.rb
352 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/time/publicize_conversion_methods.rb
353 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/time/conversions.rb
354 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/date_time/calculations.rb
355 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/date_time/conversions.rb
356 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/process/daemon.rb
357 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/time/calculations.rb
358 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/string/conversions.rb
359 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/i18n-0.6.5/lib/i18n/core_ext/string/interpolate.rb
360 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/string/interpolation.rb
361 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/rexml/rexml.rb
362 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/rexml.rb
363 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/file/path.rb
364 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/module/method_names.rb
365 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/ruby/shim.rb
366 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/module/attr_internal.rb
367 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/module/anonymous.rb
368 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/actionpack-3.2.15/lib/abstract_controller.rb
369 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/cgi/util.rb
370 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/erb.rb
371 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/string/output_safety.rb
372 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/actionpack-3.2.15/lib/action_view.rb
373 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/actionpack-3.2.15/lib/action_controller/vendor/html-scanner.rb
374 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/load_error.rb
375 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/name_error.rb
376 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/uri.rb
377 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/actionpack-3.2.15/lib/action_controller.rb
378 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/actionpack-3.2.15/lib/action_view/railtie.rb
379 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/actionpack-3.2.15/lib/abstract_controller/railties/routes_helpers.rb
380 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/actionpack-3.2.15/lib/action_controller/railties/paths.rb
381 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/actionpack-3.2.15/lib/action_controller/railtie.rb
382 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/railtie.rb
383 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/actionmailer-3.2.15/lib/action_mailer/version.rb
384 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/class/delegating_attributes.rb
385 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/module/reachable.rb
386 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/class/subclasses.rb
387 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/class.rb
388 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/array/uniq_by.rb
389 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/actionmailer-3.2.15/lib/action_mailer.rb
390 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/actionmailer-3.2.15/lib/action_mailer/railtie.rb
391 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activeresource-3.2.15/lib/active_resource/exceptions.rb
392 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activeresource-3.2.15/lib/active_resource/version.rb
393 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activeresource-3.2.15/lib/active_resource.rb
394 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activeresource-3.2.15/lib/active_resource/railtie.rb
395 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/actionpack-3.2.15/lib/sprockets/railtie.rb
396 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/benchmarkable.rb
397 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/module/qualified_const.rb
398 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/string/starts_ends_with.rb
399 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/dependencies.rb
400 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/time/marshal.rb
401 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/time/acts_like.rb
402 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/date/acts_like.rb
403 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/date/freeze.rb
404 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/date/conversions.rb
405 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/date_time/acts_like.rb
406 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/date_time/zones.rb
407 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/integer/time.rb
408 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/numeric/time.rb
409 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/time.rb
410 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/hash/deep_merge.rb
411 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/hash_with_indifferent_access.rb
412 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/hash/indifferent_access.rb
413 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/hash/slice.rb
414 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/string/behavior.rb
415 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/object/duplicable.rb
416 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/errors.rb
417 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/log_subscriber.rb
418 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/log_subscriber.rb
419 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/explain_subscriber.rb
420 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/persistence.rb
421 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/hash/except.rb
422 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activemodel-3.2.15/lib/active_model/naming.rb
423 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/query_cache.rb
424 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/querying.rb
425 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/readonly_attributes.rb
426 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/model_schema.rb
427 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activemodel-3.2.15/lib/active_model/translation.rb
428 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/translation.rb
429 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/inheritance.rb
430 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/scoping/default.rb
431 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/array/access.rb
432 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/array/grouping.rb
433 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/array/random_access.rb
434 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/array/prepend_and_append.rb
435 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/array.rb
436 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/scoping/named.rb
437 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/dynamic_matchers.rb
438 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/sanitization.rb
439 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activemodel-3.2.15/lib/active_model/mass_assignment_security/permission_set.rb
440 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activemodel-3.2.15/lib/active_model/mass_assignment_security/sanitizer.rb
441 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activemodel-3.2.15/lib/active_model/mass_assignment_security.rb
442 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/attribute_assignment.rb
443 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activemodel-3.2.15/lib/active_model/conversion.rb
444 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/integration.rb
445 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activemodel-3.2.15/lib/active_model/errors.rb
446 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activemodel-3.2.15/lib/active_model/validations/callbacks.rb
447 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activemodel-3.2.15/lib/active_model/validator.rb
448 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activemodel-3.2.15/lib/active_model/validations/acceptance.rb
449 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activemodel-3.2.15/lib/active_model/validations/confirmation.rb
450 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/range/blockless_step.rb
451 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/range/conversions.rb
452 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/range/include_range.rb
453 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/range/overlaps.rb
454 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/range/cover.rb
455 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/core_ext/range.rb
456 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activemodel-3.2.15/lib/active_model/validations/exclusion.rb
457 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activemodel-3.2.15/lib/active_model/validations/format.rb
458 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activemodel-3.2.15/lib/active_model/validations/inclusion.rb
459 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activemodel-3.2.15/lib/active_model/validations/length.rb
460 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activemodel-3.2.15/lib/active_model/validations/numericality.rb
461 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activemodel-3.2.15/lib/active_model/validations/presence.rb
462 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activemodel-3.2.15/lib/active_model/validations/validates.rb
463 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activemodel-3.2.15/lib/active_model/validations/with.rb
464 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activemodel-3.2.15/lib/active_model/validations.rb
465 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/validations/associated.rb
466 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/validations/uniqueness.rb
467 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/validations.rb
468 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/counter_cache.rb
469 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/locking/optimistic.rb
470 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/locking/pessimistic.rb
471 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/attribute_methods/read.rb
472 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/attribute_methods/write.rb
473 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/attribute_methods/before_type_cast.rb
474 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/attribute_methods/query.rb
475 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/attribute_methods/primary_key.rb
476 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/attribute_methods/time_zone_conversion.rb
477 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activemodel-3.2.15/lib/active_model/dirty.rb
478 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/attribute_methods/dirty.rb
479 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/timestamp.rb
480 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/attribute_methods/serialization.rb
481 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/attribute_methods/deprecated_underscore_read.rb
482 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/callbacks.rb
483 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activemodel-3.2.15/lib/active_model/observer_array.rb
484 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activemodel-3.2.15/lib/active_model/observing.rb
485 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activemodel-3.2.15/lib/active_model/callbacks.rb
486 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/associations.rb
487 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/identity_map.rb
488 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activemodel-3.2.15/lib/active_model/secure_password.rb
489 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/explain.rb
490 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/autosave_association.rb
491 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/nested_attributes.rb
492 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/associations/builder/association.rb
493 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/associations/builder/singular_association.rb
494 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/associations/builder/has_one.rb
495 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/associations/builder/collection_association.rb
496 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/associations/builder/has_many.rb
497 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/associations/builder/belongs_to.rb
498 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/associations/builder/has_and_belongs_to_many.rb
499 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/aggregations.rb
500 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/transactions.rb
501 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-3.2.15/lib/active_record/reflection.rb
502 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/multi_json-1.8.2/lib/multi_json/options.rb
503 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/multi_json-1.8.2/lib/multi_json/version.rb
504 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/multi_json-1.8.2/lib/multi_json/load_error.rb
505 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/multi_json-1.8.2/lib/multi_json.rb
506 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-3.2.15/lib/active_support/json/decoding.rb
507 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/json-1.8.1/lib/json/version.rb
508 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/json-1.8.1/lib/json/generic_object.rb
509 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/json-1.8.1/lib/json/common.rb
510 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/enc/utf_16be.so
511 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/enc/utf_16le.so
512 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/enc/utf_32be.so
513 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/enc/utf_32le.so
514 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/json-1.8.1/lib/json/ext/parser.so
515 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/json-1.8.1/lib/json/ext/generator.so
* Process memory map:
00400000-00401000 r-xp 00000000 fc:00 2230335 /home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/ruby
00600000-00601000 r--p 00000000 fc:00 2230335 /home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/ruby
00601000-00602000 rw-p 00001000 fc:00 2230335 /home/jam/.rvm/rubies/ruby-2.0.0-p247/bin/ruby
00cbb000-02b22000 rw-p 00000000 00:00 0 [heap]
7fd2a3d80000-7fd2a3d95000 r-xp 00000000 fc:00 1572908 /lib/x86_64-linux-gnu/libgcc_s.so.1
7fd2a3d95000-7fd2a3f94000 ---p 00015000 fc:00 1572908 /lib/x86_64-linux-gnu/libgcc_s.so.1
7fd2a3f94000-7fd2a3f95000 r--p 00014000 fc:00 1572908 /lib/x86_64-linux-gnu/libgcc_s.so.1
7fd2a3f95000-7fd2a3f96000 rw-p 00015000 fc:00 1572908 /lib/x86_64-linux-gnu/libgcc_s.so.1
7fd2a3f96000-7fd2a3f9e000 r-xp 00000000 fc:00 2493168 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/json-1.8.1/lib/json/ext/generator.so
7fd2a3f9e000-7fd2a419d000 ---p 00008000 fc:00 2493168 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/json-1.8.1/lib/json/ext/generator.so
7fd2a419d000-7fd2a419e000 r--p 00007000 fc:00 2493168 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/json-1.8.1/lib/json/ext/generator.so
7fd2a419e000-7fd2a419f000 rw-p 00008000 fc:00 2493168 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/json-1.8.1/lib/json/ext/generator.so
7fd2a419f000-7fd2a41a0000 r-xp 00000000 fc:00 2229480 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/enc/utf_32le.so
7fd2a41a0000-7fd2a439f000 ---p 00001000 fc:00 2229480 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/enc/utf_32le.so
7fd2a439f000-7fd2a43a0000 r--p 00000000 fc:00 2229480 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/enc/utf_32le.so
7fd2a43a0000-7fd2a43a1000 rw-p 00001000 fc:00 2229480 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/enc/utf_32le.so
7fd2a43a1000-7fd2a43a2000 r-xp 00000000 fc:00 2229448 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/enc/utf_32be.so
7fd2a43a2000-7fd2a45a1000 ---p 00001000 fc:00 2229448 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/enc/utf_32be.so
7fd2a45a1000-7fd2a45a2000 r--p 00000000 fc:00 2229448 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/enc/utf_32be.so
7fd2a45a2000-7fd2a45a3000 rw-p 00001000 fc:00 2229448 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/enc/utf_32be.so
7fd2a45a3000-7fd2a45a4000 r-xp 00000000 fc:00 2229439 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/enc/utf_16le.so
7fd2a45a4000-7fd2a47a3000 ---p 00001000 fc:00 2229439 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/enc/utf_16le.so
7fd2a47a3000-7fd2a47a4000 r--p 00000000 fc:00 2229439 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/enc/utf_16le.so
7fd2a47a4000-7fd2a47a5000 rw-p 00001000 fc:00 2229439 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/enc/utf_16le.so
7fd2a47a5000-7fd2a47a6000 r-xp 00000000 fc:00 2229440 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/enc/utf_16be.so
7fd2a47a6000-7fd2a49a5000 ---p 00001000 fc:00 2229440 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/enc/utf_16be.so
7fd2a49a5000-7fd2a49a6000 r--p 00000000 fc:00 2229440 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/enc/utf_16be.so
7fd2a49a6000-7fd2a49a7000 rw-p 00001000 fc:00 2229440 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/enc/utf_16be.so
7fd2a49a7000-7fd2a4b97000 r-xp 00000000 fc:00 938271 /usr/lib/libruby-1.9.1.so.1.9.1
7fd2a4b97000-7fd2a4d96000 ---p 001f0000 fc:00 938271 /usr/lib/libruby-1.9.1.so.1.9.1
7fd2a4d96000-7fd2a4d9b000 r--p 001ef000 fc:00 938271 /usr/lib/libruby-1.9.1.so.1.9.1
7fd2a4d9b000-7fd2a4d9f000 rw-p 001f4000 fc:00 938271 /usr/lib/libruby-1.9.1.so.1.9.1
7fd2a4d9f000-7fd2a4dbb000 rw-p 00000000 00:00 0
7fd2a4dbb000-7fd2a4dc1000 r-xp 00000000 fc:00 2493172 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/json-1.8.1/lib/json/ext/parser.so
7fd2a4dc1000-7fd2a4fc0000 ---p 00006000 fc:00 2493172 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/json-1.8.1/lib/json/ext/parser.so
7fd2a4fc0000-7fd2a4fc1000 r--p 00005000 fc:00 2493172 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/json-1.8.1/lib/json/ext/parser.so
7fd2a4fc1000-7fd2a4fc2000 rw-p 00006000 fc:00 2493172 /home/jam/.rvm/gems/ruby-2.0.0-p247/gems/json-1.8.1/lib/json/ext/parser.so
7fd2a4fc2000-7fd2a4fe2000 r-xp 00000000 fc:00 938243 /usr/lib/x86_64-linux-gnu/libyaml-0.so.2.0.2
7fd2a4fe2000-7fd2a51e1000 ---p 00020000 fc:00 938243 /usr/lib/x86_64-linux-gnu/libyaml-0.so.2.0.2
7fd2a51e1000-7fd2a51e2000 r--p 0001f000 fc:00 938243 /usr/lib/x86_64-linux-gnu/libyaml-0.so.2.0.2
7fd2a51e2000-7fd2a51e3000 rw-p 00020000 fc:00 938243 /usr/lib/x86_64-linux-gnu/libyaml-0.so.2.0.2
7fd2a51e3000-7fd2a51e9000 r-xp 00000000 fc:00 2229434 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/psych.so
7fd2a51e9000-7fd2a53e8000 ---p 00006000 fc:00 2229434 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/psych.so
7fd2a53e8000-7fd2a53e9000 r--p 00005000 fc:00 2229434 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/psych.so
7fd2a53e9000-7fd2a53ea000 rw-p 00006000 fc:00 2229434 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/psych.so
7fd2a53ea000-7fd2a541c000 r-xp 00000000 fc:00 2229497 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/date_core.so
7fd2a541c000-7fd2a561c000 ---p 00032000 fc:00 2229497 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/date_core.so
7fd2a561c000-7fd2a561d000 r--p 00032000 fc:00 2229497 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/date_core.so
7fd2a561d000-7fd2a561e000 rw-p 00033000 fc:00 2229497 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/date_core.so
7fd2a561e000-7fd2a5620000 rw-p 00000000 00:00 0
7fd2a5620000-7fd2a5634000 r-xp 00000000 fc:00 2229399 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/bigdecimal.so
7fd2a5634000-7fd2a5833000 ---p 00014000 fc:00 2229399 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/bigdecimal.so
7fd2a5833000-7fd2a5834000 r--p 00013000 fc:00 2229399 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/bigdecimal.so
7fd2a5834000-7fd2a5835000 rw-p 00014000 fc:00 2229399 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/bigdecimal.so
7fd2a5835000-7fd2a583a000 r-xp 00000000 fc:00 2229498 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/strscan.so
7fd2a583a000-7fd2a5a39000 ---p 00005000 fc:00 2229498 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/strscan.so
7fd2a5a39000-7fd2a5a3a000 r--p 00004000 fc:00 2229498 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/strscan.so
7fd2a5a3a000-7fd2a5a3b000 rw-p 00005000 fc:00 2229498 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/strscan.so
7fd2a5a3b000-7fd2a5a42000 r-xp 00000000 fc:00 2229401 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/stringio.so
7fd2a5a42000-7fd2a5c41000 ---p 00007000 fc:00 2229401 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/stringio.so
7fd2a5c41000-7fd2a5c42000 r--p 00006000 fc:00 2229401 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/stringio.so
7fd2a5c42000-7fd2a5c43000 rw-p 00007000 fc:00 2229401 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/stringio.so
7fd2a5c43000-7fd2a5c95000 r-xp 00000000 fc:00 1572880 /lib/x86_64-linux-gnu/libssl.so.1.0.0
7fd2a5c95000-7fd2a5e95000 ---p 00052000 fc:00 1572880 /lib/x86_64-linux-gnu/libssl.so.1.0.0
7fd2a5e95000-7fd2a5e98000 r--p 00052000 fc:00 1572880 /lib/x86_64-linux-gnu/libssl.so.1.0.0
7fd2a5e98000-7fd2a5e9e000 rw-p 00055000 fc:00 1572880 /lib/x86_64-linux-gnu/libssl.so.1.0.0
7fd2a5e9e000-7fd2a5e9f000 rw-p 00000000 00:00 0
7fd2a5e9f000-7fd2a5eed000 r-xp 00000000 fc:00 2229414 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/openssl.so
7fd2a5eed000-7fd2a60ed000 ---p 0004e000 fc:00 2229414 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/openssl.so
7fd2a60ed000-7fd2a60ee000 r--p 0004e000 fc:00 2229414 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/openssl.so
7fd2a60ee000-7fd2a60f0000 rw-p 0004f000 fc:00 2229414 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/openssl.so
7fd2a60f0000-7fd2a60f1000 rw-p 00000000 00:00 0
7fd2a60f1000-7fd2a60f2000 r-xp 00000000 fc:00 2229402 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/fcntl.so
7fd2a60f2000-7fd2a62f1000 ---p 00001000 fc:00 2229402 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/fcntl.so
7fd2a62f1000-7fd2a62f2000 r--p 00000000 fc:00 2229402 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/fcntl.so
7fd2a62f2000-7fd2a62f3000 rw-p 00001000 fc:00 2229402 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/fcntl.so
7fd2a62f3000-7fd2a6316000 r-xp 00000000 fc:00 2229409 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/socket.so
7fd2a6316000-7fd2a6516000 ---p 00023000 fc:00 2229409 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/socket.so
7fd2a6516000-7fd2a6517000 r--p 00023000 fc:00 2229409 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/socket.so
7fd2a6517000-7fd2a6518000 rw-p 00024000 fc:00 2229409 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/socket.so
7fd2a6518000-7fd2a651b000 r-xp 00000000 fc:00 2229502 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/digest.so
7fd2a651b000-7fd2a671a000 ---p 00003000 fc:00 2229502 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/digest.so
7fd2a671a000-7fd2a671b000 r--p 00002000 fc:00 2229502 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/digest.so
7fd2a671b000-7fd2a671c000 rw-p 00003000 fc:00 2229502 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/digest.so
7fd2a671c000-7fd2a6732000 r-xp 00000000 fc:00 1573092 /lib/x86_64-linux-gnu/libz.so.1.2.3.4
7fd2a6732000-7fd2a6931000 ---p 00016000 fc:00 1573092 /lib/x86_64-linux-gnu/libz.so.1.2.3.4
7fd2a6931000-7fd2a6932000 r--p 00015000 fc:00 1573092 /lib/x86_64-linux-gnu/libz.so.1.2.3.4
7fd2a6932000-7fd2a6933000 rw-p 00016000 fc:00 1573092 /lib/x86_64-linux-gnu/libz.so.1.2.3.4
7fd2a6933000-7fd2a6ad2000 r-xp 00000000 fc:00 1572883 /lib/x86_64-linux-gnu/libcrypto.so.1.0.0
7fd2a6ad2000-7fd2a6cd1000 ---p 0019f000 fc:00 1572883 /lib/x86_64-linux-gnu/libcrypto.so.1.0.0
7fd2a6cd1000-7fd2a6cec000 r--p 0019e000 fc:00 1572883 /lib/x86_64-linux-gnu/libcrypto.so.1.0.0
7fd2a6cec000-7fd2a6cf7000 rw-p 001b9000 fc:00 1572883 /lib/x86_64-linux-gnu/libcrypto.so.1.0.0
7fd2a6cf7000-7fd2a6cfb000 rw-p 00000000 00:00 0
7fd2a6cfb000-7fd2a6cfc000 r-xp 00000000 fc:00 2229423 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/digest/sha1.so
7fd2a6cfc000-7fd2a6efb000 ---p 00001000 fc:00 2229423 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/digest/sha1.so
7fd2a6efb000-7fd2a6efc000 r--p 00000000 fc:00 2229423 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/digest/sha1.so
7fd2a6efc000-7fd2a6efd000 rw-p 00001000 fc:00 2229423 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/digest/sha1.so
7fd2a6efd000-7fd2a6f00000 r-xp 00000000 fc:00 2229429 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/etc.so
7fd2a6f00000-7fd2a70ff000 ---p 00003000 fc:00 2229429 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/etc.so
7fd2a70ff000-7fd2a7100000 r--p 00002000 fc:00 2229429 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/etc.so
7fd2a7100000-7fd2a7101000 rw-p 00003000 fc:00 2229429 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/etc.so
7fd2a7101000-7fd2a7108000 r-xp 00000000 fc:00 2229501 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/pathname.so
7fd2a7108000-7fd2a7307000 ---p 00007000 fc:00 2229501 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/pathname.so
7fd2a7307000-7fd2a7308000 r--p 00006000 fc:00 2229501 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/pathname.so
7fd2a7308000-7fd2a7309000 rw-p 00007000 fc:00 2229501 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/pathname.so
7fd2a7309000-7fd2a730b000 r-xp 00000000 fc:00 2229473 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/enc/trans/transdb.so
7fd2a730b000-7fd2a750b000 ---p 00002000 fc:00 2229473 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/enc/trans/transdb.so
7fd2a750b000-7fd2a750c000 r--p 00002000 fc:00 2229473 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/enc/trans/transdb.so
7fd2a750c000-7fd2a750d000 rw-p 00003000 fc:00 2229473 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/enc/trans/transdb.so
7fd2a750d000-7fd2a750f000 r-xp 00000000 fc:00 2229441 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/enc/encdb.so
7fd2a750f000-7fd2a770e000 ---p 00002000 fc:00 2229441 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/enc/encdb.so
7fd2a770e000-7fd2a770f000 r--p 00001000 fc:00 2229441 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/enc/encdb.so
7fd2a770f000-7fd2a7710000 rw-p 00002000 fc:00 2229441 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/x86_64-linux/enc/encdb.so
7fd2a7710000-7fd2a79d9000 r--p 00000000 fc:00 923218 /usr/lib/locale/locale-archive
7fd2a79d9000-7fd2a7ad4000 r-xp 00000000 fc:00 1578039 /lib/x86_64-linux-gnu/libm-2.15.so
7fd2a7ad4000-7fd2a7cd3000 ---p 000fb000 fc:00 1578039 /lib/x86_64-linux-gnu/libm-2.15.so
7fd2a7cd3000-7fd2a7cd4000 r--p 000fa000 fc:00 1578039 /lib/x86_64-linux-gnu/libm-2.15.so
7fd2a7cd4000-7fd2a7cd5000 rw-p 000fb000 fc:00 1578039 /lib/x86_64-linux-gnu/libm-2.15.so
7fd2a7cd5000-7fd2a7cde000 r-xp 00000000 fc:00 1578040 /lib/x86_64-linux-gnu/libcrypt-2.15.so
7fd2a7cde000-7fd2a7ede000 ---p 00009000 fc:00 1578040 /lib/x86_64-linux-gnu/libcrypt-2.15.so
7fd2a7ede000-7fd2a7edf000 r--p 00009000 fc:00 1578040 /lib/x86_64-linux-gnu/libcrypt-2.15.so
7fd2a7edf000-7fd2a7ee0000 rw-p 0000a000 fc:00 1578040 /lib/x86_64-linux-gnu/libcrypt-2.15.so
7fd2a7ee0000-7fd2a7f0e000 rw-p 00000000 00:00 0
7fd2a7f0e000-7fd2a7f10000 r-xp 00000000 fc:00 1578030 /lib/x86_64-linux-gnu/libdl-2.15.so
7fd2a7f10000-7fd2a8110000 ---p 00002000 fc:00 1578030 /lib/x86_64-linux-gnu/libdl-2.15.so
7fd2a8110000-7fd2a8111000 r--p 00002000 fc:00 1578030 /lib/x86_64-linux-gnu/libdl-2.15.so
7fd2a8111000-7fd2a8112000 rw-p 00003000 fc:00 1578030 /lib/x86_64-linux-gnu/libdl-2.15.so
7fd2a8112000-7fd2a8119000 r-xp 00000000 fc:00 1578035 /lib/x86_64-linux-gnu/librt-2.15.so
7fd2a8119000-7fd2a8318000 ---p 00007000 fc:00 1578035 /lib/x86_64-linux-gnu/librt-2.15.so
7fd2a8318000-7fd2a8319000 r--p 00006000 fc:00 1578035 /lib/x86_64-linux-gnu/librt-2.15.so
7fd2a8319000-7fd2a831a000 rw-p 00007000 fc:00 1578035 /lib/x86_64-linux-gnu/librt-2.15.so
7fd2a831a000-7fd2a8332000 r-xp 00000000 fc:00 1578033 /lib/x86_64-linux-gnu/libpthread-2.15.so
7fd2a8332000-7fd2a8531000 ---p 00018000 fc:00 1578033 /lib/x86_64-linux-gnu/libpthread-2.15.so
7fd2a8531000-7fd2a8532000 r--p 00017000 fc:00 1578033 /lib/x86_64-linux-gnu/libpthread-2.15.so
7fd2a8532000-7fd2a8533000 rw-p 00018000 fc:00 1578033 /lib/x86_64-linux-gnu/libpthread-2.15.so
7fd2a8533000-7fd2a8537000 rw-p 00000000 00:00 0
7fd2a8537000-7fd2a86ec000 r-xp 00000000 fc:00 1578031 /lib/x86_64-linux-gnu/libc-2.15.so
7fd2a86ec000-7fd2a88eb000 ---p 001b5000 fc:00 1578031 /lib/x86_64-linux-gnu/libc-2.15.so
7fd2a88eb000-7fd2a88ef000 r--p 001b4000 fc:00 1578031 /lib/x86_64-linux-gnu/libc-2.15.so
7fd2a88ef000-7fd2a88f1000 rw-p 001b8000 fc:00 1578031 /lib/x86_64-linux-gnu/libc-2.15.so
7fd2a88f1000-7fd2a88f6000 rw-p 00000000 00:00 0
7fd2a88f6000-7fd2a8b4a000 r-xp 00000000 fc:00 2229274 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/libruby.so.2.0.0
7fd2a8b4a000-7fd2a8d49000 ---p 00254000 fc:00 2229274 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/libruby.so.2.0.0
7fd2a8d49000-7fd2a8d4e000 r--p 00253000 fc:00 2229274 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/libruby.so.2.0.0
7fd2a8d4e000-7fd2a8d51000 rw-p 00258000 fc:00 2229274 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/libruby.so.2.0.0
7fd2a8d51000-7fd2a8d72000 rw-p 00000000 00:00 0
7fd2a8d72000-7fd2a8d94000 r-xp 00000000 fc:00 1578045 /lib/x86_64-linux-gnu/ld-2.15.so
7fd2a8e6c000-7fd2a8e6d000 r--s 00000000 fc:00 2231868 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/gems/2.0.0/bin/rake
7fd2a8e7f000-7fd2a8f86000 rw-p 00000000 00:00 0
7fd2a8f86000-7fd2a8f87000 r--s 00000000 fc:00 2231868 /home/jam/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/gems/2.0.0/bin/rake
7fd2a8f87000-7fd2a8f8e000 r--s 00000000 fc:00 929597 /usr/lib/x86_64-linux-gnu/gconv/gconv-modules.cache
7fd2a8f8e000-7fd2a8f8f000 ---p 00000000 00:00 0
7fd2a8f8f000-7fd2a8f94000 rw-p 00000000 00:00 0
7fd2a8f94000-7fd2a8f95000 r--p 00022000 fc:00 1578045 /lib/x86_64-linux-gnu/ld-2.15.so
7fd2a8f95000-7fd2a8f97000 rw-p 00023000 fc:00 1578045 /lib/x86_64-linux-gnu/ld-2.15.so
7fff9c15f000-7fff9c1e3000 rw-p 00000000 00:00 0 [stack]
7fff9c1ff000-7fff9c200000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
[NOTE]
You may have encountered a bug in the Ruby interpreter or extension libraries.
Bug reports are welcome.
For details: http://www.ruby-lang.org/bugreport.html
Aborted (core dumped)

View File

@ -0,0 +1,82 @@
require 'spec_helper'
describe ApiAffiliateController do
render_views
let(:partner1) {FactoryGirl.create(:affiliate_partner)}
let(:user_partner1) { partner1.partner_user }
let(:partner2) {FactoryGirl.create(:affiliate_partner)}
let(:user_partner2) { partner2.partner_user }
before(:each) do
controller.current_user = user_partner1
end
describe "traffic_index" do
it "empty" do
get :traffic_index
response.should be_success
JSON.parse(response.body)['traffics'].should eq([])
end
it "single item" do
traffic_total = FactoryGirl.create(:affiliate_traffic_total, affiliate_partner: partner1, visits: 5, signups: 0, day:Date.today)
get :traffic_index
response.should be_success
JSON.parse(response.body)['traffics'].should eq([{"day" => Date.today.to_s, "visits" => 5, "signups" => 0, "affiliate_partner_id" => partner1.id}])
end
end
describe "monthly_index" do
it "empty" do
get :monthly_index
response.should be_success
JSON.parse(response.body)['monthlies'].should eq([])
end
it "single item" do
monthly = FactoryGirl.create(:affiliate_monthly_payment, affiliate_partner: partner1, closed: true, due_amount_in_cents: 20, month: 1, year: 2015)
get :monthly_index
response.should be_success
JSON.parse(response.body)['monthlies'].should eq([{"closed" => true, "month" => 1, "year" => 2015, "due_amount_in_cents" => 20, "affiliate_partner_id" => partner1.id}])
end
end
describe "quarterly_index" do
it "empty" do
get :quarterly_index
response.should be_success
JSON.parse(response.body)['quarterlies'].should eq([])
end
it "single item" do
quarterly = FactoryGirl.create(:affiliate_quarterly_payment, affiliate_partner: partner1, paid: true, closed: true, due_amount_in_cents: 20, quarter: 1, year: 2015)
get :quarterly_index
response.should be_success
JSON.parse(response.body)['quarterlies'].should eq([{"closed" => true, "paid" => true, "quarter" => 1, "year" => 2015, "due_amount_in_cents" => 20, "affiliate_partner_id" => partner1.id}])
end
it "not paid is excluded" do
quarterly = FactoryGirl.create(:affiliate_quarterly_payment, affiliate_partner: partner1, paid: false, closed: true, due_amount_in_cents: 20, quarter: 1, year: 2015)
get :quarterly_index
response.should be_success
JSON.parse(response.body)['quarterlies'].should eq([])
end
it "not closed is excluded" do
quarterly = FactoryGirl.create(:affiliate_quarterly_payment, affiliate_partner: partner1, paid: true, closed: false, due_amount_in_cents: 20, quarter: 1, year: 2015)
get :quarterly_index
response.should be_success
JSON.parse(response.body)['quarterlies'].should eq([])
end
end
end

View File

@ -0,0 +1,106 @@
require 'spec_helper'
describe ApiLinksController do
render_views
let(:partner1) {FactoryGirl.create(:affiliate_partner)}
let(:user_partner1) { partner1.partner_user }
before(:each) do
ClaimedRecording.delete_all
Recording.delete_all
MusicSession.delete_all
JamTrackRight.delete_all
JamTrack.delete_all
controller.current_user = nil
end
describe "jamtrack_song_index" do
it "succeeds with empty data" do
get :jamtrack_song_index, format:'json', affiliate_id: partner1.id
response.status.should eq(200)
body = JSON.parse(response.body)
body.length.should eq(0)
end
it "succeeds with data" do
jam_track = FactoryGirl.create(:jam_track)
get :jamtrack_song_index, format:'json', affiliate_id: partner1.id
response.status.should eq(200)
body = JSON.parse(response.body)
body.length.should eq(1)
body[0]['url'].should_not be_nil
body[0]['target'].should_not be_nil
end
end
describe "jamkazam_general_index" do
it "succeeds" do
get :jamkazam_general_index, format:'json', affiliate_id: partner1.id
response.status.should eq(200)
body = JSON.parse(response.body)
body.length.should eq(3)
end
end
describe "session_index" do
let(:open_params) {
{
name: "session 1",
description: "my session",
genres: ['ambient'],
musician_access: true,
fan_access: true,
approval_required: true,
fan_chat: true,
legal_policy: 'Standard',
language: 'eng',
start: "Thu Jul 10 2020 10:00 PM",
duration: 30,
timezone: "Central Time (US & Canada),America/Chicago",
open_rsvps: true,
legal_terms: true,
recurring_mode: 'once',
isUnstructuredRsvp: true,
rsvp_slots: [{ instrument_id: "other", proficiency_level: 1, approve: true}]
}
}
it "succeeds with no data" do
get :session_index, format:'json', affiliate_id: partner1.id
response.status.should eq(200)
body = JSON.parse(response.body)
body.length.should eq(0)
end
it "succeeds with one scheduled session" do
session = MusicSession.create(user_partner1, open_params)
get :session_index, format:'json', affiliate_id: partner1.id
response.status.should eq(200)
body = JSON.parse(response.body)
body.length.should eq(1)
end
end
describe "recording_index" do
it "succeeds with no data" do
get :recording_index, format:'json', affiliate_id: partner1.id
response.status.should eq(200)
body = JSON.parse(response.body)
body.length.should eq(0)
end
it "succeeds with one recording" do
claimed_recording1 = FactoryGirl.create(:claimed_recording, user: user_partner1)
puts claimed_recording1.inspect
get :recording_index, format:'json', affiliate_id: partner1.id
response.status.should eq(200)
body = JSON.parse(response.body)
body.length.should eq(1)
end
end
end

View File

@ -777,4 +777,37 @@ FactoryGirl.define do
transaction_type JamRuby::RecurlyTransactionWebHook::FAILED_PAYMENT transaction_type JamRuby::RecurlyTransactionWebHook::FAILED_PAYMENT
end end
end end
factory :affiliate_partner, class: 'JamRuby::AffiliatePartner' do
sequence(:partner_name) { |n| "partner-#{n}" }
entity_type 'Individual'
signed_at Time.now
association :partner_user, factory: :user
end
factory :affiliate_quarterly_payment, class: 'JamRuby::AffiliateQuarterlyPayment' do
year 2015
quarter 0
association :affiliate_partner, factory: :affiliate_partner
end
factory :affiliate_monthly_payment, class: 'JamRuby::AffiliateMonthlyPayment' do
year 2015
month 1
association :affiliate_partner, factory: :affiliate_partner
end
factory :affiliate_referral_visit, class: 'JamRuby::AffiliateReferralVisit' do
ip_address '1.1.1.1'
association :affiliate_partner, factory: :affiliate_partner
end
factory :affiliate_traffic_total, class: 'JamRuby::AffiliateTrafficTotal' do
day Date.today
association :affiliate_partner, factory: :affiliate_partner
end
factory :affiliate_legalese, class: 'JamRuby::AffiliateLegalese' do
legalese Faker::Lorem.paragraphs(6).join("\n\n")
end
end end

View File

@ -0,0 +1,152 @@
require 'spec_helper'
describe "Account Affiliate", :js => true, :type => :feature, :capybara_feature => true do
subject { page }
let(:user) {FactoryGirl.create(:user)}
let(:partner) { FactoryGirl.create(:affiliate_partner) }
let(:jam_track) {FactoryGirl.create(:jam_track)}
before(:each) do
JamTrackRight.delete_all
JamTrack.delete_all
AffiliateQuarterlyPayment.delete_all
AffiliateMonthlyPayment.delete_all
AffiliateTrafficTotal.delete_all
UserMailer.deliveries.clear
emulate_client
end
describe "account overview" do
it "shows correct values for partner" do
partner.referral_user_count = 3
partner.cumulative_earnings_in_cents = 10000
partner.save!
sign_in_poltergeist partner.partner_user
visit "/client#/account"
find('.account-mid.affiliate .user-referrals', text: 'You have referred 3 users to date.')
find('.account-mid.affiliate .affiliate-earnings', text: 'You have earned $100.00 to date.')
end
it "shows correct values for unaffiliated user" do
sign_in_poltergeist user
visit "/client#/account"
find('.account-mid.affiliate .not-affiliated', text: 'You are not currently a JamKazam affiliate.')
find('.account-mid.affiliate .learn-affiliate')
end
end
describe "account affiliate page" do
before(:each) do
sign_in_poltergeist partner.partner_user
end
it "works on no data" do
jam_track.touch
visit "/client#/account/affiliatePartner"
find('.tab-account', text: 'So please provide this data, and be sure to keep it current!')
# take a look at the links tab
find('a#affiliate-partner-links-link').trigger(:click)
find('#account-affiliate-partner tr td.target')
# can't find this on the page for some reason:
#jk_select('Custom Link', '#account-affiliate-partner select.link_type')
#find('.link-type-prompt[data-type="custom_links"]')
find('a#affiliate-partner-signups-link').trigger(:click)
find('table.traffic-table')
find('a#affiliate-partner-earnings-link').trigger(:click)
find('table.payment-table')
find('a#affiliate-partner-agreement-link').trigger(:click)
find('h2', text: 'JamKazam Affiliate Agreement')
find('span.c0', text: 'Updated: April 30, 2015')
end
it "shows data" do
visit "/client#/account/affiliatePartner"
find('.tab-account', text: 'So please provide this data, and be sure to keep it current!')
# verify traffic data shows correctly
day1 = Date.parse('2015-04-05')
FactoryGirl.create(:affiliate_traffic_total, affiliate_partner: partner, day: day1, signups: 1, visits:2)
find('a#affiliate-partner-signups-link').trigger(:click)
find('table.traffic-table tr td.day', text: "April 5")
find('table.traffic-table tr td.signups', text: '1')
find('table.traffic-table tr td.visits', text: '2')
find('a#affiliate-partner-earnings-link').trigger(:click)
find('table.payment-table')
day2 = Date.parse('2015-04-07')
FactoryGirl.create(:affiliate_traffic_total, affiliate_partner: partner, day: day2, signups: 3, visits:4)
find('a#affiliate-partner-signups-link').trigger(:click)
find('table.traffic-table tr td.day', text: "April 7")
find('table.traffic-table tr td.signups', text: '3')
find('table.traffic-table tr td.visits', text: '4')
# verify earnings data correctly
FactoryGirl.create(:affiliate_monthly_payment, affiliate_partner:partner, year:2015, month:1, due_amount_in_cents:20, jamtracks_sold: 1, closed:true)
find('a#affiliate-partner-earnings-link').trigger(:click)
find('table.payment-table tr td.month', text: "January 2015")
find('table.payment-table tr td.sales', text: 'JamTracks: 1 unit sold')
find('table.payment-table tr td.earnings', text: '$0.20')
find('a#affiliate-partner-signups-link').trigger(:click)
find('table.traffic-table')
FactoryGirl.create(:affiliate_monthly_payment, affiliate_partner:partner, year:2015, month:2, due_amount_in_cents:40, jamtracks_sold: 2, closed:true)
FactoryGirl.create(:affiliate_monthly_payment, affiliate_partner:partner, year:2015, month:3, due_amount_in_cents:60, jamtracks_sold: 3, closed:true)
quarter1 = FactoryGirl.create(:affiliate_quarterly_payment, affiliate_partner:partner, year:2015, quarter:0, due_amount_in_cents:120, jamtracks_sold: 6, closed:true, paid:false)
FactoryGirl.create(:affiliate_monthly_payment, affiliate_partner:partner, year:2015, month:4, due_amount_in_cents:2000, jamtracks_sold: 100, closed:true)
find('a#affiliate-partner-earnings-link').trigger(:click)
find('table.payment-table tr td.month', text: "January 2015")
find('table.payment-table tr td.sales', text: 'JamTracks: 1 unit sold')
find('table.payment-table tr td.earnings', text: '$0.20')
find('table.payment-table tr td.month', text: "February 2015")
find('table.payment-table tr td.sales', text: 'JamTracks: 2 units sold')
find('table.payment-table tr td.earnings', text: '$0.40')
find('table.payment-table tr td.month', text: "March 2015")
find('table.payment-table tr td.sales', text: 'JamTracks: 3 units sold')
find('table.payment-table tr td.earnings', text: '$0.60')
find('table.payment-table tr td.month', text: "1st Quarter 2015")
find('table.payment-table tr td.earnings', text: 'No earning were paid, as the $10 minimum threshold was not reached.')
find('a#affiliate-partner-signups-link').trigger(:click)
find('table.traffic-table')
quarter1.paid = true
quarter1.save!
FactoryGirl.create(:affiliate_quarterly_payment, affiliate_partner:partner, year:2015, quarter:1, due_amount_in_cents:2000, jamtracks_sold: 100, closed:true, paid:true)
find('a#affiliate-partner-earnings-link').trigger(:click)
find('table.payment-table tr td.month', text: "January 2015")
find('table.payment-table tr td.sales', text: 'JamTracks: 1 unit sold')
find('table.payment-table tr td.earnings', text: '$0.20')
find('table.payment-table tr td.month', text: "February 2015")
find('table.payment-table tr td.sales', text: 'JamTracks: 2 units sold')
find('table.payment-table tr td.earnings', text: '$0.40')
find('table.payment-table tr td.month', text: "March 2015")
find('table.payment-table tr td.sales', text: 'JamTracks: 3 units sold')
find('table.payment-table tr td.earnings', text: '$0.60')
find('table.payment-table tr td.month', text: "1st Quarter 2015")
find('table.payment-table tr td.earnings', text: 'PAID $1.20')
find('table.payment-table tr td.month', text: "2nd Quarter 2015")
find('table.payment-table tr td.earnings', text: 'PAID $20.00')
end
end
end

View File

@ -0,0 +1,90 @@
require 'spec_helper'
describe "Affiliate Program", :js => true, :type => :feature, :capybara_feature => true do
subject { page }
let(:user) { FactoryGirl.create(:user) }
before(:each) do
User.delete_all
AffiliateQuarterlyPayment.delete_all
AffiliateMonthlyPayment.delete_all
AffiliateTrafficTotal.delete_all
AffiliatePartner.delete_all
end
before(:all) do
@old_recaptcha=Rails.application.config.recaptcha_enable
Rails.application.config.recaptcha_enable=false
end
after(:all) do
Rails.application.config.recaptcha_enable=@old_recaptcha
end
describe "Affiliate Program signup page" do
it "logged in user creates affiliate" do
fast_signin user, '/affiliateProgram'
find('input#entity_individual').trigger(:click)
find('.agree-button').trigger(:click)
find('h1', text: 'congratulations')
find('.button-orange', text: 'GO TO AFFILIATE PAGE').trigger(:click)
find('.tab-account', text: 'So please provide this data, and be sure to keep it current!')
partner = AffiliatePartner.first
partner.partner_user.should eq(user)
partner.entity_type.should eq('Individual')
end
it "logged in user creates entity affiliate" do
fast_signin user, '/affiliateProgram'
find('input#entity_entity').trigger(:click)
fill_in('entity-name', with: 'Mr. Bubbles')
select('Sole Proprietor', from:'entity-type')
find('.agree-button').trigger(:click)
find('h1', text: 'congratulations')
find('.button-orange', text: 'GO TO AFFILIATE PAGE').trigger(:click)
find('.tab-account', text: 'So please provide this data, and be sure to keep it current!')
partner = AffiliatePartner.first
partner.partner_user.should eq(user)
partner.entity_type.should eq('Sole Proprietor')
end
it "new user creates individual affiliate" do
visit '/affiliateProgram'
find('input#entity_individual').trigger(:click)
find('.agree-button').trigger(:click)
find('h1', text: 'congratulations')
find('.button-orange', text: 'GO SIGNUP').trigger(:click)
fill_in "jam_ruby_user[first_name]", with: "Affiliate1"
fill_in "jam_ruby_user[last_name]", with: "Someone"
fill_in "jam_ruby_user[email]", with: "affiliate1@jamkazam.com"
fill_in "jam_ruby_user[password]", with: "jam123"
fill_in "jam_ruby_user[password_confirmation]", with: "jam123"
check("jam_ruby_user[instruments][drums][selected]")
check("jam_ruby_user[terms_of_service]")
click_button "CREATE ACCOUNT"
should have_title("JamKazam | Congratulations")
found_user = User.first
partner = AffiliatePartner.first
partner.partner_user.should eq(found_user)
partner.entity_type.should eq('Individual')
end
end
end

View File

@ -0,0 +1,59 @@
require 'spec_helper'
describe "affiliate visit tracking", :js => true, :type => :feature, :capybara_feature => true do
subject { page }
let(:user) { FactoryGirl.create(:user) }
let(:partner) { FactoryGirl.create(:affiliate_partner) }
let(:affiliate_params) { partner.affiliate_query_params }
before(:each) do
AffiliateTrafficTotal.delete_all
AffiliateReferralVisit.delete_all
end
before(:all) do
@old_recaptcha=Rails.application.config.recaptcha_enable
Rails.application.config.recaptcha_enable=false
end
after(:all) do
Rails.application.config.recaptcha_enable=@old_recaptcha
end
# the ways that a user might signup:
# on free jamtrack redemption flow - this is verified in checkout_spec.rb
# via facebook
# /signup
it "verifies that a signup via /signup page, when coming from a referral, attributes partner" do
visit '/?' + affiliate_params
should_be_at_root
AffiliateReferralVisit.count.should eq(1)
visit '/signup'
fill_in "jam_ruby_user[first_name]", with: "Affiliate"
fill_in "jam_ruby_user[last_name]", with: "Referral"
fill_in "jam_ruby_user[email]", with: "referral1@jamkazam.com"
fill_in "jam_ruby_user[password]", with: "jam123"
fill_in "jam_ruby_user[password_confirmation]", with: "jam123"
check("jam_ruby_user[instruments][drums][selected]")
check("jam_ruby_user[terms_of_service]")
click_button "CREATE ACCOUNT"
should have_title("JamKazam | Congratulations")
referral = User.find_by_email('referral1@jamkazam.com')
referral.affiliate_referral.should eq(partner)
AffiliatePartner.tally_up(referral.created_at.to_date + 1)
partner.reload
partner.referral_user_count.should eq(1)
total = AffiliateTrafficTotal.first
total.signups.should eq(1)
end
end

View File

@ -0,0 +1,36 @@
require 'spec_helper'
describe "affiliate visit tracking" do
subject { page }
let(:user) { FactoryGirl.create(:user) }
let(:partner) { FactoryGirl.create(:affiliate_partner) }
let(:affiliate_params) { partner.affiliate_query_params }
before(:each) do
AffiliateReferralVisit.delete_all
end
it "tracks" do
visit '/?' + affiliate_params
should_be_at_root
AffiliateReferralVisit.count.should eq(1)
visit = AffiliateReferralVisit.first
visit.visited_url.should eq('/?' + affiliate_params)
visit.affiliate_partner_id.should eq(partner.id)
visit.first_visit.should be_true
download_url = '/downloads?' + affiliate_params
visit download_url
find('h2.create-account-header')
AffiliateReferralVisit.count.should eq(2)
visit = AffiliateReferralVisit.find_by_visited_url(download_url)
visit.affiliate_partner_id.should eq(partner.id)
visit.first_visit.should be_false
end
end

View File

@ -827,6 +827,123 @@ describe "Checkout", :js => true, :type => :feature, :capybara_feature => true d
end end
it "for anonymous user with referral" do
partner = FactoryGirl.create(:affiliate_partner)
affiliate_params = partner.affiliate_query_params
visit '/landing/jamtracks/acdc-backinblack?' + affiliate_params
find('a.browse-jamtracks').trigger(:click)
find('h1', text: 'jamtracks')
#find('a', text: 'What is a JamTrack?')
find("a.jamtrack-add-cart[data-jamtrack-id=\"#{jamtrack_acdc_backinblack.id}\"]", text: 'GET IT FREE!').trigger(:click)
find('h3', text: 'OR SIGN UP USING YOUR EMAIL')
shopping_carts = ShoppingCart.all
shopping_carts.count.should eq(1)
shopping_cart = shopping_carts[0]
shopping_cart.anonymous_user_id.should_not be_nil
shopping_cart.user_id.should be_nil
fill_in 'first_name', with: 'Seth'
fill_in 'last_name', with: 'Call'
fill_in 'email', with: 'guy_referral@jamkazam.com'
fill_in 'password', with: 'jam123'
find('.right-side .terms_of_service input').trigger(:click) # accept TOS
# try to submit, and see order page
find('.signup-submit').trigger(:click)
find('.jam-tracks-in-browser')
guy = User.find_by_email('guy_referral@jamkazam.com')
guy.affiliate_referral.should eq(partner)
guy.reload
# verify sales data
guy.sales.length.should eq(1)
sale = guy.sales.first
sale.sale_line_items.length.should eq(1)
acdc_sale = sale.sale_line_items[0]
acdc_sale.affiliate_referral.should eq(partner)
acdc_sale.affiliate_refunded.should be_false
acdc_sale.affiliate_refunded_at.should be_nil
acdc_sale.affiliate_referral_fee_in_cents.should eq(0)
# this is a little cheat to make the billing info dropdown already say US
guy.country = 'US'
guy.save!
# now, go back to checkout flow again, and make sure we are told there are no free jam tracks
visit "/client#/jamtrackBrowse"
find("a.jamtrack-add-cart[data-jamtrack-id=\"#{jamtrack_pearljam_evenflow.id}\"]", text: 'ADD TO CART').trigger(:click)
find('h1', text: 'shopping cart')
find('.cart-item-caption', text: "JamTrack: #{jamtrack_pearljam_evenflow.name}")
find('.cart-item-price', text: "$ #{jamtrack_pearljam_evenflow.price}")
find('.shopping-sub-total', text:"Subtotal:$ #{jamtrack_pearljam_evenflow.price}")
# attempt to checkout
find('a.button-orange', text: 'PROCEED TO CHECKOUT').trigger(:click)
# should be at payment page
# this should take us to the payment screen
find('p.payment-prompt')
# 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'
#jk_select('US', '#checkoutPaymentScreen #divBillingCountry #billing-country')
find('#payment-info-next').trigger(:click)
# should be taken straight to order page
# now see order page, and everything should no longer appear free
find('p.order-prompt')
find('.order-items-value.order-total', text:'$1.99')
find('.order-items-value.shipping-handling', text:'$0.00')
find('.order-items-value.sub-total', text:'$1.99')
find('.order-items-value.taxes', text:'$0.16')
find('.order-items-value.grand-total', text:'$2.15')
# 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.jam-tracks-in-browser')
guy.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
jam_track_right = jamtrack_pearljam_evenflow.right_for_user(guy)
# make sure it appears the user actually bought the jamtrack!
jam_track_right.should_not be_nil
jam_track_right.redeemed.should be_false
guy.has_redeemable_jamtrack.should be_false
# verify sales data
guy.sales.length.should eq(2)
sale = guy.sales.last
sale.sale_line_items.length.should eq(1)
acdc_sale = SaleLineItem.find_by_recurly_adjustment_uuid(jam_track_right.recurly_adjustment_uuid)
acdc_sale.affiliate_referral.should eq(partner)
acdc_sale.affiliate_refunded.should be_false
acdc_sale.affiliate_refunded_at.should be_nil
acdc_sale.affiliate_referral_fee_in_cents.should eq(20)
end
it "for existing user with a freebie available (already logged in)" do it "for existing user with a freebie available (already logged in)" do

View File

@ -182,9 +182,7 @@ describe UserManager do
describe "signup" do describe "signup" do
let!(:user) { FactoryGirl.create(:user) } let!(:user) { FactoryGirl.create(:user) }
let!(:partner) { let!(:partner) {
AffiliatePartner.create_with_params({:partner_name => Faker::Company.name, AffiliatePartner.create_with_web_params(user, {:partner_name => Faker::Company.name, entity_type:'Individual'})
:partner_code => Faker::Lorem.words(1)[0],
:user_email => user.email})
} }
it "signup successfully" do it "signup successfully" do
@ -200,7 +198,7 @@ describe UserManager do
instruments: @instruments, instruments: @instruments,
musician:true, musician:true,
signup_confirm_url: "http://localhost:3000/confirm", signup_confirm_url: "http://localhost:3000/confirm",
affiliate_referral_id: AffiliatePartner.coded_id(partner.partner_code)) affiliate_referral_id: partner.id)
user.errors.any?.should be_false user.errors.any?.should be_false
user.first_name.should == "bob" user.first_name.should == "bob"

View File

@ -6,9 +6,7 @@ describe "Affiliate Reports", :type => :api do
let!(:user) { FactoryGirl.create(:user) } let!(:user) { FactoryGirl.create(:user) }
let!(:partner) { let!(:partner) {
AffiliatePartner.create_with_params({:partner_name => Faker::Company.name, AffiliatePartner.create_with_web_params(user, {:partner_name => Faker::Company.name, entity_type:'Individual'})
:partner_code => Faker::Lorem.words[0],
:user_email => user.email})
} }
it "valid score" do it "valid score" do