bill_forward 1.2014.296
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +27 -0
- data/.idea/.name +1 -0
- data/.idea/compiler.xml +23 -0
- data/.idea/copyright/profiles_settings.xml +3 -0
- data/.idea/encodings.xml +5 -0
- data/.idea/inspectionProfiles/Project_Default.xml +11 -0
- data/.idea/inspectionProfiles/profiles_settings.xml +7 -0
- data/.idea/misc.xml +23 -0
- data/.idea/modules.xml +9 -0
- data/.idea/scopes/scope_settings.xml +5 -0
- data/.idea/vcs.xml +7 -0
- data/.rspec +2 -0
- data/Gemfile +9 -0
- data/LICENSE.md +22 -0
- data/README.md +227 -0
- data/Rakefile +73 -0
- data/bill_forward.gemspec +29 -0
- data/bill_forward.iml +28 -0
- data/lib/bill_forward.rb +18 -0
- data/lib/bill_forward/billing_entity.rb +263 -0
- data/lib/bill_forward/client.rb +355 -0
- data/lib/bill_forward/custom_hash.rb +14 -0
- data/lib/bill_forward/deny_method.rb +4 -0
- data/lib/bill_forward/entities/account.rb +19 -0
- data/lib/bill_forward/entities/address.rb +25 -0
- data/lib/bill_forward/entities/amendments/amendment.rb +11 -0
- data/lib/bill_forward/entities/amendments/invoice_recalculation_amendment.rb +10 -0
- data/lib/bill_forward/entities/api_configuration.rb +11 -0
- data/lib/bill_forward/entities/authorize_net_token.rb +9 -0
- data/lib/bill_forward/entities/credit_note.rb +13 -0
- data/lib/bill_forward/entities/invoice.rb +25 -0
- data/lib/bill_forward/entities/invoice_parts/invoice_line.rb +37 -0
- data/lib/bill_forward/entities/invoice_parts/invoice_payment.rb +29 -0
- data/lib/bill_forward/entities/invoice_parts/tax_line.rb +23 -0
- data/lib/bill_forward/entities/invoice_parts/taxation_link.rb +5 -0
- data/lib/bill_forward/entities/organisation.rb +37 -0
- data/lib/bill_forward/entities/payment_method.rb +5 -0
- data/lib/bill_forward/entities/payment_method_subscription_link.rb +5 -0
- data/lib/bill_forward/entities/pricing_component.rb +21 -0
- data/lib/bill_forward/entities/pricing_component_tier.rb +5 -0
- data/lib/bill_forward/entities/pricing_component_value.rb +5 -0
- data/lib/bill_forward/entities/pricing_component_value_change.rb +5 -0
- data/lib/bill_forward/entities/product.rb +5 -0
- data/lib/bill_forward/entities/product_rate_plan.rb +19 -0
- data/lib/bill_forward/entities/profile.rb +15 -0
- data/lib/bill_forward/entities/role.rb +4 -0
- data/lib/bill_forward/entities/subscription.rb +53 -0
- data/lib/bill_forward/entities/unit_of_measure.rb +5 -0
- data/lib/bill_forward/insertable_entity.rb +32 -0
- data/lib/bill_forward/mutable_entity.rb +47 -0
- data/lib/bill_forward/resource_path.rb +11 -0
- data/lib/bill_forward/type_check.rb +21 -0
- data/lib/bill_forward/version.rb +4 -0
- data/spec/component/account_spec.rb +200 -0
- data/spec/component/billing_entity_spec.rb +153 -0
- data/spec/component/invoice_spec.rb +155 -0
- data/spec/component/subscription_spec.rb +357 -0
- data/spec/functional/account_spec.rb +25 -0
- data/spec/functional/bad_citizen/account_spec.rb +103 -0
- data/spec/functional/bad_citizen/credit_note_spec.rb +41 -0
- data/spec/functional/bad_citizen/payment_method_spec.rb +34 -0
- data/spec/functional/bad_citizen/product_rate_plan_spec.rb +105 -0
- data/spec/functional/bad_citizen/product_spec.rb +22 -0
- data/spec/functional/bad_citizen/situational/authorize_net_token_spec.rb +27 -0
- data/spec/functional/bad_citizen/situational/invoice_recalculation_amendment_spec.rb +27 -0
- data/spec/functional/bad_citizen/situational/invoice_spec.rb +22 -0
- data/spec/functional/bad_citizen/situational/malordered_entity_spec.rb +43 -0
- data/spec/functional/bad_citizen/situational/organisation_spec.rb +39 -0
- data/spec/functional/bad_citizen/situational/payment_method_spec.rb +47 -0
- data/spec/functional/bad_citizen/situational/subscription_chargeable_spec.rb +255 -0
- data/spec/functional/bad_citizen/subscription_spec.rb +179 -0
- data/spec/functional/bad_citizen/subscription_with_credit_spec.rb +240 -0
- data/spec/functional/bad_citizen/unit_of_measure_spec.rb +20 -0
- data/spec/functional/billing_entity_spec.rb +22 -0
- data/spec/functional/client_spec.rb +24 -0
- data/spec/functional/organisation_spec.rb +28 -0
- data/spec/setup_test_constants.rb +73 -0
- data/spec/spec_helper.rb +11 -0
- data/spec/syntax/account_spec.rb +24 -0
- data/spec/syntax/address_spec.rb +19 -0
- data/spec/syntax/api_configuration_spec.rb +13 -0
- data/spec/syntax/billing_entity_spec.rb +93 -0
- data/spec/syntax/client_spec.rb +8 -0
- metadata +287 -0
@@ -0,0 +1,14 @@
|
|
1
|
+
module BillForward
|
2
|
+
# Note: does not use indifferent access! Only entities themselves have indifferent access!
|
3
|
+
class OrderedHashWithDotAccess < ActiveSupport::OrderedHash
|
4
|
+
def method_missing(method_id, *arguments, &block)
|
5
|
+
# no call to super; our criteria is all keys.
|
6
|
+
#setter
|
7
|
+
if /^(\w+)=$/ =~ method_id.to_s
|
8
|
+
return self[$1] = arguments.first
|
9
|
+
end
|
10
|
+
#getter
|
11
|
+
self[method_id.to_s]
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module BillForward
|
2
|
+
# This entity exposes the following child entities via method_missing:
|
3
|
+
#
|
4
|
+
# Role[] .roles
|
5
|
+
# PaymentMethod[] .paymentMethods
|
6
|
+
# Profile .profile
|
7
|
+
class Account < MutableEntity
|
8
|
+
@resource_path = BillForward::ResourcePath.new("accounts", "account")
|
9
|
+
|
10
|
+
protected
|
11
|
+
def unserialize_all(hash)
|
12
|
+
super
|
13
|
+
unserialize_entity('profile', Profile, hash)
|
14
|
+
|
15
|
+
unserialize_array_of_entities('roles', Role, hash)
|
16
|
+
unserialize_array_of_entities('paymentMethods', PaymentMethod, hash)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module BillForward
|
2
|
+
class Address < MutableEntity
|
3
|
+
@resource_path = BillForward::ResourcePath.new('addresses', 'address')
|
4
|
+
|
5
|
+
class << self
|
6
|
+
def get_by_id(id, query_params = {}, customClient = nil)
|
7
|
+
raise DenyMethod.new 'Get by ID support is denied for this entity; '+
|
8
|
+
'at the time of writing, no API endpoint exists to support it.'+
|
9
|
+
'The entity can be GETted through cascade only (i.e. GET a related entity).'
|
10
|
+
end
|
11
|
+
|
12
|
+
def get_all(query_params = {}, customClient = nil)
|
13
|
+
raise DenyMethod.new 'Get All support is denied for this entity; '+
|
14
|
+
'at the time of writing, no API endpoint exists to support it.'+
|
15
|
+
'The entity can be GETted through cascade only (i.e. GET a related entity).'
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def save()
|
20
|
+
raise DenyMethod.new 'Save support is denied for this entity; '+
|
21
|
+
'at the time of writing, the provided API endpoint is not functioning.'+
|
22
|
+
'The entity can be saved through cascade only (i.e. save a related entity).'
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module BillForward
|
2
|
+
class Amendment < InsertableEntity
|
3
|
+
@resource_path = BillForward::ResourcePath.new("amendments", "amendment")
|
4
|
+
|
5
|
+
def initialize(*args)
|
6
|
+
raise AbstractInstantiateError.new('This abstract class cannot be instantiated!') if self.class == Amendment
|
7
|
+
super
|
8
|
+
end
|
9
|
+
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module BillForward
|
2
|
+
class APIConfiguration < MutableEntity
|
3
|
+
class << self
|
4
|
+
def create(entity = nil)
|
5
|
+
raise DenyMethod.new 'Create support is denied for this entity; '+
|
6
|
+
'at the time of writing, no API endpoint exists to support it. '+
|
7
|
+
'The entity can be created through cascade only (i.e. instantiated within another entity).'
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
module BillForward
|
2
|
+
class AuthorizeNetToken < MutableEntity
|
3
|
+
# WARNING: resource paths for AuthorizeNetTokens do not follow the usual pattern;
|
4
|
+
# instead of posting to 'root' of a URL root reserved for AuthorizeNetTokens,
|
5
|
+
# this routing is a bit less standard; for example we can't GET from the same
|
6
|
+
# place we POST to.
|
7
|
+
@resource_path = BillForward::ResourcePath.new('vaulted-gateways/authorize-net', 'authorizeNetToken')
|
8
|
+
end
|
9
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module BillForward
|
2
|
+
class CreditNote < MutableEntity
|
3
|
+
@resource_path = BillForward::ResourcePath.new('credit-notes', 'creditNote')
|
4
|
+
|
5
|
+
class << self
|
6
|
+
def get_all(query_params = {}, customClient = nil)
|
7
|
+
raise DenyMethod.new 'Get All support is denied for this entity; '+
|
8
|
+
'at the time of writing, no API endpoint exists to support it.'+
|
9
|
+
'The entity can be GETted by ID only.'
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module BillForward
|
2
|
+
# This entity exposes the following child entities via method_missing:
|
3
|
+
#
|
4
|
+
# InvoiceLine[] .invoiceLines
|
5
|
+
# TaxLine[] .taxLines
|
6
|
+
# InvoicePayment[] .invoicePayments
|
7
|
+
class Invoice < MutableEntity
|
8
|
+
@resource_path = BillForward::ResourcePath.new('invoices', 'invoice')
|
9
|
+
|
10
|
+
class << self
|
11
|
+
def create(entity = nil)
|
12
|
+
raise DenyMethod.new 'Create support is denied for this entity; '+
|
13
|
+
'Invoices are generated instead by the BillForward Engines.'
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
protected
|
18
|
+
def unserialize_all(hash)
|
19
|
+
super
|
20
|
+
unserialize_array_of_entities('invoiceLines', InvoiceLine, hash)
|
21
|
+
unserialize_array_of_entities('taxLines', TaxLine, hash)
|
22
|
+
unserialize_array_of_entities('invoicePayments', InvoicePayment, hash)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module BillForward
|
2
|
+
# This entity exposes the following child entities via method_missing:
|
3
|
+
#
|
4
|
+
# UnitOfMeasure .unitOfMeasure
|
5
|
+
class InvoiceLine < MutableEntity
|
6
|
+
class << self
|
7
|
+
def create(entity = nil)
|
8
|
+
raise DenyMethod.new 'Create support is denied for this entity; '+
|
9
|
+
'at the time of writing, no API endpoint exists to support it. '+
|
10
|
+
'The entity can be created through cascade only (i.e. instantiated within another entity).'
|
11
|
+
end
|
12
|
+
|
13
|
+
def get_by_id(id, query_params = {}, customClient = nil)
|
14
|
+
raise DenyMethod.new 'Get by ID support is denied for this entity; '+
|
15
|
+
'at the time of writing, no API endpoint exists to support it.'+
|
16
|
+
'The entity can be GETted through cascade only (i.e. GET a related entity).'
|
17
|
+
end
|
18
|
+
|
19
|
+
def get_all(query_params = {}, customClient = nil)
|
20
|
+
raise DenyMethod.new 'Get All support is denied for this entity; '+
|
21
|
+
'at the time of writing, no API endpoint exists to support it.'+
|
22
|
+
'The entity can be GETted through cascade only (i.e. GET a related entity).'
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def save()
|
27
|
+
raise DenyMethod.new 'Save support is denied for this entity; '+
|
28
|
+
'at the time of writing, the provided API endpoint is not functioning.'+
|
29
|
+
'The entity can be saved through cascade only (i.e. save a related entity).'
|
30
|
+
end
|
31
|
+
protected
|
32
|
+
def unserialize_all(hash)
|
33
|
+
super
|
34
|
+
unserialize_entity('unitOfMeasure', UnitOfMeasure, hash)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module BillForward
|
2
|
+
class InvoicePayment < MutableEntity
|
3
|
+
class << self
|
4
|
+
def create(entity = nil)
|
5
|
+
raise DenyMethod.new 'Create support is denied for this entity; '+
|
6
|
+
'at the time of writing, no API endpoint exists to support it. '+
|
7
|
+
'The entity can be created through cascade only (i.e. instantiated within another entity).'
|
8
|
+
end
|
9
|
+
|
10
|
+
def get_by_id(id, query_params = {}, customClient = nil)
|
11
|
+
raise DenyMethod.new 'Get by ID support is denied for this entity; '+
|
12
|
+
'at the time of writing, no API endpoint exists to support it.'+
|
13
|
+
'The entity can be GETted through cascade only (i.e. GET a related entity).'
|
14
|
+
end
|
15
|
+
|
16
|
+
def get_all(query_params = {}, customClient = nil)
|
17
|
+
raise DenyMethod.new 'Get All support is denied for this entity; '+
|
18
|
+
'at the time of writing, no API endpoint exists to support it.'+
|
19
|
+
'The entity can be GETted through cascade only (i.e. GET a related entity).'
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def save()
|
24
|
+
raise DenyMethod.new 'Save support is denied for this entity; '+
|
25
|
+
'at the time of writing, the provided API endpoint is not functioning.'+
|
26
|
+
'The entity can be saved through cascade only (i.e. save a related entity).'
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module BillForward
|
2
|
+
class TaxLine < InsertableEntity
|
3
|
+
class << self
|
4
|
+
def create(entity = nil)
|
5
|
+
raise DenyMethod.new 'Create support is denied for this entity; '+
|
6
|
+
'at the time of writing, no API endpoint exists to support it. '+
|
7
|
+
'The entity can be created through cascade only (i.e. instantiated within another entity).'
|
8
|
+
end
|
9
|
+
|
10
|
+
def get_by_id(id, query_params = {}, customClient = nil)
|
11
|
+
raise DenyMethod.new 'Get by ID support is denied for this entity; '+
|
12
|
+
'at the time of writing, no API endpoint exists to support it.'+
|
13
|
+
'The entity can be GETted through cascade only (i.e. GET a related entity).'
|
14
|
+
end
|
15
|
+
|
16
|
+
def get_all(query_params = {}, customClient = nil)
|
17
|
+
raise DenyMethod.new 'Get All support is denied for this entity; '+
|
18
|
+
'at the time of writing, no API endpoint exists to support it.'+
|
19
|
+
'The entity can be GETted through cascade only (i.e. GET a related entity).'
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module BillForward
|
2
|
+
# This entity exposes the following child entities via method_missing:
|
3
|
+
#
|
4
|
+
# APIConfiguration[] .apiConfigurations
|
5
|
+
class Organisation < MutableEntity
|
6
|
+
@resource_path = BillForward::ResourcePath.new("organizations", "organization")
|
7
|
+
|
8
|
+
class << self
|
9
|
+
def get_mine(options = {}, customClient = nil)
|
10
|
+
client = customClient
|
11
|
+
client = singleton_client if client.nil?
|
12
|
+
|
13
|
+
route = resource_path.path
|
14
|
+
endpoint = 'mine'
|
15
|
+
url_full = "#{route}/#{endpoint}"
|
16
|
+
|
17
|
+
response = client.get(url_full)
|
18
|
+
results = response["results"]
|
19
|
+
|
20
|
+
# maybe use build_entity_array here for consistency
|
21
|
+
entity_array = Array.new
|
22
|
+
# maybe it's an empty array, but that's okay too.
|
23
|
+
results.each do |value|
|
24
|
+
entity = self.new(value, client)
|
25
|
+
entity_array.push(entity)
|
26
|
+
end
|
27
|
+
entity_array
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
protected
|
32
|
+
def unserialize_all(hash)
|
33
|
+
super
|
34
|
+
unserialize_array_of_entities('apiConfigurations', APIConfiguration, hash)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module BillForward
|
2
|
+
# This entity exposes the following child entities via method_missing:
|
3
|
+
#
|
4
|
+
# PricingComponentTier[] .tiers
|
5
|
+
class PricingComponent < MutableEntity
|
6
|
+
@resource_path = BillForward::ResourcePath.new("pricing-components", "PricingComponent")
|
7
|
+
|
8
|
+
def self.get_all(options=nil, customClient=nil)
|
9
|
+
raise ArgumentError.new('Get All support is denied for this entity;
|
10
|
+
at the time of writing, no working API endpoint exists to support it.
|
11
|
+
The entity can be GETted through cascade (i.e. GET a related entity), or by ID only.'
|
12
|
+
)
|
13
|
+
end
|
14
|
+
|
15
|
+
protected
|
16
|
+
def unserialize_all(hash)
|
17
|
+
super
|
18
|
+
unserialize_array_of_entities('tiers', PricingComponentTier, hash)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module BillForward
|
2
|
+
# This entity exposes the following child entities via method_missing:
|
3
|
+
#
|
4
|
+
# Product .product
|
5
|
+
# TaxationLink[] .taxation
|
6
|
+
# PricingComponent[] .pricingComponents
|
7
|
+
class ProductRatePlan < MutableEntity
|
8
|
+
@resource_path = BillForward::ResourcePath.new("product-rate-plans", "productRatePlan")
|
9
|
+
|
10
|
+
protected
|
11
|
+
def unserialize_all(hash)
|
12
|
+
super
|
13
|
+
unserialize_entity('product', Product, hash)
|
14
|
+
|
15
|
+
unserialize_array_of_entities('taxation', TaxationLink, hash)
|
16
|
+
unserialize_array_of_entities('pricingComponents', PricingComponent, hash)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module BillForward
|
2
|
+
# This entity exposes the following child entities via method_missing:
|
3
|
+
#
|
4
|
+
# Address[] .addresses
|
5
|
+
class Profile < MutableEntity
|
6
|
+
@resource_path = BillForward::ResourcePath.new("profiles", "profile")
|
7
|
+
|
8
|
+
protected
|
9
|
+
def unserialize_all(hash)
|
10
|
+
super
|
11
|
+
|
12
|
+
unserialize_array_of_entities('addresses', Address, hash)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module BillForward
|
2
|
+
# This entity exposes the following child entities via method_missing:
|
3
|
+
#
|
4
|
+
# PricingComponentValue[] .pricingComponentValues
|
5
|
+
# PricingComponentValueChange[] .pricingComponentValueChanges
|
6
|
+
class Subscription < MutableEntity
|
7
|
+
@resource_path = BillForward::ResourcePath.new("subscriptions", "subscription")
|
8
|
+
|
9
|
+
class << self
|
10
|
+
def get_by_account_id(id, query_params = {}, customClient = nil)
|
11
|
+
client = customClient
|
12
|
+
client = singleton_client if client.nil?
|
13
|
+
|
14
|
+
raise ArgumentError.new("id cannot be nil") if id.nil?
|
15
|
+
TypeCheck.verifyObj(Hash, query_params, 'query_params')
|
16
|
+
|
17
|
+
route = resource_path.path
|
18
|
+
endpoint = 'account'
|
19
|
+
url_full = "#{route}/#{endpoint}/#{id}"
|
20
|
+
|
21
|
+
response = client.get(url_full, query_params)
|
22
|
+
results = response["results"]
|
23
|
+
|
24
|
+
# maybe use build_entity_array here for consistency
|
25
|
+
entity_array = Array.new
|
26
|
+
# maybe it's an empty array, but that's okay too.
|
27
|
+
results.each do |value|
|
28
|
+
entity = self.new(value, client)
|
29
|
+
entity_array.push(entity)
|
30
|
+
end
|
31
|
+
entity_array
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def activate
|
36
|
+
set_state_param('state', 'AwaitingPayment')
|
37
|
+
response = save
|
38
|
+
response
|
39
|
+
end
|
40
|
+
|
41
|
+
protected
|
42
|
+
def unserialize_all(hash)
|
43
|
+
super
|
44
|
+
# always has these:
|
45
|
+
unserialize_array_of_entities('pricingComponentValues', PricingComponentValue, hash)
|
46
|
+
unserialize_array_of_entities('pricingComponentValueChanges', PricingComponentValueChange, hash)
|
47
|
+
|
48
|
+
|
49
|
+
# think about the other entities later..
|
50
|
+
# unserialize_array_of_entities('paymentMethodSubscriptionLinks', PaymentMethodSubscriptionLink, hash)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|