chartmogul-ruby 1.7.1 → 2.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.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/test.yml +44 -0
  3. data/.rspec +0 -0
  4. data/2.0-Upgrade.md +9 -0
  5. data/README.md +8 -2
  6. data/changelog.md +14 -0
  7. data/chartmogul-ruby.gemspec +1 -1
  8. data/fixtures/vcr_cassettes/ChartMogul_Customer/API_Interactions/correctly_interracts_with_the_API.yml +67 -119
  9. data/fixtures/vcr_cassettes/ChartMogul_Metrics_ActivitiesExport/get_activities_export.yml +43 -0
  10. data/fixtures/vcr_cassettes/ChartMogul_Metrics_ActivitiesExport/post_activities_export.yml +83 -0
  11. data/fixtures/vcr_cassettes/ChartMogul_Metrics_Activity.yml +37 -0
  12. data/fixtures/vcr_cassettes/ChartMogul_Metrics_Activity/behaves_like_PageableWithAnchor/should_be_pageable.yml +44 -0
  13. data/fixtures/vcr_cassettes/ChartMogul_Metrics_Activity/should_have_Activity_entries.yml +17 -14
  14. data/fixtures/vcr_cassettes/{ChartMogul_Metrics_Activity → ChartMogul_Metrics_Customers_Activity}/behaves_like_Pageable/should_be_pageable.yml +0 -0
  15. data/fixtures/vcr_cassettes/ChartMogul_Metrics_Customers_Activity/should_have_Activity_entries.yml +41 -0
  16. data/fixtures/vcr_cassettes/{ChartMogul_Metrics_Subscription → ChartMogul_Metrics_Customers_Subscription}/behaves_like_Pageable/should_be_pageable.yml +0 -0
  17. data/fixtures/vcr_cassettes/{ChartMogul_Metrics_Subscription → ChartMogul_Metrics_Customers_Subscription}/should_have_Subscription_entries.yml +0 -0
  18. data/lib/chartmogul.rb +10 -3
  19. data/lib/chartmogul/api/actions/all.rb +1 -1
  20. data/lib/chartmogul/api/actions/create.rb +2 -2
  21. data/lib/chartmogul/api/actions/custom.rb +1 -1
  22. data/lib/chartmogul/api/actions/retrieve.rb +2 -1
  23. data/lib/chartmogul/api/actions/update.rb +2 -2
  24. data/lib/chartmogul/api_resource.rb +8 -4
  25. data/lib/chartmogul/concerns/pageable_with_anchor.rb +14 -0
  26. data/lib/chartmogul/config_attributes.rb +17 -1
  27. data/lib/chartmogul/customer.rb +2 -2
  28. data/lib/chartmogul/metrics/activities_export.rb +38 -0
  29. data/lib/chartmogul/metrics/activity.rb +12 -8
  30. data/lib/chartmogul/metrics/customers/activity.rb +38 -0
  31. data/lib/chartmogul/metrics/customers/subscription.rb +41 -0
  32. data/lib/chartmogul/utils/hash_snake_caser.rb +9 -2
  33. data/lib/chartmogul/utils/json_parser.rb +2 -4
  34. data/lib/chartmogul/version.rb +1 -1
  35. data/pre-commit.example +0 -0
  36. metadata +18 -9
  37. data/.travis.yml +0 -25
  38. data/lib/chartmogul/metrics/subscription.rb +0 -39
@@ -0,0 +1,83 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: post
5
+ uri: https://api.chartmogul.com/v1/activities_export
6
+ body:
7
+ encoding: UTF-8
8
+ string: '{"start-date":"2020-01-01T00:00:00Z","end-date":"2020-12-31T00:00:00Z","type":"new_biz"}'
9
+ headers:
10
+ User-Agent:
11
+ - Faraday v1.0.1
12
+ Content-Type:
13
+ - application/json
14
+ Authorization:
15
+ - Basic hidden
16
+ response:
17
+ status:
18
+ code: 200
19
+ message: OK
20
+ headers:
21
+ server:
22
+ - nginx/1.10.1
23
+ date:
24
+ - Fri, 09 Jul 2021 14:37:32 GMT
25
+ content-type:
26
+ - application/json
27
+ transfer-encoding:
28
+ - chunked
29
+ connection:
30
+ - keep-alive
31
+ vary:
32
+ - Accept-Encoding, Accept-Encoding
33
+ status:
34
+ - 200 OK
35
+ access-control-allow-credentials:
36
+ - 'true'
37
+ body:
38
+ encoding: ASCII-8BIT
39
+ string: '{"id":"17042239-3674-4a61-b838-b6b307f28506","status":"pending","file_url":null,"params":{"kind":"activities","params":{"activity_type":"new_biz","start_date":"2020-01-01
40
+ 00:00:00 +0000","end_date":"2020-12-31 00:00:00 +0000"}},"expires_at":null,"created_at":"2021-07-09T14:37:32+00:00"}'
41
+ http_version:
42
+ recorded_at: Fri, 09 Jul 2021 14:37:32 GMT
43
+ - request:
44
+ method: get
45
+ uri: https://api.chartmogul.com/v1/activities_export/17042239-3674-4a61-b838-b6b307f28506
46
+ body:
47
+ encoding: US-ASCII
48
+ string: ''
49
+ headers:
50
+ User-Agent:
51
+ - Faraday v1.0.1
52
+ Content-Type:
53
+ - application/json
54
+ Authorization:
55
+ - Basic hidden
56
+ response:
57
+ status:
58
+ code: 200
59
+ message: OK
60
+ headers:
61
+ server:
62
+ - nginx/1.10.1
63
+ date:
64
+ - Fri, 09 Jul 2021 14:38:10 GMT
65
+ content-type:
66
+ - application/json
67
+ transfer-encoding:
68
+ - chunked
69
+ connection:
70
+ - keep-alive
71
+ vary:
72
+ - Accept-Encoding, Accept-Encoding
73
+ status:
74
+ - 200 OK
75
+ access-control-allow-credentials:
76
+ - 'true'
77
+ body:
78
+ encoding: ASCII-8BIT
79
+ string: '{"id":"17042239-3674-4a61-b838-b6b307f28506","status":"succeeded","file_url":"https://chartmogul-customer-export.s3.eu-west-1.amazonaws.com/activities-acme-corp-062ea48c-5d74-46dd-bd60-23206cdc241a.zip?X-Amz-Algorithm=AWS4-HMAC-SHA256\u0026X-Amz-Credential=123%2Feu-west-1%2Fs3%2Faws4_request\u0026X-Amz-Date=20210709T135547Z\u0026X-Amz-Expires=604800\u0026X-Amz-SignedHeaders=host\u0026X-Amz-Signature=abc","params":{"kind":"activities","params":{"end_date":"2020-12-31
80
+ 00:00:00 +0000","start_date":"2020-01-01 00:00:00 +0000","activity_type":"new_biz"}},"expires_at":"2021-07-16T14:37:43+00:00","created_at":"2021-07-09T14:37:32+00:00"}'
81
+ http_version:
82
+ recorded_at: Fri, 09 Jul 2021 14:38:10 GMT
83
+ recorded_with: VCR 5.1.0
@@ -0,0 +1,37 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: get
5
+ uri: https://api.chartmogul.com/v1/activities
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers:
10
+ User-Agent:
11
+ - Faraday v1.0.1
12
+ Content-Type:
13
+ - application/json
14
+ Authorization:
15
+ - Basic hidden
16
+ response:
17
+ status:
18
+ code: 401
19
+ message: Unauthorized
20
+ headers:
21
+ server:
22
+ - nginx/1.10.1
23
+ date:
24
+ - Fri, 18 Jun 2021 10:37:37 GMT
25
+ content-type:
26
+ - application/json
27
+ transfer-encoding:
28
+ - chunked
29
+ connection:
30
+ - keep-alive
31
+ status:
32
+ - 401 Unauthorized
33
+ body:
34
+ encoding: UTF-8
35
+ string: '{"code":401,"message":"No valid API key provided","param":null}'
36
+ recorded_at: Fri, 18 Jun 2021 10:37:37 GMT
37
+ recorded_with: VCR 6.0.0
@@ -0,0 +1,44 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: get
5
+ uri: https://api.chartmogul.com/v1/activities?per_page=2
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers:
10
+ User-Agent:
11
+ - Faraday v1.0.1
12
+ Content-Type:
13
+ - application/json
14
+ Authorization:
15
+ - Basic hidden
16
+ response:
17
+ status:
18
+ code: 200
19
+ message: OK
20
+ headers:
21
+ server:
22
+ - nginx/1.10.1
23
+ date:
24
+ - Fri, 18 Jun 2021 11:59:07 GMT
25
+ content-type:
26
+ - application/json
27
+ transfer-encoding:
28
+ - chunked
29
+ connection:
30
+ - keep-alive
31
+ vary:
32
+ - Accept-Encoding, Accept-Encoding
33
+ status:
34
+ - 200 OK
35
+ access-control-allow-credentials:
36
+ - 'true'
37
+ body:
38
+ encoding: ASCII-8BIT
39
+ string: '{"entries":[{"description":"purchased the Basic1 plan","activity-mrr-movement":4478,"activity-mrr":4478,"activity-arr":53736,"date":"2016-08-01T06:28:25+00:00","type":"new_biz","currency":"EUR","subscription-external-id":"si_18dZuXAN0YShtow4jjqxxNnW","plan-external-id":"a3e832e1-1bd1-4889-8466-8efdbfbdd94b","customer-name":"Customer
40
+ for test@example.com","customer-uuid":"6456e930-8c8e-11eb-a506-0ff43d2cc026","customer-external-id":"cus_8vQm8XjeEOw75p","billing-connector-uuid":"decdeb4c-8c8d-11eb-a506-b3974867f58c","uuid":"2f545d5f-f241-458c-8e99-38c0e5a6e6ff"},{"description":"purchased
41
+ the Basic1 plan","activity-mrr-movement":4425,"activity-mrr":4425,"activity-arr":53100,"date":"2016-08-17T09:28:10+00:00","type":"new_biz","currency":"EUR","subscription-external-id":"si_18jQLGAN0YShtow4kFWpOMVX","plan-external-id":"a3e832e1-1bd1-4889-8466-8efdbfbdd94b","customer-name":"Customer
42
+ for test@example.com","customer-uuid":"63ad1285-8c8e-11eb-a506-47d6b1cc7553","customer-external-id":"cus_91TH9rjhhYCpai","billing-connector-uuid":"decdeb4c-8c8d-11eb-a506-b3974867f58c","uuid":"9d5ba7fd-e06d-4750-a8f6-2983f3a30fb2"}],"has_more":true,"per_page":2}'
43
+ recorded_at: Fri, 18 Jun 2021 11:59:07 GMT
44
+ recorded_with: VCR 6.0.0
@@ -2,13 +2,13 @@
2
2
  http_interactions:
3
3
  - request:
4
4
  method: get
5
- uri: https://api.chartmogul.com/v1/customers/cus_91af761e-9d0a-11e5-b514-1feab446feac/activities
5
+ uri: https://api.chartmogul.com/v1/activities?per_page=2
6
6
  body:
7
7
  encoding: US-ASCII
8
8
  string: ''
9
9
  headers:
10
10
  User-Agent:
11
- - Faraday v0.9.2
11
+ - Faraday v1.0.1
12
12
  Content-Type:
13
13
  - application/json
14
14
  Authorization:
@@ -16,26 +16,29 @@ http_interactions:
16
16
  response:
17
17
  status:
18
18
  code: 200
19
- message:
19
+ message: OK
20
20
  headers:
21
21
  server:
22
- - nginx/1.9.10
22
+ - nginx/1.10.1
23
23
  date:
24
- - Fri, 01 Jul 2016 14:47:49 GMT
24
+ - Fri, 18 Jun 2021 11:59:07 GMT
25
25
  content-type:
26
26
  - application/json
27
- content-length:
28
- - '278'
27
+ transfer-encoding:
28
+ - chunked
29
29
  connection:
30
- - close
30
+ - keep-alive
31
+ vary:
32
+ - Accept-Encoding, Accept-Encoding
31
33
  status:
32
34
  - 200 OK
33
35
  access-control-allow-credentials:
34
36
  - 'true'
35
37
  body:
36
- encoding: UTF-8
37
- string: '{"entries":[{"id":16664702,"description":"purchased the Yael Cohen
38
- plan","activity-mrr-movement":10871,"activity-mrr":10871,"activity-arr":130452,"date":"2015-04-16T13:38:29+00:00","type":"new_biz","currency":"USD","currency-sign":"$","subscription_external_id":"si_IJxVS1c1TjSB0s"}],"has_more":false,"per_page":200,"page":1}'
39
- http_version:
40
- recorded_at: Fri, 01 Jul 2016 14:47:49 GMT
41
- recorded_with: VCR 3.0.3
38
+ encoding: ASCII-8BIT
39
+ string: '{"entries":[{"description":"purchased the Basic1 plan","activity-mrr-movement":4478,"activity-mrr":4478,"activity-arr":53736,"date":"2016-08-01T06:28:25+00:00","type":"new_biz","currency":"EUR","subscription-external-id":"si_18dZuXAN0YShtow4jjqxxNnW","plan-external-id":"a3e832e1-1bd1-4889-8466-8efdbfbdd94b","customer-name":"Customer
40
+ for test@example.com","customer-uuid":"6456e930-8c8e-11eb-a506-0ff43d2cc026","customer-external-id":"cus_8vQm8XjeEOw75p","billing-connector-uuid":"decdeb4c-8c8d-11eb-a506-b3974867f58c","uuid":"2f545d5f-f241-458c-8e99-38c0e5a6e6ff"},{"description":"purchased
41
+ the Basic1 plan","activity-mrr-movement":4425,"activity-mrr":4425,"activity-arr":53100,"date":"2016-08-17T09:28:10+00:00","type":"new_biz","currency":"EUR","subscription-external-id":"si_18jQLGAN0YShtow4kFWpOMVX","plan-external-id":"a3e832e1-1bd1-4889-8466-8efdbfbdd94b","customer-name":"Customer
42
+ for test@example.com","customer-uuid":"63ad1285-8c8e-11eb-a506-47d6b1cc7553","customer-external-id":"cus_91TH9rjhhYCpai","billing-connector-uuid":"decdeb4c-8c8d-11eb-a506-b3974867f58c","uuid":"9d5ba7fd-e06d-4750-a8f6-2983f3a30fb2"}],"has_more":true,"per_page":2}'
43
+ recorded_at: Fri, 18 Jun 2021 11:59:07 GMT
44
+ recorded_with: VCR 6.0.0
@@ -0,0 +1,41 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: get
5
+ uri: https://api.chartmogul.com/v1/customers/cus_91af761e-9d0a-11e5-b514-1feab446feac/activities
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers:
10
+ User-Agent:
11
+ - Faraday v0.9.2
12
+ Content-Type:
13
+ - application/json
14
+ Authorization:
15
+ - Basic hidden
16
+ response:
17
+ status:
18
+ code: 200
19
+ message:
20
+ headers:
21
+ server:
22
+ - nginx/1.9.10
23
+ date:
24
+ - Fri, 01 Jul 2016 14:47:49 GMT
25
+ content-type:
26
+ - application/json
27
+ content-length:
28
+ - '278'
29
+ connection:
30
+ - close
31
+ status:
32
+ - 200 OK
33
+ access-control-allow-credentials:
34
+ - 'true'
35
+ body:
36
+ encoding: UTF-8
37
+ string: '{"entries":[{"id":16664702,"description":"purchased the Yael Cohen
38
+ plan","activity-mrr-movement":10871,"activity-mrr":10871,"activity-arr":130452,"date":"2015-04-16T13:38:29+00:00","type":"new_biz","currency":"USD","currency-sign":"$","subscription_external_id":"si_IJxVS1c1TjSB0s"}],"has_more":false,"per_page":200,"page":1}'
39
+ http_version:
40
+ recorded_at: Fri, 01 Jul 2016 14:47:49 GMT
41
+ recorded_with: VCR 3.0.3
data/lib/chartmogul.rb CHANGED
@@ -43,6 +43,7 @@ require 'chartmogul/concerns/entries'
43
43
  require 'chartmogul/concerns/summary'
44
44
  require 'chartmogul/concerns/pageable'
45
45
  require 'chartmogul/concerns/pageable2'
46
+ require 'chartmogul/concerns/pageable_with_anchor'
46
47
 
47
48
  require 'chartmogul/subscription'
48
49
  require 'chartmogul/invoice'
@@ -66,8 +67,10 @@ require 'chartmogul/metrics/mrr_churn_rate'
66
67
  require 'chartmogul/metrics/all_key_metrics'
67
68
  require 'chartmogul/metrics/base'
68
69
 
70
+ require 'chartmogul/metrics/customers/activity'
71
+ require 'chartmogul/metrics/customers/subscription'
69
72
  require 'chartmogul/metrics/activity'
70
- require 'chartmogul/metrics/subscription'
73
+ require 'chartmogul/metrics/activities_export'
71
74
 
72
75
  require 'chartmogul/enrichment/customer'
73
76
 
@@ -79,10 +82,14 @@ module ChartMogul
79
82
  class << self
80
83
  extend ConfigAttributes
81
84
 
85
+ def global_config
86
+ @global_config ||= ChartMogul::Configuration.new
87
+ end
82
88
 
89
+ # This configuration is thread-safe and fits multi-account async
90
+ # jobs processing use case.
83
91
  def config
84
- Thread.current[CONFIG_THREAD_KEY] = ChartMogul::Configuration.new if Thread.current[CONFIG_THREAD_KEY].nil?
85
- Thread.current[CONFIG_THREAD_KEY]
92
+ Thread.current[CONFIG_THREAD_KEY] ||= ChartMogul::Configuration.new
86
93
  end
87
94
 
88
95
  config_accessor :account_token
@@ -16,7 +16,7 @@ module ChartMogul
16
16
  end
17
17
  end
18
18
 
19
- json = ChartMogul::Utils::JSONParser.parse(resp.body, skip_case_conversion: skip_case_conversion)
19
+ json = ChartMogul::Utils::JSONParser.parse(resp.body, immutable_keys: immutable_keys)
20
20
  new_from_json(json)
21
21
  end
22
22
  end
@@ -15,7 +15,7 @@ module ChartMogul
15
15
  req.body = JSON.dump(serialize_for_write)
16
16
  end
17
17
  end
18
- json = ChartMogul::Utils::JSONParser.parse(resp.body, skip_case_conversion: self.class.skip_case_conversion)
18
+ json = ChartMogul::Utils::JSONParser.parse(resp.body, immutable_keys: self.class.immutable_keys)
19
19
 
20
20
  assign_all_attributes(json)
21
21
  end
@@ -30,7 +30,7 @@ module ChartMogul
30
30
  req.body = JSON.dump(resource.serialize_for_write)
31
31
  end
32
32
  end
33
- json = ChartMogul::Utils::JSONParser.parse(resp.body, skip_case_conversion: skip_case_conversion)
33
+ json = ChartMogul::Utils::JSONParser.parse(resp.body, immutable_keys: immutable_keys)
34
34
 
35
35
  new_from_json(json)
36
36
  end
@@ -25,7 +25,7 @@ module ChartMogul
25
25
  req.body = JSON.dump(body_data)
26
26
  end
27
27
  end
28
- ChartMogul::Utils::JSONParser.parse(resp.body, skip_case_conversion: skip_case_conversion)
28
+ ChartMogul::Utils::JSONParser.parse(resp.body, immutable_keys: immutable_keys)
29
29
  end
30
30
 
31
31
  def custom!(http_method, http_path, body_data = {})
@@ -15,7 +15,8 @@ module ChartMogul
15
15
  req.headers['Content-Type'] = 'application/json'
16
16
  end
17
17
  end
18
- json = ChartMogul::Utils::JSONParser.parse(resp.body, skip_case_conversion: skip_case_conversion)
18
+
19
+ json = ChartMogul::Utils::JSONParser.parse(resp.body, immutable_keys: immutable_keys)
19
20
  new_from_json(json)
20
21
  end
21
22
  end
@@ -16,7 +16,7 @@ module ChartMogul
16
16
  end
17
17
  end
18
18
 
19
- json = ChartMogul::Utils::JSONParser.parse(resp.body, skip_case_conversion: self.class.skip_case_conversion)
19
+ json = ChartMogul::Utils::JSONParser.parse(resp.body, immutable_keys: self.class.immutable_keys)
20
20
 
21
21
  assign_all_attributes(json)
22
22
  end
@@ -31,7 +31,7 @@ module ChartMogul
31
31
  req.body = JSON.dump(resource.serialize_for_write)
32
32
  end
33
33
  end
34
- json = ChartMogul::Utils::JSONParser.parse(resp.body, skip_case_conversion: skip_case_conversion)
34
+ json = ChartMogul::Utils::JSONParser.parse(resp.body, immutable_keys: immutable_keys)
35
35
 
36
36
  new_from_json(json)
37
37
  end
@@ -17,7 +17,7 @@ module ChartMogul
17
17
  MAX_INTERVAL = 60
18
18
  THREAD_CONNECTION_KEY = 'chartmogul_ruby.api_resource.connection'
19
19
 
20
- class << self; attr_reader :resource_path, :resource_name, :resource_root_key, :skip_case_conversion end
20
+ class << self; attr_reader :resource_path, :resource_name, :resource_root_key end
21
21
 
22
22
  def self.set_resource_path(path)
23
23
  @resource_path = ChartMogul::ResourcePath.new(path)
@@ -31,9 +31,13 @@ module ChartMogul
31
31
  @resource_root_key = root_key
32
32
  end
33
33
 
34
- # When true, response hash keys won't be converted to snake case
35
- def self.set_skip_case_conversion(value)
36
- @skip_case_conversion = value
34
+ def self.immutable_keys
35
+ @immutable_keys ||= []
36
+ end
37
+
38
+ # When set with keys, nested hash keys of these immutable keys won't be converted to snake case
39
+ def self.set_immutable_keys(array)
40
+ @immutable_keys = array
37
41
  end
38
42
 
39
43
  def self.connection
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ChartMogul
4
+ module Concerns
5
+ module PageableWithAnchor
6
+ def self.included(base)
7
+ base.instance_eval do
8
+ readonly_attr :has_more
9
+ readonly_attr :per_page
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -4,7 +4,7 @@ module ChartMogul
4
4
  module ConfigAttributes
5
5
  def config_accessor(attribute, default_value = nil)
6
6
  define_method(attribute) do
7
- attr = config.send(attribute) || default_value
7
+ attr = config.send(attribute) || global_config.send(attribute) || default_value
8
8
  if attr.nil?
9
9
  raise ConfigurationError, "Configuration for #{attribute} not set"
10
10
  end
@@ -12,9 +12,25 @@ module ChartMogul
12
12
  attr
13
13
  end
14
14
 
15
+ define_method("global_#{attribute}") do
16
+ attr = global_config.send(attribute) || default_value
17
+ if attr.nil?
18
+ raise ConfigurationError, "Global configuration for #{attribute} not set"
19
+ end
20
+
21
+ attr
22
+ end
23
+
15
24
  define_method("#{attribute}=") do |val|
16
25
  config.send("#{attribute}=", val)
17
26
  Thread.current[ChartMogul::APIResource::THREAD_CONNECTION_KEY] = nil
27
+ val
28
+ end
29
+
30
+ define_method("global_#{attribute}=") do |val|
31
+ global_config.send("#{attribute}=", val)
32
+ Thread.current[ChartMogul::APIResource::THREAD_CONNECTION_KEY] = nil
33
+ val
18
34
  end
19
35
  end
20
36
  end