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.
Files changed (33) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +48 -0
  3. data/Gemfile.lock +70 -0
  4. data/VERSION +1 -0
  5. data/affiliate-window-0.2.0.pre1.gem +0 -0
  6. data/affiliate-window.gemspec +68 -0
  7. data/lib/affiliate-window/account.rb +48 -0
  8. data/lib/affiliate-window/clients/affiliate_service.rb +45 -0
  9. data/lib/affiliate-window/clients/category.rb +19 -0
  10. data/lib/affiliate-window/clients/merchant.rb +32 -0
  11. data/lib/affiliate-window/clients/shop_window.rb +45 -0
  12. data/lib/affiliate-window/helpers/account.rb +25 -0
  13. data/lib/affiliate-window/helpers/client.rb +23 -0
  14. data/lib/affiliate-window/helpers/csv.rb +24 -0
  15. data/lib/affiliate-window/models/transaction.rb +92 -0
  16. data/lib/affiliate-window/version.rb +10 -0
  17. data/spec/affiliate_window/account_spec.rb +33 -0
  18. data/spec/affiliate_window/clients/affiliate_service_spec.rb +51 -0
  19. data/spec/affiliate_window/clients/category_spec.rb +39 -0
  20. data/spec/affiliate_window/clients/merchant_spec.rb +48 -0
  21. data/spec/affiliate_window/clients/shop_window_spec.rb +41 -0
  22. data/spec/affiliate_window/helpers/account_spec.rb +0 -0
  23. data/spec/affiliate_window/helpers/csv_spec.rb +43 -0
  24. data/spec/affiliate_window/models/transaction_spec.rb +44 -0
  25. data/spec/affiliate_window_spec.rb +28 -0
  26. data/spec/fixtures/csv/merchants.csv +3 -0
  27. data/spec/fixtures/responses/affiliate_service_v3.wsdl +1039 -0
  28. data/spec/fixtures/responses/get_transaction_list.xml +310 -0
  29. data/spec/fixtures/responses/gtl.xml +300 -0
  30. data/spec/fixtures/responses/merchants.csv +32 -0
  31. data/spec/helper.rb +62 -0
  32. data/wsdl/affiliate_service_v3.wsdl +1029 -0
  33. 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,10 @@
1
+ module AffiliateWindow
2
+ module Version
3
+ MAJOR = 0
4
+ MINOR = 2
5
+ PATCH = 1
6
+ BUILD = 'pre1'
7
+
8
+ STRING = [MAJOR, MINOR, PATCH, BUILD].compact.join('.')
9
+ end
10
+ 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
@@ -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