affiliate-window 0.2.0.pre1 → 0.2.1.pre1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|