cheddargetter_client_ruby 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/Gemfile ADDED
@@ -0,0 +1,11 @@
1
+ source "http://rubygems.org"
2
+ gem "httparty", ">= 0.4.3"
3
+
4
+
5
+ group :development do
6
+ gem "shoulda", ">= 0"
7
+ gem "bundler", "~> 1.0.0"
8
+ gem "jeweler", "~> 1.5.1"
9
+ gem "rcov", ">= 0"
10
+ gem "ruby-debug"
11
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,32 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ columnize (0.3.2)
5
+ crack (0.1.8)
6
+ git (1.2.5)
7
+ httparty (0.6.1)
8
+ crack (= 0.1.8)
9
+ jeweler (1.5.1)
10
+ bundler (~> 1.0.0)
11
+ git (>= 1.2.5)
12
+ rake
13
+ linecache (0.43)
14
+ rake (0.8.7)
15
+ rcov (0.9.9)
16
+ ruby-debug (0.10.4)
17
+ columnize (>= 0.1)
18
+ ruby-debug-base (~> 0.10.4.0)
19
+ ruby-debug-base (0.10.4)
20
+ linecache (>= 0.3)
21
+ shoulda (2.11.3)
22
+
23
+ PLATFORMS
24
+ ruby
25
+
26
+ DEPENDENCIES
27
+ bundler (~> 1.0.0)
28
+ httparty (>= 0.4.3)
29
+ jeweler (~> 1.5.1)
30
+ rcov
31
+ ruby-debug
32
+ shoulda
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License
2
+
3
+ Copyright (c) 2010 Expected Behavior, LLC
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,68 @@
1
+ = Cheddar Getter API Client for Ruby
2
+
3
+ This is a Ruby wrapper for the CheddarGetter[http://cheddargetter.com] API.
4
+ It allows you to interface with the Cheddar Getter API using simple calls, i.e.:
5
+
6
+ client = CheddarGetter::Client.new(:product_code => "YOUR_PRODUCT_CODE",
7
+ :username => "your.username@example.com",
8
+ :password => "your.password")
9
+
10
+ client.new_customer(
11
+ :code => 'EXAMPLE_CUSTOMER',
12
+ :firstName => 'Example',
13
+ :lastName => 'Customer',
14
+ :email => 'example_customer@example.com',
15
+ :subscription => {
16
+ :planCode => 'THE_PLAN_CODE',
17
+ :ccFirstName => 'Example',
18
+ :ccLastName' => 'Customer',
19
+ :ccNumber' => '4111111111111111',
20
+ :ccExpiration => '04/2011',
21
+ :ccZip' => '90210'
22
+ }
23
+ )
24
+
25
+ See the `example` directory for more usage examples.
26
+ It is modeled directly after cheddargetter-client-php[https://github.com/marcguyer/cheddargetter-client-php], the official PHP library, with a number of ruby-isms to make life easier.
27
+
28
+
29
+ == Installation
30
+
31
+ This library should be installed as a gem. It is hosted on Gemcutter[http://gemcutter.org].
32
+
33
+ If you don't have your system set up to use gemcutter, follow the instructions on their site, i.e.:
34
+
35
+ $ gem install gemcutter
36
+ $ gem tumble
37
+
38
+ This will install Gemcutter and set your gem sources to search the gemcutter repos.
39
+
40
+ Then you can install this library as a gem:
41
+
42
+ $ gem install cheddargetter_client_ruby
43
+
44
+
45
+ === Requirements
46
+
47
+ This library requires HTTParty version 0.4.3 or greater.
48
+
49
+ $ gem install httparty
50
+
51
+
52
+ === Usage
53
+
54
+ Simply require this library before you use it:
55
+
56
+ require 'cheddargetter_client_ruby'
57
+
58
+
59
+ If you're using Rails, you could include this gem in your configuration, i.e. in `environment.rb`
60
+
61
+ config.gem 'cheddargetter_client_ruby'
62
+
63
+ Check out the example[https://github.com/expectedbehavior/cheddargetter_client_ruby/tree/master/example] to see usage details. You can also check out the Cheddar Getter API documention[http://cheddargetter.com/developers].
64
+
65
+ == Copyright
66
+
67
+ Copyright (c) 2010 Expected Behavior. See LICENSE.txt for further details.
68
+
data/Rakefile ADDED
@@ -0,0 +1,49 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ begin
4
+ Bundler.setup(:default, :development)
5
+ rescue Bundler::BundlerError => e
6
+ $stderr.puts e.message
7
+ $stderr.puts "Run `bundle install` to install missing gems"
8
+ exit e.status_code
9
+ end
10
+ require 'rake'
11
+
12
+ require 'jeweler'
13
+ Jeweler::Tasks.new do |gem|
14
+ gem.name = "cheddargetter_client_ruby"
15
+ gem.homepage = "http://github.com/expectedbehavior/cheddargetter_client_ruby"
16
+ gem.license = "MIT"
17
+ gem.summary = "A CheddarGetter API wrapper for Ruby"
18
+ gem.description = "A CheddarGetter API wrapper for Ruby"
19
+ gem.email = "support@expectedbehavior.com"
20
+ gem.authors = ["Expected Behavior"]
21
+ gem.add_runtime_dependency 'httparty', '>= 0.4.3'
22
+ end
23
+ Jeweler::RubygemsDotOrgTasks.new
24
+
25
+ require 'rake/testtask'
26
+ Rake::TestTask.new(:test) do |test|
27
+ test.libs << 'lib' << 'test'
28
+ test.pattern = 'test/**/test_*.rb'
29
+ test.verbose = true
30
+ end
31
+
32
+ require 'rcov/rcovtask'
33
+ Rcov::RcovTask.new do |test|
34
+ test.libs << 'test'
35
+ test.pattern = 'test/**/test_*.rb'
36
+ test.verbose = true
37
+ end
38
+
39
+ task :default => :test
40
+
41
+ require 'rake/rdoctask'
42
+ Rake::RDocTask.new do |rdoc|
43
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
44
+
45
+ rdoc.rdoc_dir = 'rdoc'
46
+ rdoc.title = "cheddargetter_client_ruby #{version}"
47
+ rdoc.rdoc_files.include('README*')
48
+ rdoc.rdoc_files.include('lib/**/*.rb')
49
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
@@ -0,0 +1,79 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{cheddargetter_client_ruby}
8
+ s.version = "0.1.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Expected Behavior"]
12
+ s.date = %q{2010-12-09}
13
+ s.description = %q{A CheddarGetter API wrapper for Ruby}
14
+ s.email = %q{support@expectedbehavior.com}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE.txt",
17
+ "README.rdoc"
18
+ ]
19
+ s.files = [
20
+ ".document",
21
+ "Gemfile",
22
+ "Gemfile.lock",
23
+ "LICENSE.txt",
24
+ "README.rdoc",
25
+ "Rakefile",
26
+ "VERSION",
27
+ "cheddargetter_client_ruby.gemspec",
28
+ "example/README",
29
+ "example/example.rb",
30
+ "lib/cheddar_getter/client.rb",
31
+ "lib/cheddar_getter/client_exception.rb",
32
+ "lib/cheddar_getter/response.rb",
33
+ "lib/cheddar_getter/response_exception.rb",
34
+ "lib/cheddargetter_client_ruby.rb",
35
+ "test/helper.rb",
36
+ "test/test_cheddargetter_client_ruby.rb"
37
+ ]
38
+ s.homepage = %q{http://github.com/expectedbehavior/cheddargetter_client_ruby}
39
+ s.licenses = ["MIT"]
40
+ s.require_paths = ["lib"]
41
+ s.rubygems_version = %q{1.3.7}
42
+ s.summary = %q{A CheddarGetter API wrapper for Ruby}
43
+ s.test_files = [
44
+ "test/helper.rb",
45
+ "test/test_cheddargetter_client_ruby.rb"
46
+ ]
47
+
48
+ if s.respond_to? :specification_version then
49
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
50
+ s.specification_version = 3
51
+
52
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
53
+ s.add_runtime_dependency(%q<httparty>, [">= 0.4.3"])
54
+ s.add_development_dependency(%q<shoulda>, [">= 0"])
55
+ s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
56
+ s.add_development_dependency(%q<jeweler>, ["~> 1.5.1"])
57
+ s.add_development_dependency(%q<rcov>, [">= 0"])
58
+ s.add_development_dependency(%q<ruby-debug>, [">= 0"])
59
+ s.add_runtime_dependency(%q<httparty>, [">= 0.4.3"])
60
+ else
61
+ s.add_dependency(%q<httparty>, [">= 0.4.3"])
62
+ s.add_dependency(%q<shoulda>, [">= 0"])
63
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
64
+ s.add_dependency(%q<jeweler>, ["~> 1.5.1"])
65
+ s.add_dependency(%q<rcov>, [">= 0"])
66
+ s.add_dependency(%q<ruby-debug>, [">= 0"])
67
+ s.add_dependency(%q<httparty>, [">= 0.4.3"])
68
+ end
69
+ else
70
+ s.add_dependency(%q<httparty>, [">= 0.4.3"])
71
+ s.add_dependency(%q<shoulda>, [">= 0"])
72
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
73
+ s.add_dependency(%q<jeweler>, ["~> 1.5.1"])
74
+ s.add_dependency(%q<rcov>, [">= 0"])
75
+ s.add_dependency(%q<ruby-debug>, [">= 0"])
76
+ s.add_dependency(%q<httparty>, [">= 0.4.3"])
77
+ end
78
+ end
79
+
data/example/README ADDED
@@ -0,0 +1,9 @@
1
+ The example script requires modification to work for your purposes.
2
+
3
+ The username, password and productCode must be customized.
4
+
5
+ The script makes use of two different pricing plans:
6
+ * A free plan with code=FREE
7
+ * A paid plan with code=PREMIUM
8
+
9
+ You must either create these pricing plans in the CG admin GUI or substitute your own plan codes
@@ -0,0 +1,122 @@
1
+ require 'rubygems'
2
+ require 'cheddargetter_client_ruby'
3
+
4
+ FREE_PLAN = "FREE"
5
+ PAID_PLAN = "PREMIUM"
6
+
7
+ client = CheddarGetter::Client.new(:product_code => "YOUR_PRODUCT_CODE",
8
+ :username => "your.username@example.com",
9
+ :password => "your.password")
10
+
11
+ puts ""
12
+ puts "********************************************************************"
13
+ puts "** DELETING PREVIOUSLY CREATED EXAMPLE CUSTOMERS **"
14
+ puts "********************************************************************"
15
+
16
+ # delete customers if they're already there
17
+ response = client.delete_all_customers
18
+ if response.valid?
19
+ puts "\tDeleted old customers"
20
+ else
21
+ puts "\tERROR: #{response.error_message}"
22
+ end
23
+
24
+ puts ""
25
+ puts "********************************************************************"
26
+ puts "** CREATE CUSTOMER ON THE FREE PLAN **"
27
+ puts "********************************************************************"
28
+
29
+ # create a customer on a free plan
30
+ data = {
31
+ :code => 'MILTON_WADDAMS',
32
+ :firstName => 'Milton',
33
+ :lastName => 'Waddams',
34
+ :email => 'milt@initech.com',
35
+ :subscription => {
36
+ :planCode => FREE_PLAN
37
+ }
38
+ }
39
+
40
+ response = client.new_customer(data)
41
+ if response.valid?
42
+ puts "\tCreated Milton Waddams with code=MILTON_WADDAMS"
43
+ else
44
+ puts "\tERROR: #{response.error_message}"
45
+ end
46
+
47
+ puts ""
48
+ puts "********************************************************************"
49
+ puts "** SIMULATE ERROR CREATING CUSTOMER ON PAID PLAN **"
50
+ puts "********************************************************************"
51
+
52
+ # try to create a customer on a paid plan (simulated error)
53
+ data = {
54
+ :code => 'BILL_LUMBERG',
55
+ :firstName => 'Bill',
56
+ :lastName => 'Lumberg',
57
+ :email => 'bill@initech.com',
58
+ :subscription => {
59
+ :planCode => PAID_PLAN,
60
+ :ccNumber => '4111111111111111',
61
+ :ccExpiration => '10/2014',
62
+ :ccCardCode => '123',
63
+ :ccFirstName => 'Bill',
64
+ :ccLastName => 'Lumberg',
65
+ :ccZip => '05003' # simulates an error of "Credit card type is not accepted"
66
+ }
67
+ }
68
+
69
+ response = client.new_customer(data)
70
+ if response.valid?
71
+ puts "\tCreated Bill Lumberg with code=BILL_LUMBERG. (This should not have happened)"
72
+ else
73
+ puts "\tExpect Error: #{response.error_message}"
74
+ end
75
+
76
+ puts ""
77
+ puts "********************************************************************"
78
+ puts "** CREATE CUSTOMER ON PAID PLAN AND GET CURRENT **"
79
+ puts "** INVOICE INFORMATION **"
80
+ puts "********************************************************************"
81
+
82
+ data = {
83
+ :code => 'BILL_LUMBERG',
84
+ :firstName => 'Bill',
85
+ :lastName => 'Lumberg',
86
+ :email => 'bill@initech.com',
87
+ :subscription => {
88
+ :planCode => PAID_PLAN,
89
+ :ccNumber => '4111111111111111',
90
+ :ccExpiration => '10/2014',
91
+ :ccCardCode => '123',
92
+ :ccFirstName => 'Bill',
93
+ :ccLastName => 'Lumberg',
94
+ :ccZip => '90210'
95
+ }
96
+ }
97
+
98
+
99
+ response = client.new_customer(data)
100
+ if response.valid?
101
+ puts "\tCreated Bill Lumberg with code=BILL_LUMBERG"
102
+ else
103
+ puts "\tERROR: #{response.error_message}"
104
+ end
105
+
106
+ #get lumberg and display current details
107
+ response = client.get_customer(:code => 'BILL_LUMBERG')
108
+ if response.valid?
109
+ customer = response.customer
110
+ subscription = response.customer_subscription
111
+ plan = response.customer_plan
112
+ invoice = response.customer_invoice
113
+
114
+ puts "\t#{customer[:firstName]} #{customer[:lastName]}"
115
+ puts "\tPricing Plan: #{plan[:name]}"
116
+ puts "\tPending Invoice Scheduled: #{invoice[:billingDatetime].strftime('%m/%d/%Y')}"
117
+ invoice[:charges].each do |charge|
118
+ puts "\t\t(#{charge[:quantity]}) #{charge[:code]} $#{charge[:eachAmount]*charge[:quantity]}"
119
+ end
120
+ else
121
+ puts "\tERROR: #{response.error_message}"
122
+ end
@@ -0,0 +1,385 @@
1
+ module CheddarGetter
2
+ class Client
3
+ include HTTParty
4
+
5
+ base_uri "https://cheddargetter.com/"
6
+ attr_accessor :product_code, :product_id, :username, :password
7
+
8
+ #options:
9
+ #
10
+ #{
11
+ # :username => required, your CheddarGetter username
12
+ # :password => required, your CheddarGetter password
13
+ # :product_id => this or product_code is required
14
+ # :product_code => this or product_id is required
15
+ #}
16
+ def initialize(options = { })
17
+ self.product_code = options[:product_code]
18
+ self.product_id = options[:product_id]
19
+ self.username = options[:username]
20
+ self.password = options[:password]
21
+
22
+ raise CheddarGetter::ClientException.new(":username is required") unless self.username
23
+ raise CheddarGetter::ClientException.new(":password is required") unless self.password
24
+ unless self.product_code || self.product_id
25
+ raise CheddarGetter::ClientException.new(":product_code or :product_id are required")
26
+ end
27
+ end
28
+
29
+ #https://cheddargetter.com/developers#all-plans
30
+ def get_plans
31
+ do_request(:item => :plans, :action => :get)
32
+ end
33
+
34
+ #https://cheddargetter.com/developers#single-plan
35
+ #
36
+ #id_hash: {:code => plan_code} OR {:id => plan_id}
37
+ def get_plan(id_hash = { })
38
+ do_request(:item => :plans, :action => :get, :id_hash => id_hash)
39
+ end
40
+
41
+ #https://cheddargetter.com/developers#all-customers
42
+ #
43
+ #Any, all, or none of this data hash can be given.
44
+ #It just filters the returned customers
45
+ #
46
+ #data:
47
+ #
48
+ #{
49
+ # :subscriptionStatus => "activeOnly" or "canceledOnly",
50
+ # :planCode => plan_code, #can take an array of plan codes
51
+ # :createdAfterDate => date,
52
+ # :createdBeforeDate => date,
53
+ # :canceledAfterDate => date,
54
+ # :canceledBeforeDate => date,
55
+ # :orderBy => "name" (default), "company", "plan", "billingDatetime" or "createdDatetime"
56
+ # :orderByDirection => "asc" (default) or "desc"
57
+ # :search => Tcustomer name, company, email address and last four digits of credit card.
58
+ #}
59
+ def get_customers(data = nil)
60
+ do_request(:item => :customers, :action => :get, :data => data)
61
+ end
62
+
63
+ #https://cheddargetter.com/developers#single-customer
64
+ #
65
+ #id_hash: {:code => customer_code} OR {:id => customer_id}
66
+ def get_customer(id_hash = { })
67
+ do_request(:item => :customers, :action => :get, :id_hash => id_hash)
68
+ end
69
+
70
+ #https://cheddargetter.com/developers#add-customer
71
+ #
72
+ #data:
73
+ #
74
+ #{
75
+ # :code => required,
76
+ # :firstName => required,
77
+ # :lastName => required,
78
+ # :email => required,
79
+ # :company => not_required,
80
+ # :isVatExempt => not_required,
81
+ # :vatNumber => not_required,
82
+ # :notes => not_required,
83
+ # :firstContactDatetime => not_required,
84
+ # :referer => not_required,
85
+ # :campaignTerm => not_required,
86
+ # :campaignName => not_required,
87
+ # :campaignSource => not_required,
88
+ # :campaignMedium => not_required,
89
+ # :campaignContent => not_required,
90
+ # :metaData => { #not_required
91
+ # :any_user_defined_value => not_required
92
+ # },
93
+ # :subscription => { #required
94
+ # :planCode => required,
95
+ # :initialBillDate => not_required,
96
+ # :ccNumber => required_if_not_free,
97
+ # :ccExpiration => required_if_not_free,
98
+ # :ccCardCode => required_if_not_free,
99
+ # :ccFirstName => required_if_not_free,
100
+ # :ccLastName => required_if_not_free,
101
+ # :ccCompany => not_required,
102
+ # :ccCountry => not_required,
103
+ # :ccAddress => not_required,
104
+ # :ccCity => not_required,
105
+ # :ccState => not_required,
106
+ # :ccZip => required_if_not_free
107
+ # },
108
+ # :charges => { #not required
109
+ # :user_defined => {
110
+ # :chargeCode => required_if_adding_a_charge,
111
+ # :quantity => required_if_adding_a_charge,
112
+ # :eachAmount => required_if_adding_a_charge,
113
+ # :description => not_required
114
+ # }
115
+ # },
116
+ # :items => { #not required
117
+ # :user_defined => {
118
+ # :itemCode => required_if_setting_an_item,
119
+ # :quantity => required_if_setting_an_item
120
+ # }
121
+ # }
122
+ #}
123
+ def new_customer(data = { })
124
+ do_request(:item => :customers, :action => :new, :data => data)
125
+ end
126
+
127
+ #https://cheddargetter.com/developers#update-customer-subscription
128
+ #
129
+ #id_hash: {:code => customer_code} OR {:id => customer_id}
130
+ #
131
+ #data:
132
+ #
133
+ #{
134
+ # :firstName => not_required,
135
+ # :lastName => not_required,
136
+ # :email => not_required,
137
+ # :company => not_required,
138
+ # :isVatExempt => not_required,
139
+ # :vatNumber => not_required,
140
+ # :notes => not_required,
141
+ # :firstContactDatetime => not_required,
142
+ # :referer => not_required,
143
+ # :campaignTerm => not_required,
144
+ # :campaignName => not_required,
145
+ # :campaignSource => not_required,
146
+ # :campaignMedium => not_required,
147
+ # :campaignContent => not_required,
148
+ # :metaData => { #not_required
149
+ # :any_user_defined_value => not_required
150
+ # },
151
+ # :subscription => { #not_required
152
+ # :planCode => not_required,
153
+ # :changeBillDate => not_required,
154
+ # :ccNumber => not_required_unless_plan_change_from_free_to_paid,
155
+ # :ccExpiration => not_required_unless_plan_change_from_free_to_paid,
156
+ # :ccCardCode => not_required_unless_plan_change_from_free_to_paid,
157
+ # :ccFirstName => not_required_unless_plan_change_from_free_to_paid,
158
+ # :ccLastName => not_required_unless_plan_change_from_free_to_paid,
159
+ # :ccCompany => not_required,
160
+ # :ccCountry => not_required,
161
+ # :ccAddress => not_required,
162
+ # :ccCity => not_required,
163
+ # :ccState => not_required,
164
+ # :ccZip => not_required_unless_plan_change_from_free_to_paid
165
+ # },
166
+ #}
167
+ def edit_customer(id_hash = { }, data = { })
168
+ do_request(:item => :customers, :action => :edit, :id_hash => id_hash, :data => data)
169
+ end
170
+
171
+ #https://cheddargetter.com/developers#update-customer
172
+ #
173
+ #id_hash: {:code => customer_code} OR {:id => customer_id}
174
+ #
175
+ #data:
176
+ #
177
+ #{
178
+ # :firstName => not_required,
179
+ # :lastName => not_required,
180
+ # :email => not_required,
181
+ # :company => not_required,
182
+ # :notes => not_required,
183
+ # :metaData => { #not_required
184
+ # :any_user_defined_value => not_required
185
+ # },
186
+ #}
187
+ def edit_customer_only(id_hash = { }, data = { })
188
+ do_request(:item => :customers, :action => "edit-customer", :id_hash => id_hash, :data => data)
189
+ end
190
+
191
+ #https://cheddargetter.com/developers#delete-customer
192
+ #
193
+ #id_hash: {:code => customer_code} OR {:id => customer_id}
194
+ def delete_customer(id_hash = { })
195
+ do_request(:item => :customers, :action => :delete, :id_hash => id_hash)
196
+ end
197
+
198
+ #https://cheddargetter.com/developers#delete-all-customers
199
+ def delete_all_customers
200
+ do_request(:item => :customers, :action => "delete-all/confirm/1")
201
+ end
202
+
203
+ #https://cheddargetter.com/developers#update-subscription
204
+ #
205
+ #id_hash: {:code => customer_code} OR {:id => customer_id}
206
+ #
207
+ #data:
208
+ #
209
+ #{
210
+ # :planCode => not_required,
211
+ # :changeBillDate => not_required,
212
+ # :ccNumber => not_required_unless_plan_change_from_free_to_paid,
213
+ # :ccExpiration => not_required_unless_plan_change_from_free_to_paid,
214
+ # :ccCardCode => not_required_unless_plan_change_from_free_to_paid,
215
+ # :ccFirstName => not_required_unless_plan_change_from_free_to_paid,
216
+ # :ccLastName => not_required_unless_plan_change_from_free_to_paid,
217
+ # :ccCompany => not_required,
218
+ # :ccCountry => not_required,
219
+ # :ccAddress => not_required,
220
+ # :ccCity => not_required,
221
+ # :ccState => not_required,
222
+ # :ccZip => not_required_unless_plan_change_from_free_to_paid
223
+ #}
224
+ def edit_subscription(id_hash = { }, data = { })
225
+ do_request(:item => :customers, :action => "edit-subscription", :id_hash => id_hash, :data => data)
226
+ end
227
+
228
+ #https://cheddargetter.com/developers#cancel-subscription
229
+ #
230
+ #id_hash: {:code => customer_code} OR {:id => customer_id}
231
+ def cancel_subscription(id_hash = { })
232
+ do_request(:item => :customers, :action => :cancel, :id_hash => id_hash)
233
+ end
234
+
235
+ #https://cheddargetter.com/developers#add-item-quantity
236
+ #
237
+ #id_hash:
238
+ #
239
+ #{
240
+ # :code => Either code or id are required (this is the customer code)
241
+ # :id => Either code or id are required (this is the customer id)
242
+ # :item_code => Either item code or item id are required
243
+ # :item_id => Either item code or item id are required
244
+ #}
245
+ #
246
+ #data: (not required)
247
+ #
248
+ #{ :quantity => treated_as_1_if_not_set }
249
+ def add_item_quantity(id_hash = { }, data = { })
250
+ do_request(:item => :customers, :action => "add-item-quantity", :id_hash => id_hash,
251
+ :data => data, :add_item_id => true)
252
+ end
253
+
254
+ #https://cheddargetter.com/developers#remove-item-quantity
255
+ #
256
+ #id_hash:
257
+ #
258
+ #{
259
+ # :code => Either code or id are required (this is the customer code)
260
+ # :id => Either code or id are required (this is the customer id)
261
+ # :item_code => Either item code or item id are required
262
+ # :item_id => Either item code or item id are required
263
+ #}
264
+ #
265
+ #data: (not required)
266
+ #
267
+ #{ :quantity => treated_as_1_if_not_set }
268
+ def remove_item_quantity(id_hash = { }, data = { })
269
+ do_request(:item => :customers, :action => "remove-item-quantity", :id_hash => id_hash,
270
+ :data => data, :add_item_id => true)
271
+ end
272
+
273
+ #https://cheddargetter.com/developers#set-item-quantity
274
+ #
275
+ #id_hash:
276
+ #
277
+ #{
278
+ # :code => Either code or id are required (this is the customer code)
279
+ # :id => Either code or id are required (this is the customer id)
280
+ # :item_code => Either item code or item id are required
281
+ # :item_id => Either item code or item id are required
282
+ #}
283
+ #
284
+ #data: { :quantity => required }
285
+ def set_item_quantity(id_hash = { }, data = { })
286
+ do_request(:item => :customers, :action => "set-item-quantity", :id_hash => id_hash,
287
+ :data => data, :add_item_id => true)
288
+ end
289
+
290
+ #https://cheddargetter.com/developers#add-charge
291
+ #
292
+ #id_hash: {:code => customer_code} OR {:id => customer_id}
293
+ #
294
+ #data:
295
+ #
296
+ #{
297
+ # :chargeCode => required,
298
+ # :quantity => required,
299
+ # :eachAmount => required,
300
+ # :description => not_required
301
+ #}
302
+ def add_charge(id_hash = { }, data = { })
303
+ do_request(:item => :customers, :action => "add-charge", :id_hash => id_hash, :data => data)
304
+ end
305
+
306
+ private
307
+ def get_identifier_string(type, id_hash)
308
+ code = type ? "#{type}_code".to_sym : :code
309
+ id = type ? "#{type}_id".to_sym : :id
310
+
311
+ if id_hash[code]
312
+ str = type ? "#{type}Code" : "code"
313
+ "/#{str}/#{CGI.escape(id_hash[code].to_s)}"
314
+ elsif id_hash[id]
315
+ str = type ? "#{type}Id" : "id"
316
+ "/#{str}/#{CGI.escape(id_hash[id].to_s)}"
317
+ else
318
+ raise CheddarGetter::ClientException.new("Either a :#{code} or :#{id} is required")
319
+ end
320
+ end
321
+
322
+ def do_request(options)
323
+ data = options[:data]
324
+ deep_fix_request_data!(data)
325
+
326
+ path = "/xml/#{options[:item]}/#{options[:action]}"
327
+ path += get_identifier_string(nil, options[:id_hash]) if options[:id_hash]
328
+ path += get_identifier_string("item", options[:id_hash]) if options[:add_item_id]
329
+ path += if product_code
330
+ "/productCode/#{CGI.escape(product_code.to_s)}"
331
+ elsif product_id
332
+ "/productId/#{CGI.escape(product_id.to_s)}"
333
+ else
334
+ raise CheddarGetter::ClientException.new("A product code or id is required to make requests.")
335
+ end
336
+
337
+ response = if data
338
+ CheddarGetter::Client.post(path, :body => data, :basic_auth => {
339
+ :username => self.username,
340
+ :password => self.password
341
+ })
342
+ else
343
+ CheddarGetter::Client.get(path, :basic_auth => {
344
+ :username => self.username,
345
+ :password => self.password
346
+ })
347
+ end
348
+
349
+ CheddarGetter::Response.new(response)
350
+ end
351
+
352
+ FIX_UP_KEYS = {
353
+ :ccExpiration => :month_year,
354
+ :isVatExempt => :boolean,
355
+ :initialBillDate => :year_month_day,
356
+ :createdAfterDate => :year_month_day,
357
+ :createdBeforeDate => :year_month_day,
358
+ :canceledAfterDate => :year_month_day,
359
+ :canceledBeforeDate => :year_month_day
360
+ }
361
+
362
+ def deep_fix_request_data!(data)
363
+ if data.is_a?(Array)
364
+ data.each do |v|
365
+ deep_fix_request_data!(v)
366
+ end
367
+ elsif data.is_a?(Hash)
368
+ data.each do |k, v|
369
+ deep_fix_request_data!(v)
370
+ type = FIX_UP_KEYS[k]
371
+ if type
372
+ data[k] = case type
373
+ when :month_year then v.respond_to?(:strftime) ? v.strftime("%m/%Y") : v
374
+ when :boolean then v ? "1" : "0"
375
+ when :year_month_day then v.respond_to?(:strftime) ? v.strftime("%Y/%m/%d") : v
376
+ else v
377
+ end
378
+ end
379
+ end
380
+ end
381
+ end
382
+
383
+ end
384
+ end
385
+