chart_mogul 0.0.1 → 0.1.0
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 +1 -0
- data/README.md +48 -5
- data/lib/chart_mogul/client.rb +21 -5
- data/lib/chart_mogul/import/invoice.rb +73 -0
- data/lib/chart_mogul/import_api.rb +94 -6
- data/lib/chart_mogul/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7d2be0447fd155e52b53b2dec55b2a17cffa455c
|
4
|
+
data.tar.gz: df71a2c81fdb91fdab2b922e05887f856d7a35fb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4f03903826ba697eff43e9d1ea3692c03ef53399d0f3e7d3d01e4f0600c07240c284d1f0b6399a226d904d744dccf94f30be801fc8b8536c38d34aa66c3319f3
|
7
|
+
data.tar.gz: 5b9859eac58650c90ac7662743680bc9394448897cb466074542fbdf25e45d8b39a38308bec75aba99e14f36f6c8afe2310f6285d58b0fa25916f8953d458f86
|
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -1,8 +1,6 @@
|
|
1
1
|
# ChartMogul
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
TODO: Delete this and the text above, and describe your gem
|
3
|
+
This gem is designed to streamline interaction with the [ChartMogul](https://dev.chartmogul.com) API. The initial focus has been on support for the [Import API](link!!).
|
6
4
|
|
7
5
|
## Installation
|
8
6
|
|
@@ -22,7 +20,52 @@ Or install it yourself as:
|
|
22
20
|
|
23
21
|
## Usage
|
24
22
|
|
25
|
-
|
23
|
+
Credentials are provided in the Account / API area of the ChartMogul application and comprise an `account_token` and `secret_key`.
|
24
|
+
|
25
|
+
This can be passed in when insantiating a `ChartMogul::Client` instance, eg:
|
26
|
+
|
27
|
+
```ruby
|
28
|
+
client = ChartMogul::Client.new(account_token: 'token value', secret_key: 'secret value')
|
29
|
+
```
|
30
|
+
|
31
|
+
If not passed to the constructor the values returned by the `CHART_MOGUL_ACCOUNT_TOKEN` and `CHART_MOGUL_SECRET_KEY` environment variables are used.
|
32
|
+
|
33
|
+
Methods for access the API are exposed on the `client`.
|
34
|
+
|
35
|
+
### Reading data
|
36
|
+
|
37
|
+
Reading methods, `list_` prefix, are either presented as simple methods that page through all responses from the API and present a fully populated Array of typed objects.
|
38
|
+
|
39
|
+
```ruby
|
40
|
+
client.list_customers # => [ Import::Customer, Import::Customer ]
|
41
|
+
```
|
42
|
+
|
43
|
+
and as an iterative version, with an `_each` suffix, that expects a block. Useful for those situations where you're dealing with a lot of records and don't want them necessarily all in memory. This again handles the paging transparently.
|
44
|
+
|
45
|
+
The block is yielded to with a typed object.
|
46
|
+
|
47
|
+
```ruby
|
48
|
+
client.list_customers_each do |customer|
|
49
|
+
# do something with the Import::Customer here
|
50
|
+
end
|
51
|
+
```
|
52
|
+
|
53
|
+
### Importing data
|
54
|
+
|
55
|
+
Data records are imported by passing a Hash of attributes to a `create_` prefixed method.
|
56
|
+
|
57
|
+
```ruby
|
58
|
+
client.create_plan({
|
59
|
+
data_source_uuid: "ds_2323232",
|
60
|
+
name: "Top Plan",
|
61
|
+
interval_count: 1,
|
62
|
+
interval_unit: :month
|
63
|
+
})
|
64
|
+
```
|
65
|
+
|
66
|
+
Dates and times are expected as `Time` objects. The gem handles the formatting required by the ChartMogul API.
|
67
|
+
|
68
|
+
Where possible pre request validation is also handled by the gem. `ArgumentErrors` with a description of the variable are raised in the event that pre submit validation fails.
|
26
69
|
|
27
70
|
## Development
|
28
71
|
|
@@ -32,7 +75,7 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
|
|
32
75
|
|
33
76
|
## Contributing
|
34
77
|
|
35
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/
|
78
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/adambird/chart_mogul. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](contributor-covenant.org) code of conduct.
|
36
79
|
|
37
80
|
|
38
81
|
## License
|
data/lib/chart_mogul/client.rb
CHANGED
@@ -30,6 +30,10 @@ module ChartMogul
|
|
30
30
|
end
|
31
31
|
end
|
32
32
|
|
33
|
+
def credentials?
|
34
|
+
account_token && secret_key
|
35
|
+
end
|
36
|
+
|
33
37
|
def ping?
|
34
38
|
response = connection.get("/v1/ping")
|
35
39
|
preprocess_response(response)[:data] == 'pong!'
|
@@ -37,7 +41,9 @@ module ChartMogul
|
|
37
41
|
|
38
42
|
def paged_get(path, params, data_field)
|
39
43
|
begin
|
40
|
-
|
44
|
+
params[:page_number] = 1 unless params[:page_number]
|
45
|
+
response = connection.get(path, params)
|
46
|
+
result = preprocess_response(response)
|
41
47
|
yield result[data_field]
|
42
48
|
params[:page_number] = result[:current_page]
|
43
49
|
end while params[:page_number] < result[:total_pages]
|
@@ -51,23 +57,33 @@ module ChartMogul
|
|
51
57
|
raise UnauthorizedError.new
|
52
58
|
when 422
|
53
59
|
result = JSON.parse(response.body, symbolize_names: true)
|
54
|
-
raise ValidationError.new(result
|
60
|
+
raise ValidationError.new(result)
|
55
61
|
else
|
56
62
|
puts response.inspect
|
57
63
|
raise StandardError.new("#{response.status} #{response.body.slice(0,50)}")
|
58
64
|
end
|
59
65
|
end
|
60
66
|
|
67
|
+
def format_datetime(value)
|
68
|
+
value.strftime("%Y-%m-%d %H:%M:%S")
|
69
|
+
end
|
70
|
+
|
61
71
|
class UnauthorizedError < StandardError
|
62
72
|
end
|
63
73
|
|
64
74
|
class ValidationError < StandardError
|
65
75
|
|
66
76
|
attr_reader :errors
|
77
|
+
attr_reader :body
|
67
78
|
|
68
|
-
def initialize(
|
69
|
-
@
|
70
|
-
|
79
|
+
def initialize(result)
|
80
|
+
@body = result
|
81
|
+
if result[:errors]
|
82
|
+
@errors = result[:errors]
|
83
|
+
super("validation errors for #{@errors.keys.join(', ')}")
|
84
|
+
else
|
85
|
+
super("validation errors #{@body}")
|
86
|
+
end
|
71
87
|
end
|
72
88
|
|
73
89
|
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
module ChartMogul
|
2
|
+
module Import
|
3
|
+
class Invoice
|
4
|
+
|
5
|
+
attr_reader :uuid
|
6
|
+
attr_reader :date
|
7
|
+
attr_reader :external_id
|
8
|
+
attr_reader :currency
|
9
|
+
attr_reader :due_date
|
10
|
+
attr_reader :line_items
|
11
|
+
attr_reader :transactions
|
12
|
+
|
13
|
+
class LineItem
|
14
|
+
attr_reader :uuid
|
15
|
+
attr_reader :external_id
|
16
|
+
attr_reader :type
|
17
|
+
attr_reader :subscription_uuid
|
18
|
+
attr_reader :plan_uuid
|
19
|
+
attr_reader :prorated
|
20
|
+
attr_reader :service_period_start
|
21
|
+
attr_reader :service_period_end
|
22
|
+
attr_reader :amount_in_cents
|
23
|
+
attr_reader :quantity
|
24
|
+
attr_reader :discount_code
|
25
|
+
attr_reader :discount_amount_in_cents
|
26
|
+
attr_reader :tax_amount_in_cents
|
27
|
+
|
28
|
+
def initialize(args)
|
29
|
+
%i{uuid external_id type subscription_uuid plan_uuid prorated amount_in_cents quantity discount_code discount_amount_in_cents tax_amount_in_cents}
|
30
|
+
.each do |key|
|
31
|
+
instance_variable_set("@#{key}", args[key])
|
32
|
+
end
|
33
|
+
|
34
|
+
%i{service_period_start service_period_end}
|
35
|
+
.each do |key|
|
36
|
+
instance_variable_set("@#{key}", Time.parse(args[key])) if args[key]
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
|
43
|
+
class Transaction
|
44
|
+
attr_reader :uuid
|
45
|
+
attr_reader :external_id
|
46
|
+
attr_reader :type
|
47
|
+
attr_reader :date
|
48
|
+
attr_reader :result
|
49
|
+
|
50
|
+
def initialize(args)
|
51
|
+
%i{uuid external_id type result}
|
52
|
+
.each do |key|
|
53
|
+
instance_variable_set("@#{key}", args[key])
|
54
|
+
end
|
55
|
+
|
56
|
+
instance_variable_set("@#{:date}", Time.parse(args[:date])) if args[:date]
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
|
61
|
+
def initialize(args)
|
62
|
+
@uuid = args[:uuid]
|
63
|
+
@external_id = args[:external_id]
|
64
|
+
@currency = args[:currency]
|
65
|
+
@date = Time.parse(args[:date]) if args[:date]
|
66
|
+
@due_date = Time.parse(args[:due_date]) if args[:due_date]
|
67
|
+
|
68
|
+
@line_items = args[:line_items].map { |li| LineItem.new(li) }
|
69
|
+
@transactions = args[:transactions].map { |li| Transaction.new(li) }
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
require_relative 'import/customer'
|
2
2
|
require_relative 'import/data_source'
|
3
3
|
require_relative 'import/plan'
|
4
|
+
require_relative 'import/invoice'
|
4
5
|
|
5
6
|
module ChartMogul
|
6
7
|
module ImportApi
|
@@ -70,7 +71,7 @@ module ChartMogul
|
|
70
71
|
# Returns an Enumerable that will yield a ChartMogul::Import::Customer for
|
71
72
|
# each record
|
72
73
|
def list_customers_each(options={}, &block)
|
73
|
-
params = {
|
74
|
+
params = {}
|
74
75
|
params[:data_source_uuid] = options[:data_source_uuid] if options[:data_source_uuid]
|
75
76
|
|
76
77
|
paged_get("/v1/import/customers", params, :customers) do |customers|
|
@@ -80,13 +81,13 @@ module ChartMogul
|
|
80
81
|
end
|
81
82
|
end
|
82
83
|
|
83
|
-
# Public -
|
84
|
+
# Public - import a Customer
|
84
85
|
#
|
85
86
|
# args - Hash of params see https://dev.chartmogul.com/docs/customers
|
86
87
|
# Mandatory: :data_source_uuid, :external_id, :name
|
87
88
|
#
|
88
89
|
# Returns a ChartMogul::Import::Customer
|
89
|
-
def
|
90
|
+
def import_customer(args)
|
90
91
|
[:data_source_uuid, :external_id, :name].each do |attribute|
|
91
92
|
refute_blank! args[attribute], attribute
|
92
93
|
end
|
@@ -127,7 +128,7 @@ module ChartMogul
|
|
127
128
|
# Returns an Enumerable that will yield a ChartMogul::Import::Plan for
|
128
129
|
# each record
|
129
130
|
def list_plans_each(options={}, &block)
|
130
|
-
params = {
|
131
|
+
params = {}
|
131
132
|
params[:data_source_uuid] = options[:data_source_uuid] if options[:data_source_uuid]
|
132
133
|
|
133
134
|
paged_get("/v1/import/plans", params, :plans) do |plans|
|
@@ -137,13 +138,13 @@ module ChartMogul
|
|
137
138
|
end
|
138
139
|
end
|
139
140
|
|
140
|
-
# Public -
|
141
|
+
# Public - import a Plan
|
141
142
|
#
|
142
143
|
# args - Hash of params see https://dev.chartmogul.com/docs/plans
|
143
144
|
# Mandatory: :data_source_uuid, :name, :interval_count, :interval_unit
|
144
145
|
#
|
145
146
|
# Returns a ChartMogul::Import::Plan
|
146
|
-
def
|
147
|
+
def import_plan(args)
|
147
148
|
[:data_source_uuid, :name, :interval_unit, :interval_count].each do |attribute|
|
148
149
|
refute_blank! args[attribute], attribute
|
149
150
|
end
|
@@ -158,5 +159,92 @@ module ChartMogul
|
|
158
159
|
|
159
160
|
Import::Plan.new(preprocess_response(response))
|
160
161
|
end
|
162
|
+
|
163
|
+
# Public - import a single Invoice. Convenience method that
|
164
|
+
# maps the output (and validation errors) to a single operation
|
165
|
+
#
|
166
|
+
# customer_id - ChartMogul id for the customer
|
167
|
+
# invoice - Hash of params see https://dev.chartmogul.com/docs/invoices
|
168
|
+
# See invoice_invoices for mandatory attributes
|
169
|
+
#
|
170
|
+
# Returns an Array of ChartMogul::Import::Invoice
|
171
|
+
def import_invoice(customer_id, invoice)
|
172
|
+
invoices = import_invoices(customer_id, [ invoice ])
|
173
|
+
invoices.first
|
174
|
+
|
175
|
+
rescue ChartMogul::Client::ValidationError => e
|
176
|
+
# restructure ValidationError to map the single invoice error that was returned
|
177
|
+
if e.body[:invoices]
|
178
|
+
raise ChartMogul::Client::ValidationError.new(e.body[:invoices].first)
|
179
|
+
else
|
180
|
+
raise
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
# Public - import Invoices
|
185
|
+
#
|
186
|
+
# customer_id - ChartMogul id for the customer
|
187
|
+
# invoices - Array of Hash of params see https://dev.chartmogul.com/docs/invoices
|
188
|
+
# Mandatory: :external_id, :date, :currency, :line_items
|
189
|
+
#
|
190
|
+
# Returns an Array of ChartMogul::Import::Invoice
|
191
|
+
def import_invoices(customer_id, invoices)
|
192
|
+
refute_blank! customer_id, "customer_id"
|
193
|
+
refute! invoices.nil? && invoices.empty?, "invoices required"
|
194
|
+
|
195
|
+
args = { invoices: invoices }
|
196
|
+
|
197
|
+
args[:invoices].each do |invoice|
|
198
|
+
[:external_id, :date, :currency].each do |attribute|
|
199
|
+
refute_blank! invoice[attribute], attribute
|
200
|
+
end
|
201
|
+
|
202
|
+
invoice[:date] = format_datetime(invoice[:date])
|
203
|
+
|
204
|
+
assert! invoice[:line_items] && invoice[:line_items].any?, "line_items is required"
|
205
|
+
|
206
|
+
invoice[:line_items].each do |line_item|
|
207
|
+
line_item[:service_period_start] = format_datetime(line_item[:service_period_start]) if line_item[:service_period_start]
|
208
|
+
line_item[:service_period_end] = format_datetime(line_item[:service_period_end]) if line_item[:service_period_end]
|
209
|
+
assert! line_item[:quantity].nil? || line_item[:quantity] > 0, "line_item quantity must be greater than zero if specified"
|
210
|
+
end
|
211
|
+
|
212
|
+
end
|
213
|
+
|
214
|
+
response = connection.post do |request|
|
215
|
+
request.url "/v1/import/customers/#{customer_id}/invoices"
|
216
|
+
request.headers['Content-Type'] = "application/json"
|
217
|
+
request.body = args.to_json
|
218
|
+
end
|
219
|
+
|
220
|
+
preprocess_response(response)[:invoices].map { |i| Import::Invoice.new(i) }
|
221
|
+
end
|
222
|
+
|
223
|
+
# Public - list of Customer invoices
|
224
|
+
# customer_id - ChartMogul id for the customer
|
225
|
+
#
|
226
|
+
# Returns an Array of ChartMogul::Import::Invoice
|
227
|
+
def list_invoices(customer_id)
|
228
|
+
invoices = []
|
229
|
+
list_invoices_each(customer_id) { |i| invoices << i }
|
230
|
+
invoices
|
231
|
+
end
|
232
|
+
|
233
|
+
# Public - iterate through all invoices
|
234
|
+
#
|
235
|
+
# customer_id - ChartMogul id for the customer
|
236
|
+
#
|
237
|
+
# Returns an Enumerable that will yield a ChartMogul::Import::Invoice for
|
238
|
+
# each record
|
239
|
+
def list_invoices_each(customer_id, &block)
|
240
|
+
refute_blank! customer_id, "customer_id"
|
241
|
+
|
242
|
+
paged_get("/v1/import/customers/#{customer_id}/invoices", {}, :invoices) do |invoices|
|
243
|
+
invoices.each do |invoice|
|
244
|
+
yield Import::Invoice.new(invoice)
|
245
|
+
end
|
246
|
+
end
|
247
|
+
end
|
248
|
+
|
161
249
|
end
|
162
250
|
end
|
data/lib/chart_mogul/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: chart_mogul
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Adam Bird
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-04-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: faraday
|
@@ -103,6 +103,7 @@ files:
|
|
103
103
|
- lib/chart_mogul/client.rb
|
104
104
|
- lib/chart_mogul/import/customer.rb
|
105
105
|
- lib/chart_mogul/import/data_source.rb
|
106
|
+
- lib/chart_mogul/import/invoice.rb
|
106
107
|
- lib/chart_mogul/import/plan.rb
|
107
108
|
- lib/chart_mogul/import_api.rb
|
108
109
|
- lib/chart_mogul/version.rb
|