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,25 @@
|
|
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_by_id' do
|
9
|
+
context 'upon looking up non-existent ID' do
|
10
|
+
it "should find empty results" do
|
11
|
+
account_id = "nonexist"
|
12
|
+
|
13
|
+
expect{BillForward::Account.get_by_id account_id}.to raise_error(IndexError)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
describe '::get_all' do
|
18
|
+
it "should find accounts" do
|
19
|
+
accounts = BillForward::Account.get_all
|
20
|
+
accounts_first = accounts.first
|
21
|
+
|
22
|
+
expect(accounts_first['@type']).to eq(BillForward::Account.resource_path.entity_name)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
require File.join(File.expand_path(File.dirname(__FILE__)), "..", "..", "spec_helper")
|
2
|
+
# we want unique numbers to test updates with
|
3
|
+
require 'SecureRandom'
|
4
|
+
|
5
|
+
describe BillForward::Account do
|
6
|
+
before :all do
|
7
|
+
@client = BillForwardTest::TEST_CLIENT
|
8
|
+
BillForward::Client.default_client = @client
|
9
|
+
end
|
10
|
+
describe '::create' do
|
11
|
+
context 'upon creating minimal account' do
|
12
|
+
before :all do
|
13
|
+
@created_account = BillForward::Account.create
|
14
|
+
end
|
15
|
+
subject (:account) { @created_account }
|
16
|
+
it "can get property" do
|
17
|
+
expect(account['@type']).to eq(BillForward::Account.resource_path.entity_name)
|
18
|
+
end
|
19
|
+
# it "can be retired" do
|
20
|
+
# expect(account.deleted).to eq(false)
|
21
|
+
|
22
|
+
# retired_account = account.delete
|
23
|
+
# expect(retired_account.deleted).to eq(true)
|
24
|
+
# end
|
25
|
+
end
|
26
|
+
context 'upon creating account with profile' do
|
27
|
+
describe 'the created account' do
|
28
|
+
before :all do
|
29
|
+
@email = 'always@testing.is.moe'
|
30
|
+
addresses = Array.new
|
31
|
+
addresses.push(
|
32
|
+
BillForward::Address.new({
|
33
|
+
'addressLine1' => 'address line 1',
|
34
|
+
'addressLine2' => 'address line 2',
|
35
|
+
'addressLine3' => 'address line 3',
|
36
|
+
'city' => 'London',
|
37
|
+
'province' => 'London',
|
38
|
+
'country' => 'United Kingdom',
|
39
|
+
'postcode' => 'SW1 1AS',
|
40
|
+
'landline' => '02000000000',
|
41
|
+
'primaryAddress' => true
|
42
|
+
}))
|
43
|
+
profile = BillForward::Profile.new({
|
44
|
+
'email' => @email,
|
45
|
+
'firstName' => 'Test',
|
46
|
+
'addresses' => addresses
|
47
|
+
})
|
48
|
+
account = BillForward::Account.new({
|
49
|
+
'profile' => profile
|
50
|
+
})
|
51
|
+
@created_account = BillForward::Account.create account
|
52
|
+
end
|
53
|
+
subject (:account) { @created_account }
|
54
|
+
it "can get property" do
|
55
|
+
expect(account['@type']).to eq(BillForward::Account.resource_path.entity_name)
|
56
|
+
end
|
57
|
+
it "has profile" do
|
58
|
+
profile = account.profile
|
59
|
+
expect(profile.email).to eq(@email)
|
60
|
+
end
|
61
|
+
context 'after creation' do
|
62
|
+
before :all do
|
63
|
+
@gotten_account = BillForward::Account.get_by_id @created_account.id
|
64
|
+
end
|
65
|
+
subject (:account) { @gotten_account }
|
66
|
+
it "can be gotten" do
|
67
|
+
expect(account['@type']).to eq(BillForward::Account.resource_path.entity_name)
|
68
|
+
expect(account.id).to eq(@created_account.id)
|
69
|
+
end
|
70
|
+
it "can be updated" do
|
71
|
+
expect(account.deleted).to eq(false)
|
72
|
+
account.deleted = true
|
73
|
+
expect(account.deleted).to eq(true)
|
74
|
+
updated_account = account.save
|
75
|
+
|
76
|
+
expect(updated_account.deleted).to eq(true)
|
77
|
+
end
|
78
|
+
describe "profile" do
|
79
|
+
subject (:profile) { account.profile }
|
80
|
+
it 'has expected properties' do
|
81
|
+
expect(profile.email).to eq(@email)
|
82
|
+
end
|
83
|
+
it 'has updatable properties' do
|
84
|
+
unique_value = SecureRandom.hex(10)
|
85
|
+
profile.firstName = unique_value
|
86
|
+
updated_profile = profile.save
|
87
|
+
|
88
|
+
expect(updated_profile.firstName).to eq(unique_value)
|
89
|
+
end
|
90
|
+
it 'can update properties via cascade' do
|
91
|
+
unique_value = SecureRandom.hex(10)
|
92
|
+
profile.firstName = unique_value
|
93
|
+
updated_account = account.save
|
94
|
+
updated_profile = updated_account.profile
|
95
|
+
|
96
|
+
expect(updated_profile.firstName).to eq(unique_value)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require File.join(File.expand_path(File.dirname(__FILE__)), "..", "..", "spec_helper")
|
2
|
+
|
3
|
+
describe BillForward::CreditNote do
|
4
|
+
before :all do
|
5
|
+
@client = BillForwardTest::TEST_CLIENT
|
6
|
+
BillForward::Client.default_client = @client
|
7
|
+
end
|
8
|
+
describe '::create' do
|
9
|
+
context 'account exists' do
|
10
|
+
context 'account has credit note payment method' do
|
11
|
+
before :all do
|
12
|
+
@created_account = BillForward::Account.create
|
13
|
+
|
14
|
+
payment_method = BillForward::PaymentMethod.new({
|
15
|
+
'accountID' => @created_account.id,
|
16
|
+
'name' => 'Credit Notes',
|
17
|
+
'description' => 'Pay using credit',
|
18
|
+
# engines will link this to an invoice once paid, for the sake of refunds
|
19
|
+
'linkID' => '',
|
20
|
+
'gateway' => 'credit_note',
|
21
|
+
'userEditable' => 0,
|
22
|
+
'priority' => 100,
|
23
|
+
'reusable' => 1
|
24
|
+
})
|
25
|
+
created_payment_method = BillForward::PaymentMethod::create(payment_method)
|
26
|
+
end
|
27
|
+
subject (:account) { @created_account }
|
28
|
+
it 'issues credit' do
|
29
|
+
credit_note = BillForward::CreditNote.new({
|
30
|
+
"accountID" => account.id,
|
31
|
+
"nominalValue" => 15,
|
32
|
+
"currency" => "USD"
|
33
|
+
})
|
34
|
+
created_credit_note = BillForward::CreditNote.create(credit_note)
|
35
|
+
|
36
|
+
expect(created_credit_note['@type']).to eq(BillForward::CreditNote.resource_path.entity_name)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require File.join(File.expand_path(File.dirname(__FILE__)), "..", "..", "spec_helper")
|
2
|
+
|
3
|
+
describe BillForward::PaymentMethod do
|
4
|
+
before :all do
|
5
|
+
@client = BillForwardTest::TEST_CLIENT
|
6
|
+
BillForward::Client.default_client = @client
|
7
|
+
end
|
8
|
+
describe '::create' do
|
9
|
+
context 'account exists' do
|
10
|
+
context 'using credit' do
|
11
|
+
before :all do
|
12
|
+
@created_account = BillForward::Account.create
|
13
|
+
end
|
14
|
+
subject (:account) { @created_account }
|
15
|
+
it 'creates a payment method' do
|
16
|
+
payment_method = BillForward::PaymentMethod.new({
|
17
|
+
'accountID' => account.id,
|
18
|
+
'name' => 'Credit Notes',
|
19
|
+
'description' => 'Pay using credit',
|
20
|
+
# engines will link this to an invoice once paid, for the sake of refunds
|
21
|
+
'linkID' => '',
|
22
|
+
'gateway' => 'credit_note',
|
23
|
+
'userEditable' => 0,
|
24
|
+
'priority' => 100,
|
25
|
+
'reusable' => 1
|
26
|
+
})
|
27
|
+
created_payment_method = BillForward::PaymentMethod::create(payment_method)
|
28
|
+
|
29
|
+
expect(created_payment_method['@type']).to eq(BillForward::PaymentMethod.resource_path.entity_name)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
require File.join(File.expand_path(File.dirname(__FILE__)), "..", "..", "spec_helper")
|
2
|
+
|
3
|
+
describe BillForward::ProductRatePlan do
|
4
|
+
before :all do
|
5
|
+
@client = BillForwardTest::TEST_CLIENT
|
6
|
+
BillForward::Client.default_client = @client
|
7
|
+
end
|
8
|
+
describe '::create' do
|
9
|
+
context 'product and pricing components already exist' do
|
10
|
+
before :all do
|
11
|
+
unit_of_measure = BillForward::UnitOfMeasure.new({
|
12
|
+
'name' => 'Devices',
|
13
|
+
'displayedAs' => 'Devices',
|
14
|
+
'roundingScheme' => 'UP',
|
15
|
+
})
|
16
|
+
created_uom = BillForward::UnitOfMeasure.create(unit_of_measure)
|
17
|
+
|
18
|
+
|
19
|
+
product = BillForward::Product.new({
|
20
|
+
'productType' => 'non-recurring',
|
21
|
+
'state' => 'prod',
|
22
|
+
'name' => 'Month of Paracetamoxyfrusebendroneomycin',
|
23
|
+
'description' => 'It can cure the common cold and being struck by lightning',
|
24
|
+
'durationPeriod' => 'days',
|
25
|
+
'duration' => 28,
|
26
|
+
})
|
27
|
+
@created_product = BillForward::Product::create(product)
|
28
|
+
|
29
|
+
|
30
|
+
tiers_for_flat_component_1 = Array.new()
|
31
|
+
tiers_for_flat_component_1.push(
|
32
|
+
BillForward::PricingComponentTier.new({
|
33
|
+
'lowerThreshold' => 1,
|
34
|
+
'upperThreshold' => 1,
|
35
|
+
'pricingType' => 'fixed',
|
36
|
+
'price' => 1,
|
37
|
+
}))
|
38
|
+
|
39
|
+
tiers_for_tiered_component_1 = Array.new()
|
40
|
+
tiers_for_tiered_component_1.push(
|
41
|
+
BillForward::PricingComponentTier.new({
|
42
|
+
'lowerThreshold' => 1,
|
43
|
+
'upperThreshold' => 1,
|
44
|
+
'pricingType' => 'fixed',
|
45
|
+
'price' => 10,
|
46
|
+
}),
|
47
|
+
BillForward::PricingComponentTier.new({
|
48
|
+
'lowerThreshold' => 2,
|
49
|
+
'upperThreshold' => 10,
|
50
|
+
'pricingType' => 'unit',
|
51
|
+
'price' => 5
|
52
|
+
}),
|
53
|
+
BillForward::PricingComponentTier.new({
|
54
|
+
'lowerThreshold' => 11,
|
55
|
+
'upperThreshold' => 100,
|
56
|
+
'pricingType' => 'unit',
|
57
|
+
'price' => 2
|
58
|
+
}))
|
59
|
+
|
60
|
+
|
61
|
+
pricing_components = Array.new()
|
62
|
+
pricing_components.push(
|
63
|
+
BillForward::PricingComponent.new({
|
64
|
+
'@type' => 'flatPricingComponent',
|
65
|
+
'chargeModel' => 'flat',
|
66
|
+
'name' => 'Devices used, fixed',
|
67
|
+
'description' => 'How many devices you use, I guess',
|
68
|
+
'unitOfMeasureID' => created_uom.id,
|
69
|
+
'chargeType' => 'subscription',
|
70
|
+
'upgradeMode' => 'immediate',
|
71
|
+
'downgradeMode' => 'immediate',
|
72
|
+
'defaultQuantity' => 1,
|
73
|
+
'tiers' => tiers_for_flat_component_1
|
74
|
+
}),
|
75
|
+
BillForward::PricingComponent.new({
|
76
|
+
'@type' => 'tieredPricingComponent',
|
77
|
+
'chargeModel' => 'tiered',
|
78
|
+
'name' => 'Devices used, tiered',
|
79
|
+
'description' => 'How many devices you use, but with a tiering system',
|
80
|
+
'unitOfMeasureID' => created_uom.id,
|
81
|
+
'chargeType' => 'subscription',
|
82
|
+
'upgradeMode' => 'immediate',
|
83
|
+
'downgradeMode' => 'immediate',
|
84
|
+
'defaultQuantity' => 10,
|
85
|
+
'tiers' => tiers_for_tiered_component_1
|
86
|
+
}))
|
87
|
+
|
88
|
+
@pricing_components = pricing_components
|
89
|
+
end
|
90
|
+
subject(:product) { @created_product }
|
91
|
+
subject(:pricing_components) { @pricing_components }
|
92
|
+
it 'creates a Product' do
|
93
|
+
prp = BillForward::ProductRatePlan.new({
|
94
|
+
'currency' => 'USD',
|
95
|
+
'name' => 'A sound plan',
|
96
|
+
'pricingComponents' => pricing_components,
|
97
|
+
'productID' => product.id,
|
98
|
+
})
|
99
|
+
created_prp = BillForward::ProductRatePlan.create(prp)
|
100
|
+
|
101
|
+
expect(created_prp['@type']).to eq(BillForward::ProductRatePlan.resource_path.entity_name)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require File.join(File.expand_path(File.dirname(__FILE__)), "..", "..", "spec_helper")
|
2
|
+
|
3
|
+
describe BillForward::Product 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 Product' do
|
10
|
+
product = BillForward::Product.new({
|
11
|
+
'productType' => 'non-recurring',
|
12
|
+
'state' => 'prod',
|
13
|
+
'name' => 'Month of Paracetamoxyfrusebendroneomycin',
|
14
|
+
'description' => 'It can cure the common cold and being struck by lightning',
|
15
|
+
'durationPeriod' => 'days',
|
16
|
+
'duration' => 28,
|
17
|
+
})
|
18
|
+
created_product = BillForward::Product::create(product)
|
19
|
+
expect(created_product['@type']).to eq(BillForward::Product.resource_path.entity_name)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require File.join(File.expand_path(File.dirname(__FILE__)), "..", "..", "..", "spec_helper")
|
2
|
+
|
3
|
+
describe BillForward::AuthorizeNetToken do
|
4
|
+
before :all do
|
5
|
+
@client = BillForwardTest::TEST_CLIENT
|
6
|
+
BillForward::Client.default_client = @client
|
7
|
+
|
8
|
+
# Authorize.Net credentials used to test adding a tokenized card
|
9
|
+
@authorize_net_customer_profile_id = BillForwardTest::AUTHORIZE_NET_CUSTOMER_PROFILE_ID
|
10
|
+
@authorize_net_customer_payment_profile_id = BillForwardTest::AUTHORIZE_NET_CUSTOMER_PAYMENT_PROFILE_ID
|
11
|
+
@authorize_net_card_last_4_digits = BillForwardTest::AUTHORIZE_NET_CARD_LAST_4_DIGITS
|
12
|
+
end
|
13
|
+
describe '::create' do
|
14
|
+
it 'creates a token' do
|
15
|
+
created_account = BillForward::Account.create
|
16
|
+
|
17
|
+
authorize_net_token = BillForward::AuthorizeNetToken.new({
|
18
|
+
'accountID' => created_account.id,
|
19
|
+
'customerProfileID' => @authorize_net_customer_profile_id,
|
20
|
+
'customerPaymentProfileID' => @authorize_net_customer_payment_profile_id,
|
21
|
+
'lastFourDigits' => @authorize_net_card_last_4_digits,
|
22
|
+
})
|
23
|
+
|
24
|
+
created_token = BillForward::AuthorizeNetToken.create(authorize_net_token)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require File.join(File.expand_path(File.dirname(__FILE__)), "..", "..", "..", "spec_helper")
|
2
|
+
|
3
|
+
describe BillForward::InvoiceRecalculationAmendment do
|
4
|
+
before :all do
|
5
|
+
@client = BillForwardTest::TEST_CLIENT
|
6
|
+
BillForward::Client.default_client = @client
|
7
|
+
|
8
|
+
# Existing invoice supplied from test constants, as we cannot create invoices ourselves
|
9
|
+
@invoice_id = BillForwardTest::USUAL_INVOICE_ID
|
10
|
+
end
|
11
|
+
describe '#new' do
|
12
|
+
before :all do
|
13
|
+
invoice = BillForward::Invoice.get_by_id @invoice_id
|
14
|
+
@invoice = invoice
|
15
|
+
end
|
16
|
+
subject (:invoice) { @invoice }
|
17
|
+
it "can be created" do
|
18
|
+
amendment = BillForward::InvoiceRecalculationAmendment.new({
|
19
|
+
'subscriptionID' => invoice.subscriptionID,
|
20
|
+
'invoiceID' => invoice.id,
|
21
|
+
'newInvoiceState' => 'Paid'
|
22
|
+
})
|
23
|
+
|
24
|
+
created_amendment = BillForward::InvoiceRecalculationAmendment.create(amendment)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require File.join(File.expand_path(File.dirname(__FILE__)), "..", "..", "..", "spec_helper")
|
2
|
+
|
3
|
+
describe BillForward::Invoice do
|
4
|
+
before :all do
|
5
|
+
@client = BillForwardTest::TEST_CLIENT
|
6
|
+
BillForward::Client.default_client = @client
|
7
|
+
|
8
|
+
# Existing invoice supplied from test constants, as we cannot create invoices ourselves
|
9
|
+
@invoice_id = BillForwardTest::USUAL_INVOICE_ID
|
10
|
+
end
|
11
|
+
subject (:invoice_id) { @invoice_id }
|
12
|
+
describe '::get_by_id' do
|
13
|
+
context 'where invoice exists' do
|
14
|
+
it "gets the invoice" do
|
15
|
+
invoice = BillForward::Invoice.get_by_id invoice_id
|
16
|
+
|
17
|
+
expect(invoice.id).to eq(invoice_id)
|
18
|
+
expect(invoice['@type']).to eq(BillForward::Invoice.resource_path.entity_name)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'time'
|
2
|
+
require File.join(File.expand_path(File.dirname(__FILE__)), "..", "..", "..", "spec_helper")
|
3
|
+
|
4
|
+
describe BillForward::Amendment do
|
5
|
+
before :all do
|
6
|
+
@client = BillForwardTest::TEST_CLIENT
|
7
|
+
BillForward::Client.default_client = @client
|
8
|
+
@invoice_id = 'mocking this anyway'
|
9
|
+
@subscription_id = 'mocking this anyway'
|
10
|
+
end
|
11
|
+
describe '::create' do
|
12
|
+
context 'with malformed request body' do
|
13
|
+
it "produces a 400 Server Error" do
|
14
|
+
# we will mock the serialization anyway
|
15
|
+
subscription = BillForward::Subscription.new
|
16
|
+
|
17
|
+
time_string = Time.now.iso8601.sub! '+00:00', 'Z'
|
18
|
+
|
19
|
+
amendment = BillForward::InvoiceRecalculationAmendment.new({
|
20
|
+
'subscription' => subscription,
|
21
|
+
'invoiceID' => @invoice_id,
|
22
|
+
"invoiceVersionID" => @invoice_id,
|
23
|
+
'newInvoiceState' => 'Pending',
|
24
|
+
"actioningTime" => time_string
|
25
|
+
})
|
26
|
+
|
27
|
+
amendment = double
|
28
|
+
allow(amendment).to receive(:_client).and_return(@client)
|
29
|
+
allow(amendment.class).to receive(:resource_path).and_return(BillForward::InvoiceRecalculationAmendment.resource_path)
|
30
|
+
allow(amendment).to receive(:serialize).and_return(malformed_serialize)
|
31
|
+
|
32
|
+
expect{BillForward::InvoiceRecalculationAmendment.create(amendment)}.to raise_error(BillForward::ApiError, /400/)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def malformed_serialize
|
39
|
+
# produces a request body where some nested entities have @type key in a non-top position within their JSON.
|
40
|
+
# specifically the @type on flatPricingComponent is not, in this request, the first key within its object.
|
41
|
+
# this is known to cause Server Error. (API prints Exception Description: Missing class indicator field from database row [UnmarshalRecordImpl()])
|
42
|
+
'{"@type":"InvoiceRecalculationAmendment","newInvoiceState":"Pending","invoiceID":"B0ED27EF-B956-4AE8-9FD2-9A5BDFA551B3","subscription":{"@type":"subscription","name":"Memorable Subscription","description":"Memorable Subscription Description","currentPeriodEnd":"2014-09-24T17:22:02Z","initialPeriodStart":"2014-09-24T17:21:02Z","fixedTerms":[],"changedBy":"System","id":"ACD66517-6F32-44CB-AF8C-3097F97E1E67","managedBy":"BillForward","organizationID":"7F3D3A3C-BAA4-4698-9645-EC33F853B3D8","subscriptionEnd":"2014-09-24T17:22:02Z","accountID":"14384081-3A24-460A-AE67-40E0488B267A","pricingComponentValues":[{"changedBy":"614E626E-72BF-4B69-B40E-0B72A1BB7CF4","id":"29F353B6-BE3E-4E31-8E26-84F70F3FB0F3","organizationID":"7F3D3A3C-BAA4-4698-9645-EC33F853B3D8","pricingComponentID":"71753C8E-E477-4DF6-8C32-20FACA3E5B20","updated":"2014-09-24T17:21:02Z","subscriptionID":"ACD66517-6F32-44CB-AF8C-3097F97E1E67","created":"2014-09-24T17:21:02Z","value":1},{"changedBy":"614E626E-72BF-4B69-B40E-0B72A1BB7CF4","id":"8597315B-A9F7-45C4-B145-DF6584528B02","organizationID":"7F3D3A3C-BAA4-4698-9645-EC33F853B3D8","pricingComponentID":"C37D16B1-5E39-4B75-BEC0-03AB4085941E","updated":"2014-09-24T17:21:02Z","subscriptionID":"ACD66517-6F32-44CB-AF8C-3097F97E1E67","created":"2014-09-24T17:21:02Z","value":5}],"type":"Subscription","currentPeriodStart":"2014-09-24T17:21:02Z","pricingComponentValueChanges":[],"updated":"2014-09-24T17:22:04Z","successfulPeriods":1,"productRatePlan":{"name":"A sound plan","validFrom":"2014-09-24T17:21:00Z","changedBy":"614E626E-72BF-4B69-B40E-0B72A1BB7CF4","id":"BFE95484-D1D0-4296-ABB8-C2A3D4CE95EF","organizationID":"7F3D3A3C-BAA4-4698-9645-EC33F853B3D8","taxation":[],"product":{"name":"Month of Paracetamoxyfrusebendroneomycin","description":"It can cure the common cold and being struck by lightning","durationPeriod":"minutes","deleted":false,"changedBy":"614E626E-72BF-4B69-B40E-0B72A1BB7CF4","id":"0CE0A471-A8B1-4E33-B5F4-115947DE8C55","organizationID":"7F3D3A3C-BAA4-4698-9645-EC33F853B3D8","productType":"non-recurring","duration":1,"trial":0,"updated":"2014-09-24T17:20:59Z","created":"2014-09-24T17:20:59Z","trialPeriod":"none","state":"prod"},"proRataMode":"WithCoupon","pricingComponents":[{"name":"Devices used, fixed","description":"How many devices you use, I guess","chargeType":"subscription","defaultQuantity":1,"minQuantity":0,"validFrom":"2014-09-24T17:21:00Z","changedBy":"614E626E-72BF-4B69-B40E-0B72A1BB7CF4","id":"71753C8E-E477-4DF6-8C32-20FACA3E5B20","chargeModel":"flat","downgradeMode":"immediate","organizationID":"7F3D3A3C-BAA4-4698-9645-EC33F853B3D8","versionID":"71753C8E-E477-4DF6-8C32-20FACA3E5B20","updated":"2014-09-24T17:21:01Z","unitOfMeasureID":"6EB5B013-AFD3-4FC6-BDED-73FC681F23EE","upgradeMode":"immediate","created":"2014-09-24T17:21:01Z","tiers":[{"changedBy":"614E626E-72BF-4B69-B40E-0B72A1BB7CF4","id":"EA6A046F-B436-4D5F-A4CE-14638E2A574C","organizationID":"7F3D3A3C-BAA4-4698-9645-EC33F853B3D8","price":1.0,"pricingComponentID":"71753C8E-E477-4DF6-8C32-20FACA3E5B20","lowerThreshold":1,"pricingType":"fixed","created":"2014-09-24T17:21:01Z","pricingComponentVersionID":"71753C8E-E477-4DF6-8C32-20FACA3E5B20","productRatePlanID":"BFE95484-D1D0-4296-ABB8-C2A3D4CE95EF","upperThreshold":1}],"unitOfMeasure":{"name":"Devices","deleted":false,"changedBy":"614E626E-72BF-4B69-B40E-0B72A1BB7CF4","id":"6EB5B013-AFD3-4FC6-BDED-73FC681F23EE","organizationID":"7F3D3A3C-BAA4-4698-9645-EC33F853B3D8","roundingScheme":"UP","updated":"2014-09-24T17:20:58Z","created":"2014-09-24T17:20:58Z","displayedAs":"Devices"},"productRatePlanID":"BFE95484-D1D0-4296-ABB8-C2A3D4CE95EF","@type":"flatPricingComponent"},{"name":"Devices used, tiered","description":"How many devices you use, but with a tiering system","chargeType":"usage","defaultQuantity":10,"minQuantity":0,"validFrom":"2014-09-24T17:21:00Z","changedBy":"614E626E-72BF-4B69-B40E-0B72A1BB7CF4","id":"C37D16B1-5E39-4B75-BEC0-03AB4085941E","chargeModel":"tiered","downgradeMode":"immediate","organizationID":"7F3D3A3C-BAA4-4698-9645-EC33F853B3D8","versionID":"C37D16B1-5E39-4B75-BEC0-03AB4085941E","updated":"2014-09-24T17:21:01Z","unitOfMeasureID":"6EB5B013-AFD3-4FC6-BDED-73FC681F23EE","upgradeMode":"immediate","created":"2014-09-24T17:21:01Z","tiers":[{"changedBy":"614E626E-72BF-4B69-B40E-0B72A1BB7CF4","id":"7B86D8A6-CFB1-4CD9-B438-617F4E060C3A","organizationID":"7F3D3A3C-BAA4-4698-9645-EC33F853B3D8","price":5.0,"pricingComponentID":"C37D16B1-5E39-4B75-BEC0-03AB4085941E","lowerThreshold":2,"pricingType":"unit","created":"2014-09-24T17:21:01Z","pricingComponentVersionID":"C37D16B1-5E39-4B75-BEC0-03AB4085941E","productRatePlanID":"BFE95484-D1D0-4296-ABB8-C2A3D4CE95EF","upperThreshold":10},{"changedBy":"614E626E-72BF-4B69-B40E-0B72A1BB7CF4","id":"B3E8C950-A71E-434D-8988-1F964430768B","organizationID":"7F3D3A3C-BAA4-4698-9645-EC33F853B3D8","price":10.0,"pricingComponentID":"C37D16B1-5E39-4B75-BEC0-03AB4085941E","lowerThreshold":1,"pricingType":"fixed","created":"2014-09-24T17:21:01Z","pricingComponentVersionID":"C37D16B1-5E39-4B75-BEC0-03AB4085941E","productRatePlanID":"BFE95484-D1D0-4296-ABB8-C2A3D4CE95EF","upperThreshold":1},{"changedBy":"614E626E-72BF-4B69-B40E-0B72A1BB7CF4","id":"D05839BB-8E35-48FD-AB66-F1CDF0E59D9C","organizationID":"7F3D3A3C-BAA4-4698-9645-EC33F853B3D8","price":2.0,"pricingComponentID":"C37D16B1-5E39-4B75-BEC0-03AB4085941E","lowerThreshold":11,"pricingType":"unit","created":"2014-09-24T17:21:01Z","pricingComponentVersionID":"C37D16B1-5E39-4B75-BEC0-03AB4085941E","productRatePlanID":"BFE95484-D1D0-4296-ABB8-C2A3D4CE95EF","upperThreshold":100}],"unitOfMeasure":{"name":"Devices","deleted":false,"changedBy":"614E626E-72BF-4B69-B40E-0B72A1BB7CF4","id":"6EB5B013-AFD3-4FC6-BDED-73FC681F23EE","organizationID":"7F3D3A3C-BAA4-4698-9645-EC33F853B3D8","roundingScheme":"UP","updated":"2014-09-24T17:20:58Z","created":"2014-09-24T17:20:58Z","displayedAs":"Devices"},"productRatePlanID":"BFE95484-D1D0-4296-ABB8-C2A3D4CE95EF","@type":"tieredPricingComponent"}],"updated":"2014-09-24T17:21:00Z","currency":"USD","taxStatus":"inclusive","created":"2014-09-24T17:21:00Z","productID":"0CE0A471-A8B1-4E33-B5F4-115947DE8C55","fixedTermDefinitions":[]},"created":"2014-09-24T17:21:02Z","paymentMethodSubscriptionLinks":[{"deleted":false,"changedBy":"614E626E-72BF-4B69-B40E-0B72A1BB7CF4","id":"1A89116E-D17D-4610-B139-6E4559CC85FD","organizationID":"7F3D3A3C-BAA4-4698-9645-EC33F853B3D8","updated":"2014-09-24T17:21:02Z","subscriptionID":"ACD66517-6F32-44CB-AF8C-3097F97E1E67","created":"2014-09-24T17:21:02Z","paymentMethodID":"612D5A60-4F6A-455D-9C03-685A6D96A8D4","paymentMethod":{"name":"Credit Notes","description":"Pay using credit","userEditable":false,"deleted":false,"changedBy":"614E626E-72BF-4B69-B40E-0B72A1BB7CF4","id":"612D5A60-4F6A-455D-9C03-685A6D96A8D4","priority":100,"organizationID":"7F3D3A3C-BAA4-4698-9645-EC33F853B3D8","reusable":true,"accountID":"14384081-3A24-460A-AE67-40E0488B267A","linkID":"","updated":"2014-09-24T17:20:56Z","created":"2014-09-24T17:20:56Z","gateway":"credit_note"}}],"state":"Expired","productRatePlanID":"BFE95484-D1D0-4296-ABB8-C2A3D4CE95EF","productID":"0CE0A471-A8B1-4E33-B5F4-115947DE8C55"},"invoiceVersionID":"B0ED27EF-B956-4AE8-9FD2-9A5BDFA551B3","actioningTime":"2014-09-25T18:34:46Z"}'
|
43
|
+
end
|