chartmogul-ruby 0.1.1

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 (105) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +9 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +4 -0
  5. data/ChartMogul_Metrics_MRRChurnRate/behaves_like_Metrics_API_resource/behaves_like_Summary/should_have_summary.yml +40 -0
  6. data/ChartMogul_Metrics_MRRChurnRate/behaves_like_Metrics_API_resource/should_have_entries.yml +40 -0
  7. data/Gemfile +4 -0
  8. data/LICENSE.txt +21 -0
  9. data/README.md +82 -0
  10. data/Rakefile +6 -0
  11. data/bin/console +14 -0
  12. data/bin/setup +8 -0
  13. data/changelog.md +8 -0
  14. data/chartmogul-ruby.gemspec +29 -0
  15. data/fixtures/vcr_cassettes/ChartMogul_DataSource/API_Interactions/correctly_interracts_with_the_API.yml +189 -0
  16. data/fixtures/vcr_cassettes/ChartMogul_DataSource/API_Interactions/correctly_raises_errors_on_404.yml +46 -0
  17. data/fixtures/vcr_cassettes/ChartMogul_DataSource/API_Interactions/correctly_raises_errors_on_422.yml +48 -0
  18. data/fixtures/vcr_cassettes/ChartMogul_Enrichment_Customer/API_Interactions/adds_custom_attributes.yml +80 -0
  19. data/fixtures/vcr_cassettes/ChartMogul_Enrichment_Customer/API_Interactions/adds_required_tags.yml +79 -0
  20. data/fixtures/vcr_cassettes/ChartMogul_Enrichment_Customer/API_Interactions/raises_404_if_no_customers_found.yml +38 -0
  21. data/fixtures/vcr_cassettes/ChartMogul_Enrichment_Customer/API_Interactions/removes_custom_attributes.yml +80 -0
  22. data/fixtures/vcr_cassettes/ChartMogul_Enrichment_Customer/API_Interactions/removes_tags.yml +80 -0
  23. data/fixtures/vcr_cassettes/ChartMogul_Enrichment_Customer/API_Interactions/returns_all_customers_through_list_all_endpoint.yml +47 -0
  24. data/fixtures/vcr_cassettes/ChartMogul_Enrichment_Customer/API_Interactions/returns_customer_through_retrieve_endpoint.yml +42 -0
  25. data/fixtures/vcr_cassettes/ChartMogul_Enrichment_Customer/API_Interactions/returns_right_customers_through_search_endpoint.yml +43 -0
  26. data/fixtures/vcr_cassettes/ChartMogul_Enrichment_Customer/API_Interactions/updates_custom_attributes.yml +82 -0
  27. data/fixtures/vcr_cassettes/ChartMogul_Import_Customer/API_Interactions/correctly_handles_a_422_response.yml +50 -0
  28. data/fixtures/vcr_cassettes/ChartMogul_Import_Customer/API_Interactions/correctly_interracts_with_the_API.yml +240 -0
  29. data/fixtures/vcr_cassettes/ChartMogul_Import_CustomerInvoices/API_Interactions/correctly_interracts_with_the_API.yml +298 -0
  30. data/fixtures/vcr_cassettes/ChartMogul_Import_DataSource/API_Interactions/correctly_interracts_with_the_API.yml +189 -0
  31. data/fixtures/vcr_cassettes/ChartMogul_Import_DataSource/API_Interactions/correctly_raises_errors_on_404.yml +46 -0
  32. data/fixtures/vcr_cassettes/ChartMogul_Import_DataSource/API_Interactions/correctly_raises_errors_on_422.yml +48 -0
  33. data/fixtures/vcr_cassettes/ChartMogul_Import_Plan/API_Interractions/correctly_handles_a_422_error.yml +51 -0
  34. data/fixtures/vcr_cassettes/ChartMogul_Import_Plan/API_Interractions/correctly_interracts_with_the_API.yml +152 -0
  35. data/fixtures/vcr_cassettes/ChartMogul_Import_Subscription/API_Interactions/correctly_interracts_with_the_API.yml +340 -0
  36. data/fixtures/vcr_cassettes/ChartMogul_Import_Transactions_Payment/API_Interactions/correctly_interracts_with_the_API.yml +243 -0
  37. data/fixtures/vcr_cassettes/ChartMogul_Metrics_ARPA/behaves_like_Metrics_API_resource/behaves_like_Summary/should_have_summary.yml +42 -0
  38. data/fixtures/vcr_cassettes/ChartMogul_Metrics_ARPA/behaves_like_Metrics_API_resource/should_have_entries.yml +42 -0
  39. data/fixtures/vcr_cassettes/ChartMogul_Metrics_ARR/behaves_like_Metrics_API_resource/behaves_like_Summary/should_have_summary.yml +42 -0
  40. data/fixtures/vcr_cassettes/ChartMogul_Metrics_ARR/behaves_like_Metrics_API_resource/should_have_entries.yml +42 -0
  41. data/fixtures/vcr_cassettes/ChartMogul_Metrics_ASP/behaves_like_Metrics_API_resource/behaves_like_Summary/should_have_summary.yml +40 -0
  42. data/fixtures/vcr_cassettes/ChartMogul_Metrics_ASP/behaves_like_Metrics_API_resource/should_have_entries.yml +40 -0
  43. data/fixtures/vcr_cassettes/ChartMogul_Metrics_Activity/behaves_like_Pageable/should_be_pageable.yml +41 -0
  44. data/fixtures/vcr_cassettes/ChartMogul_Metrics_Activity/should_have_Activity_entries.yml +41 -0
  45. data/fixtures/vcr_cassettes/ChartMogul_Metrics_AllKeyMetric/should_have_entries.yml +42 -0
  46. data/fixtures/vcr_cassettes/ChartMogul_Metrics_CustomerChurnRate/behaves_like_Metrics_API_resource/behaves_like_Summary/should_have_summary.yml +40 -0
  47. data/fixtures/vcr_cassettes/ChartMogul_Metrics_CustomerChurnRate/behaves_like_Metrics_API_resource/should_have_entries.yml +40 -0
  48. data/fixtures/vcr_cassettes/ChartMogul_Metrics_CustomerCount/behaves_like_Metrics_API_resource/behaves_like_Summary/should_have_summary.yml +42 -0
  49. data/fixtures/vcr_cassettes/ChartMogul_Metrics_CustomerCount/behaves_like_Metrics_API_resource/should_have_entries.yml +42 -0
  50. data/fixtures/vcr_cassettes/ChartMogul_Metrics_LTV/behaves_like_Metrics_API_resource/behaves_like_Summary/should_have_summary.yml +40 -0
  51. data/fixtures/vcr_cassettes/ChartMogul_Metrics_LTV/behaves_like_Metrics_API_resource/should_have_entries.yml +40 -0
  52. data/fixtures/vcr_cassettes/ChartMogul_Metrics_MRR/behaves_like_Summary/should_have_summary.yml +42 -0
  53. data/fixtures/vcr_cassettes/ChartMogul_Metrics_MRR/should_have_entries.yml +42 -0
  54. data/fixtures/vcr_cassettes/ChartMogul_Metrics_MRRChurnRate/behaves_like_Metrics_API_resource/behaves_like_Summary/should_have_summary.yml +40 -0
  55. data/fixtures/vcr_cassettes/ChartMogul_Metrics_MRRChurnRate/behaves_like_Metrics_API_resource/should_have_entries.yml +40 -0
  56. data/fixtures/vcr_cassettes/ChartMogul_Metrics_Subscription/behaves_like_Pageable/should_be_pageable.yml +40 -0
  57. data/fixtures/vcr_cassettes/ChartMogul_Metrics_Subscription/should_have_Subscription_entries.yml +40 -0
  58. data/lib/chartmogul.rb +77 -0
  59. data/lib/chartmogul/api/actions/all.rb +28 -0
  60. data/lib/chartmogul/api/actions/create.rb +39 -0
  61. data/lib/chartmogul/api/actions/custom.rb +42 -0
  62. data/lib/chartmogul/api/actions/destroy.rb +14 -0
  63. data/lib/chartmogul/api/actions/update.rb +19 -0
  64. data/lib/chartmogul/api_resource.rb +57 -0
  65. data/lib/chartmogul/concerns/entries.rb +37 -0
  66. data/lib/chartmogul/concerns/pageable.rb +14 -0
  67. data/lib/chartmogul/concerns/summary.rb +20 -0
  68. data/lib/chartmogul/config_attributes.rb +15 -0
  69. data/lib/chartmogul/configuration.rb +6 -0
  70. data/lib/chartmogul/enrichment/customer.rb +114 -0
  71. data/lib/chartmogul/errors/chartmogul_error.rb +19 -0
  72. data/lib/chartmogul/errors/configuration_error.rb +4 -0
  73. data/lib/chartmogul/errors/forbidden_error.rb +4 -0
  74. data/lib/chartmogul/errors/not_found_error.rb +4 -0
  75. data/lib/chartmogul/errors/resource_invalid_error.rb +4 -0
  76. data/lib/chartmogul/errors/schema_invalid_error.rb +4 -0
  77. data/lib/chartmogul/import/customer.rb +38 -0
  78. data/lib/chartmogul/import/customer_invoices.rb +40 -0
  79. data/lib/chartmogul/import/data_source.rb +19 -0
  80. data/lib/chartmogul/import/invoice.rb +64 -0
  81. data/lib/chartmogul/import/line_items/one_time.rb +25 -0
  82. data/lib/chartmogul/import/line_items/subscription.rb +31 -0
  83. data/lib/chartmogul/import/plan.rb +21 -0
  84. data/lib/chartmogul/import/subscription.rb +30 -0
  85. data/lib/chartmogul/import/transactions/payment.rb +26 -0
  86. data/lib/chartmogul/import/transactions/refund.rb +26 -0
  87. data/lib/chartmogul/metrics/activity.rb +32 -0
  88. data/lib/chartmogul/metrics/all_key_metrics.rb +25 -0
  89. data/lib/chartmogul/metrics/arpa.rb +19 -0
  90. data/lib/chartmogul/metrics/arr.rb +19 -0
  91. data/lib/chartmogul/metrics/asp.rb +19 -0
  92. data/lib/chartmogul/metrics/base.rb +56 -0
  93. data/lib/chartmogul/metrics/customer_churn_rate.rb +19 -0
  94. data/lib/chartmogul/metrics/customer_count.rb +19 -0
  95. data/lib/chartmogul/metrics/ltv.rb +19 -0
  96. data/lib/chartmogul/metrics/mrr.rb +26 -0
  97. data/lib/chartmogul/metrics/mrr_churn_rate.rb +19 -0
  98. data/lib/chartmogul/metrics/subscription.rb +35 -0
  99. data/lib/chartmogul/object.rb +119 -0
  100. data/lib/chartmogul/resource_path.rb +42 -0
  101. data/lib/chartmogul/summary.rb +7 -0
  102. data/lib/chartmogul/utils/hash_snake_caser.rb +50 -0
  103. data/lib/chartmogul/utils/json_parser.rb +11 -0
  104. data/lib/chartmogul/version.rb +3 -0
  105. metadata +232 -0
@@ -0,0 +1,37 @@
1
+ module ChartMogul
2
+ module Concerns
3
+ module Entries
4
+ def self.included(base)
5
+ base.extend ClassMethods
6
+ base.send :prepend, InstanceMethods
7
+
8
+ base.instance_eval do
9
+ readonly_attr :entries, default: []
10
+
11
+ include API::Actions::All
12
+
13
+ include Enumerable
14
+ def_delegators :entries, :each, :[], :<<, :size, :length
15
+ end
16
+ end
17
+
18
+ module ClassMethods
19
+ def set_entry_class(klass)
20
+ instance_variable_set("@entry_class", klass)
21
+ end
22
+
23
+ def get_entry_class
24
+ instance_variable_get("@entry_class")
25
+ end
26
+ end
27
+
28
+ module InstanceMethods
29
+ def set_entries(entries_attributes)
30
+ @entries = entries_attributes.map do |entity|
31
+ self.class.get_entry_class.new_from_json(entity)
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,14 @@
1
+ module ChartMogul
2
+ module Concerns
3
+ module Pageable
4
+ def self.included(base)
5
+ base.instance_eval do
6
+ readonly_attr :has_more
7
+ readonly_attr :per_page
8
+ readonly_attr :page
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
14
+
@@ -0,0 +1,20 @@
1
+ module ChartMogul
2
+ module Concerns
3
+ module Summary
4
+ def self.included(base)
5
+ base.send :prepend, InstanceMethods
6
+
7
+ base.instance_eval do
8
+ readonly_attr :summary
9
+ end
10
+ end
11
+
12
+ module InstanceMethods
13
+ def set_summary(summary_attributes)
14
+ @summary = ChartMogul::Summary.new_from_json(summary_attributes)
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+
@@ -0,0 +1,15 @@
1
+ module ChartMogul
2
+ module ConfigAttributes
3
+ def config_accessor(attribute)
4
+ define_method(attribute) do
5
+ attr = config.send(attribute)
6
+ raise ConfigurationError.new("Configuration for #{attribute} not set") if attr.nil?
7
+ attr
8
+ end
9
+
10
+ define_method("#{attribute}=") do |val|
11
+ config.send("#{attribute}=", val)
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,6 @@
1
+ module ChartMogul
2
+ class Configuration
3
+ attr_accessor :account_token
4
+ attr_accessor :secret_key
5
+ end
6
+ end
@@ -0,0 +1,114 @@
1
+ module ChartMogul
2
+ module Enrichment
3
+ class Customer < APIResource
4
+ set_resource_name 'Customer'
5
+
6
+ readonly_attr :id
7
+ readonly_attr :uuid
8
+ readonly_attr :external_id
9
+ readonly_attr :name
10
+ readonly_attr :email
11
+ readonly_attr :status
12
+ readonly_attr :customer_since, type: :time
13
+ readonly_attr :attributes
14
+ readonly_attr :address
15
+ readonly_attr :mrr
16
+ readonly_attr :arr
17
+ readonly_attr :billing_system_url
18
+ readonly_attr :chartmogul_url
19
+ readonly_attr :billing_system_type
20
+ readonly_attr :currency
21
+ readonly_attr :currency_sign
22
+
23
+ include API::Actions::Custom
24
+
25
+ def tags
26
+ @attributes[:tags]
27
+ end
28
+
29
+ def custom_attributes
30
+ @attributes[:custom]
31
+ end
32
+
33
+ def add_tags!(*tags)
34
+ self.tags = custom_without_assign!(:post,
35
+ "/v1/customers/#{id}/attributes/tags",
36
+ tags: tags)[:tags]
37
+ end
38
+
39
+ def remove_tags!(*tags)
40
+ self.tags = custom_without_assign!(:delete,
41
+ "/v1/customers/#{id}/attributes/tags",
42
+ tags: tags)[:tags]
43
+ end
44
+
45
+ def add_custom_attributes!(*custom_attrs)
46
+ self.custom_attributes = custom_without_assign!(:post,
47
+ "/v1/customers/#{id}/attributes/custom",
48
+ custom: custom_attrs)[:custom]
49
+ end
50
+
51
+ def update_custom_attributes!(custom_attrs = {})
52
+ self.custom_attributes = custom_without_assign!(:put,
53
+ "/v1/customers/#{id}/attributes/custom",
54
+ custom: custom_attrs)[:custom]
55
+ end
56
+
57
+ def remove_custom_attributes!(*custom_attrs)
58
+ self.custom_attributes = custom_without_assign!(:delete,
59
+ "/v1/customers/#{id}/attributes/custom",
60
+ custom: custom_attrs)[:custom]
61
+ end
62
+
63
+ def self.retrieve(customer_id)
64
+ custom!(:get, "/v1/customers/#{customer_id}")
65
+ end
66
+
67
+ def self.all(options = {})
68
+ Customers.all(options)
69
+ end
70
+
71
+ def self.search(email)
72
+ Customers.search(email)
73
+ end
74
+
75
+ private
76
+
77
+ def tags=(tags)
78
+ @attributes[:tags] = tags
79
+ end
80
+
81
+ def custom_attributes=(custom_attributes = {})
82
+ @attributes[:custom] = typecast_custom_attributes(custom_attributes)
83
+ end
84
+
85
+ def set_attributes(attributes_attributes)
86
+ @attributes = attributes_attributes
87
+ @attributes[:custom] = typecast_custom_attributes(attributes_attributes[:custom])
88
+ end
89
+
90
+ def typecast_custom_attributes(custom_attributes)
91
+ return {} unless custom_attributes
92
+ custom_attributes.each_with_object({}) do |(key, value), hash|
93
+ hash[key] = value.instance_of?(String) ? (Time.parse(value) rescue value) : value
94
+ end
95
+ end
96
+ end
97
+
98
+ class Customers < APIResource
99
+ set_resource_name 'Customers'
100
+ set_resource_path '/v1/customers'
101
+
102
+ include Concerns::Entries
103
+ include API::Actions::Custom
104
+ include Concerns::Pageable
105
+
106
+ set_entry_class Customer
107
+
108
+ def self.search(email)
109
+ path = ChartMogul::ResourcePath.new('/v1/customers/search')
110
+ custom!(:get, path.apply_with_get_params(email: email))
111
+ end
112
+ end
113
+ end
114
+ end
@@ -0,0 +1,19 @@
1
+ module ChartMogul
2
+ class ChartMogulError < StandardError
3
+ attr_accessor :message
4
+ attr_accessor :response
5
+ attr_accessor :http_status
6
+
7
+ def initialize(message, http_status:nil, response:nil)
8
+ @message = message
9
+ @http_status = http_status
10
+ @response = response
11
+ end
12
+
13
+ def to_s
14
+ status = @http_status ? " (HTTP Status: #{@http_status.to_s})" : ''
15
+ response = @response ? "\nResponse: #{@response.to_s}" : ''
16
+ "#{message}#{status}#{response}"
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,4 @@
1
+ module ChartMogul
2
+ class ConfigurationError < ChartMogulError
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module ChartMogul
2
+ class ForbiddenError < ChartMogulError
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module ChartMogul
2
+ class NotFoundError < ChartMogulError
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module ChartMogul
2
+ class ResourceInvalidError < ChartMogulError
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module ChartMogul
2
+ class SchemaInvalidError < ChartMogulError
3
+ end
4
+ end
@@ -0,0 +1,38 @@
1
+ module ChartMogul
2
+ module Import
3
+ class Customer < APIResource
4
+ set_resource_name 'Customer'
5
+ set_resource_path '/v1/import/customers'
6
+ set_resource_root_key :customers
7
+
8
+ readonly_attr :uuid
9
+
10
+ writeable_attr :external_id
11
+ writeable_attr :name
12
+ writeable_attr :email
13
+ writeable_attr :company
14
+ writeable_attr :country
15
+ writeable_attr :state
16
+ writeable_attr :city
17
+ writeable_attr :zip
18
+
19
+ writeable_attr :data_source_uuid
20
+
21
+ include API::Actions::All
22
+ include API::Actions::Create
23
+ include API::Actions::Destroy
24
+
25
+ def subscriptions
26
+ @subscriptions ||= Subscription.all(customer_uuid: uuid)
27
+ end
28
+
29
+ def invoices
30
+ @invoices ||= CustomerInvoices.all(customer_uuid: uuid)
31
+ end
32
+
33
+ def invoices=(invoices_array)
34
+ @invoices = CustomerInvoices.new(customer_uuid: uuid, invoices: invoices_array)
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,40 @@
1
+ require 'forwardable'
2
+
3
+ module ChartMogul
4
+ module Import
5
+ class CustomerInvoices < APIResource
6
+ extend Forwardable
7
+ include Enumerable
8
+
9
+ set_resource_name 'Invoices'
10
+ set_resource_path '/v1/import/customers/:customer_uuid/invoices'
11
+
12
+ writeable_attr :invoices, default: []
13
+
14
+ writeable_attr :customer_uuid
15
+
16
+ include API::Actions::All
17
+ include API::Actions::Create
18
+
19
+ def serialize_invoices
20
+ map(&:serialize_for_write)
21
+ end
22
+
23
+ def_delegators :invoices, :each, :[], :<<, :size, :length
24
+
25
+ private
26
+
27
+ def set_invoices(invoices_attributes)
28
+ @invoices = invoices_attributes.map.with_index do |invoice_attributes, index|
29
+ existing_invoice = invoices[index]
30
+
31
+ if existing_invoice
32
+ existing_invoice.assign_all_attributes(invoice_attributes)
33
+ else
34
+ Invoice.new_from_json(invoice_attributes)
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,19 @@
1
+ module ChartMogul
2
+ module Import
3
+ class DataSource < APIResource
4
+ set_resource_name 'Data Source'
5
+ set_resource_path '/v1/import/data_sources'
6
+ set_resource_root_key :data_sources
7
+
8
+ readonly_attr :uuid
9
+ readonly_attr :status
10
+ readonly_attr :created_at, type: :time
11
+
12
+ writeable_attr :name
13
+
14
+ include API::Actions::All
15
+ include API::Actions::Create
16
+ include API::Actions::Destroy
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,64 @@
1
+ module ChartMogul
2
+ module Import
3
+ class Invoice < ChartMogul::Object
4
+ readonly_attr :uuid
5
+
6
+ writeable_attr :date, type: :time
7
+ writeable_attr :currency
8
+ writeable_attr :line_items, default: []
9
+ writeable_attr :transactions, default: []
10
+ writeable_attr :external_id
11
+ writeable_attr :due_date, type: :time
12
+
13
+ def serialize_line_items
14
+ line_items.map(&:serialize_for_write)
15
+ end
16
+
17
+ def serialize_transactions
18
+ transactions.map(&:serialize_for_write)
19
+ end
20
+
21
+ private
22
+
23
+ def set_line_items(line_items_attributes)
24
+ @line_items = line_items_attributes.map.with_index do |line_item_attributes, index|
25
+ existing_line_item = line_items[index]
26
+
27
+ if existing_line_item
28
+ existing_line_item.assign_all_attributes(line_item_attributes)
29
+ else
30
+ line_item_class(line_item_attributes[:type])
31
+ .new_from_json(line_item_attributes.merge(invoice_uuid: uuid))
32
+ end
33
+ end
34
+ end
35
+
36
+ def set_transactions(transactions_attributes)
37
+ @transactions = transactions_attributes.map.with_index do |transaction_attributes, index|
38
+ existing_transaction = transactions[index]
39
+
40
+ if existing_transaction
41
+ existing_transaction.assign_all_attributes(transaction_attributes)
42
+ else
43
+ transaction_class(transaction_attributes[:type])
44
+ .new_from_json(transaction_attributes.merge(invoice_uuid: uuid))
45
+ end
46
+ end
47
+ end
48
+
49
+ def line_item_class(type)
50
+ case type
51
+ when 'subscription' then ChartMogul::Import::LineItems::Subscription
52
+ when 'one_time' then ChartMogul::Import::LineItems::OneTime
53
+ end
54
+ end
55
+
56
+ def transaction_class(type)
57
+ case type
58
+ when 'payment' then ChartMogul::Import::Transactions::Payment
59
+ when 'refund' then ChartMogul::Import::Transactions::Refund
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,25 @@
1
+ module ChartMogul
2
+ module Import
3
+ module LineItems
4
+ class OneTime < ChartMogul::Object
5
+ readonly_attr :uuid
6
+
7
+ writeable_attr :type, default: 'one_time'
8
+ writeable_attr :amount_in_cents
9
+ writeable_attr :description
10
+ writeable_attr :quantity
11
+ writeable_attr :discount_amount_in_cents
12
+ writeable_attr :discount_code
13
+ writeable_attr :tax_amount_in_cents
14
+ writeable_attr :external_id
15
+
16
+ writeable_attr :invoice_uuid
17
+
18
+ def initialize(attributes = {})
19
+ super(attributes)
20
+ @type = 'one_time'
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end