Update Affliate Code and Reports to 2021 spec
Add support to account for subscriptions Change rate to 30%. JamTracks 25cents Reports updated for end users and admin
This commit is contained in:
parent
c07e799fdb
commit
cf47777115
File diff suppressed because one or more lines are too long
|
|
@ -72,6 +72,7 @@ gem 'jquery-ui-rails'# , '5.0.5' #, '4.2.1'
|
|||
gem 'jquery-rails'# , '4.1.1' # both this and jquery-ui-rails are pinned; if you unpin, jquery/autocomplete is missing during precomplie
|
||||
gem 'rails-jquery-autocomplete' # This is the maintained version of rails3-jquery-autocomplete
|
||||
gem 'activeadmin' #, '1.0.0.pre4'# github: 'activeadmin', branch: 'master'
|
||||
gem 'activeadmin-searchable_select'
|
||||
gem 'mime-types', '1.25'
|
||||
#gem 'meta_search'
|
||||
gem 'fog'
|
||||
|
|
|
|||
|
|
@ -47,6 +47,10 @@ GEM
|
|||
ransack (>= 1.8.7)
|
||||
sass (~> 3.1)
|
||||
sprockets (< 4.1)
|
||||
activeadmin-searchable_select (1.4.0)
|
||||
activeadmin (>= 1.x, < 3)
|
||||
jquery-rails (>= 3.0, < 5)
|
||||
select2-rails (~> 4.0)
|
||||
activeadmin_addons (1.7.1)
|
||||
active_material
|
||||
railties
|
||||
|
|
@ -695,6 +699,7 @@ PLATFORMS
|
|||
DEPENDENCIES
|
||||
aasm
|
||||
activeadmin
|
||||
activeadmin-searchable_select
|
||||
activeadmin_addons
|
||||
amqp (= 0.9.8)
|
||||
auto_strip_attributes (= 2.6.0)
|
||||
|
|
@ -788,7 +793,7 @@ DEPENDENCIES
|
|||
zip-codes
|
||||
|
||||
RUBY VERSION
|
||||
ruby 2.3.1p112
|
||||
ruby 2.4.1p111
|
||||
|
||||
BUNDLED WITH
|
||||
1.17.3
|
||||
|
|
|
|||
|
|
@ -0,0 +1,108 @@
|
|||
class AffiliateCohortsHelper
|
||||
def self.percentage(opTop, opBottom)
|
||||
"#{(opTop/opBottom * 100).round(1)}%"
|
||||
end
|
||||
|
||||
def self.quarter(date)
|
||||
case date.month
|
||||
when 1, 2, 3 then 0
|
||||
when 4, 5, 6 then 1
|
||||
when 7, 8, 9 then 2
|
||||
when 10, 11, 12 then 3
|
||||
end
|
||||
end
|
||||
|
||||
def self.payments_for_months(affiliate_partner, year, start_month, end_month)
|
||||
JamRuby::AffiliateMonthlyPayment.where(
|
||||
"affiliate_partner_id = ? AND month >= ? AND month <= ? AND year = ?",
|
||||
affiliate_partner.id,
|
||||
start_month,
|
||||
end_month,
|
||||
year
|
||||
).order('month DESC')
|
||||
end
|
||||
|
||||
def self.payments_for_quarter(affiliate_partner, year, quarter)
|
||||
JamRuby::AffiliateQuarterlyPayment.where(
|
||||
"affiliate_partner_id = ? AND quarter = ? AND year = ?",
|
||||
affiliate_partner.id,
|
||||
quarter,
|
||||
year
|
||||
).order('quarter DESC')
|
||||
end
|
||||
|
||||
def self.all_time_payments(affiliate_partner)
|
||||
JamRuby::AffiliateQuarterlyPayment.where(
|
||||
"affiliate_partner_id = ?", affiliate_partner.id
|
||||
)
|
||||
end
|
||||
|
||||
def self.current_quarter_payments(affiliate_partner)
|
||||
AffiliateCohortsHelper.payments_for_quarter(affiliate_partner,
|
||||
Date.today.year,
|
||||
AffiliateCohortsHelper.quarter(Date.today)
|
||||
)
|
||||
end
|
||||
|
||||
def self.current_quarter_monthly_payments(affiliate_partner)
|
||||
AffiliateCohortsHelper.payments_for_months(affiliate_partner,
|
||||
Date.today.beginning_of_quarter.year,
|
||||
Date.today.beginning_of_quarter.month,
|
||||
Date.today.end_of_quarter.month
|
||||
)
|
||||
end
|
||||
|
||||
def self.prior_quarter_payments(affiliate_partner)
|
||||
prev_quarter_start = (Date.today.beginning_of_quarter - 1.day).beginning_of_quarter
|
||||
prev_quarter = AffiliateCohortsHelper.quarter(prev_quarter_start)
|
||||
AffiliateCohortsHelper.payments_for_quarter(affiliate_partner,
|
||||
prev_quarter_start.year,
|
||||
prev_quarter
|
||||
)
|
||||
end
|
||||
|
||||
def self.prior_quarter_payable_amount(affiliate_partner)
|
||||
total = AffiliateCohortsHelper.prior_quarter_payments(affiliate_partner).inject(0.0){ | sum, payment |
|
||||
sum += payment.due_amount_in_cents }
|
||||
paid = AffiliateCohortsHelper.prior_quarter_payments(affiliate_partner).where(paid: false).inject(0.0){ | sum, payment |
|
||||
sum += payment.due_amount_in_cents }
|
||||
(total - paid) / 100.0
|
||||
end
|
||||
end
|
||||
|
||||
ActiveAdmin.register_page "Affiliate Cohorts" do
|
||||
menu parent: 'Reports'
|
||||
|
||||
content :title => "Affiliate Cohorts" do
|
||||
table_for AffiliatePartner.includes(:partner_user).all do
|
||||
column 'Affiliate Name' do |partner|
|
||||
link_to partner.partner_name, admin_affiliate_path(partner)
|
||||
end
|
||||
column 'Affiliate ID', :id
|
||||
column 'Affiliate Email', Proc.new{ | partner | partner.partner_user.email}
|
||||
column 'Affiliate Paypal', Proc.new{| partner | partner&.paypal_id }
|
||||
column 'All Time Users', :referral_user_count
|
||||
column 'All Time Subscribers', Proc.new{ | partner | partner.subscribed_user_referrals.size }
|
||||
column 'All Time Subscriber Conversion Rate', Proc.new{ | partner |
|
||||
AffiliateCohortsHelper.percentage(partner.subscribed_user_referrals.size.to_f, partner.referral_user_count.to_f) }
|
||||
column 'All Time Revenues', Proc.new{ | partner |
|
||||
number_to_currency(AffiliateCohortsHelper.all_time_payments(partner).inject(0.0){ | sum, payment | sum += payment.due_amount_in_cents } / 100.0)
|
||||
}
|
||||
column 'Current Quarter Revenues', Proc.new{ | partner |
|
||||
number_to_currency(AffiliateCohortsHelper.current_quarter_payments(partner).inject(0.0){ | sum, payment | sum += payment.due_amount_in_cents } / 100.0 )
|
||||
}
|
||||
column 'Current Quarter Revenues by Month', Proc.new{ | partner |
|
||||
AffiliateCohortsHelper.current_quarter_monthly_payments(partner).each do |monthly_payment|
|
||||
li "#{Date::MONTHNAMES[monthly_payment.month]} #{monthly_payment.year} - #{number_to_currency(monthly_payment.due_amount_in_cents.to_f / 100.0)}"
|
||||
end
|
||||
''.html_safe
|
||||
}
|
||||
column 'Prior Quarter Revenues', Proc.new{ | partner |
|
||||
number_to_currency(AffiliateCohortsHelper.prior_quarter_payments(partner).inject(0.0){ | sum, payment | sum += payment.due_amount_in_cents } / 100.0)
|
||||
}
|
||||
column 'Prior Quarter Payable', Proc.new{ | partner |
|
||||
number_to_currency(AffiliateCohortsHelper.prior_quarter_payable_amount(partner))
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
ActiveAdmin.register JamRuby::AffiliateLink, :as => 'Affiliate Links' do
|
||||
|
||||
menu :label => 'Links', :parent => 'Affiliates'
|
||||
|
||||
config.sort_order = 'created_at ASC'
|
||||
config.batch_actions = false
|
||||
# config.clear_action_items!
|
||||
config.filters = false
|
||||
config.per_page = 50
|
||||
config.paginate = true
|
||||
|
||||
#form :partial => 'form'
|
||||
|
||||
|
||||
form do |f|
|
||||
f.inputs 'Fields' do
|
||||
f.input(:name, :input_html => { :maxlength => 255 })
|
||||
f.input(:link, :input_html => { :maxlength => 255 })
|
||||
end
|
||||
f.actions
|
||||
end
|
||||
|
||||
index do
|
||||
|
||||
column 'Name' do |oo|
|
||||
oo.name
|
||||
end
|
||||
column 'Link' do |oo|
|
||||
oo.link
|
||||
end
|
||||
actions
|
||||
end
|
||||
end
|
||||
|
|
@ -9,22 +9,51 @@ ActiveAdmin.register JamRuby::AffiliatePartner, :as => 'Affiliates' do
|
|||
config.per_page = 50
|
||||
config.paginate = true
|
||||
|
||||
form :partial => 'form'
|
||||
#form :partial => 'form'
|
||||
|
||||
scope("Active", default: true) { |scope| scope.where('partner_user_id IS NOT NULL').order('referral_user_count desc') }
|
||||
scope("Unpaid") { |partner| partner.unpaid }
|
||||
|
||||
controller do
|
||||
helper 'active_admin/subscription'
|
||||
end
|
||||
|
||||
form do |f|
|
||||
f.inputs 'Fields' do
|
||||
f.input(:partner_name, :input_html => { :maxlength => 128 })
|
||||
f.input(:partner_user, as: :searchable_select, hint: 'This person is the owner of the affiliate. Has access to reporting info in account section of www.jamkazam.com')
|
||||
f.input(:entity_type, :as => :select, :collection => AffiliatePartner::ENTITY_TYPES)
|
||||
f.input(:rate)
|
||||
f.input(:paypal_id)
|
||||
end
|
||||
f.actions
|
||||
end
|
||||
|
||||
index do
|
||||
|
||||
# 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 '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 '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 '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 '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 '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
|
||||
|
|
@ -32,6 +61,22 @@ ActiveAdmin.register JamRuby::AffiliatePartner, :as => 'Affiliates' do
|
|||
actions
|
||||
end
|
||||
|
||||
show do |affiliate_partner|
|
||||
|
||||
attributes_table do
|
||||
row :id
|
||||
row :partner_name
|
||||
row :entity_type
|
||||
row :rate
|
||||
row :address
|
||||
row :tax_identifier
|
||||
row :paypal_id
|
||||
end
|
||||
|
||||
|
||||
render 'earnings', { affiliate_partner: affiliate_partner }
|
||||
|
||||
end
|
||||
|
||||
action_item :only => [:show] do
|
||||
link_to("Mark Paid",
|
||||
|
|
|
|||
|
|
@ -1,5 +1,11 @@
|
|||
ActiveAdmin.register JamRuby::User, :as => 'Users' do
|
||||
|
||||
searchable_select_options(scope: User.all,
|
||||
text_attribute: :username,
|
||||
filter: lambda do |term, scope|
|
||||
scope.ransack(full_name_or_email_cont: term).result
|
||||
end)
|
||||
|
||||
collection_action :autocomplete_user_email, :method => :get
|
||||
|
||||
actions :all, :except => [:destroy]
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
// require jquery.ui.autocomplete
|
||||
//= require cocoon
|
||||
//= require active_admin/base
|
||||
//= require active_admin/searchable_select
|
||||
// //= require autocomplete-rails
|
||||
//= require base
|
||||
//= require_tree .
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
// Active Admin's got SASS!
|
||||
@import "active_admin/mixins";
|
||||
@import "active_admin/base";
|
||||
@import "active_admin/searchable_select";
|
||||
|
||||
// Overriding any non-variable SASS must be done after the fact.
|
||||
// For example, to change the default status-tag color:
|
||||
|
|
|
|||
|
|
@ -0,0 +1,20 @@
|
|||
module ActiveAdmin
|
||||
module SubscriptionHelper
|
||||
def subscription_plan_name(code)
|
||||
case code
|
||||
when 'jamrubysilver'
|
||||
'Silver'
|
||||
when 'jamrubygold'
|
||||
'Gold'
|
||||
when 'jamrubyplatinum'
|
||||
'Platinum'
|
||||
when 'jamsubgoldyearly'
|
||||
'Gold Yearly'
|
||||
when 'jamsubsilveryearly'
|
||||
'Silver Yearly'
|
||||
when 'jamsubplatinumyearly'
|
||||
'Platinum Yearly'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -39,5 +39,4 @@ module ApplicationHelper
|
|||
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,42 @@
|
|||
<h3>Earnings by Month</h3>
|
||||
<table class="index_table index">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Month</th>
|
||||
<th>JamTracks</th>
|
||||
<th>Subscriptions</th>
|
||||
<th>Affiliate Earnings</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<% AffiliateMonthlyPayment.index(affiliate_partner.partner_user, {})[0].each do |payment| %>
|
||||
<tr>
|
||||
<td>
|
||||
<%= Date::MONTHNAMES[payment.month] if payment.month %>
|
||||
<%= payment.year %>
|
||||
</td>
|
||||
<td>
|
||||
<% if payment.jamtracks_sold > 0 %>
|
||||
JamTracks: <%= pluralize payment.jamtracks_sold, 'unit' %>
|
||||
<% end %>
|
||||
</td>
|
||||
<td>
|
||||
<%
|
||||
month_start = Date.new(payment.year, payment.month, 1)
|
||||
month_end = Date.new(payment.year, payment.month, 1).end_of_month
|
||||
AffiliateDistribution.subscription_plans_count(affiliate_partner.id, month_start, month_end).each do |plan_count|
|
||||
%>
|
||||
<div>
|
||||
<%= subscription_plan_name(plan_count[:plan]) -%>: <%= pluralize(plan_count.count, 'unit') -%> sold
|
||||
</div>
|
||||
<%
|
||||
end
|
||||
%>
|
||||
</td>
|
||||
<td>
|
||||
<%= number_to_currency(payment.due_amount_in_cents.to_f/100.0) %>
|
||||
</td>
|
||||
</tr>
|
||||
<% end %>
|
||||
</tbody>
|
||||
</table>
|
||||
|
|
@ -2,6 +2,7 @@
|
|||
<%= f.semantic_errors *f.object.errors.keys %>
|
||||
<%= f.inputs do %>
|
||||
<%= f.input(:partner_name, :input_html => {:maxlength => 128}) %>
|
||||
<%= f.input(:partner_user, as: :searchable_select, ajax: true, hint: 'The user that manages/owns this affiliate. They can see affiliate reports') %>
|
||||
<%= f.input(:entity_type, :as => :select, :collection => AffiliatePartner::ENTITY_TYPES) %>
|
||||
<%= f.input(:rate) %>
|
||||
<% end %>
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ gem 'fog-brightbox', '0.11.0' # pinned until we are on ruby 2.5; then remove
|
|||
gem 'faraday', '0.9.2' # pinned untnil we are on ruby 2.5; then remove
|
||||
gem 'ruby-prof', '0.15.9' # pinned until we are on ruby 2.5; then remove
|
||||
gem 'rubyzip', '1.2.0' # pinned until we are on ruby 2.5; then remove
|
||||
gem 'recurly', '2.7.0' # should upgrade to 3.x when we have time to validaate
|
||||
gem 'recurly', '2.18.16' # should upgrade to 3.x when we have time to validaate
|
||||
gem 'icalendar', '2.4.0' # pinned until we are on ruby 2.5; then remove
|
||||
gem 'email_validator', '1.6.0' # pinned until we are on ruby 2.5, then remove
|
||||
gem 'redis', '3.3.0' # pinned until we are on 2.5; then remove
|
||||
|
|
@ -103,6 +103,7 @@ group :test do
|
|||
gem 'time_difference'
|
||||
# gem 'byebug'
|
||||
gem 'stripe-ruby-mock'
|
||||
gem 'webmock', '~> 3.11', '>= 3.11.2'
|
||||
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -51,6 +51,8 @@ GEM
|
|||
minitest (~> 5.1)
|
||||
thread_safe (~> 0.3, >= 0.3.4)
|
||||
tzinfo (~> 1.1)
|
||||
addressable (2.7.0)
|
||||
public_suffix (>= 2.0.2, < 5.0)
|
||||
aliyun-sdk (0.8.0)
|
||||
nokogiri (~> 1.6)
|
||||
rest-client (~> 2.0)
|
||||
|
|
@ -80,6 +82,8 @@ GEM
|
|||
json (>= 1.7)
|
||||
coderay (1.1.3)
|
||||
concurrent-ruby (1.1.8)
|
||||
crack (0.4.5)
|
||||
rexml
|
||||
crass (1.0.6)
|
||||
dante (0.2.0)
|
||||
database_cleaner (1.4.1)
|
||||
|
|
@ -272,6 +276,7 @@ GEM
|
|||
rails (>= 3.0)
|
||||
globalid (0.4.2)
|
||||
activesupport (>= 4.2.0)
|
||||
hashdiff (1.0.1)
|
||||
http-accept (1.7.0)
|
||||
http-cookie (1.0.3)
|
||||
domain_name (~> 0.5)
|
||||
|
|
@ -330,6 +335,7 @@ GEM
|
|||
pry (0.13.1)
|
||||
coderay (~> 1.1)
|
||||
method_source (~> 1.0)
|
||||
public_suffix (4.0.6)
|
||||
raabro (1.4.0)
|
||||
rack (1.6.13)
|
||||
rack-protection (1.5.5)
|
||||
|
|
@ -368,7 +374,7 @@ GEM
|
|||
json (>= 1.8)
|
||||
nokogiri (~> 1.5)
|
||||
optimist (~> 3.0)
|
||||
recurly (2.7.0)
|
||||
recurly (2.18.16)
|
||||
redis (3.3.0)
|
||||
redis-namespace (1.5.2)
|
||||
redis (~> 3.0, >= 3.0.4)
|
||||
|
|
@ -405,6 +411,7 @@ GEM
|
|||
http-cookie (>= 1.0.2, < 2.0)
|
||||
mime-types (>= 1.16, < 4.0)
|
||||
netrc (~> 0.8)
|
||||
rexml (3.2.4)
|
||||
rspec (2.11.0)
|
||||
rspec-core (~> 2.11.0)
|
||||
rspec-expectations (~> 2.11.0)
|
||||
|
|
@ -468,6 +475,10 @@ GEM
|
|||
rack (>= 1.0.0)
|
||||
warden (1.2.7)
|
||||
rack (>= 1.0)
|
||||
webmock (3.11.2)
|
||||
addressable (>= 2.3.6)
|
||||
crack (>= 0.3.2)
|
||||
hashdiff (>= 0.4.0, < 2.0.0)
|
||||
will_paginate (3.3.0)
|
||||
xml-simple (1.1.8)
|
||||
xmlrpc (0.3.1)
|
||||
|
|
@ -516,7 +527,7 @@ DEPENDENCIES
|
|||
pry
|
||||
rails-observers (= 0.1.2)
|
||||
railties (= 4.2.8)
|
||||
recurly (= 2.7.0)
|
||||
recurly (= 2.18.16)
|
||||
redis (= 3.3.0)
|
||||
redis-namespace (= 1.5.2)
|
||||
resque
|
||||
|
|
@ -543,11 +554,12 @@ DEPENDENCIES
|
|||
time_difference
|
||||
timecop
|
||||
uuidtools (= 2.1.2)
|
||||
webmock (~> 3.11, >= 3.11.2)
|
||||
will_paginate
|
||||
zip-codes
|
||||
|
||||
RUBY VERSION
|
||||
ruby 2.4.1p111
|
||||
ruby 2.3.1p112
|
||||
|
||||
BUNDLED WITH
|
||||
1.17.3
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
class CreateInitStructure < ActiveRecord::Migration
|
||||
def up
|
||||
# this can't apply in production or staging, -- and schema.rb captures this test/dev environments
|
||||
return if ENV['RAILS_ENV'] == 'production'
|
||||
|
||||
ActiveRecord::Base.connection.execute(IO.read(File.expand_path("../../init_db.sql", __FILE__)))
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,18 @@
|
|||
class PayPalFieldForAffiliate < ActiveRecord::Migration
|
||||
def self.up
|
||||
execute "ALTER TABLE affiliate_partners ADD COLUMN paypal_id VARCHAR(255)"
|
||||
execute %(
|
||||
CREATE TABLE affiliate_links (
|
||||
id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||
name VARCHAR(255) NOT NULL,
|
||||
link VARCHAR(1024) NOT NULL,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
)
|
||||
)
|
||||
end
|
||||
def self.down
|
||||
execute "DROP TABLE affiliate_links"
|
||||
execute "ALTER TABLE affiliate_partners DROP COLUMN paypal_id"
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
class ChangeAffiliateDistributionsSaleLineItemIdNotNull < ActiveRecord::Migration
|
||||
def self.up
|
||||
#change_column_null :affiliate_distributions, :sale_line_item_id, true
|
||||
execute "ALTER TABLE affiliate_distributions ALTER COLUMN sale_line_item_id DROP NOT NULL"
|
||||
end
|
||||
|
||||
def self.down
|
||||
#change_column_null :affiliate_distributions, :sale_line_item_id, false
|
||||
execute "ALTER TABLE affiliate_distributions ALTER COLUMN sale_line_item_id SET NOT NULL"
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
class AddRecurlyTransactionsLastSyncAtToGenericState < ActiveRecord::Migration
|
||||
|
||||
def self.up
|
||||
#add_column :generic_state, :recurly_transactions_last_sync_at, :datetime
|
||||
execute "ALTER TABLE generic_state ADD COLUMN recurly_transactions_last_sync_at TIMESTAMP"
|
||||
end
|
||||
|
||||
def self.down
|
||||
#remove_column :generic_state, :recurly_transactions_last_sync_at, :datetime
|
||||
execute "ALTER TABLE generic_state REMOVE COLUMN recurly_transactions_last_sync_at"
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
class AddProductTypeToAffiliateDistributions < ActiveRecord::Migration
|
||||
|
||||
def self.up
|
||||
execute("ALTER TABLE affiliate_distributions ADD COLUMN product_type VARCHAR(64)")
|
||||
end
|
||||
|
||||
def self.down
|
||||
execute("ALTER TABLE affiliate_distributions REMOVE COLUMN product_type")
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
class SetDefaultForAffiliateDistributionsProductType < ActiveRecord::Migration
|
||||
|
||||
def self.up
|
||||
execute("UPDATE affiliate_distributions SET product_type = 'JamTrack'")
|
||||
execute("ALTER TABLE affiliate_distributions ALTER COLUMN product_type SET DEFAULT 'JamTrack'")
|
||||
end
|
||||
|
||||
def self.down
|
||||
execute("ALTER TABLE affiliate_distributions ALTER COLUMN DROP DEFAULT")
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
class AddProductCodeToAffiliateDistributions < ActiveRecord::Migration
|
||||
def self.up
|
||||
execute("ALTER TABLE affiliate_distributions ADD COLUMN product_code VARCHAR(64)")
|
||||
end
|
||||
|
||||
def self.down
|
||||
execute("ALTER TABLE affiliate_distributions DROP COLUMN IF EXISTS product_code")
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
class JamTrackShareInCentsToAffiliatePartners < ActiveRecord::Migration
|
||||
|
||||
def self.up
|
||||
execute("ALTER TABLE affiliate_partners ADD COLUMN jamtrack_share_in_cents NUMERIC(8,2)")
|
||||
end
|
||||
|
||||
def self.down
|
||||
execute("ALTER TABLE affiliate_partners DROP COLUMN IF EXISTS jamtrack_share_in_cents")
|
||||
end
|
||||
|
||||
end
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
class SetDefaultValuesOfJamTrackShareInCents < ActiveRecord::Migration
|
||||
|
||||
def self.up
|
||||
execute("UPDATE affiliate_partners SET jamtrack_share_in_cents = 25")
|
||||
execute("ALTER TABLE affiliate_partners ALTER COLUMN jamtrack_share_in_cents SET DEFAULT 25")
|
||||
end
|
||||
|
||||
def self.down
|
||||
execute("ALTER TABLE affiliate_partners ALTER COLUMN DROP DEFAULT")
|
||||
end
|
||||
|
||||
end
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
class AddFirstSubscribedAtToUsers < ActiveRecord::Migration
|
||||
|
||||
def self.up
|
||||
execute("ALTER TABLE users ADD COLUMN first_subscribed_at TIMESTAMP WITHOUT TIME ZONE")
|
||||
execute("UPDATE users SET first_subscribed_at = NOW() WHERE recurly_subscription_id IS NOT NULL")
|
||||
end
|
||||
|
||||
def self.down
|
||||
execute("ALTER TABLE users DROP COLUMN first_subscribed_at")
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
class AddExternalIdToAffiliateDistributions < ActiveRecord::Migration
|
||||
|
||||
def self.up
|
||||
execute("ALTER TABLE affiliate_distributions ADD COLUMN external_id character varying(64)")
|
||||
execute("ALTER TABLE affiliate_distributions ADD CONSTRAINT affiliate_distributions_external_id_key UNIQUE (external_id)")
|
||||
end
|
||||
|
||||
def self.down
|
||||
execute("ALTER TABLE affiliate_distributions DROP CONSTRAINT affiliate_distributions_external_id_key")
|
||||
execute("ALTER TABLE affiliate_distributions DROP COLUMN external_id")
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
class ChangeAffiliatePartnersRateDefault < ActiveRecord::Migration
|
||||
def self.up
|
||||
execute("ALTER TABLE affiliate_partners ALTER COLUMN rate SET DEFAULT 0.30")
|
||||
end
|
||||
|
||||
def self.down
|
||||
execute("ALTER TABLE affiliate_partners ALTER COLUMN rate SET DEFAULT 0.10")
|
||||
end
|
||||
end
|
||||
|
|
@ -260,6 +260,7 @@ 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/affiliate_link"
|
||||
require "jam_ruby/models/chat_message"
|
||||
require "jam_ruby/models/shopping_cart"
|
||||
require "jam_ruby/models/generic_state"
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ case JamRuby::Environment.mode
|
|||
Recurly.api_key = "7d623daabfc2434fa2a893bb008eb3e6"
|
||||
Recurly.subdomain = 'jamkazam-development'
|
||||
else
|
||||
Recurly.api_key = "4631527f203b41848523125b3ae51341"
|
||||
Recurly.api_key = "1d0f1bdd30fe403cb78a0663d0915e81"
|
||||
Recurly.subdomain = 'jamkazam-test'
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -15,5 +15,18 @@ module JamRuby
|
|||
distribution.sale_line_item = sale_line_item
|
||||
distribution
|
||||
end
|
||||
|
||||
def self.subscription_plans_count(affiliate_referral_id, start_at, end_at)
|
||||
AffiliateDistribution.where(
|
||||
affiliate_referral_id: affiliate_referral_id,
|
||||
product_type: 'Subscription').where("
|
||||
DATE(affiliate_distributions.created_at) >= ?", start_at).where("
|
||||
DATE(affiliate_distributions.created_at) <= ?", end_at).group_by(&:product_code).map do |product_code, distributions|
|
||||
{
|
||||
plan: product_code,
|
||||
count: distributions.size
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,7 @@
|
|||
class JamRuby::AffiliateLink < ActiveRecord::Base
|
||||
|
||||
attr_accessible :link, :name, as: :admin
|
||||
|
||||
validates :link, presence: true, length: {maximum: 1000}
|
||||
validates :name, presence: true, length: {maximum: 255}
|
||||
end
|
||||
|
|
@ -25,7 +25,7 @@ class JamRuby::AffiliateMonthlyPayment < ActiveRecord::Base
|
|||
query = AffiliateMonthlyPayment
|
||||
.paginate(page: page, per_page: per_page)
|
||||
.where(affiliate_partner_id: user.affiliate_partner.id)
|
||||
.order('year ASC, month ASC')
|
||||
.order('year DESC, month DESC')
|
||||
|
||||
if query.length == 0
|
||||
[query, nil]
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ class JamRuby::AffiliatePartner < ActiveRecord::Base
|
|||
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
|
||||
has_many :affiliate_distributions, :class_name => "JamRuby::AffiliateDistribution", foreign_key: :affiliate_referral_id
|
||||
has_many :links, :class_name => "JamRuby::AffiliateLink", foreign_key: :affiliate_partner_id
|
||||
attr_accessible :partner_name, :partner_code, :partner_user_id, :entity_type, :rate, as: :admin
|
||||
|
||||
ENTITY_TYPES = %w{ Individual Sole\ Proprietor Limited\ Liability\ Company\ (LLC) Partnership Trust/Estate S\ Corporation C\ Corporation Other }
|
||||
|
|
@ -53,6 +54,7 @@ class JamRuby::AffiliatePartner < ActiveRecord::Base
|
|||
before_save do |record|
|
||||
record.address ||= ADDRESS_SCHEMA.clone
|
||||
record.entity_type ||= ENTITY_TYPES.first
|
||||
record.partner_user_id = nil if record.partner_user_id == '' #for activeadmin coercion
|
||||
end
|
||||
|
||||
def display_name
|
||||
|
|
@ -141,22 +143,25 @@ class JamRuby::AffiliatePartner < ActiveRecord::Base
|
|||
end
|
||||
|
||||
def created_within_affiliate_window(user, sale_time)
|
||||
sale_time - user.created_at < 2.years
|
||||
sale_time - user.created_at < 3.years
|
||||
end
|
||||
|
||||
def should_attribute_sale?(shopping_cart, user_to_check, instance)
|
||||
raise "Not a JamTrack sale" if !shopping_cart.is_jam_track?
|
||||
|
||||
if created_within_affiliate_window(user_to_check, Time.now)
|
||||
product_info = shopping_cart.product_info(instance)
|
||||
# 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
|
||||
|
||||
if shopping_cart.is_lesson?
|
||||
applicable_rate = lesson_rate
|
||||
else
|
||||
applicable_rate = rate
|
||||
end
|
||||
{fee_in_cents: (product_info[:price] * 100 * real_quantity * applicable_rate.to_f).round}
|
||||
# if shopping_cart.is_lesson?
|
||||
# applicable_rate = lesson_rate
|
||||
# else
|
||||
# applicable_rate = rate
|
||||
# end
|
||||
#{fee_in_cents: (product_info[:price] * 100 * real_quantity * applicable_rate.to_f).round}
|
||||
|
||||
{ fee_in_cents: (real_quantity * jamtrack_share_in_cents.to_f).round}
|
||||
else
|
||||
false
|
||||
end
|
||||
|
|
@ -283,6 +288,21 @@ class JamRuby::AffiliatePartner < ActiveRecord::Base
|
|||
affiliate_distributions.affiliate_refunded = TRUE
|
||||
}
|
||||
end
|
||||
|
||||
def self.subscription_distribution_sub_query(start_date, end_date, table_name)
|
||||
%{
|
||||
FROM affiliate_distributions INNER JOIN affiliate_partners
|
||||
ON affiliate_distributions.affiliate_referral_id = affiliate_partners.id
|
||||
WHERE
|
||||
affiliate_distributions.product_type = 'Subscription'
|
||||
AND
|
||||
(DATE(affiliate_distributions.created_at) >= DATE('#{start_date}'))
|
||||
AND
|
||||
(DATE(affiliate_distributions.created_at) <= DATE('#{end_date}'))
|
||||
AND affiliate_distributions.affiliate_referral_id = #{table_name}.affiliate_partner_id
|
||||
}
|
||||
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)
|
||||
|
|
@ -318,7 +338,11 @@ class JamRuby::AffiliatePartner < ActiveRecord::Base
|
|||
(SELECT -SUM(affiliate_distributions.affiliate_referral_fee_in_cents)
|
||||
#{sale_items_refunded_subquery(start_date, end_date, 'affiliate_monthly_payments')}
|
||||
), 0)
|
||||
|
||||
+
|
||||
COALESCE(
|
||||
(SELECT SUM(affiliate_distributions.affiliate_referral_fee_in_cents)
|
||||
#{subscription_distribution_sub_query(start_date, end_date, 'affiliate_monthly_payments')}
|
||||
), 0)
|
||||
WHERE closed = FALSE AND year = #{year} AND month = #{month}
|
||||
}
|
||||
|
||||
|
|
@ -371,6 +395,11 @@ class JamRuby::AffiliatePartner < ActiveRecord::Base
|
|||
(SELECT -SUM(affiliate_distributions.affiliate_referral_fee_in_cents)
|
||||
#{sale_items_refunded_subquery(start_date, end_date, 'affiliate_quarterly_payments')}
|
||||
), 0)
|
||||
+
|
||||
COALESCE(
|
||||
(SELECT SUM(affiliate_distributions.affiliate_referral_fee_in_cents)
|
||||
#{subscription_distribution_sub_query(start_date, end_date, 'affiliate_quarterly_payments')}
|
||||
), 0)
|
||||
|
||||
WHERE closed = FALSE AND paid = FALSE AND year = #{year} AND quarter = #{quarter}
|
||||
}
|
||||
|
|
@ -507,6 +536,18 @@ class JamRuby::AffiliatePartner < ActiveRecord::Base
|
|||
AffiliatePartner::AFFILIATE_PARAMS + self.id.to_s
|
||||
end
|
||||
|
||||
# def subscribed_user_referrals
|
||||
# user_referrals.joins(:sales).where("sales.sale_type = ?", Sale::SUBSCRIPTION_SALE)
|
||||
# end
|
||||
|
||||
def subscribed_user_referrals
|
||||
user_referrals.where("first_subscribed_at IS NOT NULL")
|
||||
end
|
||||
|
||||
# def revenues_from_subscriptions
|
||||
# subscribed_user_referrals.select("sales.recurly_total_in_cents").inject(0){ | sum, cent | sum += cent } / 100.0
|
||||
# end
|
||||
|
||||
def to_s
|
||||
display_name
|
||||
end
|
||||
|
|
|
|||
|
|
@ -28,13 +28,21 @@ module JamRuby
|
|||
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) OR payment_type='monthly'")
|
||||
# .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')
|
||||
|
||||
query = AffiliatePayment
|
||||
.includes(affiliate_quarterly_payment: [], affiliate_monthly_payment:[])
|
||||
.includes(:affiliate_monthly_payment => { :affiliate_partner => :affiliate_distributions })
|
||||
.where(affiliate_partner_id: affiliate_partner_id)
|
||||
.where("(payment_type='quarterly' AND closed = true) OR payment_type='monthly'")
|
||||
.where("payment_type='monthly'")
|
||||
.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')
|
||||
.order('year DESC, month DESC')
|
||||
|
||||
if query.length == 0
|
||||
[query, nil]
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ class JamRuby::AffiliateTrafficTotal < ActiveRecord::Base
|
|||
.paginate(page: page, per_page: per_page)
|
||||
.where(affiliate_partner_id: user.affiliate_partner.id)
|
||||
.where('visits != 0 OR signups != 0')
|
||||
.order('day ASC')
|
||||
.order('day DESC')
|
||||
|
||||
if query.length == 0
|
||||
[query, nil]
|
||||
|
|
|
|||
|
|
@ -43,6 +43,10 @@ module JamRuby
|
|||
GenericState.singleton.event_page_top_logo_url
|
||||
end
|
||||
|
||||
def self.recurly_transactions_last_sync_at
|
||||
GenericState.singleton.recurly_transactions_last_sync_at
|
||||
end
|
||||
|
||||
def self.connection_policy
|
||||
GenericState.connection_policy
|
||||
end
|
||||
|
|
|
|||
|
|
@ -385,6 +385,7 @@ module JamRuby
|
|||
#send_take_lesson_poke
|
||||
#first_lesson_instructions
|
||||
subscription_sync
|
||||
subscription_transaction_sync
|
||||
end
|
||||
|
||||
def self.subscription_sync
|
||||
|
|
@ -422,6 +423,12 @@ module JamRuby
|
|||
@@log.info(msg)
|
||||
end
|
||||
|
||||
def self.subscription_transaction_sync
|
||||
recurly_client = RecurlyClient.new
|
||||
last_sync_at = GenericState.recurly_transactions_last_sync_at
|
||||
recurly_client.sync_transactions({ begin_time: last_sync_at.iso8601 })
|
||||
end
|
||||
|
||||
def self.first_lesson_instructions
|
||||
User.came_through_amazon.joins(taken_lessons: [:music_session, :lesson_booking])
|
||||
.where('lesson_bookings.recurring = FALSE')
|
||||
|
|
|
|||
|
|
@ -344,6 +344,7 @@ module JamRuby
|
|||
begin
|
||||
subscription = create_subscription(current_user, plan_code, account, current_user.subscription_trial_ended? ? nil : current_user.subscription_trial_ends_at)
|
||||
current_user.recurly_subscription_id = subscription.uuid
|
||||
current_user.first_subscribed_at = Time.now if current_user.first_subscribed_at.nil?
|
||||
if current_user.subscription_trial_ended?
|
||||
current_user.subscription_plan_code = get_highest_plan(subscription)
|
||||
current_user.subscription_plan_code_set_at = DateTime.now
|
||||
|
|
@ -464,6 +465,7 @@ module JamRuby
|
|||
puts "Repairing subscription ID on account"
|
||||
user.update_attribute(:recurly_subscription_id, subscription.uuid)
|
||||
user.recurly_subscription_id = subscription.uuid
|
||||
user.first_subscribed_at = Time.now if user.first_subscribed_at.nil?
|
||||
end
|
||||
|
||||
return [subscription, account]
|
||||
|
|
@ -637,6 +639,46 @@ module JamRuby
|
|||
|
||||
end
|
||||
|
||||
def sync_transactions(options = {})
|
||||
ActiveRecord::Base.transaction do
|
||||
options.merge!({ sort: :updated_at, state: :successful })
|
||||
Recurly::Transaction.find_each(options) do |transaction |
|
||||
if AffiliateDistribution.find_by_external_id(transaction.uuid)
|
||||
begin
|
||||
Bugsnag.notify("ActiveRecord::RecordNotUnique: duplicate affiliate_distribution for Recurly transaction uuid #{transaction.uuid} was prevented from been added.")
|
||||
rescue => exception
|
||||
Rails.logger.error(exception) unless Rails.env.test?
|
||||
end
|
||||
next
|
||||
end
|
||||
|
||||
# these next lines try to ascertain that the transaction we've hit describes a true subscription
|
||||
# jamtrack transactions are handled entirely separately, so this should avoid those, and perhaps other 'odd'
|
||||
# transactions in Recurly
|
||||
next if transaction.status != 'success' || transaction.source != 'subscription'
|
||||
next if transaction.subscriptions.length == 0
|
||||
subscription = transaction.subscriptions.first
|
||||
next if subscription.plan == nil || subscription.plan.plan_code == nil
|
||||
|
||||
account = transaction.details["account"]
|
||||
user = User.find(account.account_code)
|
||||
affiliate_partner = user.affiliate_referral
|
||||
if !affiliate_partner.nil? && affiliate_partner.created_within_affiliate_window(user, transaction.created_at.to_time)
|
||||
affiliate_distribution = AffiliateDistribution.new
|
||||
affiliate_distribution.product_type = "Subscription"
|
||||
affiliate_distribution.affiliate_referral = affiliate_partner
|
||||
fee_in_cents = transaction.amount_in_cents * affiliate_partner.rate
|
||||
affiliate_distribution.affiliate_referral_fee_in_cents = fee_in_cents
|
||||
affiliate_distribution.created_at = transaction.created_at.to_time
|
||||
affiliate_distribution.product_code = subscription.plan.plan_code
|
||||
affiliate_distribution.external_id = transaction.uuid #external_id is a unique column. should raises error if duplicates
|
||||
affiliate_distribution.save!
|
||||
end
|
||||
end
|
||||
GenericState.singleton.update_attribute(:recurly_transactions_last_sync_at, Time.now)
|
||||
end
|
||||
end
|
||||
|
||||
def find_or_create_account(current_user, billing_info, recurly_token = nil)
|
||||
account = get_account(current_user)
|
||||
|
||||
|
|
@ -653,6 +695,7 @@ module JamRuby
|
|||
end
|
||||
|
||||
private
|
||||
|
||||
def account_hash(current_user, billing_info)
|
||||
options = {
|
||||
account_code: current_user.id,
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ module JamRuby
|
|||
def self.perform
|
||||
@@log.debug("waking up")
|
||||
|
||||
Teacher.randomize_order
|
||||
#Teacher.randomize_order
|
||||
|
||||
bounced_emails
|
||||
|
||||
|
|
|
|||
|
|
@ -16,9 +16,23 @@ namespace :db do
|
|||
|
||||
desc "Migrate the database"
|
||||
task :migrate do
|
||||
version = ARGV[1]
|
||||
if !version.nil?
|
||||
version = version.to_i
|
||||
end
|
||||
|
||||
ActiveRecord::Base.establish_connection(db_config)
|
||||
migrate_dir = File.expand_path("../../../../../db/migrate", __FILE__)
|
||||
ActiveRecord::Migrator.migrate(migrate_dir)
|
||||
ActiveRecord::Migrator.migrate(migrate_dir, version)
|
||||
puts "#{ENV['RAILS_ENV']} database migrated."
|
||||
end
|
||||
|
||||
desc "Rollback the database"
|
||||
task :rollback do
|
||||
steps = (ARGV[1] || "1").to_i
|
||||
ActiveRecord::Base.establish_connection(db_config)
|
||||
migrate_dir = File.expand_path("../../../../../db/migrate", __FILE__)
|
||||
ActiveRecord::Migrator.rollback(migrate_dir, steps)
|
||||
puts "#{ENV['RAILS_ENV']} database migrated."
|
||||
end
|
||||
|
||||
|
|
@ -48,7 +62,7 @@ namespace :db do
|
|||
namespace :g do
|
||||
desc "Generate migration"
|
||||
task :migration do
|
||||
name = ARGV[1] || raise("Specify name: rake g:migration your_migration")
|
||||
name = ARGV[1] || raise("Specify name: rake db:g:migration your_migration")
|
||||
timestamp = Time.now.strftime("%Y%m%d%H%M%S")
|
||||
path = File.expand_path("../../../../../db/migrate/#{timestamp}_#{name}.rb", __FILE__)
|
||||
migration_class = name.split("_").map(&:capitalize).join
|
||||
|
|
|
|||
|
|
@ -23,7 +23,9 @@ module JamRuby
|
|||
|
||||
def self.migrate_database
|
||||
ENV['RAILS_ENV'] = 'test'
|
||||
Rake.application.init
|
||||
# invoke init in this way; otherwise any args passed to rspec will pass through to the rake task and blow it up.
|
||||
# for instance, bundle exec rspec spec/some.rb -e "specific test" will cause a weird error
|
||||
Rake.application.init('rake', [])
|
||||
Rake.application.load_rakefile
|
||||
Rake::Task['db:jam_ruby:migrate'].invoke
|
||||
end
|
||||
|
|
|
|||
|
|
@ -885,6 +885,11 @@ FactoryGirl.define do
|
|||
legalese Faker::Lorem.paragraphs(6).join("\n\n")
|
||||
end
|
||||
|
||||
factory :affiliate_distribution, class: 'JamRuby::AffiliateDistribution' do
|
||||
association :affiliate_referral, factory: :affiliate_partner
|
||||
affiliate_referral_fee_in_cents 15
|
||||
end
|
||||
|
||||
factory :gift_card, class: 'JamRuby::GiftCard' do
|
||||
sequence(:code) { n.to_s }
|
||||
card_type JamRuby::GiftCardType::JAM_TRACKS_5
|
||||
|
|
|
|||
|
|
@ -0,0 +1,34 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe AffiliateDistribution do
|
||||
let(:affiliate_partner){ FactoryGirl.create(:affiliate_partner) }
|
||||
let(:affiliate_distribution1){ FactoryGirl.create(:affiliate_distribution, created_at: DateTime.new(2015, 1, 31), product_type: 'Subscription', product_code: 'jamsubsilver', affiliate_referral: affiliate_partner) }
|
||||
let(:affiliate_distribution2){ FactoryGirl.create(:affiliate_distribution, created_at: DateTime.new(2015, 2, 1), product_type: 'Subscription', product_code: 'jamsubsilver', affiliate_referral: affiliate_partner) }
|
||||
let(:affiliate_distribution3){ FactoryGirl.create(:affiliate_distribution, created_at: DateTime.new(2015, 2, 2), product_type: 'Subscription', product_code: 'jamsubgold', affiliate_referral: affiliate_partner) }
|
||||
let(:affiliate_distribution4){ FactoryGirl.create(:affiliate_distribution, created_at: DateTime.new(2015, 2, 3), product_type: 'Subscription', product_code: 'jamsubgold', affiliate_referral: affiliate_partner) }
|
||||
let(:affiliate_distribution5){ FactoryGirl.create(:affiliate_distribution, created_at: DateTime.new(2015, 2, 7), product_type: 'Subscription', product_code: 'jamsubplatinum', affiliate_referral: affiliate_partner) }
|
||||
let(:affiliate_distribution6){ FactoryGirl.create(:affiliate_distribution, created_at: DateTime.new(2015, 3, 1), product_type: 'Subscription', product_code: 'jamsubsilver', affiliate_referral: affiliate_partner) }
|
||||
|
||||
it "gives subscription plans counts for a partner between start and end dates" do
|
||||
|
||||
affiliate_distribution1.reload
|
||||
affiliate_distribution2.reload
|
||||
affiliate_distribution3.reload
|
||||
affiliate_distribution4.reload
|
||||
affiliate_distribution5.reload
|
||||
affiliate_distribution6.reload
|
||||
|
||||
start_date = Date.new(2015, 2, 1)
|
||||
end_date = Date.new(2015, 2, 7)
|
||||
|
||||
expect(AffiliateDistribution.count).to eq(6)
|
||||
expect(AffiliateDistribution.subscription_plans_count(affiliate_partner.id, start_date, end_date)).to eq(
|
||||
[
|
||||
{ plan: 'jamsubsilver', count: 1 },
|
||||
{ plan: 'jamsubgold', count: 2 },
|
||||
{ plan: 'jamsubplatinum', count: 1 }
|
||||
]
|
||||
)
|
||||
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe AffiliateMonthlyPayment do
|
||||
let(:partner) { FactoryGirl.create(:affiliate_partner) }
|
||||
|
||||
it ".index orders DESC" do
|
||||
|
||||
monthly1 = FactoryGirl.create(:affiliate_monthly_payment, closed: true, month: 2, year: 2015, affiliate_partner: partner)
|
||||
monthly2 = FactoryGirl.create(:affiliate_monthly_payment, closed: true, month: 3, year: 2015, affiliate_partner: partner)
|
||||
monthly3 = FactoryGirl.create(:affiliate_monthly_payment, closed: true, month: 4, year: 2015, affiliate_partner: partner)
|
||||
monthly4 = FactoryGirl.create(:affiliate_monthly_payment, closed: true, month: 1, year: 2016, affiliate_partner: partner)
|
||||
|
||||
monthly_payments = AffiliateMonthlyPayment.index(partner.partner_user, {})[0]
|
||||
expect(monthly_payments.map(&:year)).to eq [2016, 2015, 2015, 2015]
|
||||
expect(monthly_payments.map(&:month)).to eq [1, 4, 3, 2]
|
||||
end
|
||||
end
|
||||
|
|
@ -61,16 +61,16 @@ describe AffiliatePartner do
|
|||
FactoryGirl.create(:user, :created_at => Time.now - 6.days, :affiliate_referral_id => partner.id)
|
||||
FactoryGirl.create(:user, :created_at => Time.now - 6.days, :affiliate_referral_id => partner.id)
|
||||
FactoryGirl.create(:user, :created_at => Time.now - 3.days, :affiliate_referral_id => partner.id)
|
||||
FactoryGirl.create(:user, :created_at => Time.now - 2.days, :affiliate_referral_id => partner.id)
|
||||
recent = FactoryGirl.create(:user, :created_at => Time.now - 2.days, :affiliate_referral_id => partner.id)
|
||||
partner.reload
|
||||
expect(partner.referral_user_count).to eq(6)
|
||||
|
||||
by_date = partner.referrals_by_date
|
||||
expect(by_date.count).to eq(4)
|
||||
keys = by_date.keys
|
||||
expect(keys.first).to eq(Date.parse((Time.now - 2.days).to_s))
|
||||
expect(keys.first).to eq(Date.parse((Time.now.utc - 2.days).to_s))
|
||||
expect(by_date[keys.first]).to eq(1)
|
||||
expect(keys.last).to eq(Date.parse((Time.now - 7.days).to_s))
|
||||
expect(keys.last).to eq(Date.parse((Time.now.utc - 7.days).to_s))
|
||||
expect(by_date[keys.last]).to eq(2)
|
||||
end
|
||||
|
||||
|
|
@ -100,37 +100,44 @@ describe AffiliatePartner do
|
|||
|
||||
describe "should_attribute_sale?" do
|
||||
|
||||
it "raise error if not a JamTrack sale" do
|
||||
shopping_cart = double('shopping_cart', is_jam_track?: false)
|
||||
user.affiliate_referral = partner
|
||||
user.save!
|
||||
expect{ partner.should_attribute_sale?(shopping_cart, user, jam_track)}.to raise_error(RuntimeError, "Not a JamTrack sale")
|
||||
end
|
||||
|
||||
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
|
||||
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})
|
||||
user.should_attribute_sale?(shopping_cart).should eq({ fee_in_cents:25 } )
|
||||
end
|
||||
|
||||
it "user with an affiliate relationship (with a custom rate) buying a jamtrack" do
|
||||
it "user with an affiliate relationship (with a custom rate) buying a JamTrack. Custom rate should not attribute to affiliate share" do
|
||||
user.affiliate_referral = partner
|
||||
user.save!
|
||||
partner.rate = 0.25
|
||||
partner.save!
|
||||
shopping_cart = ShoppingCart.create user, jam_track, 1, false
|
||||
user.should_attribute_sale?(shopping_cart).should eq({fee_in_cents:50})
|
||||
user.should_attribute_sale?(shopping_cart).should eq( { fee_in_cents:25 } )
|
||||
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})
|
||||
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.created_at = (365 * 3 + 1).days.ago
|
||||
user.save!
|
||||
shopping_cart = ShoppingCart.create user, jam_track, 1, false
|
||||
user.should_attribute_sale?(shopping_cart).should be_false
|
||||
|
|
@ -142,21 +149,27 @@ describe AffiliatePartner 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
|
||||
|
||||
it "user created 3 years, 1 day ago" do
|
||||
days_future = 365 * 3 + 1
|
||||
partner.created_within_affiliate_window(user, days_future.days.from_now).should be_false
|
||||
end
|
||||
|
||||
it "user created 1 day before 3 years" do
|
||||
days_future = 365 * 3 - 1
|
||||
partner.created_within_affiliate_window(user, days_future.days.from_now).should be_true
|
||||
end
|
||||
end
|
||||
|
||||
describe "tally_up" do
|
||||
let(:partner1) {FactoryGirl.create(:affiliate_partner)}
|
||||
let(:partner2) {FactoryGirl.create(:affiliate_partner)}
|
||||
#let(:partner3) {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
|
||||
|
|
@ -335,11 +348,10 @@ describe AffiliatePartner do
|
|||
quarter.last_updated.should_not be_nil
|
||||
end
|
||||
|
||||
it "totals with sales data" do
|
||||
it "totals with JamTrack sales" 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)
|
||||
|
|
@ -349,8 +361,6 @@ describe AffiliatePartner do
|
|||
freebie_sale.affiliate_distributions.first.save!
|
||||
freebie_sale.save!
|
||||
|
||||
|
||||
|
||||
AffiliatePartner.ensure_quarters_exist(2015, 0)
|
||||
AffiliateQuarterlyPayment.count.should eq(2)
|
||||
AffiliatePartner.total_quarters(2015, 0)
|
||||
|
|
@ -364,7 +374,7 @@ describe AffiliatePartner do
|
|||
# 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.affiliate_referral_fee_in_cents.should eq(25)
|
||||
real_sale.created_at = Date.new(2015, 1, 1)
|
||||
real_sale.save!
|
||||
real_sale.affiliate_distributions.first.created_at = real_sale.created_at
|
||||
|
|
@ -372,7 +382,7 @@ describe AffiliatePartner do
|
|||
AffiliatePartner.ensure_quarters_exist(2015, 0)
|
||||
AffiliatePartner.total_quarters(2015, 0)
|
||||
quarter = partner1.quarters.first
|
||||
quarter.due_amount_in_cents.should eq(20)
|
||||
quarter.due_amount_in_cents.should eq(25)
|
||||
quarter.jamtracks_sold.should eq(1)
|
||||
quarter = partner2.quarters.first
|
||||
quarter.due_amount_in_cents.should eq(0)
|
||||
|
|
@ -381,7 +391,7 @@ describe AffiliatePartner do
|
|||
# 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.affiliate_referral_fee_in_cents.should eq(25)
|
||||
real_sale.created_at = Date.new(2015, 1, 1)
|
||||
real_sale.save!
|
||||
real_sale.affiliate_distributions.first.created_at = real_sale.created_at
|
||||
|
|
@ -390,16 +400,16 @@ describe AffiliatePartner do
|
|||
AffiliatePartner.ensure_quarters_exist(2015, 0)
|
||||
AffiliatePartner.total_quarters(2015, 0)
|
||||
quarter = partner1.quarters.first
|
||||
quarter.due_amount_in_cents.should eq(20)
|
||||
quarter.due_amount_in_cents.should eq(25)
|
||||
quarter.jamtracks_sold.should eq(1)
|
||||
quarter = partner2.quarters.first
|
||||
quarter.due_amount_in_cents.should eq(20)
|
||||
quarter.due_amount_in_cents.should eq(25)
|
||||
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.affiliate_referral_fee_in_cents.should eq(25)
|
||||
real_sale.created_at = Date.new(2015, 1, 1)
|
||||
real_sale.save!
|
||||
real_sale.affiliate_distributions.first.created_at = real_sale.created_at
|
||||
|
|
@ -407,10 +417,10 @@ describe AffiliatePartner do
|
|||
AffiliatePartner.ensure_quarters_exist(2015, 0)
|
||||
AffiliatePartner.total_quarters(2015, 0)
|
||||
quarter = partner1.quarters.first
|
||||
quarter.due_amount_in_cents.should eq(40)
|
||||
quarter.due_amount_in_cents.should eq(50)
|
||||
quarter.jamtracks_sold.should eq(2)
|
||||
quarter = partner2.quarters.first
|
||||
quarter.due_amount_in_cents.should eq(20)
|
||||
quarter.due_amount_in_cents.should eq(25)
|
||||
quarter.jamtracks_sold.should eq(1)
|
||||
|
||||
|
||||
|
|
@ -423,16 +433,16 @@ describe AffiliatePartner do
|
|||
AffiliatePartner.ensure_quarters_exist(2015, 0)
|
||||
AffiliatePartner.total_quarters(2015, 0)
|
||||
quarter = partner1.quarters.first
|
||||
quarter.due_amount_in_cents.should eq(40)
|
||||
quarter.due_amount_in_cents.should eq(50)
|
||||
quarter.jamtracks_sold.should eq(2)
|
||||
quarter = partner2.quarters.first
|
||||
quarter.due_amount_in_cents.should eq(20)
|
||||
quarter.due_amount_in_cents.should eq(25)
|
||||
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.affiliate_referral_fee_in_cents.should eq(25)
|
||||
real_sale.created_at = Date.new(2014, 12, 31)
|
||||
real_sale.save!
|
||||
real_sale.affiliate_distributions.first.created_at = real_sale.created_at
|
||||
|
|
@ -440,16 +450,16 @@ describe AffiliatePartner do
|
|||
AffiliatePartner.ensure_quarters_exist(2015, 0)
|
||||
AffiliatePartner.total_quarters(2015, 0)
|
||||
quarter = partner1.quarters.first
|
||||
quarter.due_amount_in_cents.should eq(40)
|
||||
quarter.due_amount_in_cents.should eq(50)
|
||||
quarter.jamtracks_sold.should eq(2)
|
||||
quarter = partner2.quarters.first
|
||||
quarter.due_amount_in_cents.should eq(20)
|
||||
quarter.due_amount_in_cents.should eq(25)
|
||||
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.affiliate_referral_fee_in_cents.should eq(25)
|
||||
real_sale.created_at = Date.new(2015, 4, 1)
|
||||
real_sale.save!
|
||||
real_sale.affiliate_distributions.first.created_at = real_sale.created_at
|
||||
|
|
@ -458,16 +468,16 @@ describe AffiliatePartner do
|
|||
AffiliatePartner.ensure_quarters_exist(2015, 0)
|
||||
AffiliatePartner.total_quarters(2015, 0)
|
||||
quarter = partner1.quarters.first
|
||||
quarter.due_amount_in_cents.should eq(40)
|
||||
quarter.due_amount_in_cents.should eq(50)
|
||||
quarter.jamtracks_sold.should eq(2)
|
||||
quarter = partner2.quarters.first
|
||||
quarter.due_amount_in_cents.should eq(20)
|
||||
quarter.due_amount_in_cents.should eq(25)
|
||||
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.affiliate_referral_fee_in_cents.should eq(25)
|
||||
real_sale.created_at = Date.new(2015, 3, 31)
|
||||
real_sale.save!
|
||||
real_sale.affiliate_distributions.first.created_at = real_sale.created_at
|
||||
|
|
@ -475,10 +485,10 @@ describe AffiliatePartner do
|
|||
AffiliatePartner.ensure_quarters_exist(2015, 0)
|
||||
AffiliatePartner.total_quarters(2015, 0)
|
||||
quarter = partner1.quarters.first
|
||||
quarter.due_amount_in_cents.should eq(60)
|
||||
quarter.due_amount_in_cents.should eq(75)
|
||||
quarter.jamtracks_sold.should eq(3)
|
||||
quarter = partner2.quarters.first
|
||||
quarter.due_amount_in_cents.should eq(20)
|
||||
quarter.due_amount_in_cents.should eq(25)
|
||||
# now refund it
|
||||
real_sale.affiliate_refunded_at = Date.new(2015, 3, 1)
|
||||
real_sale.affiliate_refunded = true
|
||||
|
|
@ -489,9 +499,10 @@ describe AffiliatePartner do
|
|||
AffiliatePartner.ensure_quarters_exist(2015, 0)
|
||||
AffiliatePartner.total_quarters(2015, 0)
|
||||
quarter = partner1.quarters.first
|
||||
quarter.due_amount_in_cents.should eq(40)
|
||||
quarter.due_amount_in_cents.should eq(50)
|
||||
quarter.jamtracks_sold.should eq(2)
|
||||
quarter = partner2.quarters.first
|
||||
quarter.due_amount_in_cents.should eq(20)
|
||||
quarter.due_amount_in_cents.should eq(25)
|
||||
quarter.jamtracks_sold.should eq(1)
|
||||
|
||||
|
||||
|
|
@ -499,7 +510,7 @@ describe AffiliatePartner do
|
|||
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)
|
||||
payment.due_amount_in_cents.should eq(25)
|
||||
|
||||
# and now refund it in the 3rd quarter
|
||||
real_sale_later.affiliate_refunded_at = Date.new(2015, 7, 1)
|
||||
|
|
@ -510,16 +521,139 @@ describe AffiliatePartner do
|
|||
real_sale_later.affiliate_distributions.first.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.due_amount_in_cents.should eq(25)
|
||||
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.due_amount_in_cents.should eq(-25)
|
||||
payment.jamtracks_sold.should eq(-1)
|
||||
|
||||
end
|
||||
|
||||
it "totals subscriptions with JamTrack sales" do
|
||||
|
||||
FactoryGirl.create(:affiliate_distribution,
|
||||
product_type: 'Subscription',
|
||||
product_code: 'jamsubsliver',
|
||||
affiliate_referral: partner1,
|
||||
affiliate_referral_fee_in_cents: 15,
|
||||
created_at: Date.new(2015, 1, 1)
|
||||
)
|
||||
partner1.touch
|
||||
|
||||
AffiliatePartner.ensure_quarters_exist(2015, 0)
|
||||
AffiliatePartner.total_quarters(2015, 0)
|
||||
|
||||
quarter = partner1.quarters.first
|
||||
quarter.due_amount_in_cents.should eq(15)
|
||||
|
||||
FactoryGirl.create(:affiliate_distribution,
|
||||
product_type: 'Subscription',
|
||||
product_code: 'jamsubgold',
|
||||
affiliate_referral: partner2,
|
||||
affiliate_referral_fee_in_cents: 30,
|
||||
created_at: Date.new(2015, 1, 1)
|
||||
)
|
||||
partner2.touch
|
||||
|
||||
AffiliatePartner.ensure_quarters_exist(2015, 0)
|
||||
AffiliatePartner.total_quarters(2015, 0)
|
||||
|
||||
quarter = partner2.quarters.first
|
||||
expect(quarter).not_to eq(nil)
|
||||
quarter.due_amount_in_cents.should eq(30)
|
||||
|
||||
#subscribe by non-affiliate user should not create affiliate payments
|
||||
FactoryGirl.create(:user)
|
||||
AffiliatePartner.ensure_quarters_exist(2015, 0)
|
||||
expect { AffiliatePartner.total_quarters(2015, 0)}.to change(AffiliateQuarterlyPayment, :count).by(0)
|
||||
|
||||
# lets add JamTrack sale
|
||||
# create a real sale by user1 who is affiliated with 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(25)
|
||||
real_sale.created_at = Date.new(2015, 1, 1)
|
||||
real_sale.save!
|
||||
real_sale.affiliate_distributions.first.created_at = real_sale.created_at
|
||||
real_sale.affiliate_distributions.first.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(1)
|
||||
|
||||
quarter = partner2.quarters.first
|
||||
quarter.due_amount_in_cents.should eq(30)
|
||||
quarter.jamtracks_sold.should eq(0)
|
||||
|
||||
# create a real sale for user2 who is affiliated with 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(25)
|
||||
real_sale.created_at = Date.new(2015, 1, 1)
|
||||
real_sale.save!
|
||||
real_sale.affiliate_distributions.first.created_at = real_sale.created_at
|
||||
real_sale.affiliate_distributions.first.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(1)
|
||||
quarter = partner2.quarters.first
|
||||
quarter.due_amount_in_cents.should eq(55)
|
||||
quarter.jamtracks_sold.should eq(1)
|
||||
|
||||
#affiliate earnings from subscriptions from previous quater should not attribute to quater been considered
|
||||
FactoryGirl.create(:affiliate_distribution,
|
||||
product_type: 'Subscription',
|
||||
product_code: 'jamsubgold',
|
||||
affiliate_referral: partner1,
|
||||
affiliate_referral_fee_in_cents: 30,
|
||||
created_at: Date.new(2014, 12, 31)
|
||||
)
|
||||
partner1.touch
|
||||
|
||||
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(55)
|
||||
|
||||
#affiliate earnings from subscriptions of next quater should not attribute to quater been considered
|
||||
FactoryGirl.create(:affiliate_distribution,
|
||||
product_type: 'Subscription',
|
||||
product_code: 'jamsubgold',
|
||||
affiliate_referral: partner2,
|
||||
affiliate_referral_fee_in_cents: 30,
|
||||
created_at: Date.new(2015, 04, 01)
|
||||
)
|
||||
partner2.touch
|
||||
|
||||
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(55)
|
||||
|
||||
#earnings in second quarter
|
||||
AffiliatePartner.ensure_quarters_exist(2015, 1)
|
||||
AffiliatePartner.total_quarters(2015, 1)
|
||||
quarter = partner1.quarters[1]
|
||||
quarter.due_amount_in_cents.should eq(0)
|
||||
quarter = partner2.quarters[1]
|
||||
quarter.due_amount_in_cents.should eq(30)
|
||||
|
||||
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -528,7 +662,7 @@ describe AffiliatePartner do
|
|||
AffiliatePartner.tally_up(Date.new(2015, 1, 1))
|
||||
end
|
||||
|
||||
it "successive runs" do
|
||||
it "successive for JamTrack Sales" 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
|
||||
|
|
@ -560,6 +694,7 @@ describe AffiliatePartner do
|
|||
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
|
||||
|
|
@ -576,7 +711,7 @@ describe AffiliatePartner do
|
|||
|
||||
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.affiliate_referral_fee_in_cents.should eq(25)
|
||||
real_sale.created_at = Date.new(2015, 4, 1)
|
||||
real_sale.save!
|
||||
real_sale.affiliate_distributions.first.created_at = real_sale.created_at
|
||||
|
|
@ -589,7 +724,7 @@ describe AffiliatePartner do
|
|||
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.due_amount_in_cents.should eq(25)
|
||||
quarter2.jamtracks_sold.should eq(1)
|
||||
quarter2.closed.should be_false
|
||||
|
||||
|
|
@ -606,7 +741,7 @@ describe AffiliatePartner do
|
|||
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.due_amount_in_cents.should eq(25)
|
||||
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)
|
||||
|
|
@ -622,7 +757,7 @@ describe AffiliatePartner do
|
|||
|
||||
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.affiliate_referral_fee_in_cents.should eq(25)
|
||||
real_sale.created_at = Date.new(2015, 1, 1)
|
||||
real_sale.save!
|
||||
real_sale.affiliate_distributions.first.created_at = real_sale.created_at
|
||||
|
|
@ -646,6 +781,109 @@ describe AffiliatePartner do
|
|||
month.jamtracks_sold.should eq(0)
|
||||
month.closed.should be_true
|
||||
end
|
||||
|
||||
it "successive for affiliate subscriptions and JamTrack Sales" 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)
|
||||
AffiliateMonthlyPayment.count.should eq(0)
|
||||
|
||||
FactoryGirl.create(:affiliate_distribution,
|
||||
product_type: 'Subscription',
|
||||
product_code: 'jamsubgold',
|
||||
affiliate_referral: partner1,
|
||||
affiliate_referral_fee_in_cents: 30,
|
||||
created_at: Date.new(2015, 1, 1)
|
||||
)
|
||||
|
||||
# partner is created
|
||||
partner1.touch
|
||||
|
||||
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(25)
|
||||
real_sale.created_at = Date.new(2015, 1, 1)
|
||||
real_sale.save!
|
||||
real_sale.affiliate_distributions.first.created_at = real_sale.created_at
|
||||
real_sale.affiliate_distributions.first.save!
|
||||
|
||||
|
||||
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(55)
|
||||
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.due_amount_in_cents.should eq(55)
|
||||
month.closed.should be_false
|
||||
month.jamtracks_sold.should eq(1)
|
||||
|
||||
month = AffiliateMonthlyPayment.find_by_month_and_year_and_affiliate_partner_id!(2, 2015, partner1.id)
|
||||
month.due_amount_in_cents.should eq(0)
|
||||
month.closed.should be_false
|
||||
month.jamtracks_sold.should eq(0)
|
||||
|
||||
month = AffiliateMonthlyPayment.find_by_month_and_year_and_affiliate_partner_id!(3, 2015, partner1.id)
|
||||
month.due_amount_in_cents.should eq(0)
|
||||
month.closed.should be_false
|
||||
month.jamtracks_sold.should eq(0)
|
||||
|
||||
#user of partner 1 purchases a JamTrack in 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(25)
|
||||
real_sale.created_at = Date.new(2015, 3, 1)
|
||||
real_sale.save!
|
||||
real_sale.affiliate_distributions.first.created_at = real_sale.created_at
|
||||
real_sale.affiliate_distributions.first.save!
|
||||
|
||||
AffiliatePartner.tally_up(Date.new(2015, 4, 1))
|
||||
|
||||
month = AffiliateMonthlyPayment.find_by_month_and_year_and_affiliate_partner_id!(1, 2015, partner1.id)
|
||||
month.due_amount_in_cents.should eq(55)
|
||||
month.closed.should be_true
|
||||
month.jamtracks_sold.should eq(1)
|
||||
|
||||
month = AffiliateMonthlyPayment.find_by_month_and_year_and_affiliate_partner_id!(2, 2015, partner1.id)
|
||||
month.due_amount_in_cents.should eq(0)
|
||||
month.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.due_amount_in_cents.should eq(0) #because this quarter has been closed before
|
||||
month.closed.should be_true
|
||||
month.jamtracks_sold.should eq(0)
|
||||
|
||||
quarter = AffiliateQuarterlyPayment.find_by_quarter_and_year_and_affiliate_partner_id!(0, 2015, partner1.id)
|
||||
quarter.due_amount_in_cents.should eq(55)
|
||||
quarter.closed.should be_true
|
||||
quarter.jamtracks_sold.should eq(1)
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
describe "tally_traffic_totals" do
|
||||
|
|
|
|||
|
|
@ -14,26 +14,32 @@ describe AffiliatePayment 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)
|
||||
monthly4 = FactoryGirl.create(:affiliate_monthly_payment, affiliate_partner: partner, closed: true, due_amount_in_cents: 40, month: 1, year: 2016)
|
||||
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)
|
||||
|
||||
results.length.should eq(4)
|
||||
result1 = results[0]
|
||||
result2 = results[1]
|
||||
result3 = results[2]
|
||||
result4 = results[3]
|
||||
result5 = results[4]
|
||||
#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)
|
||||
result4.payment_type.should eq('monthly')
|
||||
result4.due_amount_in_cents.should eq(10)
|
||||
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)
|
||||
result3.due_amount_in_cents.should eq(20)
|
||||
result2.payment_type.should eq('monthly')
|
||||
result2.due_amount_in_cents.should eq(30)
|
||||
result1.payment_type.should eq('monthly')
|
||||
result1.due_amount_in_cents.should eq(40)
|
||||
|
||||
#NOTE: removeing quarter payments from AffiliatePayment.index
|
||||
#"affiliate earnings" in client now only lists monthly payments
|
||||
expect(results.map(&:payment_type)).not_to include("quarterly")
|
||||
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
|
@ -1,13 +1,10 @@
|
|||
require 'spec_helper'
|
||||
|
||||
require 'webmock/rspec'
|
||||
|
||||
describe "User Subscriptions" do
|
||||
|
||||
let(:user1) {FactoryGirl.create(:user)}
|
||||
let(:client) { RecurlyClient.new }
|
||||
before(:each) do
|
||||
|
||||
end
|
||||
|
||||
it "empty results" do
|
||||
user1.touch
|
||||
|
|
@ -70,7 +67,443 @@ describe "User Subscriptions" do
|
|||
user1.subscription_last_checked_at.should_not be_nil
|
||||
user1.subscription_plan_code.should be_nil
|
||||
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
describe 'Subscription transactions sync' do
|
||||
let(:client) { RecurlyClient.new }
|
||||
let(:affiliate_partner) { FactoryGirl.create(:affiliate_partner) }
|
||||
let(:user) { FactoryGirl.create(:user, affiliate_referral: affiliate_partner) }
|
||||
let(:user2) { FactoryGirl.create(:user, affiliate_referral: affiliate_partner) }
|
||||
let(:transaction_response){
|
||||
transaction_response_xml(user)
|
||||
}
|
||||
let(:billing_info) {
|
||||
info = {}
|
||||
info[:first_name] = user.first_name
|
||||
info[:last_name] = user.last_name
|
||||
info[:address1] = 'Test Address 1'
|
||||
info[:address2] = 'Test Address 2'
|
||||
info[:city] = user.city
|
||||
info[:state] = user.state
|
||||
info[:country] = user.country
|
||||
info[:zip] = '12345'
|
||||
info[:number] = '4111-1111-1111-1111'
|
||||
info[:month] = '08'
|
||||
info[:year] = '2025'
|
||||
info[:verification_value] = '111'
|
||||
info
|
||||
}
|
||||
describe "using recurly API over internet" do
|
||||
it "fetches transactions created after GenericState.recurly_transactions_last_sync_at" do
|
||||
# pending("test this directly on recurly without stubbing. [maybe can omit as it tests recurly api?]")
|
||||
last_sync_at = Time.now
|
||||
WebMock.allow_net_connect!
|
||||
|
||||
# create user account and subscription in recurly
|
||||
account1 = client.find_or_create_account(user, billing_info)
|
||||
subscription1 = client.create_subscription(user, 'jamsubgold', account1, starts_at = nil)
|
||||
subscription1.should_not be_nil
|
||||
|
||||
expect { client.sync_transactions({ begin_time: last_sync_at.iso8601 }) }.to change(AffiliateDistribution, :count).by(1)
|
||||
AffiliateDistribution.order(:created_at).last.external_id.should_not be_nil
|
||||
AffiliateDistribution.order(:created_at).last.product_code.should_not be_nil
|
||||
|
||||
GenericState.singleton.reload
|
||||
|
||||
new_last_sync_at = GenericState.recurly_transactions_last_sync_at
|
||||
expect(last_sync_at < new_last_sync_at).to be true
|
||||
|
||||
# create second user account and subscription in recurly
|
||||
account2 = client.find_or_create_account(user2, billing_info)
|
||||
subscription2 = client.create_subscription(user2, 'jamsubplatinumyearly', account2, starts_at = nil)
|
||||
|
||||
GenericState.singleton.update_attribute(:recurly_transactions_last_sync_at, new_last_sync_at)
|
||||
expect { client.sync_transactions({ begin_time: new_last_sync_at.iso8601 }) }.to change(AffiliateDistribution, :count).by(1)
|
||||
AffiliateDistribution.order(:created_at).last.external_id.should_not be_nil
|
||||
AffiliateDistribution.order(:created_at).last.product_code.should_not be_nil
|
||||
end
|
||||
end
|
||||
describe "using mocked recurly" do
|
||||
before(:each) do
|
||||
#allow(recurly_transaction).to receive(:find_each).and_return(transaction) #works in rspec >=2.14
|
||||
|
||||
WebMock.stub_request(:get, /recurly.com\/v2\/transactions\?\S+/).
|
||||
to_return(status: 200, body: transaction_response, headers: {})
|
||||
|
||||
Recurly::Transaction.any_instance.stub(:subscriptions).and_return([
|
||||
Recurly::Subscription.new
|
||||
])
|
||||
|
||||
Recurly::Subscription.any_instance.stub(:plan).and_return([
|
||||
Recurly::Plan.new(plan_code: "jamsubgold")
|
||||
])
|
||||
end
|
||||
|
||||
it "creates AffiliateDistribution records for successful recurring transactions" do
|
||||
expect { client.sync_transactions }.to change(AffiliateDistribution, :count).by(2)
|
||||
end
|
||||
|
||||
# it "error out for when same transaction data been fetched" do
|
||||
# expect { client.sync_transactions }.to change(AffiliateDistribution, :count).by(2)
|
||||
# expect { client.sync_transactions }.to raise_error(ActiveRecord::RecordNotUnique)
|
||||
# end
|
||||
|
||||
it "does not create AffiliateDistribution for same transaction previously been created" do
|
||||
expect { client.sync_transactions }.to change(AffiliateDistribution, :count).by(2)
|
||||
expect { client.sync_transactions }.to change(AffiliateDistribution, :count).by(0)
|
||||
end
|
||||
|
||||
it "does not create AffiliateDistribution records when there is no affiliate partner" do
|
||||
user.affiliate_referral = nil
|
||||
user.save!
|
||||
AffiliateDistribution.delete_all
|
||||
transaction_response = transaction_response_xml(user)
|
||||
WebMock.stub_request(:get, /recurly.com\/v2\/transactions\?\S+/).
|
||||
to_return(status: 200, body: transaction_response, headers: {})
|
||||
expect { client.sync_transactions }.to change(AffiliateDistribution, :count).by(0)
|
||||
end
|
||||
|
||||
it "does not create AffiliateDistribution if out of affiliate window" do
|
||||
AffiliateDistribution.delete_all
|
||||
transaction_response = lapse_transaction_response_xml(user)
|
||||
WebMock.stub_request(:get, /recurly.com\/v2\/transactions\?\S+/).
|
||||
to_return(status: 200, body: transaction_response, headers: {})
|
||||
#expect { client.sync_transactions }.to change(AffiliateDistribution, :count).by(0)
|
||||
client.sync_transactions
|
||||
end
|
||||
|
||||
it "assigns correct affiliate partner" do
|
||||
client.sync_transactions
|
||||
AffiliateDistribution.all.each do |affiliate_distribution|
|
||||
expect(affiliate_distribution.affiliate_referral).to_not eq(nil)
|
||||
expect(affiliate_distribution.affiliate_referral).to eq(affiliate_partner)
|
||||
end
|
||||
end
|
||||
|
||||
it "updates affiliate referral fee" do
|
||||
client.sync_transactions
|
||||
most_recently_created = AffiliateDistribution.order(created_at: :desc).first
|
||||
expect(most_recently_created.affiliate_referral_fee_in_cents).to_not eq(nil)
|
||||
expect(most_recently_created.affiliate_referral_fee_in_cents).to eq(30)
|
||||
end
|
||||
|
||||
it "change affiliate rate and updates referral fee" do
|
||||
affiliate_partner.rate = 0.20
|
||||
affiliate_partner.save!
|
||||
client.sync_transactions
|
||||
most_recently_created = AffiliateDistribution.order(created_at: :desc).first
|
||||
expect(most_recently_created.affiliate_referral_fee_in_cents).to eq(20)
|
||||
end
|
||||
|
||||
it "sets subscription product_type" do
|
||||
client.sync_transactions
|
||||
AffiliateDistribution.all.each do |affiliate_distribution|
|
||||
expect(affiliate_distribution.product_type).to_not eq(nil)
|
||||
expect(affiliate_distribution.product_type).to eq('Subscription')
|
||||
end
|
||||
end
|
||||
|
||||
it "sets subscription product_code" do
|
||||
client.sync_transactions
|
||||
AffiliateDistribution.all.each do |affiliate_distribution|
|
||||
expect(affiliate_distribution.product_code).to_not eq(nil)
|
||||
expect(affiliate_distribution.product_code).to eq('jamsubgold')
|
||||
end
|
||||
end
|
||||
|
||||
it "does not error out if begin_time is nil" do
|
||||
expect{ client.sync_transactions( { begin_time: nil } ) }.not_to raise_error
|
||||
end
|
||||
|
||||
it "changes GenericState.recurly_transactions_last_sync_at" do
|
||||
before_time = GenericState.recurly_transactions_last_sync_at
|
||||
client.sync_transactions
|
||||
after_time = GenericState.recurly_transactions_last_sync_at
|
||||
expect(before_time).not_to eq(after_time)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
def transaction_response_xml(user)
|
||||
<<-XMLDATA
|
||||
<transactions type="array">
|
||||
<transaction href="https://your-subdomain.recurly.com/v2/transactions/374adcf4d716c1afc7b0b64bb79d4381" type="credit_card">
|
||||
<account href="https://your-subdomain.recurly.com/v2/accounts/1"/>
|
||||
<invoice href="https://your-subdomain.recurly.com/v2/invoices/1005"/>
|
||||
<subscriptions href="https://your-subdomain.recurly.com/v2/transactions/374adcf4d716c1afc7b0b64bb79d4381/subscriptions"/>
|
||||
<uuid>374adcf4d716c1afc7b0b64bb79d4381</uuid>
|
||||
<action>purchase</action>
|
||||
<amount_in_cents type="integer">100</amount_in_cents>
|
||||
<tax_in_cents type="integer">9</tax_in_cents>
|
||||
<currency>USD</currency>
|
||||
<status>success</status>
|
||||
<payment_method>credit_card</payment_method>
|
||||
<reference>2216615</reference>
|
||||
<source>transaction</source>
|
||||
<recurring type="boolean">true</recurring>
|
||||
<test type="boolean">true</test>
|
||||
<voidable type="boolean">true</voidable>
|
||||
<refundable type="boolean">true</refundable>
|
||||
<ip_address>127.0.0.1</ip_address>
|
||||
<cvv_result code="" nil="nil"/>
|
||||
<avs_result code="D">Street address and postal code match.</avs_result>
|
||||
<avs_result_street nil="nil"/>
|
||||
<avs_result_postal nil="nil"/>
|
||||
<created_at type="datetime">#{10.minutes.ago.strftime('%Y-%m-%dT%H:%M:%SZ')}</created_at>
|
||||
<updated_at type="datetime">#{10.minutes.ago.strftime('%Y-%m-%dT%H:%M:%SZ')}</updated_at>
|
||||
<details>
|
||||
<account>
|
||||
<account_code>#{user.id}</account_code>
|
||||
<first_name>Verena</first_name>
|
||||
<last_name>Example</last_name>
|
||||
<company>New Company Name</company>
|
||||
<email>verena@example.com</email>
|
||||
<billing_info type="credit_card">
|
||||
<first_name>Verena</first_name>
|
||||
<last_name>Example</last_name>
|
||||
<address1>123 Main St.</address1>
|
||||
<address2 nil="nil"/>
|
||||
<city>San Francisco</city>
|
||||
<state>CA</state>
|
||||
<zip>94105</zip>
|
||||
<country>US</country>
|
||||
<phone nil="nil"/>
|
||||
<vat_number nil="nil"/>
|
||||
<card_type>Visa</card_type>
|
||||
<year type="integer">2019</year>
|
||||
<month type="integer">12</month>
|
||||
<first_six>411111</first_six>
|
||||
<last_four>1111</last_four>
|
||||
</billing_info>
|
||||
</account>
|
||||
</details>
|
||||
<a name="refund" href="https://your-subdomain.recurly.com/v2/transactions/374adcf4d716c1afc7b0b64bb79d4381" method="delete"/>
|
||||
</transaction>
|
||||
|
||||
<transaction href="https://your-subdomain.recurly.com/v2/transactions/374adcf4d716c1afc7b0b64bb79d4382" type="credit_card">
|
||||
<account href="https://your-subdomain.recurly.com/v2/accounts/1"/>
|
||||
<invoice href="https://your-subdomain.recurly.com/v2/invoices/1005"/>
|
||||
<subscriptions href="https://your-subdomain.recurly.com/v2/transactions/374adcf4d716c1afc7b0b64bb79d4382/subscriptions"/>
|
||||
<uuid>374adcf4d716c1afc7b0b64bb79d4382</uuid>
|
||||
<action>purchase</action>
|
||||
<amount_in_cents type="integer">200</amount_in_cents>
|
||||
<tax_in_cents type="integer">9</tax_in_cents>
|
||||
<currency>USD</currency>
|
||||
<status>success</status>
|
||||
<payment_method>credit_card</payment_method>
|
||||
<reference>2216615</reference>
|
||||
<source>transaction</source>
|
||||
<recurring type="boolean">true</recurring>
|
||||
<test type="boolean">true</test>
|
||||
<voidable type="boolean">true</voidable>
|
||||
<refundable type="boolean">true</refundable>
|
||||
<ip_address>127.0.0.1</ip_address>
|
||||
<cvv_result code="" nil="nil"/>
|
||||
<avs_result code="D">Street address and postal code match.</avs_result>
|
||||
<avs_result_street nil="nil"/>
|
||||
<avs_result_postal nil="nil"/>
|
||||
<created_at type="datetime">#{20.minutes.ago.strftime('%Y-%m-%dT%H:%M:%SZ')}</created_at>
|
||||
<updated_at type="datetime">#{20.minutes.ago.strftime('%Y-%m-%dT%H:%M:%SZ')}</updated_at>
|
||||
<details>
|
||||
<account>
|
||||
<account_code>#{user.id}</account_code>
|
||||
<first_name>Verena</first_name>
|
||||
<last_name>Example</last_name>
|
||||
<company>New Company Name</company>
|
||||
<email>verena@example.com</email>
|
||||
<billing_info type="credit_card">
|
||||
<first_name>Verena</first_name>
|
||||
<last_name>Example</last_name>
|
||||
<address1>123 Main St.</address1>
|
||||
<address2 nil="nil"/>
|
||||
<city>San Francisco</city>
|
||||
<state>CA</state>
|
||||
<zip>94105</zip>
|
||||
<country>US</country>
|
||||
<phone nil="nil"/>
|
||||
<vat_number nil="nil"/>
|
||||
<card_type>Visa</card_type>
|
||||
<year type="integer">2019</year>
|
||||
<month type="integer">12</month>
|
||||
<first_six>411111</first_six>
|
||||
<last_four>1111</last_four>
|
||||
</billing_info>
|
||||
</account>
|
||||
</details>
|
||||
<a name="refund" href="https://your-subdomain.recurly.com/v2/transactions/374adcf4d716c1afc7b0b64bb79d4382" method="delete"/>
|
||||
</transaction>
|
||||
|
||||
|
||||
<transaction href="https://your-subdomain.recurly.com/v2/transactions/374adcf4d716c1afc7b0b64bb79d4383" type="credit_card">
|
||||
<account href="https://your-subdomain.recurly.com/v2/accounts/1"/>
|
||||
<invoice href="https://your-subdomain.recurly.com/v2/invoices/1005"/>
|
||||
<subscriptions href="https://your-subdomain.recurly.com/v2/transactions/374adcf4d716c1afc7b0b64bb79d4383/subscriptions"/>
|
||||
<uuid>374adcf4d716c1afc7b0b64bb79d4383</uuid>
|
||||
<action>purchase</action>
|
||||
<amount_in_cents type="integer">200</amount_in_cents>
|
||||
<tax_in_cents type="integer">9</tax_in_cents>
|
||||
<currency>USD</currency>
|
||||
<status>failed</status>
|
||||
<payment_method>credit_card</payment_method>
|
||||
<reference>2216615</reference>
|
||||
<source>transaction</source>
|
||||
<recurring type="boolean">true</recurring>
|
||||
<test type="boolean">true</test>
|
||||
<voidable type="boolean">true</voidable>
|
||||
<refundable type="boolean">true</refundable>
|
||||
<ip_address>127.0.0.1</ip_address>
|
||||
<cvv_result code="" nil="nil"/>
|
||||
<avs_result code="D">Street address and postal code match.</avs_result>
|
||||
<avs_result_street nil="nil"/>
|
||||
<avs_result_postal nil="nil"/>
|
||||
<created_at type="datetime">#{20.minutes.ago.strftime('%Y-%m-%dT%H:%M:%SZ')}</created_at>
|
||||
<updated_at type="datetime">#{20.minutes.ago.strftime('%Y-%m-%dT%H:%M:%SZ')}</updated_at>
|
||||
<details>
|
||||
<account>
|
||||
<account_code>#{user.id}</account_code>
|
||||
<first_name>Verena</first_name>
|
||||
<last_name>Example</last_name>
|
||||
<company>New Company Name</company>
|
||||
<email>verena@example.com</email>
|
||||
<billing_info type="credit_card">
|
||||
<first_name>Verena</first_name>
|
||||
<last_name>Example</last_name>
|
||||
<address1>123 Main St.</address1>
|
||||
<address2 nil="nil"/>
|
||||
<city>San Francisco</city>
|
||||
<state>CA</state>
|
||||
<zip>94105</zip>
|
||||
<country>US</country>
|
||||
<phone nil="nil"/>
|
||||
<vat_number nil="nil"/>
|
||||
<card_type>Visa</card_type>
|
||||
<year type="integer">2019</year>
|
||||
<month type="integer">12</month>
|
||||
<first_six>411111</first_six>
|
||||
<last_four>1111</last_four>
|
||||
</billing_info>
|
||||
</account>
|
||||
</details>
|
||||
<a name="refund" href="https://your-subdomain.recurly.com/v2/transactions/374adcf4d716c1afc7b0b64bb79d4383" method="delete"/>
|
||||
</transaction>
|
||||
|
||||
<transaction href="https://your-subdomain.recurly.com/v2/transactions/374adcf4d716c1afc7b0b64bb79d4384" type="credit_card">
|
||||
<account href="https://your-subdomain.recurly.com/v2/accounts/1"/>
|
||||
<invoice href="https://your-subdomain.recurly.com/v2/invoices/1005"/>
|
||||
<subscriptions href="https://your-subdomain.recurly.com/v2/transactions/374adcf4d716c1afc7b0b64bb79d4384/subscriptions"/>
|
||||
<uuid>374adcf4d716c1afc7b0b64bb79d4384</uuid>
|
||||
<action>purchase</action>
|
||||
<amount_in_cents type="integer">200</amount_in_cents>
|
||||
<tax_in_cents type="integer">9</tax_in_cents>
|
||||
<currency>USD</currency>
|
||||
<status>success</status>
|
||||
<payment_method>credit_card</payment_method>
|
||||
<reference>2216615</reference>
|
||||
<source>transaction</source>
|
||||
<recurring type="boolean">false</recurring>
|
||||
<test type="boolean">true</test>
|
||||
<voidable type="boolean">true</voidable>
|
||||
<refundable type="boolean">true</refundable>
|
||||
<ip_address>127.0.0.1</ip_address>
|
||||
<cvv_result code="" nil="nil"/>
|
||||
<avs_result code="D">Street address and postal code match.</avs_result>
|
||||
<avs_result_street nil="nil"/>
|
||||
<avs_result_postal nil="nil"/>
|
||||
<created_at type="datetime">#{20.minutes.ago.strftime('%Y-%m-%dT%H:%M:%SZ')}</created_at>
|
||||
<updated_at type="datetime">#{20.minutes.ago.strftime('%Y-%m-%dT%H:%M:%SZ')}</updated_at>
|
||||
<details>
|
||||
<account>
|
||||
<account_code>#{user.id}</account_code>
|
||||
<first_name>Verena</first_name>
|
||||
<last_name>Example</last_name>
|
||||
<company>New Company Name</company>
|
||||
<email>verena@example.com</email>
|
||||
<billing_info type="credit_card">
|
||||
<first_name>Verena</first_name>
|
||||
<last_name>Example</last_name>
|
||||
<address1>123 Main St.</address1>
|
||||
<address2 nil="nil"/>
|
||||
<city>San Francisco</city>
|
||||
<state>CA</state>
|
||||
<zip>94105</zip>
|
||||
<country>US</country>
|
||||
<phone nil="nil"/>
|
||||
<vat_number nil="nil"/>
|
||||
<card_type>Visa</card_type>
|
||||
<year type="integer">2019</year>
|
||||
<month type="integer">12</month>
|
||||
<first_six>411111</first_six>
|
||||
<last_four>1111</last_four>
|
||||
</billing_info>
|
||||
</account>
|
||||
</details>
|
||||
<a name="refund" href="https://your-subdomain.recurly.com/v2/transactions/374adcf4d716c1afc7b0b64bb79d4384" method="delete"/>
|
||||
</transaction>
|
||||
|
||||
</transactions>
|
||||
XMLDATA
|
||||
end
|
||||
|
||||
def lapse_transaction_response_xml(user)
|
||||
<<-XMLDATA
|
||||
<transactions type="array">
|
||||
<transaction href="https://your-subdomain.recurly.com/v2/transactions/374adcf4d716c1afc7b0b64bb79d4385" type="credit_card">
|
||||
<account href="https://your-subdomain.recurly.com/v2/accounts/1"/>
|
||||
<invoice href="https://your-subdomain.recurly.com/v2/invoices/1005"/>
|
||||
<subscriptions href="https://your-subdomain.recurly.com/v2/transactions/374adcf4d716c1afc7b0b64bb79d4385/subscriptions"/>
|
||||
<uuid>374adcf4d716c1afc7b0b64bb79d4385</uuid>
|
||||
<action>purchase</action>
|
||||
<amount_in_cents type="integer">100</amount_in_cents>
|
||||
<tax_in_cents type="integer">9</tax_in_cents>
|
||||
<currency>USD</currency>
|
||||
<status>success</status>
|
||||
<payment_method>credit_card</payment_method>
|
||||
<reference>2216615</reference>
|
||||
<source>transaction</source>
|
||||
<recurring type="boolean">true</recurring>
|
||||
<test type="boolean">true</test>
|
||||
<voidable type="boolean">true</voidable>
|
||||
<refundable type="boolean">true</refundable>
|
||||
<ip_address>127.0.0.1</ip_address>
|
||||
<cvv_result code="" nil="nil"/>
|
||||
<avs_result code="D">Street address and postal code match.</avs_result>
|
||||
<avs_result_street nil="nil"/>
|
||||
<avs_result_postal nil="nil"/>
|
||||
<created_at type="datetime">#{(365.days + 1.day).ago.strftime('%Y-%m-%dT%H:%M:%SZ')}</created_at>
|
||||
<updated_at type="datetime">#{(365.days + 1.day).ago.strftime('%Y-%m-%dT%H:%M:%SZ')}</updated_at>
|
||||
<details>
|
||||
<account>
|
||||
<account_code>#{user.id}</account_code>
|
||||
<first_name>Verena</first_name>
|
||||
<last_name>Example</last_name>
|
||||
<company>New Company Name</company>
|
||||
<email>verena@example.com</email>
|
||||
<billing_info type="credit_card">
|
||||
<first_name>Verena</first_name>
|
||||
<last_name>Example</last_name>
|
||||
<address1>123 Main St.</address1>
|
||||
<address2 nil="nil"/>
|
||||
<city>San Francisco</city>
|
||||
<state>CA</state>
|
||||
<zip>94105</zip>
|
||||
<country>US</country>
|
||||
<phone nil="nil"/>
|
||||
<vat_number nil="nil"/>
|
||||
<card_type>Visa</card_type>
|
||||
<year type="integer">2019</year>
|
||||
<month type="integer">12</month>
|
||||
<first_six>411111</first_six>
|
||||
<last_four>1111</last_four>
|
||||
</billing_info>
|
||||
</account>
|
||||
</details>
|
||||
<a name="refund" href="https://your-subdomain.recurly.com/v2/transactions/374adcf4d716c1afc7b0b64bb79d4385" method="delete"/>
|
||||
</transaction>
|
||||
|
||||
</transactions>
|
||||
XMLDATA
|
||||
end
|
||||
|
|
@ -119,6 +119,7 @@ Recurly::API.net_http = {
|
|||
end
|
||||
|
||||
DatabaseCleaner.start
|
||||
WebMock.allow_net_connect!
|
||||
example.run
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -922,7 +922,7 @@ DEPENDENCIES
|
|||
zip-codes
|
||||
|
||||
RUBY VERSION
|
||||
ruby 2.3.1p112
|
||||
ruby 2.4.1p111
|
||||
|
||||
BUNDLED WITH
|
||||
1.17.3
|
||||
|
|
|
|||
|
|
@ -13,7 +13,8 @@
|
|||
var $screen = null;
|
||||
|
||||
function beforeShow(data) {
|
||||
userId = data.id;
|
||||
|
||||
userId = context.JK.currentUserId
|
||||
affiliatePartnerData = null;
|
||||
}
|
||||
|
||||
|
|
@ -97,11 +98,14 @@
|
|||
|
||||
function onAffiliateSignups(signups) {
|
||||
|
||||
var traffics = signupsByMonth(signups.traffics);
|
||||
console.log('traffics', traffics);
|
||||
|
||||
var $table = $screen.find('table.traffic-table tbody')
|
||||
$table.empty();
|
||||
|
||||
var template = $('#template-affiliate-partner-signups-row').html();
|
||||
context._.each(signups.traffics, function(item) {
|
||||
context._.each(traffics, function(item) {
|
||||
var $link = $(context._.template(template, item, {variable: 'data'}));
|
||||
|
||||
var $day = $link.find('td.day')
|
||||
|
|
@ -116,6 +120,41 @@
|
|||
})
|
||||
}
|
||||
|
||||
function signupsByMonth(data){
|
||||
var item,
|
||||
i = 0,
|
||||
groups = {},
|
||||
output = [],
|
||||
date, year, month, key,
|
||||
monthNames = ["January", "February", "March", "April", "May", "June",
|
||||
"July", "August", "September", "October", "November", "December"
|
||||
];
|
||||
|
||||
while (item = data[i++]) {
|
||||
date = new Date(item.day);
|
||||
year = date.getFullYear();
|
||||
month = date.getMonth();
|
||||
key = monthNames[month] + " " + year
|
||||
|
||||
groups[key] || (groups[key] = []); // exists OR create []
|
||||
groups[key].push(item);
|
||||
}
|
||||
|
||||
for (var key in groups) {
|
||||
var sumVisits = groups[key].reduce(function (s, a) {
|
||||
return s + a.visits;
|
||||
}, 0);
|
||||
|
||||
var sumSignups = groups[key].reduce(function (s, a) {
|
||||
return s + a.signups;
|
||||
}, 0);
|
||||
|
||||
output.push({ month: key, signups: sumSignups, visits: sumVisits })
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
function onAffiliatePayments(payments) {
|
||||
var $table = $screen.find('table.payment-table tbody')
|
||||
$table.empty();
|
||||
|
|
@ -124,40 +163,46 @@
|
|||
context._.each(payments.payments, function(item) {
|
||||
|
||||
var data = {}
|
||||
if(item.payment_type == 'quarterly') {
|
||||
// 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
|
||||
}
|
||||
// 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 = ''
|
||||
// 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 {
|
||||
// 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 {
|
||||
else if(item.jamtracks_sold > 1) {
|
||||
data.sold = 'JamTracks: ' + item.jamtracks_sold + ' units sold';
|
||||
}
|
||||
data.earnings = '$' + (item.due_amount_in_cents / 100).toFixed(2);
|
||||
}
|
||||
|
||||
if(item.subscriptions){
|
||||
data.subscriptions = $.map(item.subscriptions, function(subs){
|
||||
return '<div>' + getDisplayNameTier(subs.plan) + ' subscriptions - ' + subs.count + '</div>'
|
||||
});
|
||||
}
|
||||
//}
|
||||
|
||||
|
||||
var $earning = $(context._.template(template, data, {variable: 'data'}));
|
||||
|
|
@ -166,50 +211,31 @@
|
|||
})
|
||||
}
|
||||
|
||||
function getDisplayNameTier(plan_code) {
|
||||
var i, len, ref, subscriptionCode;
|
||||
if (plan_code === '') {
|
||||
plan_code = null;
|
||||
}
|
||||
ref = gon.global.subscription_codes;
|
||||
for (i = 0, len = ref.length; i < len; i++) {
|
||||
subscriptionCode = ref[i];
|
||||
if (plan_code === subscriptionCode.id) {
|
||||
return subscriptionCode.name;
|
||||
}
|
||||
}
|
||||
return "Unknown plan code=" + plan_code;
|
||||
}
|
||||
|
||||
|
||||
function updateLinks() {
|
||||
var $select = $screen.find('select.link_type')
|
||||
var value = $select.val()
|
||||
|
||||
logger.debug("value: " + value)
|
||||
// affiliatePartnerData.account.id
|
||||
|
||||
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({text: 'Unable to fetch links. Please try again later.' })
|
||||
})
|
||||
}
|
||||
rest.getLinks('all', affiliatePartnerData.account.id)
|
||||
.done(populateLinkTable)
|
||||
.fail(function() {
|
||||
app.notify({text: 'Unable to fetch links. Please try again later.' })
|
||||
})
|
||||
}
|
||||
|
||||
function _renderAffiliateTab(theTab) {
|
||||
|
|
@ -269,13 +295,21 @@
|
|||
'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()
|
||||
'tax_identifier': tab_content.find('#affiliate_partner_tax_identifier').val(),
|
||||
'paypal_id': tab_content.find('#affiliate_partner_paypal_id').val()
|
||||
}
|
||||
var button = $('#affiliate-profile-account-submit')
|
||||
button.addClass("disabled")
|
||||
rest.postAffiliatePartnerData(userId, affiliate_partner_data)
|
||||
.done(postUpdateAffiliateAccountSuccess);
|
||||
.done(postUpdateAffiliateAccountSuccess)
|
||||
.fail(function(jqXHR) {
|
||||
button.removeClass("disabled")
|
||||
alert("Unable to update affiliate information.\n\n" + jqXHR.responseText)
|
||||
})
|
||||
}
|
||||
|
||||
function postUpdateAffiliateAccountSuccess(response) {
|
||||
$('#affiliate-profile-account-submit').removeClass("disabled")
|
||||
app.notify(
|
||||
{
|
||||
title: "Affiliate Account",
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ window.SupportPage = React.createClass({
|
|||
{support_warning}
|
||||
<div className="description">
|
||||
The JamKazam help desk offers 1:1 help desk support only to our Gold and Platinum plan
|
||||
subscribers. More information on subscription plans <a href="https://jamkazam.freshdesk.com/support/solutions/articles/66000122535-what-are-jamkazam-s-free-vs-premium-features-"
|
||||
subscribers, as well as those in their initial 30-day trial period. More information on subscription plans <a href="https://jamkazam.freshdesk.com/support/solutions/articles/66000122535-what-are-jamkazam-s-free-vs-premium-features-"
|
||||
target="_blank">can be found here</a>. If you are not a Gold or Platinum subscriber,
|
||||
we'd suggest that you look for help in our <a href="https://jamkazam.freshdesk.com/support/home" target="_blank"> extensive knowledge base of
|
||||
help articles</a>,
|
||||
|
|
|
|||
|
|
@ -137,6 +137,8 @@
|
|||
table.links-table {
|
||||
min-width:100%;
|
||||
margin-top:20px;
|
||||
border-width: 1px 0 0 0;
|
||||
border-style: solid;
|
||||
|
||||
th {
|
||||
padding: 10px 0 20px;
|
||||
|
|
@ -157,7 +159,9 @@
|
|||
|
||||
.url {
|
||||
|
||||
|
||||
input {
|
||||
font-family:courier;
|
||||
background-color: transparent;
|
||||
-webkit-box-shadow:none;
|
||||
box-shadow:none;
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ body.web.landing_page.full {
|
|||
}
|
||||
|
||||
.wrapper {
|
||||
padding-top:20px;
|
||||
//padding-top:20px;
|
||||
}
|
||||
.row {
|
||||
text-align:left;
|
||||
|
|
|
|||
|
|
@ -418,7 +418,7 @@ body.web.landing_page {
|
|||
font-size:14px;
|
||||
position: absolute;
|
||||
left: 60%;
|
||||
top: 25px;
|
||||
top: 45px;
|
||||
margin: 0;
|
||||
|
||||
h1 {
|
||||
|
|
|
|||
|
|
@ -113,7 +113,11 @@ class ApiController < ApplicationController
|
|||
def affiliate_partner
|
||||
if params[:affiliate_id]
|
||||
@partner = AffiliatePartner.find(params[:affiliate_id])
|
||||
if @partner.partner_user.nil?
|
||||
if @partner.nil?
|
||||
raise JamPermissionError, ValidationMessages::PERMISSION_VALIDATION_ERROR
|
||||
elsif @partner.partner_user.nil?
|
||||
raise JamPermissionError, ValidationMessages::PERMISSION_VALIDATION_ERROR
|
||||
elsif !current_user.admin || @partner.partner_user != current_user
|
||||
raise JamPermissionError, ValidationMessages::PERMISSION_VALIDATION_ERROR
|
||||
end
|
||||
elsif current_user
|
||||
|
|
|
|||
|
|
@ -9,7 +9,27 @@ class ApiLinksController < ApiController
|
|||
@log || Logging.logger[ApiLinksController]
|
||||
end
|
||||
|
||||
def all
|
||||
links = AffiliateLink.all.order(:created_at)
|
||||
results = []
|
||||
links.each do |link|
|
||||
url = nil
|
||||
if link.link.index('?')
|
||||
url = link.link + '&' + affiliate_params.to_query
|
||||
else
|
||||
url = link.link + '?' + affiliate_params.to_query
|
||||
end
|
||||
|
||||
results << {url: url,
|
||||
target: link.name }
|
||||
end
|
||||
render json: results, status: 200
|
||||
end
|
||||
=begin
|
||||
|
||||
def jamtrack_song_index
|
||||
@affiliate_params = affiliate_params()
|
||||
|
||||
@affiliate_params = affiliate_params('jamtrack-song')
|
||||
|
||||
results = []
|
||||
|
|
@ -106,9 +126,12 @@ class ApiLinksController < ApiController
|
|||
|
||||
render json: results, status: 200
|
||||
end
|
||||
=end
|
||||
|
||||
private
|
||||
def affiliate_params(campaign)
|
||||
{utm_source:'affiliate', utm_medium: 'affiliate', utm_campaign: "#{Date.today.year}-affiliate-#{campaign}", affiliate: @partner.id}
|
||||
def affiliate_params()
|
||||
#{utm_source:'affiliate', utm_medium: 'affiliate', utm_campaign: "#{Date.today.year}-affiliate-#{campaign}", affiliate: @partner.id}#
|
||||
# the above was deemed too noisy
|
||||
{affiliate: @partner.id}
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -162,6 +162,7 @@ class ApiRecurlyController < ApiController
|
|||
render json: {:message => x.inspect, errors: x.errors}, :status => 404
|
||||
end
|
||||
end
|
||||
|
||||
def create_subscription
|
||||
begin
|
||||
sale = Sale.purchase_subscription(current_user, params[:recurly_token], params[:plan_code])
|
||||
|
|
|
|||
|
|
@ -865,14 +865,16 @@ class ApiUsersController < ApiController
|
|||
if request.post?
|
||||
oo.address = params[:address]
|
||||
oo.tax_identifier = params[:tax_identifier]
|
||||
oo.paypal_id = params[:paypal_id]
|
||||
oo.save!
|
||||
render nothing: true
|
||||
render json: {}, status: 200
|
||||
|
||||
elsif request.get?
|
||||
result = {}
|
||||
result['account'] = {
|
||||
'address' => oo.address.clone,
|
||||
'tax_identifier' => oo.tax_identifier,
|
||||
'paypal_id' => oo.paypal_id,
|
||||
'entity_type' => oo.entity_type,
|
||||
'partner_name' => oo.partner_name,
|
||||
'partner_id' => oo.partner_user_id,
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ class SupportsController < ApplicationController
|
|||
gon.plan_code = current_user.subscription_plan_code
|
||||
|
||||
@title = "Help Desk"
|
||||
@description = "The JamKazam help desk offers 1:1 help desk support only to in-trial and Gold and Platinum plan subscribers."
|
||||
@description = "The JamKazam help desk offers 1:1 help desk support only to our Gold and Platinum plan subscribers, as well as those in their initial 30-day trial period."
|
||||
render 'show', :layout => 'support'
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,9 @@
|
|||
object @quarterly
|
||||
|
||||
attribute :closed, :paid, :due_amount_in_cents, :affiliate_partner_id, :quarter, :month, :year, :payment_type, :jamtracks_sold
|
||||
|
||||
node (:subscriptions) do |payment|
|
||||
start_at = Date.new(payment.year, payment.month, 1)
|
||||
end_at = Date.new(payment.year, payment.month, 1).end_of_month
|
||||
AffiliateDistribution.subscription_plans_count(payment.affiliate_partner_id, start_at, end_at)
|
||||
end
|
||||
|
|
@ -41,12 +41,18 @@ script type="text/template" id="template-affiliate-partner-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. 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
|
||||
br
|
||||
| For fastest receipt of payment, please specify a PayPal.Me account.
|
||||
br
|
||||
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
|
||||
br
|
||||
|
||||
.affiliate-label Street Address 1:
|
||||
= text_field_tag('affiliate_partner_address1', "{{ data.address.address1 }}", {class: 'w60'})
|
||||
br
|
||||
|
|
@ -69,6 +75,18 @@ script type="text/template" id="template-affiliate-partner-account"
|
|||
.affiliate-label Tax ID:
|
||||
= text_field_tag('affiliate_partner_tax_identifier', "{{ data.tax_identifier }}", {class: 'w60'})
|
||||
br
|
||||
br
|
||||
.affiliate-label PayPal.Me:
|
||||
= text_field_tag('affiliate_partner_paypal_id', "{{ data.paypal_id }}", { class: 'w60' })
|
||||
br
|
||||
span style="padding-left:138px"
|
||||
| A PayPal.Me link looks like
|
||||
b paypal.me/YourName
|
||||
| Please read more info
|
||||
a href="https://www.paypal.com/us/smarthelp/article/What-is-PayPalMe-FAQ3025"
|
||||
| about PayPal.Me
|
||||
br
|
||||
br
|
||||
.spacer
|
||||
.input-buttons
|
||||
.right
|
||||
|
|
@ -97,55 +115,17 @@ script type="text/template" id="template-affiliate-partner-signups"
|
|||
table.traffic-table.jamtable
|
||||
thead
|
||||
tr
|
||||
th.day DATE
|
||||
th.day MONTH
|
||||
th.signups SIGNUPS
|
||||
th.visits VISITS
|
||||
tbody
|
||||
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.
|
||||
| These links include your unique affiliate ID, and users who follow these links to JamKazam and register for an account will be
|
||||
| tagged with your affiliate ID, so that you will be paid on their purchase per the terms of the
|
||||
a.affiliate-agreement rel='#' affiliate agreement
|
||||
| . You can also find a
|
||||
a.affiliate-link-page href='#' rel="external" single page listing all affiliate links
|
||||
| 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
|
||||
| This page provides you with a list of ready-to-use links you can share with your followers to let them know about JamKazam. These links include your unique affiliate ID, and users who follow these links to JamKazam and sign up for a JamKazam account will be tagged with your affiliate ID, so that when they purchase a subscription and/or JamTracks, you will be paid a revenue share on their purchase payments per the terms of the affiliate agreement.
|
||||
p.prompt
|
||||
| Click “select link” next to the link you want to use, then copy the link to the clipboard and paste it wherever you want to share it.
|
||||
|
||||
table.links-table
|
||||
thead
|
||||
|
|
@ -153,12 +133,12 @@ script type="text/template" id="template-affiliate-partner-links"
|
|||
th.target TARGET PAGE
|
||||
th.copy-link
|
||||
th.url URL
|
||||
tbody
|
||||
tbody
|
||||
|
||||
script type="text/template" id="template-affiliate-partner-signups-row"
|
||||
tr
|
||||
td.day
|
||||
| {{data.day}}
|
||||
td.month
|
||||
| {{data.month}}
|
||||
td.signups
|
||||
| {{data.signups}}
|
||||
td.visits
|
||||
|
|
@ -169,9 +149,10 @@ script type="text/template" id="template-affiliate-partner-earnings"
|
|||
thead
|
||||
tr
|
||||
th.month MONTH
|
||||
th.sales SALES
|
||||
th.sales JAMTRACKS
|
||||
th.subscriptions SUBSCRIPTIONS
|
||||
th.earnings AFFILIATE EARNINGS
|
||||
tbody
|
||||
tbody
|
||||
|
||||
script type="text/template" id="template-affiliate-partner-earnings-row"
|
||||
tr data-type="{{data.payment_type}}"
|
||||
|
|
@ -179,6 +160,8 @@ script type="text/template" id="template-affiliate-partner-earnings-row"
|
|||
| {{data.time}}
|
||||
td.sales
|
||||
| {{data.sold}}
|
||||
td.subscriptions
|
||||
| {{ data.subscriptions }}
|
||||
td.earnings
|
||||
| {{data.earnings}}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,18 +2,14 @@
|
|||
- 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
|
||||
- if !Rails.env.test?
|
||||
.video-wrapper
|
||||
.video-container
|
||||
iframe src="//www.youtube.com/embed/96YTnO_H9a4" frameborder="0" allowfullscreen
|
||||
h1 JamKazam Affiliate Program
|
||||
p Do you have an audience of musician followers on social media like Facebook, YouTube, Instagram, or Twitter - or on your website, email list, etc?
|
||||
br
|
||||
p Most of the musicians in the world don't know JamKazam exists. Now you can let your audience know about JamKazam - which is something they'll be very excited to hear about - and also generate recurring income from any of your referrals that purchase JamKazam premium subscriptions and/or JamTracks.
|
||||
br
|
||||
p JamKazam provides a 30-day free trial that makes it fun and risk-free for anyone to check out the platform. After that, users can continue with a free plan or purchase an upgrade to a premium subscription, with plans available at $4.99, $9.99, or $19.99 per month. JamKazam will pay you 30% of these revenues for a period of 3 years from the signup date of each of your referred users.
|
||||
br
|
||||
p You don't sell anything. Just share the word about a service you really like and that most others haven't heard of yet. To get started, review the affiliate agreement details below and sign up as an affiliate at the bottom of this page. Then you can go to the Account/Affiliate page in our app or website to get special links tagged with your affiliate ID that you can share with your audience. You can also track signups and earnings from that page.
|
||||
br clear="all"
|
||||
.row
|
||||
h1 JamKazam Affiliate Agreement
|
||||
|
|
@ -45,8 +41,9 @@
|
|||
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"
|
||||
|
||||
= link_to "I Agree", '#', class: "agree-button button-orange"
|
||||
= link_to "I Disagree", '#', class: "disagree-button button-grey"
|
||||
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.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<!-- 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"><span class="c0">Updated: February 9, 2021.</span></p>
|
||||
|
||||
<p class="c2 c5"><span class="c0"></span></p>
|
||||
|
||||
|
|
@ -23,7 +23,7 @@
|
|||
|
||||
<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 “</span><span class="c0 c10">Product</span><span class="c0">”
|
||||
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"> 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 (“Content”). </span>
|
||||
a product or service sold on the JamKazam Site and listed in the </span><span class="c0 c10 c17">Program Advertising Fee Schedule</span><span class="c0"> 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 (“Content”). </span>
|
||||
</p>
|
||||
|
||||
<p class="c2 c5"><span class="c0"></span></p>
|
||||
|
|
@ -157,7 +157,7 @@
|
|||
|
||||
<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"> in Section 10. Subject to the exclusions set forth below, a “</span><span class="c0 c10">Qualifying Purchase</span><span class="c0">”
|
||||
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 “</span><span class="c0 c10">Qualifying Customer</span><span class="c0">”
|
||||
occurs when a Qualifying Customer purchases and pays for a Product within three (3) years of the date on which such Qualifying Customer registered to create his/her JamKazam account. A “</span><span class="c0 c10">Qualifying Customer</span><span class="c0">”
|
||||
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 “</span><span class="c0 c10">Session</span><span class="c0">”
|
||||
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>
|
||||
|
|
@ -192,7 +192,7 @@
|
|||
<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>
|
||||
<span class="c0">We will pay you advertising fees on a quarterly basis for Qualifying Purchases paid for 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, or by or processing a digital funds transfer (e.g. PayPal) to an account you designate, but we may accrue and withhold payment of advertising fees until the total amount due to you is at least US$25.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>
|
||||
|
|
@ -218,11 +218,32 @@
|
|||
<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 “</span><span class="c0 c10">Program Advertising Fee Schedule</span><span class="c0">”).</span>
|
||||
<span class="c0">We will determine and calculate amounts payable to you as advertising fees for Qualifying Purchases as set forth below (the “</span><span class="c0 c10">Program Advertising Fee Schedule</span><span class="c0">”).</span>
|
||||
</p>
|
||||
|
||||
<p class="c2 c5"><span class="c0"></span></p>
|
||||
<a href="#" name="fcab919a72a4bb6a7511330807c3ec6acfd219eb"></a><a href="#" name="0"></a>
|
||||
|
||||
<ul class="c6 lst-kix_list_46-0 start">
|
||||
<li class="c3 c2">
|
||||
<div class="c0 c8">Product: Silver, Gold, and Platinum Monthly or Annual Subscriptions</div>
|
||||
<div class="c2">
|
||||
JamKazam will pay advertising fees of 30% of the net revenues from Qualifying Purchases by Qualifying Customers of these Products.
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="c3 c2">
|
||||
<div class="c0 c8">Product: JamTracks</div>
|
||||
<div class="c2">
|
||||
JamKazam will pay US$0.25 per JamTrack sold as a Qualifying Purchase by Qualifying Customers of these Products.
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
<%# <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">
|
||||
|
|
@ -236,11 +257,12 @@
|
|||
</p></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</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>
|
||||
<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>
|
||||
|
|
@ -351,7 +373,7 @@
|
|||
<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 (“AAA”) under its rules, including the AAA’s Supplementary Procedures for Consumer-Related Disputes. The AAA’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’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’
|
||||
<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, 3924 Knollwood Drive, Austin TX 78731. The arbitration will be conducted by the American Arbitration Association (“AAA”) under its rules, including the AAA’s Supplementary Procedures for Consumer-Related Disputes. The AAA’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’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’
|
||||
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>
|
||||
|
||||
|
|
@ -417,6 +439,6 @@
|
|||
-->
|
||||
|
||||
<div><p class="c2 c21">
|
||||
<span class="c8 c14">JamKazam Confidential </span><span class="c14 c8"> 4/17/2015</span>
|
||||
<span class="c8 c14">JamKazam Confidential </span><span class="c14 c8"> 02/09/2021</span>
|
||||
</p></div>
|
||||
</div>
|
||||
|
|
@ -5,6 +5,10 @@
|
|||
tests=(
|
||||
"spec/features/signup_spec.rb"
|
||||
"spec/features/signin_spec.rb"
|
||||
"spec/features/affiliate_program_spec.rb"
|
||||
"spec/features/affiliate_visit_tracking_spec.rb"
|
||||
"spec/features/affiliate_referral_spec.rb"
|
||||
"spec/controllers/api_affiliate_controller_spec.rb"
|
||||
)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -759,12 +759,13 @@ Rails.application.routes.draw do
|
|||
match '/live_streams/bad_audio' => 'api_alerts#bad_audio', :via => :post # used by client; don't change route
|
||||
|
||||
# links generated to help affiliates share relevant links
|
||||
get '/links/jamtrack_songs' => 'api_links#jamtrack_song_index'
|
||||
get '/links/jamtrack_bands' => 'api_links#jamtrack_band_index'
|
||||
get '/links/jamtrack_general' => 'api_links#jamtrack_general_index'
|
||||
get '/links/jamkazam' => 'api_links#jamkazam_general_index'
|
||||
get '/links/sessions' => 'api_links#session_index'
|
||||
get '/links/recordings' => 'api_links#recording_index'
|
||||
#get '/links/jamtrack_songs' => 'api_links#jamtrack_song_index'
|
||||
#get '/links/jamtrack_bands' => 'api_links#jamtrack_band_index'
|
||||
#get '/links/jamtrack_general' => 'api_links#jamtrack_general_index'
|
||||
#get '/links/jamkazam' => 'api_links#jamkazam_general_index'
|
||||
#get '/links/sessions' => 'api_links#session_index'
|
||||
#get '/links/recordings' => 'api_links#recording_index'
|
||||
get '/links/all' => 'api_links#all'
|
||||
|
||||
match '/lesson_sessions' => 'api_lesson_sessions#index', :via => :get
|
||||
match '/lesson_bookings/unprocessed' => 'api_lesson_bookings#unprocessed', :via => :get
|
||||
|
|
|
|||
|
|
@ -1,2 +1,2 @@
|
|||
#!/bin/bash
|
||||
bundle exec jam_db up --connopts=dbname:jam host:localhost user:postgres password:postgres --verbose
|
||||
RAILS_ENV=development bundle exec rake db:jam_ruby:migrate
|
||||
|
|
|
|||
|
|
@ -79,4 +79,37 @@ describe ApiAffiliateController, type: :controller do
|
|||
end
|
||||
end
|
||||
|
||||
describe "payment_index" do
|
||||
it "empty" do
|
||||
get :payment_index
|
||||
response.should be_success
|
||||
JSON.parse(response.body)['payments'].should eq([])
|
||||
end
|
||||
|
||||
it "presents single JamTrack item" do
|
||||
FactoryGirl.create(:affiliate_monthly_payment, affiliate_partner: partner1, closed: true, due_amount_in_cents: 20, month: 1, year: 2015, jamtracks_sold: 1)
|
||||
|
||||
get :payment_index
|
||||
response.should be_success
|
||||
JSON.parse(response.body)['payments'].should eq([{"closed" => true, "paid" => nil, "payment_type" => "monthly", "quarter" => nil, "month" => 1, "year" => 2015, "due_amount_in_cents" => 20, "affiliate_partner_id" => partner1.id, "jamtracks_sold" => 1, "subscriptions" => [] }])
|
||||
end
|
||||
|
||||
it "presents subscriptions" do
|
||||
#Silver plan subscription on January
|
||||
FactoryGirl.create(:affiliate_distribution,
|
||||
product_type: 'Subscription',
|
||||
product_code: 'jamsubsilver',
|
||||
affiliate_referral: partner1,
|
||||
affiliate_referral_fee_in_cents: 15,
|
||||
created_at: Date.new(2015, 1, 1)
|
||||
)
|
||||
AffiliatePartner.tally_up(Date.new(2015, 1, 1))
|
||||
|
||||
get :payment_index
|
||||
response.should be_success
|
||||
expect(JSON.parse(response.body)['payments']).to have(6).things
|
||||
expect(JSON.parse(response.body)['payments']).to include({"closed" => false, "paid" => nil, "payment_type" => "monthly", "quarter" => nil, "month" => 1, "year" => 2015, "due_amount_in_cents" => 15, "affiliate_partner_id" => partner1.id, "jamtracks_sold" => 0, "subscriptions" => [{ "plan" => "jamsubsilver", "count" => 1 }] })
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -863,6 +863,10 @@ FactoryGirl.define do
|
|||
legalese Faker::Lorem.paragraphs(6).join("\n\n")
|
||||
end
|
||||
|
||||
factory :affiliate_distribution, class: 'JamRuby::AffiliateDistribution' do
|
||||
association :affiliate_referral, factory: :affiliate_partner
|
||||
end
|
||||
|
||||
factory :gift_card, class: 'JamRuby::GiftCard' do
|
||||
sequence(:code) {|n| n.to_s}
|
||||
card_type GiftCard::JAM_TRACKS_5
|
||||
|
|
|
|||
|
|
@ -6,7 +6,9 @@ describe "Account Affiliate", :js => true, :type => :feature, :capybara_feature
|
|||
|
||||
let(:user) {FactoryGirl.create(:user)}
|
||||
let(:partner) { FactoryGirl.create(:affiliate_partner) }
|
||||
let(:user_partner) { FactoryGirl.create(:user, affiliate_referral: partner) }
|
||||
let(:jam_track) {FactoryGirl.create(:jam_track)}
|
||||
let(:sale) {Sale.create_jam_track_sale(user_partner)}
|
||||
|
||||
before(:each) do
|
||||
JamTrackRight.delete_all
|
||||
|
|
@ -14,6 +16,7 @@ describe "Account Affiliate", :js => true, :type => :feature, :capybara_feature
|
|||
AffiliateQuarterlyPayment.delete_all
|
||||
AffiliateMonthlyPayment.delete_all
|
||||
AffiliateTrafficTotal.delete_all
|
||||
AffiliateDistribution.delete_all
|
||||
UserMailer.deliveries.clear
|
||||
emulate_client
|
||||
end
|
||||
|
|
@ -44,109 +47,314 @@ describe "Account Affiliate", :js => true, :type => :feature, :capybara_feature
|
|||
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')
|
||||
find('a#affiliate-partner-links-link').click
|
||||
#find('#account-affiliate-partner tr td.target')
|
||||
find('table.links-table')
|
||||
|
||||
# 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('a#affiliate-partner-signups-link').click
|
||||
find('table.traffic-table')
|
||||
|
||||
find('a#affiliate-partner-earnings-link').trigger(:click)
|
||||
find('a#affiliate-partner-earnings-link').click
|
||||
find('table.payment-table')
|
||||
|
||||
find('a#affiliate-partner-agreement-link').trigger(:click)
|
||||
find('a#affiliate-partner-agreement-link').click
|
||||
find('h2', text: 'JamKazam Affiliate Agreement')
|
||||
find('span.c0', text: 'Updated: April 30, 2015')
|
||||
find('span.c0', text: 'Updated: February 9, 2021.')
|
||||
|
||||
#save_screenshot("account_affiliate_agreement.png")
|
||||
end
|
||||
|
||||
it "shows data" do
|
||||
it "shows signups 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')
|
||||
day1 = Date.parse('2015-01-01')
|
||||
FactoryGirl.create(:affiliate_traffic_total, affiliate_partner: partner, day: day1, signups: 1, visits: 5)
|
||||
day2 = Date.parse('2015-01-15')
|
||||
FactoryGirl.create(:affiliate_traffic_total, affiliate_partner: partner, day: day2, signups: 5, visits: 10)
|
||||
day3 = Date.parse('2015-01-31')
|
||||
FactoryGirl.create(:affiliate_traffic_total, affiliate_partner: partner, day: day3, signups: 10, visits: 20)
|
||||
|
||||
day4 = Date.parse('2015-02-01')
|
||||
FactoryGirl.create(:affiliate_traffic_total, affiliate_partner: partner, day: day4, signups: 1, visits: 2)
|
||||
|
||||
find('a#affiliate-partner-earnings-link').trigger(:click)
|
||||
day5 = Date.parse('2015-03-15')
|
||||
FactoryGirl.create(:affiliate_traffic_total, affiliate_partner: partner, day: day5, signups: 10, visits: 20)
|
||||
|
||||
day6 = Date.parse('2015-04-01')
|
||||
FactoryGirl.create(:affiliate_traffic_total, affiliate_partner: partner, day: day6, signups: 20, visits: 50)
|
||||
|
||||
day7 = Date.parse('2015-04-05')
|
||||
FactoryGirl.create(:affiliate_traffic_total, affiliate_partner: partner, day: day7, signups: 5, visits: 10)
|
||||
|
||||
find('a#affiliate-partner-signups-link').click
|
||||
|
||||
months = page.all('table.traffic-table tr td.month')
|
||||
signups = page.all('table.traffic-table tr td.signups')
|
||||
visits = page.all('table.traffic-table tr td.visits')
|
||||
|
||||
months[0].should have_content("April")
|
||||
months[1].should have_content("March")
|
||||
months[2].should have_content("February")
|
||||
months[3].should have_content("January")
|
||||
|
||||
signups[0].should have_content("25")
|
||||
signups[1].should have_content("10")
|
||||
signups[2].should have_content("1")
|
||||
signups[3].should have_content("16")
|
||||
|
||||
visits[0].should have_content("60")
|
||||
visits[1].should have_content("20")
|
||||
visits[2].should have_content("2")
|
||||
visits[3].should have_content("35")
|
||||
|
||||
find('a#affiliate-partner-earnings-link').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')
|
||||
day8 = Date.parse('2015-04-07')
|
||||
FactoryGirl.create(:affiliate_traffic_total, affiliate_partner: partner, day: day8, signups: 5, visits: 10)
|
||||
|
||||
find('a#affiliate-partner-signups-link').click
|
||||
|
||||
months = page.all('table.traffic-table tr td.month')
|
||||
signups = page.all('table.traffic-table tr td.signups')
|
||||
visits = page.all('table.traffic-table tr td.visits')
|
||||
|
||||
months[0].should have_content("April")
|
||||
signups[0].should have_content("30")
|
||||
visits[0].should have_content("70")
|
||||
|
||||
#save_screenshot("account_affiliate_signup_links.png")
|
||||
|
||||
end
|
||||
|
||||
it "shows earnings" do
|
||||
jam_track.touch
|
||||
|
||||
visit "/client#/account/affiliatePartner"
|
||||
find('.tab-account', text: 'So please provide this data, and be sure to keep it current!')
|
||||
|
||||
# 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)
|
||||
FactoryGirl.create(:affiliate_monthly_payment, affiliate_partner:partner, year:2015, month:1, due_amount_in_cents:25, jamtracks_sold: 1, closed:true)
|
||||
|
||||
find('a#affiliate-partner-earnings-link').trigger(:click)
|
||||
find('a#affiliate-partner-earnings-link').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.earnings', text: '$0.25')
|
||||
|
||||
|
||||
find('a#affiliate-partner-signups-link').trigger(:click)
|
||||
find('a#affiliate-partner-signups-link').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.')
|
||||
FactoryGirl.create(:affiliate_monthly_payment, affiliate_partner:partner, year:2015, month:2, due_amount_in_cents:50, jamtracks_sold: 2, closed:true)
|
||||
FactoryGirl.create(:affiliate_monthly_payment, affiliate_partner:partner, year:2015, month:3, due_amount_in_cents:75, jamtracks_sold: 3, closed:true)
|
||||
FactoryGirl.create(:affiliate_monthly_payment, affiliate_partner:partner, year:2015, month:4, due_amount_in_cents:0, jamtracks_sold: 0, closed:true)
|
||||
|
||||
|
||||
find('a#affiliate-partner-earnings-link').click
|
||||
|
||||
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)
|
||||
months = page.all("table.payment-table tr td.month")
|
||||
sales = page.all("table.payment-table tr td.sales")
|
||||
earnings = page.all("table.payment-table tr td.earnings")
|
||||
|
||||
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')
|
||||
months[0].should have_content("April 2015")
|
||||
months[1].should have_content("March 2015")
|
||||
months[2].should have_content("February 2015")
|
||||
months[3].should have_content("January 2015")
|
||||
|
||||
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')
|
||||
sales[0].should have_content("")
|
||||
sales[1].should have_content("JamTracks: 3 units sold")
|
||||
sales[2].should have_content("JamTracks: 2 units sold")
|
||||
sales[3].should have_content("JamTracks: 1 unit sold")
|
||||
|
||||
earnings[0].should have_content("")
|
||||
earnings[1].should have_content("$0.75")
|
||||
earnings[2].should have_content("$0.50")
|
||||
earnings[3].should have_content("$0.25")
|
||||
|
||||
#save_screenshot("account_affiliate_earnings.png")
|
||||
end
|
||||
|
||||
it "shows earnings by Subscription and JamTrack sales" do
|
||||
#Silver plan subscription on January
|
||||
FactoryGirl.create(:affiliate_distribution,
|
||||
product_type: 'Subscription',
|
||||
product_code: 'jamsubsilver',
|
||||
affiliate_referral: partner,
|
||||
affiliate_referral_fee_in_cents: 15,
|
||||
created_at: Date.new(2015, 1, 1)
|
||||
)
|
||||
|
||||
#JamTrack sale on January
|
||||
jam_track.reload
|
||||
shopping_cart = ShoppingCart.create user_partner, 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(25)
|
||||
real_sale.created_at = Date.new(2015, 1, 1)
|
||||
real_sale.save!
|
||||
real_sale.affiliate_distributions.first.created_at = real_sale.created_at
|
||||
real_sale.affiliate_distributions.first.save!
|
||||
|
||||
|
||||
#Gold plan subscription on January
|
||||
FactoryGirl.create(:affiliate_distribution,
|
||||
product_type: 'Subscription',
|
||||
product_code: 'jamsubgold',
|
||||
affiliate_referral: partner,
|
||||
affiliate_referral_fee_in_cents: 30,
|
||||
created_at: Date.new(2015, 1, 1)
|
||||
)
|
||||
|
||||
#Platinum plan subscription in February
|
||||
FactoryGirl.create(:affiliate_distribution,
|
||||
product_type: 'Subscription',
|
||||
product_code: 'jamsubplatinum',
|
||||
affiliate_referral: partner,
|
||||
affiliate_referral_fee_in_cents: 60,
|
||||
created_at: Date.new(2015, 2, 1)
|
||||
)
|
||||
|
||||
AffiliatePartner.tally_up(Date.new(2015, 2, 1))
|
||||
|
||||
visit "/client#/account/affiliatePartner"
|
||||
find('.tab-account', text: 'So please provide this data, and be sure to keep it current!')
|
||||
|
||||
find('a#affiliate-partner-earnings-link').click
|
||||
|
||||
# within('table.payment-table') do
|
||||
# find('tr td.month', text: "January 2015")
|
||||
# find('tr td.sales', text: 'JamTracks: 1 unit sold')
|
||||
# find('tr td.subscriptions', text: 'Gold subscriptions - 1')
|
||||
# find('tr td.subscriptions', text: 'Silver subscriptions - 1')
|
||||
# find('tr td.earnings', text: '$1.70')
|
||||
# end
|
||||
|
||||
months = page.all("table.payment-table tbody tr td.month")
|
||||
months[0].should have_content("March 2015")
|
||||
months[1].should have_content("February 2015")
|
||||
months[2].should have_content("January 2015")
|
||||
|
||||
sales = page.all("table.payment-table tbody tr td.sales")
|
||||
sales[0].should have_content("JamTracks: 0 units sold")
|
||||
sales[1].should have_content("JamTracks: 0 units sold")
|
||||
sales[2].should have_content("JamTracks: 1 unit sold")
|
||||
|
||||
subscriptions = page.all("table.payment-table tbody tr td.subscriptions")
|
||||
subscriptions[0].should have_content("")
|
||||
subscriptions[1].should have_content("")
|
||||
subscriptions[2].should have_content("Gold subscriptions - 1")
|
||||
subscriptions[2].should have_content("Silver subscriptions - 1")
|
||||
|
||||
earnings = page.all("table.payment-table tbody tr td.earnings")
|
||||
earnings[0].should have_content("")
|
||||
earnings[1].should have_content("$0.60")
|
||||
earnings[2].should have_content("$0.70")
|
||||
|
||||
#save_screenshot("account_affiliate_earnings_with_subscriptions.png")
|
||||
|
||||
end
|
||||
|
||||
|
||||
# it "shows data" do
|
||||
# sign_in_poltergeist partner.partner_user
|
||||
|
||||
# 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('a#affiliate-partner-signups-link').click
|
||||
# find('table.traffic-table tr td.month', text: "April 2015")
|
||||
# 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('a#affiliate-partner-earnings-link').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('a#affiliate-partner-signups-link').click
|
||||
# find('table.traffic-table tr td.month', text: "April 2015")
|
||||
# find('table.traffic-table tr td.signups', text: '4')
|
||||
# find('table.traffic-table tr td.visits', text: '6')
|
||||
|
||||
# # 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('a#affiliate-partner-earnings-link').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('a#affiliate-partner-signups-link').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('a#affiliate-partner-earnings-link').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('a#affiliate-partner-signups-link').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('a#affiliate-partner-earnings-link').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
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ describe "Affiliate Program", :js => true, :type => :feature, :capybara_feature
|
|||
let(:user) { FactoryGirl.create(:user) }
|
||||
|
||||
before(:each) do
|
||||
User.delete_all
|
||||
AffiliateQuarterlyPayment.delete_all
|
||||
AffiliateMonthlyPayment.delete_all
|
||||
AffiliateTrafficTotal.delete_all
|
||||
|
|
@ -27,16 +26,16 @@ describe "Affiliate Program", :js => true, :type => :feature, :capybara_feature
|
|||
it "logged in user creates affiliate" do
|
||||
fast_signin user, '/affiliateProgram'
|
||||
|
||||
find('input#entity_individual').trigger(:click)
|
||||
find('input#entity_individual').click
|
||||
|
||||
find('.agree-button').trigger(:click)
|
||||
find('.agree-button').click
|
||||
|
||||
find('h1', text: 'congratulations')
|
||||
find('.button-orange', text: 'GO TO AFFILIATE PAGE').trigger(:click)
|
||||
find('.button-orange', text: 'GO TO AFFILIATE PAGE').click
|
||||
|
||||
find('.tab-account', text: 'So please provide this data, and be sure to keep it current!')
|
||||
|
||||
partner = AffiliatePartner.first
|
||||
partner = AffiliatePartner.order('created_at desc').first
|
||||
partner.partner_user.should eq(user)
|
||||
partner.entity_type.should eq('Individual')
|
||||
end
|
||||
|
|
@ -44,18 +43,18 @@ describe "Affiliate Program", :js => true, :type => :feature, :capybara_feature
|
|||
it "logged in user creates entity affiliate" do
|
||||
fast_signin user, '/affiliateProgram'
|
||||
|
||||
find('input#entity_entity').trigger(:click)
|
||||
find('input#entity_entity').click
|
||||
fill_in('entity-name', with: 'Mr. Bubbles')
|
||||
select('Sole Proprietor', from:'entity-type')
|
||||
|
||||
find('.agree-button').trigger(:click)
|
||||
find('.agree-button').click
|
||||
|
||||
find('h1', text: 'congratulations')
|
||||
find('.button-orange', text: 'GO TO AFFILIATE PAGE').trigger(:click)
|
||||
find('.button-orange', text: 'GO TO AFFILIATE PAGE').click
|
||||
|
||||
find('.tab-account', text: 'So please provide this data, and be sure to keep it current!')
|
||||
|
||||
partner = AffiliatePartner.first
|
||||
partner = AffiliatePartner.order('created_at desc').first
|
||||
partner.partner_user.should eq(user)
|
||||
partner.entity_type.should eq('Sole Proprietor')
|
||||
end
|
||||
|
|
@ -63,26 +62,25 @@ describe "Affiliate Program", :js => true, :type => :feature, :capybara_feature
|
|||
it "new user creates individual affiliate" do
|
||||
visit '/affiliateProgram'
|
||||
|
||||
find('input#entity_individual').trigger(:click)
|
||||
find('input#entity_individual').click
|
||||
|
||||
find('.agree-button').trigger(:click)
|
||||
find('.agree-button').click
|
||||
|
||||
find('h1', text: 'congratulations')
|
||||
find('.button-orange', text: 'GO SIGNUP').trigger(:click)
|
||||
find('.button-orange', text: 'GO SIGNUP').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
|
||||
found_user = User.order('created_at desc').first
|
||||
partner = AffiliatePartner.order('created_at desc').first
|
||||
partner.partner_user.should eq(found_user)
|
||||
partner.entity_type.should eq('Individual')
|
||||
end
|
||||
|
|
|
|||
|
|
@ -39,7 +39,6 @@ describe "affiliate visit tracking", :js => true, :type => :feature, :capybara_
|
|||
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"
|
||||
|
||||
|
|
|
|||
|
|
@ -1,36 +0,0 @@
|
|||
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
|
||||
|
|
@ -165,6 +165,14 @@ Capybara.server = :puma
|
|||
config.visible_text_only = true
|
||||
end
|
||||
|
||||
Capybara.register_driver :jamkazam do |app|
|
||||
require 'selenium/webdriver'
|
||||
profile = Selenium::WebDriver::Firefox::Profile.new
|
||||
profile['general.useragent.override'] = "jamkazam"
|
||||
|
||||
Capybara::Selenium::Driver.new(app, :profile => profile)
|
||||
end
|
||||
|
||||
# Requires supporting ruby files with custom matchers and macros, etc,
|
||||
# in spec/support/ and its subdirectories.
|
||||
Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}
|
||||
|
|
|
|||
|
|
@ -137,6 +137,41 @@ def set_cookie(k, v)
|
|||
end
|
||||
end
|
||||
|
||||
# def sign_in_poltergeist(user, options = {})
|
||||
# validate = options[:validate]
|
||||
# validate = true if validate.nil?
|
||||
|
||||
# if user.password.nil? && !options[:password]
|
||||
# raise "user has no password. Use a user newly created so that it's password is still present"
|
||||
# end
|
||||
# uri = URI.parse(current_url)
|
||||
|
||||
# # in tests, we often have an issue where an old signin screen is unloading
|
||||
# # as this one is loading.
|
||||
# # so one way to fix this is to go to a different page in this case, and then come back to /signin
|
||||
|
||||
# if uri.path == signin_path
|
||||
# visit '/'
|
||||
# should_be_at_root
|
||||
# end
|
||||
|
||||
# visit signin_path
|
||||
# page.should have_selector('#landing-inner form.signin-form')
|
||||
|
||||
# within('#landing-inner form.signin-form') do
|
||||
# fill_in "Email Address:", with: user.email
|
||||
# fill_in "Password:", with: options[:password] || user.password
|
||||
# click_button "SIGN IN"
|
||||
# end
|
||||
|
||||
# page.should have_no_selector('h1', text: 'sign in or register')
|
||||
|
||||
# wait_until_curtain_gone
|
||||
|
||||
# # presence of this means websocket gateway is not working
|
||||
# page.should have_no_selector('.no-websocket-connection') if validate
|
||||
#end
|
||||
|
||||
def sign_in_poltergeist(user, options = {})
|
||||
validate = options[:validate]
|
||||
validate = true if validate.nil?
|
||||
|
|
@ -175,6 +210,7 @@ end
|
|||
# skip the typical login form, which redirects to /client (slow due to extra login step).
|
||||
# So this just sets the cookie, and puts you where you want to be
|
||||
def fast_signin(user, url)
|
||||
visit '/'
|
||||
set_login_cookie(user)
|
||||
visit url
|
||||
end
|
||||
|
|
@ -486,7 +522,11 @@ def request_to_join_session(joiner, options)
|
|||
end
|
||||
|
||||
def emulate_client
|
||||
page.driver.headers = { 'User-Agent' => ' JamKazam ' }
|
||||
#page.driver.headers = { 'User-Agent' => ' JamKazam ' }
|
||||
#page.driver.header 'User-Agent', 'JamKazam'
|
||||
#page.driver.options[:headers].merge!({ 'User-Agent' => ' JamKazam ' })
|
||||
#Capybara.current_session.driver.header('User-Agent', 'JamKazam')
|
||||
# page.driver.browser.header('User-Agent', ' JamKazam ')
|
||||
end
|
||||
|
||||
def create_join_session(creator, joiners=[], options={})
|
||||
|
|
|
|||
Loading…
Reference in New Issue