affiliate-window 0.2.0.pre1 → 0.2.1.pre1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +48 -0
- data/Gemfile.lock +70 -0
- data/VERSION +1 -0
- data/affiliate-window-0.2.0.pre1.gem +0 -0
- data/affiliate-window.gemspec +68 -0
- data/lib/affiliate-window/account.rb +48 -0
- data/lib/affiliate-window/clients/affiliate_service.rb +45 -0
- data/lib/affiliate-window/clients/category.rb +19 -0
- data/lib/affiliate-window/clients/merchant.rb +32 -0
- data/lib/affiliate-window/clients/shop_window.rb +45 -0
- data/lib/affiliate-window/helpers/account.rb +25 -0
- data/lib/affiliate-window/helpers/client.rb +23 -0
- data/lib/affiliate-window/helpers/csv.rb +24 -0
- data/lib/affiliate-window/models/transaction.rb +92 -0
- data/lib/affiliate-window/version.rb +10 -0
- data/spec/affiliate_window/account_spec.rb +33 -0
- data/spec/affiliate_window/clients/affiliate_service_spec.rb +51 -0
- data/spec/affiliate_window/clients/category_spec.rb +39 -0
- data/spec/affiliate_window/clients/merchant_spec.rb +48 -0
- data/spec/affiliate_window/clients/shop_window_spec.rb +41 -0
- data/spec/affiliate_window/helpers/account_spec.rb +0 -0
- data/spec/affiliate_window/helpers/csv_spec.rb +43 -0
- data/spec/affiliate_window/models/transaction_spec.rb +44 -0
- data/spec/affiliate_window_spec.rb +28 -0
- data/spec/fixtures/csv/merchants.csv +3 -0
- data/spec/fixtures/responses/affiliate_service_v3.wsdl +1039 -0
- data/spec/fixtures/responses/get_transaction_list.xml +310 -0
- data/spec/fixtures/responses/gtl.xml +300 -0
- data/spec/fixtures/responses/merchants.csv +32 -0
- data/spec/helper.rb +62 -0
- data/wsdl/affiliate_service_v3.wsdl +1029 -0
- metadata +32 -1
@@ -0,0 +1,24 @@
|
|
1
|
+
module AffiliateWindow::Helpers
|
2
|
+
|
3
|
+
# Helper methods for CSV handling.
|
4
|
+
module Csv
|
5
|
+
|
6
|
+
def csv
|
7
|
+
@csv ||= AffiliateWindow.fetch(url)
|
8
|
+
end
|
9
|
+
|
10
|
+
def all
|
11
|
+
items = [];
|
12
|
+
each { |r| items << r }
|
13
|
+
items
|
14
|
+
end
|
15
|
+
|
16
|
+
def each
|
17
|
+
CSV.foreach(csv, :headers => true, :header_converters => :symbol) do |row|
|
18
|
+
yield(row.to_hash)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
# {:i_id=>"59330775", :s_status=>"confirmed", :s_type=>"normal", :s_ip=>"193.130.64.132", :b_paid=>false, :i_payment_id=>"0", :i_merchant_id=>"2698", :f_sale_amount=>"186.29", :f_commission_amount=>"7.45", :d_click_date=>"2011-10-31 17:36:03", :d_transaction_date=>"2011-11-01 12:37:41", :d_validation_date=>"2011-11-22 10:32:50", :s_clickref=>"1185896", :a_transaction_parts=>{:transaction_part=>{:s_commission_group_name=>"Default Commission", :f_sale_amount=>"186.29", :f_commission_amount=>"7.45", :i_commission=>"4", :s_commission_type=>"percentage"}}}
|
2
|
+
require 'hashie'
|
3
|
+
|
4
|
+
class Hash
|
5
|
+
def deep_find(key)
|
6
|
+
key?(key) ? self[key] : self.values.inject(nil) {|memo, v| memo ||= v.deep_find(key) if v.respond_to?(:deep_find) }
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
module AffiliateWindow
|
11
|
+
module Models
|
12
|
+
class Transaction < Hashie::Mash
|
13
|
+
|
14
|
+
include Savon::Model
|
15
|
+
|
16
|
+
CONVERSIONS = {
|
17
|
+
:i => :to_i,
|
18
|
+
:a => :to_a,
|
19
|
+
:f => :to_f,
|
20
|
+
:d => proc { |v| Time.parse(v) },
|
21
|
+
:s => :to_s
|
22
|
+
}
|
23
|
+
|
24
|
+
KEYS = %w{
|
25
|
+
i_id s_status s_type s_ip b_paid i_payment_id i_merchant_id f_sale_amount f_commission_amount d_click_date d_transaction_date
|
26
|
+
d_validation_date s_clickref a_transaction_parts
|
27
|
+
=>{:transaction_part=>{:s_commission_group_name=>"Default Commission", :f_sale_amount=>"186.29", :f_commission_amount=>"7.45", :i_commission=>"4", :s_commission_type=>"percentage"}}}
|
28
|
+
|
29
|
+
actions :get_transaction, :get_transaction_list
|
30
|
+
|
31
|
+
class << self
|
32
|
+
|
33
|
+
def account=(account)
|
34
|
+
@account = account
|
35
|
+
end
|
36
|
+
|
37
|
+
def account
|
38
|
+
@account || ::AffiliateWindow.account
|
39
|
+
end
|
40
|
+
|
41
|
+
def client
|
42
|
+
@client ||= ::AffiliateWindow::Clients::AffiliateService.new(account)
|
43
|
+
end
|
44
|
+
|
45
|
+
def today
|
46
|
+
initialize_collection_from_hash(get_transaction_list(
|
47
|
+
:d_start_date => Time.now - 3600 * 250,
|
48
|
+
:d_end_date => Time.now,
|
49
|
+
:s_date_type => 'validation'
|
50
|
+
))
|
51
|
+
end
|
52
|
+
|
53
|
+
def initialize_collection_from_xml(response)
|
54
|
+
puts response.to_xml
|
55
|
+
parse(response.to_xml)
|
56
|
+
end
|
57
|
+
|
58
|
+
def initialize_collection_from_hash(response)
|
59
|
+
response.to_hash.deep_find(:transaction).collect do |hash|
|
60
|
+
self.new(hash)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
protected
|
67
|
+
|
68
|
+
def convert_key(key)
|
69
|
+
key.to_s.gsub(/^[#{CONVERSIONS.keys.map(&:to_s).join}]_/, '')
|
70
|
+
end
|
71
|
+
|
72
|
+
def xx_convert_value(val, duping=false) #:nodoc:
|
73
|
+
case val
|
74
|
+
when self.class
|
75
|
+
val.dup
|
76
|
+
when ::Hash
|
77
|
+
val = val.dup if duping
|
78
|
+
self.class.new(val)
|
79
|
+
when Array
|
80
|
+
val.collect{ |e| convert_value(e) }
|
81
|
+
else
|
82
|
+
val
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def xx_id
|
87
|
+
attributes[:i_id].to_i
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../helper'
|
2
|
+
|
3
|
+
module AffiliateWindow
|
4
|
+
class AccountSpec < MiniTest::Unit::TestCase
|
5
|
+
|
6
|
+
Klass = ::AffiliateWindow::Account
|
7
|
+
|
8
|
+
describe Klass do
|
9
|
+
|
10
|
+
describe '#compression_parameter' do
|
11
|
+
it 'should return an empty string if compression is :none' do
|
12
|
+
@account = account
|
13
|
+
@account.compression = :none
|
14
|
+
@account.compression_parameter.must_equal ''
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'requires a datafeed password' do
|
18
|
+
proc { Klass.new(account.attributes.merge(:datafeed_password => nil)) }.must_raise ArgumentError
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'requires an API password' do
|
22
|
+
proc { Klass.new(account.attributes.merge(:api_password => nil)) }.must_raise ArgumentError
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'requires an API key' do
|
26
|
+
proc { Klass.new(account.attributes.merge(:api_key => nil)) }.must_raise ArgumentError
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
module AffiliateWindow
|
4
|
+
module Clients
|
5
|
+
|
6
|
+
Klass = ::AffiliateWindow::Clients::AffiliateService
|
7
|
+
|
8
|
+
describe Klass do
|
9
|
+
|
10
|
+
it 'has a local cache of the WSDL document' do
|
11
|
+
File.exists?(Klass::CACHED_WSDL_PATH).must_equal true
|
12
|
+
end
|
13
|
+
|
14
|
+
describe '.new' do
|
15
|
+
it 'requires an account' do
|
16
|
+
proc { Klass.new }.must_raise ArgumentError
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe 'Instances' do
|
21
|
+
before do
|
22
|
+
FakeWeb.register_uri(:any, Klass::ENDPOINT_URL, :response => File.join(fixture_path, 'responses', 'get_transaction_list.xml'))
|
23
|
+
@client = Klass.new(account)
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'has an array of actions' do
|
27
|
+
@client.wsdl.soap_actions.must_equal Klass::ACTIONS
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'returns a transaction list' do
|
31
|
+
method = :get_transaction_list
|
32
|
+
response = @client.request(method) do
|
33
|
+
soap.body = {
|
34
|
+
:d_start_date => Time.now - 3600 * 250,
|
35
|
+
:d_end_date => Time.now,
|
36
|
+
:s_date_type => 'validation'
|
37
|
+
}
|
38
|
+
end
|
39
|
+
response.soap_fault?.must_equal false
|
40
|
+
response.http_error?.must_equal false
|
41
|
+
response.success?.must_equal true
|
42
|
+
response.to_hash[:"#{method}_response"].must_be_instance_of Hash
|
43
|
+
response.to_hash[:"#{method}_response"][:"#{method}_return"][:transaction].must_be_instance_of Array
|
44
|
+
transaction = response.to_hash[:"#{method}_response"][:"#{method}_return"][:transaction].first
|
45
|
+
transaction.must_be_instance_of Hash
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require_relative '../../helper'
|
2
|
+
|
3
|
+
module AffiliateWindow
|
4
|
+
module Clients
|
5
|
+
class CategorySpec < MiniTest::Unit::TestCase
|
6
|
+
|
7
|
+
Klass = AffiliateWindow::Clients::Category
|
8
|
+
|
9
|
+
describe Klass do
|
10
|
+
|
11
|
+
describe '.new' do
|
12
|
+
it 'requires an account' do
|
13
|
+
proc { Klass.new }.must_raise ArgumentError
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe 'Instances' do
|
18
|
+
before do
|
19
|
+
@client = Klass.new(account)
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'handles CSV files' do
|
23
|
+
@client.must_respond_to :csv
|
24
|
+
@client.must_respond_to :each
|
25
|
+
@client.must_respond_to :all
|
26
|
+
end
|
27
|
+
|
28
|
+
describe '#url' do
|
29
|
+
it 'returns a completed URL template' do
|
30
|
+
@client.url.must_match /#{account.user}/
|
31
|
+
@client.url.must_match /#{account.datafeed_password}/
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require_relative '../../helper'
|
2
|
+
|
3
|
+
module AffiliateWindow
|
4
|
+
module Clients
|
5
|
+
class MerchantSpec < MiniTest::Unit::TestCase
|
6
|
+
|
7
|
+
Klass = ::AffiliateWindow::Clients::Merchant
|
8
|
+
|
9
|
+
describe Klass do
|
10
|
+
|
11
|
+
describe '.new' do
|
12
|
+
it 'requires an account' do
|
13
|
+
proc { Klass.new }.must_raise ArgumentError
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'sets a default filter' do
|
17
|
+
client = Klass.new(nil, account)
|
18
|
+
client.filter.wont_be_empty
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'raises an error if filter is invalid' do
|
22
|
+
proc { Klass.new('DUFF_FILTER', account) }.must_raise ArgumentError
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe 'Instances' do
|
27
|
+
before do
|
28
|
+
@client = Klass.new(nil, account)
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'handles CSV files' do
|
32
|
+
@client.must_respond_to :csv
|
33
|
+
@client.must_respond_to :each
|
34
|
+
@client.must_respond_to :all
|
35
|
+
end
|
36
|
+
|
37
|
+
describe '#url' do
|
38
|
+
it 'returns a completed URL template' do
|
39
|
+
@client.url.must_match /#{account.user}/
|
40
|
+
@client.url.must_match /#{account.datafeed_password}/
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require_relative '../../helper'
|
2
|
+
|
3
|
+
module AffiliateWindow
|
4
|
+
module Clients
|
5
|
+
class ShopWindowSpec < MiniTest::Unit::TestCase
|
6
|
+
|
7
|
+
Klass = ::AffiliateWindow::Clients::ShopWindow
|
8
|
+
|
9
|
+
describe Klass do
|
10
|
+
|
11
|
+
describe '.new' do
|
12
|
+
it 'requires an account' do
|
13
|
+
proc { Klass.new }.must_raise ArgumentError
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe 'Instances' do
|
18
|
+
before do
|
19
|
+
@merchant_ids = [1,2,3]
|
20
|
+
@client = Klass.new(:account => account, :merchant_ids => @merchant_ids)
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'handles CSV files' do
|
24
|
+
@client.must_respond_to :csv
|
25
|
+
@client.must_respond_to :each
|
26
|
+
@client.must_respond_to :all
|
27
|
+
end
|
28
|
+
|
29
|
+
describe '#url' do
|
30
|
+
it 'returns a completed URL template' do
|
31
|
+
@client.url.must_match /#{account.api_key}/
|
32
|
+
@client.url.must_match /#{@merchant_ids.join(',')}/
|
33
|
+
@client.url.must_match /#{Klass::DEFAULT_COLUMNS.join(',')}/
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
File without changes
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../../helper'
|
2
|
+
|
3
|
+
module AffiliateWindow
|
4
|
+
module Helpers
|
5
|
+
class CsvSpec < MiniTest::Unit::TestCase
|
6
|
+
|
7
|
+
class ExtendedByCsvHelper
|
8
|
+
include AffiliateWindow::Helpers::Csv
|
9
|
+
def url; "http://example.com/"; end
|
10
|
+
end
|
11
|
+
|
12
|
+
describe ::AffiliateWindow::Helpers::Csv do
|
13
|
+
before do
|
14
|
+
@instance = ExtendedByCsvHelper.new
|
15
|
+
end
|
16
|
+
|
17
|
+
describe '#csv' do
|
18
|
+
it 'should return CSV path' do
|
19
|
+
AffiliateWindow.stubs(:fetch).returns('/path/to/file.csv')
|
20
|
+
@instance.csv
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe '#each' do
|
25
|
+
it 'should return each item in the CSV as a hash with symbolized keys' do
|
26
|
+
AffiliateWindow.stubs(:fetch).returns(File.join(fixture_path, 'csv', 'merchants.csv'))
|
27
|
+
@instance.each do |r|
|
28
|
+
r.must_be_kind_of Hash
|
29
|
+
r.keys.map(&:class).uniq.must_equal [Symbol]
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe '#all' do
|
35
|
+
it 'should return all items in the CSV' do
|
36
|
+
AffiliateWindow.stubs(:fetch).returns(File.join(fixture_path, 'csv', 'merchants.csv'))
|
37
|
+
@instance.all.size.must_equal 2
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../../helper'
|
2
|
+
|
3
|
+
module AffiliateWindow
|
4
|
+
module Models
|
5
|
+
class TransactionSpec < MiniTest::Unit::TestCase
|
6
|
+
|
7
|
+
Klass = ::AffiliateWindow::Models::Transaction
|
8
|
+
|
9
|
+
describe Klass do
|
10
|
+
|
11
|
+
before do
|
12
|
+
FakeWeb.register_uri(:any, AffiliateWindow::Clients::AffiliateService::ENDPOINT_URL, :response => File.join(fixture_path, 'responses', 'get_transaction_list.xml'))
|
13
|
+
Klass.account = account
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'stores an account' do
|
17
|
+
Klass.account.must_be_kind_of AffiliateWindow::Account
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'returns a transaction list' do
|
21
|
+
method = :get_transaction_list
|
22
|
+
Klass.get_transaction_list(
|
23
|
+
:d_start_date => Time.now - 3600 * 250,
|
24
|
+
:d_end_date => Time.now,
|
25
|
+
:s_date_type => 'validation'
|
26
|
+
).must_be_kind_of Savon::SOAP::Response
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'returns transactions from today' do
|
30
|
+
collection = Klass.today
|
31
|
+
transaction = collection.first
|
32
|
+
|
33
|
+
collection.must_be_kind_of Array
|
34
|
+
transaction.must_be_kind_of Klass
|
35
|
+
transaction.id.must_equal '59330775'
|
36
|
+
|
37
|
+
transaction.transaction_parts.must_be_kind_of Array
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class AffiliateWindowSpec < MiniTest::Unit::TestCase
|
4
|
+
|
5
|
+
describe ::AffiliateWindow do
|
6
|
+
|
7
|
+
it "should store an account" do
|
8
|
+
@account = account
|
9
|
+
AffiliateWindow.account = @account
|
10
|
+
AffiliateWindow.account.must_be_same_as @account
|
11
|
+
AffiliateWindow.account = nil # teardown
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should have a default user agent string" do
|
15
|
+
AffiliateWindow.user_agent.must_match /AffiliateWindow/
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should store a custom user agent string" do
|
19
|
+
AffiliateWindow.user_agent = 'AffiliateWindow test'
|
20
|
+
AffiliateWindow.user_agent.must_equal 'AffiliateWindow test'
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should fetch files and return the local filename" do
|
24
|
+
FakeWeb.register_uri(:any, 'http://affiliatewindow.com/merchants.csv', :response => File.join(fixture_path, 'responses', 'merchants.csv'))
|
25
|
+
AffiliateWindow.fetch('http://affiliatewindow.com/merchants.csv', '/tmp/test').must_equal '/tmp/test'
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|