bill_forward 1.2014.296

Sign up to get free protection for your applications and to get access to all the features.
Files changed (84) hide show
  1. data/.gitignore +27 -0
  2. data/.idea/.name +1 -0
  3. data/.idea/compiler.xml +23 -0
  4. data/.idea/copyright/profiles_settings.xml +3 -0
  5. data/.idea/encodings.xml +5 -0
  6. data/.idea/inspectionProfiles/Project_Default.xml +11 -0
  7. data/.idea/inspectionProfiles/profiles_settings.xml +7 -0
  8. data/.idea/misc.xml +23 -0
  9. data/.idea/modules.xml +9 -0
  10. data/.idea/scopes/scope_settings.xml +5 -0
  11. data/.idea/vcs.xml +7 -0
  12. data/.rspec +2 -0
  13. data/Gemfile +9 -0
  14. data/LICENSE.md +22 -0
  15. data/README.md +227 -0
  16. data/Rakefile +73 -0
  17. data/bill_forward.gemspec +29 -0
  18. data/bill_forward.iml +28 -0
  19. data/lib/bill_forward.rb +18 -0
  20. data/lib/bill_forward/billing_entity.rb +263 -0
  21. data/lib/bill_forward/client.rb +355 -0
  22. data/lib/bill_forward/custom_hash.rb +14 -0
  23. data/lib/bill_forward/deny_method.rb +4 -0
  24. data/lib/bill_forward/entities/account.rb +19 -0
  25. data/lib/bill_forward/entities/address.rb +25 -0
  26. data/lib/bill_forward/entities/amendments/amendment.rb +11 -0
  27. data/lib/bill_forward/entities/amendments/invoice_recalculation_amendment.rb +10 -0
  28. data/lib/bill_forward/entities/api_configuration.rb +11 -0
  29. data/lib/bill_forward/entities/authorize_net_token.rb +9 -0
  30. data/lib/bill_forward/entities/credit_note.rb +13 -0
  31. data/lib/bill_forward/entities/invoice.rb +25 -0
  32. data/lib/bill_forward/entities/invoice_parts/invoice_line.rb +37 -0
  33. data/lib/bill_forward/entities/invoice_parts/invoice_payment.rb +29 -0
  34. data/lib/bill_forward/entities/invoice_parts/tax_line.rb +23 -0
  35. data/lib/bill_forward/entities/invoice_parts/taxation_link.rb +5 -0
  36. data/lib/bill_forward/entities/organisation.rb +37 -0
  37. data/lib/bill_forward/entities/payment_method.rb +5 -0
  38. data/lib/bill_forward/entities/payment_method_subscription_link.rb +5 -0
  39. data/lib/bill_forward/entities/pricing_component.rb +21 -0
  40. data/lib/bill_forward/entities/pricing_component_tier.rb +5 -0
  41. data/lib/bill_forward/entities/pricing_component_value.rb +5 -0
  42. data/lib/bill_forward/entities/pricing_component_value_change.rb +5 -0
  43. data/lib/bill_forward/entities/product.rb +5 -0
  44. data/lib/bill_forward/entities/product_rate_plan.rb +19 -0
  45. data/lib/bill_forward/entities/profile.rb +15 -0
  46. data/lib/bill_forward/entities/role.rb +4 -0
  47. data/lib/bill_forward/entities/subscription.rb +53 -0
  48. data/lib/bill_forward/entities/unit_of_measure.rb +5 -0
  49. data/lib/bill_forward/insertable_entity.rb +32 -0
  50. data/lib/bill_forward/mutable_entity.rb +47 -0
  51. data/lib/bill_forward/resource_path.rb +11 -0
  52. data/lib/bill_forward/type_check.rb +21 -0
  53. data/lib/bill_forward/version.rb +4 -0
  54. data/spec/component/account_spec.rb +200 -0
  55. data/spec/component/billing_entity_spec.rb +153 -0
  56. data/spec/component/invoice_spec.rb +155 -0
  57. data/spec/component/subscription_spec.rb +357 -0
  58. data/spec/functional/account_spec.rb +25 -0
  59. data/spec/functional/bad_citizen/account_spec.rb +103 -0
  60. data/spec/functional/bad_citizen/credit_note_spec.rb +41 -0
  61. data/spec/functional/bad_citizen/payment_method_spec.rb +34 -0
  62. data/spec/functional/bad_citizen/product_rate_plan_spec.rb +105 -0
  63. data/spec/functional/bad_citizen/product_spec.rb +22 -0
  64. data/spec/functional/bad_citizen/situational/authorize_net_token_spec.rb +27 -0
  65. data/spec/functional/bad_citizen/situational/invoice_recalculation_amendment_spec.rb +27 -0
  66. data/spec/functional/bad_citizen/situational/invoice_spec.rb +22 -0
  67. data/spec/functional/bad_citizen/situational/malordered_entity_spec.rb +43 -0
  68. data/spec/functional/bad_citizen/situational/organisation_spec.rb +39 -0
  69. data/spec/functional/bad_citizen/situational/payment_method_spec.rb +47 -0
  70. data/spec/functional/bad_citizen/situational/subscription_chargeable_spec.rb +255 -0
  71. data/spec/functional/bad_citizen/subscription_spec.rb +179 -0
  72. data/spec/functional/bad_citizen/subscription_with_credit_spec.rb +240 -0
  73. data/spec/functional/bad_citizen/unit_of_measure_spec.rb +20 -0
  74. data/spec/functional/billing_entity_spec.rb +22 -0
  75. data/spec/functional/client_spec.rb +24 -0
  76. data/spec/functional/organisation_spec.rb +28 -0
  77. data/spec/setup_test_constants.rb +73 -0
  78. data/spec/spec_helper.rb +11 -0
  79. data/spec/syntax/account_spec.rb +24 -0
  80. data/spec/syntax/address_spec.rb +19 -0
  81. data/spec/syntax/api_configuration_spec.rb +13 -0
  82. data/spec/syntax/billing_entity_spec.rb +93 -0
  83. data/spec/syntax/client_spec.rb +8 -0
  84. metadata +287 -0
@@ -0,0 +1,240 @@
1
+ require File.join(File.expand_path(File.dirname(__FILE__)), "..", "..", "spec_helper")
2
+
3
+ describe BillForward::Subscription do
4
+ before :all do
5
+ @client = BillForwardTest::TEST_CLIENT
6
+ BillForward::Client.default_client = @client
7
+ end
8
+ context 'upon creating required entities for chargeable Subscription' do
9
+ before :all do
10
+ # get our organisation
11
+ organisations = BillForward::Organisation.get_mine
12
+ first_org = organisations.first
13
+
14
+
15
+ # create an account
16
+ # requires (optionally):
17
+ # - profile
18
+ # - - addresses
19
+ addresses = Array.new()
20
+ addresses.push(
21
+ BillForward::Address.new({
22
+ 'addressLine1' => 'address line 1',
23
+ 'addressLine2' => 'address line 2',
24
+ 'addressLine3' => 'address line 3',
25
+ 'city' => 'London',
26
+ 'province' => 'London',
27
+ 'country' => 'United Kingdom',
28
+ 'postcode' => 'SW1 1AS',
29
+ 'landline' => '02000000000',
30
+ 'primaryAddress' => true
31
+ }))
32
+ profile = BillForward::Profile.new({
33
+ 'email' => 'always@testing.is.moe',
34
+ 'firstName' => 'Test',
35
+ 'addresses' => addresses
36
+ })
37
+ account = BillForward::Account.new({
38
+ 'profile' => profile
39
+ })
40
+ created_account = BillForward::Account.create account
41
+
42
+
43
+ # create for our account: a new payment method, using credit notes
44
+ payment_method = BillForward::PaymentMethod.new({
45
+ 'accountID' => created_account.id,
46
+ 'name' => 'Credit Notes',
47
+ 'description' => 'Pay using credit',
48
+ # engines will link this to an invoice once paid, for the sake of refunds
49
+ 'linkID' => '',
50
+ 'gateway' => 'credit_note',
51
+ 'userEditable' => 0,
52
+ 'priority' => 100,
53
+ 'reusable' => 1
54
+ })
55
+ created_payment_method = BillForward::PaymentMethod::create(payment_method)
56
+
57
+
58
+ # issue $100 credit to our account
59
+ credit_note = BillForward::CreditNote.new({
60
+ "accountID" => created_account.id,
61
+ "nominalValue" => 100,
62
+ "currency" => "USD"
63
+ })
64
+ created_credit_note = BillForward::CreditNote.create(credit_note)
65
+
66
+
67
+ # create a unit of measure
68
+ unit_of_measure = BillForward::UnitOfMeasure.new({
69
+ 'name' => 'Devices',
70
+ 'displayedAs' => 'Devices',
71
+ 'roundingScheme' => 'UP',
72
+ })
73
+ created_uom = BillForward::UnitOfMeasure.create(unit_of_measure)
74
+
75
+
76
+ # create a product
77
+ product = BillForward::Product.new({
78
+ 'productType' => 'non-recurring',
79
+ 'state' => 'prod',
80
+ 'name' => 'Month of Paracetamoxyfrusebendroneomycin',
81
+ 'description' => 'It can cure the common cold and being struck by lightning',
82
+ 'durationPeriod' => 'minutes',
83
+ 'duration' => 1,
84
+ })
85
+ created_product = BillForward::Product::create(product)
86
+
87
+
88
+ # make product rate plan..
89
+ # requires:
90
+ # - product,
91
+ # - pricing components..
92
+ # .. - which require pricing component tiers
93
+
94
+ # create tiers..
95
+ # for a flat pricing component:
96
+ tiers_for_flat_component_1 = Array.new()
97
+ tiers_for_flat_component_1.push(
98
+ BillForward::PricingComponentTier.new({
99
+ 'lowerThreshold' => 1,
100
+ 'upperThreshold' => 1,
101
+ 'pricingType' => 'fixed',
102
+ 'price' => 1,
103
+ }))
104
+
105
+ # for a tiered pricing component:
106
+ tiers_for_tiered_component_1 = Array.new()
107
+ tiers_for_tiered_component_1.push(
108
+ BillForward::PricingComponentTier.new({
109
+ 'lowerThreshold' => 1,
110
+ 'upperThreshold' => 1,
111
+ 'pricingType' => 'fixed',
112
+ 'price' => 10,
113
+ }),
114
+ BillForward::PricingComponentTier.new({
115
+ 'lowerThreshold' => 2,
116
+ 'upperThreshold' => 10,
117
+ 'pricingType' => 'unit',
118
+ 'price' => 5
119
+ }),
120
+ BillForward::PricingComponentTier.new({
121
+ 'lowerThreshold' => 11,
122
+ 'upperThreshold' => 100,
123
+ 'pricingType' => 'unit',
124
+ 'price' => 2
125
+ }))
126
+
127
+
128
+ # create pricing components, based on these tiers
129
+ pricing_components = Array.new()
130
+ pricing_components.push(
131
+ BillForward::PricingComponent.new({
132
+ '@type' => 'flatPricingComponent',
133
+ 'chargeModel' => 'flat',
134
+ 'name' => 'Devices used, fixed',
135
+ 'description' => 'How many devices you use, I guess',
136
+ 'unitOfMeasureID' => created_uom.id,
137
+ 'chargeType' => 'subscription',
138
+ 'upgradeMode' => 'immediate',
139
+ 'downgradeMode' => 'immediate',
140
+ 'defaultQuantity' => 1,
141
+ 'tiers' => tiers_for_flat_component_1
142
+ }),
143
+ BillForward::PricingComponent.new({
144
+ '@type' => 'tieredPricingComponent',
145
+ 'chargeModel' => 'tiered',
146
+ 'name' => 'Devices used, tiered',
147
+ 'description' => 'How many devices you use, but with a tiering system',
148
+ 'unitOfMeasureID' => created_uom.id,
149
+ 'chargeType' => 'usage',
150
+ 'upgradeMode' => 'immediate',
151
+ 'downgradeMode' => 'immediate',
152
+ 'defaultQuantity' => 10,
153
+ 'tiers' => tiers_for_tiered_component_1
154
+ }))
155
+
156
+
157
+ # create product rate plan, using pricing components and product
158
+ prp = BillForward::ProductRatePlan.new({
159
+ 'currency' => 'USD',
160
+ 'name' => 'A sound plan',
161
+ 'pricingComponents' => pricing_components,
162
+ 'productID' => created_product.id,
163
+ })
164
+ created_prp = BillForward::ProductRatePlan.create(prp)
165
+
166
+
167
+ # create references for tests to use
168
+ @created_account = created_account
169
+ @created_prp = created_prp
170
+ @created_payment_method = created_payment_method
171
+ end
172
+ describe '::create' do
173
+ describe 'the subscription' do
174
+ before :all do
175
+ # make subscription..
176
+ # requires:
177
+ # - account [we have this already]
178
+ # - product rate plan [we have this already]
179
+ # - pricing component value instances (for every pricing component on the PRP)
180
+ # - payment method subscription links (for every payment method on the account)
181
+
182
+ # create PaymentMethodSubscriptionLink from payment method and organisation
183
+ payment_method_subscription_links = Array.new
184
+ payment_method_subscription_links.push(
185
+ BillForward::PaymentMethodSubscriptionLink.new({
186
+ 'paymentMethodID' => @created_payment_method.id
187
+ }))
188
+
189
+
190
+ pricing_components = @created_prp.pricingComponents
191
+ # get references to each pricing component we made
192
+ flat_pricing_component_1 = pricing_components[0]
193
+ tiered_pricing_component_1 = pricing_components[1]
194
+
195
+ # create PricingComponentValue instances for every PricingComponent on the PRP
196
+ pricing_component_values = Array.new
197
+ pricing_component_values.push(
198
+ BillForward::PricingComponentValue.new({
199
+ 'pricingComponentID' => flat_pricing_component_1.id,
200
+ 'value' => 1,
201
+ }),
202
+ BillForward::PricingComponentValue.new({
203
+ 'pricingComponentID' => tiered_pricing_component_1.id,
204
+ 'value' => 5,
205
+ }))
206
+
207
+
208
+ # create subscription
209
+ subscription = BillForward::Subscription.new({
210
+ 'type' => 'Subscription',
211
+ 'productRatePlanID' => @created_prp.id,
212
+ 'accountID' => @created_account.id,
213
+ 'name' => 'Memorable Subscription',
214
+ 'description' => 'Memorable Subscription Description',
215
+ 'paymentMethodSubscriptionLinks' => payment_method_subscription_links,
216
+ 'pricingComponentValues' => pricing_component_values
217
+ })
218
+ created_sub = BillForward::Subscription.create(subscription)
219
+
220
+ # create references for tests to use
221
+ @created_sub = created_sub
222
+ end
223
+ subject(:subscription) { @created_sub }
224
+ it 'is created' do
225
+ expect(subscription['@type']).to eq(BillForward::Subscription.resource_path.entity_name)
226
+ end
227
+ it 'can be gotten' do
228
+ gotten_subscription = BillForward::Subscription.get_by_id(subscription.id)
229
+ expect(gotten_subscription['@type']).to eq(BillForward::Subscription.resource_path.entity_name)
230
+ end
231
+ it 'can be activated' do
232
+ expect(subscription['state']).to eq('Provisioned')
233
+ updated_subscription = subscription.activate
234
+
235
+ expect(updated_subscription['state']).to eq('AwaitingPayment')
236
+ end
237
+ end
238
+ end
239
+ end
240
+ end
@@ -0,0 +1,20 @@
1
+ require File.join(File.expand_path(File.dirname(__FILE__)), "..", "..", "spec_helper")
2
+
3
+ describe BillForward::UnitOfMeasure do
4
+ before :all do
5
+ @client = BillForwardTest::TEST_CLIENT
6
+ BillForward::Client.default_client = @client
7
+ end
8
+ describe '::create' do
9
+ it 'creates a UnitOfMeasure' do
10
+ unit_of_measure = BillForward::UnitOfMeasure.new({
11
+ 'name' => 'Devices',
12
+ 'displayedAs' => 'Devices',
13
+ 'roundingScheme' => 'UP',
14
+ })
15
+ created_uom = BillForward::UnitOfMeasure.create(unit_of_measure)
16
+
17
+ expect(created_uom['@type']).to eq(BillForward::UnitOfMeasure.resource_path.entity_name)
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,22 @@
1
+ require File.join(File.expand_path(File.dirname(__FILE__)), "..", "spec_helper")
2
+
3
+ describe BillForward::BillingEntity do
4
+ before :all do
5
+ @client = BillForwardTest::TEST_CLIENT
6
+ BillForward::Client.default_client = @client
7
+ end
8
+ describe '::get_all' do
9
+ context 'with query parameters' do
10
+ it "should allow number of records to be specified" do
11
+ # ensure that at least one account exists in addition to our login
12
+ BillForward::Account.create
13
+
14
+ records = BillForward::Account.get_all({
15
+ 'records' => 1
16
+ })
17
+
18
+ expect(records.length).to eq(1)
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,24 @@
1
+ require File.join(File.expand_path(File.dirname(__FILE__)), "..", "spec_helper")
2
+
3
+ describe BillForward::Client do
4
+ describe '#new' do
5
+ before :all do
6
+ @client = BillForwardTest::TEST_CLIENT
7
+ BillForward::Client.default_client = @client
8
+ end
9
+ it "should find empty results upon looking up non-existent ID" do
10
+ account_id = "nonexist"
11
+
12
+ expect{BillForward::Account.get_by_id account_id}.to raise_error(IndexError)
13
+ end
14
+ it "should raise upon bad token" do
15
+ host=@client.host
16
+ token="badtoken"
17
+ dudclient = BillForward::Client.new(
18
+ :host => host,
19
+ :api_token => token
20
+ )
21
+ expect{BillForward::Organisation.get_mine(nil,dudclient)}.to raise_error(BillForward::ApiAuthorizationError)
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,28 @@
1
+ require File.join(File.expand_path(File.dirname(__FILE__)), "..", "spec_helper")
2
+
3
+ describe BillForward::Account do
4
+ before :all do
5
+ @client = BillForwardTest::TEST_CLIENT
6
+ BillForward::Client.default_client = @client
7
+ end
8
+ describe '::get_all' do
9
+ it 'raises permissions error' do
10
+ # 'admin' privilege is insufficient to see other organisations
11
+ expect{BillForward::Organisation::get_all}.to raise_error(BillForward::ApiError, /415/)
12
+ # TODO: consider that API v219 (at least) gives instead:
13
+ # ====
14
+ # 400 API Error.
15
+ # Type: PermissionsError
16
+ # Message: Access is denied
17
+ # ====
18
+ end
19
+ end
20
+ describe '::get_mine' do
21
+ it "should find organisations" do
22
+ organisations = BillForward::Organisation.get_mine
23
+ organisations_first = organisations.first
24
+
25
+ expect(organisations_first['@type']).to eq(BillForward::Organisation.resource_path.entity_name)
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,73 @@
1
+ # constants include BillForward credentials, required for running functional tests.
2
+ # this file, ignored from version control, allows users to specify credentials for a test account
3
+ test_constants_file = File.join(File.expand_path(File.dirname(__FILE__)), "test_constants.rb")
4
+ if (File.exist?(test_constants_file))
5
+ puts "using test constants from #{test_constants_file}"
6
+ require test_constants_file
7
+ else
8
+ puts 'using default test constants'
9
+ # The following is a template for what your 'test_constants.rb' should contain.
10
+ # If used in this placeholder state, functional tests will not pass.
11
+ module BillForwardTest
12
+ BILLFORWARD_API_HOST='insert-API-URL-here'
13
+ BILLFORWARD_API_TOKEN="insert-access-token-here OR leave-blank-for-OAUTH"
14
+
15
+ ### alternatively:
16
+ # (these values are used if you leave API token blank)
17
+ # authenticate using OAUTH:
18
+ BILLFORWARD_USERNAME="insert-username"
19
+ BILLFORWARD_PASSWORD="insert-password"
20
+ BILLFORWARD_CLIENT_ID="insert-client-id"
21
+ BILLFORWARD_CLIENT_SECRET="insert-client-secret"
22
+
23
+
24
+ # ---- Enable logging if you want (shows request and response bodies)
25
+ USE_LOGGING=false
26
+
27
+
28
+ # ---- Enable proxy if you want (for example to see requests in Fiddler)
29
+ CLIENT_PROXY_ENABLED=false
30
+ CLIENT_PROXY_URL="http://127.0.0.1:8888"
31
+
32
+
33
+ ## These constants are required only for running situational tests (not in the main run):
34
+ # ---- Required for Authorize.Net gateway tests only
35
+ AUTHORIZE_NET_LOGIN_ID = 'FILL IN WITH AUTHORIZE NET LOGIN ID'
36
+ AUTHORIZE_NET_TRANSACTION_KEY = 'FILL IN WITH AUTHORIZE NET TRANSACTION KEY'
37
+ # ---- Required for Authorize.Net tokenization tests only
38
+ AUTHORIZE_NET_CUSTOMER_PROFILE_ID = 12345678 # FILL IN WITH AUTHORIZE NET CUSTOMER PROFILE ID
39
+ AUTHORIZE_NET_CUSTOMER_PAYMENT_PROFILE_ID = 12345678 # FILL IN WITH AUTHORIZE NET CUSTOMER PAYMENT PROFILE ID
40
+ AUTHORIZE_NET_CARD_LAST_4_DIGITS = 1234
41
+
42
+
43
+ # ---- Required for Invoice tests only
44
+ USUAL_INVOICE_ID = 'FILL IN WITH EXISTING INVOICE ID'
45
+ end
46
+ end
47
+
48
+ # create BillForward client for use in all tests
49
+ # requires working credentials only when running functional tests
50
+ module BillForwardTest
51
+ if (BillForwardTest::BILLFORWARD_API_TOKEN == '')
52
+ # Authenticate using OAuth; username and password
53
+ TEST_CLIENT = BillForward::Client.new(
54
+ :host => BillForwardTest::BILLFORWARD_API_HOST,
55
+ :use_logging => BillForwardTest::USE_LOGGING,
56
+ :username => BillForwardTest::BILLFORWARD_USERNAME,
57
+ :password => BillForwardTest::BILLFORWARD_PASSWORD,
58
+ :client_id => BillForwardTest::BILLFORWARD_CLIENT_ID,
59
+ :client_secret => BillForwardTest::BILLFORWARD_CLIENT_SECRET,
60
+ :use_proxy => BillForwardTest::CLIENT_PROXY_ENABLED,
61
+ :proxy_url => BillForwardTest::CLIENT_PROXY_URL
62
+ )
63
+ else
64
+ # Authenticate instead using access token
65
+ TEST_CLIENT = BillForward::Client.new(
66
+ :host => BillForwardTest::BILLFORWARD_API_HOST,
67
+ :use_logging => BillForwardTest::USE_LOGGING,
68
+ :api_token => BillForwardTest::BILLFORWARD_API_TOKEN,
69
+ :use_proxy => BillForwardTest::CLIENT_PROXY_ENABLED,
70
+ :proxy_url => BillForwardTest::CLIENT_PROXY_URL
71
+ )
72
+ end
73
+ end
@@ -0,0 +1,11 @@
1
+ require 'bundler/setup'
2
+ Bundler.setup
3
+
4
+ require 'bill_forward' # and any other gems you need
5
+
6
+ # this file provides constants for tests to share
7
+ require File.join(File.expand_path(File.dirname(__FILE__)), "setup_test_constants")
8
+
9
+ RSpec.configure do |config|
10
+ # some (optional) config here
11
+ end
@@ -0,0 +1,24 @@
1
+ require File.join(File.expand_path(File.dirname(__FILE__)), "..", "spec_helper")
2
+
3
+ describe BillForward::Account do
4
+ describe '#new' do
5
+ it "provides access to client" do
6
+ host="http://localhost:8080/RestAPI/"
7
+ environment="development"
8
+ token="6f1f7465-fc16-4b9c-9ea0-f8c208a43ca6"
9
+ dudclient = BillForward::Client.new(
10
+ :host => host,
11
+ :environment => environment,
12
+ :api_token => token
13
+ )
14
+ account = BillForward::Account.new(nil, dudclient)
15
+ expect(account._client.host).to eq(host)
16
+ end
17
+ end
18
+ describe '::resource_path' do
19
+ it "points to expected endpoint" do
20
+ resource_path = BillForward::Account.resource_path
21
+ expect(resource_path.path).to eq("accounts")
22
+ end
23
+ end
24
+ end