active_zuora 1.3.0 → 2.6.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 (75) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +5 -0
  3. data/.octopolo.yml +4 -0
  4. data/.soyuz.yml +13 -0
  5. data/.travis.yml +7 -0
  6. data/CHANGELOG.markdown +41 -0
  7. data/Gemfile +4 -0
  8. data/MIT-LICENSE +20 -0
  9. data/README.md +191 -0
  10. data/Rakefile +9 -53
  11. data/TODO.md +2 -0
  12. data/active_zuora.gemspec +25 -59
  13. data/lib/active_zuora.rb +44 -12
  14. data/lib/active_zuora/amend.rb +43 -0
  15. data/lib/active_zuora/base.rb +84 -0
  16. data/lib/active_zuora/batch_subscribe.rb +53 -0
  17. data/lib/active_zuora/belongs_to_associations.rb +56 -0
  18. data/lib/active_zuora/billing_preview.rb +49 -0
  19. data/lib/active_zuora/collection_proxy.rb +38 -0
  20. data/lib/active_zuora/connection.rb +47 -0
  21. data/lib/active_zuora/fields.rb +129 -0
  22. data/lib/active_zuora/fields/array_field_decorator.rb +28 -0
  23. data/lib/active_zuora/fields/boolean_field.rb +12 -0
  24. data/lib/active_zuora/fields/date_field.rb +18 -0
  25. data/lib/active_zuora/fields/date_time_field.rb +19 -0
  26. data/lib/active_zuora/fields/decimal_field.rb +12 -0
  27. data/lib/active_zuora/fields/field.rb +76 -0
  28. data/lib/active_zuora/fields/integer_field.rb +11 -0
  29. data/lib/active_zuora/fields/object_field.rb +31 -0
  30. data/lib/active_zuora/fields/string_field.rb +11 -0
  31. data/lib/active_zuora/generate.rb +43 -0
  32. data/lib/active_zuora/generator.rb +244 -0
  33. data/lib/active_zuora/has_many_associations.rb +37 -0
  34. data/lib/active_zuora/has_many_proxy.rb +50 -0
  35. data/lib/active_zuora/lazy_attr.rb +52 -0
  36. data/lib/active_zuora/persistence.rb +172 -0
  37. data/lib/active_zuora/relation.rb +260 -0
  38. data/lib/active_zuora/scoping.rb +50 -0
  39. data/lib/active_zuora/subscribe.rb +42 -0
  40. data/lib/active_zuora/version.rb +3 -0
  41. data/lib/active_zuora/z_object.rb +21 -0
  42. data/spec/account_integration_spec.rb +41 -0
  43. data/spec/base_spec.rb +39 -0
  44. data/spec/belongs_to_associations_spec.rb +35 -0
  45. data/spec/collection_proxy_spec.rb +28 -0
  46. data/spec/connection_spec.rb +66 -0
  47. data/spec/fields/date_field_spec.rb +35 -0
  48. data/spec/has_many_integration_spec.rb +53 -0
  49. data/spec/lazy_attr_spec.rb +22 -0
  50. data/spec/spec_helper.rb +34 -0
  51. data/spec/subscribe_integration_spec.rb +344 -0
  52. data/spec/zobject_integration_spec.rb +104 -0
  53. data/wsdl/zuora.wsdl +1548 -0
  54. metadata +141 -53
  55. data/LICENSE +0 -202
  56. data/README.rdoc +0 -15
  57. data/VERSION +0 -1
  58. data/custom_fields.yml +0 -17
  59. data/lib/zuora/ZUORA.rb +0 -1398
  60. data/lib/zuora/ZUORADriver.rb +0 -128
  61. data/lib/zuora/ZUORAMappingRegistry.rb +0 -1488
  62. data/lib/zuora/ZuoraServiceClient.rb +0 -124
  63. data/lib/zuora/account.rb +0 -4
  64. data/lib/zuora/api.rb +0 -18
  65. data/lib/zuora/contact.rb +0 -4
  66. data/lib/zuora/rate_plan.rb +0 -4
  67. data/lib/zuora/rate_plan_data.rb +0 -4
  68. data/lib/zuora/subscribe_options.rb +0 -4
  69. data/lib/zuora/subscribe_request.rb +0 -4
  70. data/lib/zuora/subscribe_with_existing_account_request.rb +0 -4
  71. data/lib/zuora/subscription.rb +0 -4
  72. data/lib/zuora/subscription_data.rb +0 -4
  73. data/lib/zuora/zobject.rb +0 -52
  74. data/lib/zuora_client.rb +0 -181
  75. data/lib/zuora_interface.rb +0 -199
@@ -0,0 +1,50 @@
1
+ module ActiveZuora
2
+ module Scoping
3
+
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ class << self
8
+
9
+ # Delegate to :scoped
10
+ delegate :find, :all, :find_each, :to => :scoped
11
+ delegate :select, :where, :and, :or, :order, :to => :scoped
12
+ delegate :first, :last, :each, :map, :any?, :empty?, :blank?, :present?, :size, :count, :to => :scoped
13
+
14
+ # Keep track of a current scope.
15
+ attr_accessor :current_scope
16
+
17
+ end
18
+ end
19
+
20
+ module ClassMethods
21
+
22
+ def scoped
23
+ current_scope || relation
24
+ end
25
+
26
+ def unscoped
27
+ block_given? ? relation.scoped { yield } : relation
28
+ end
29
+
30
+ def exclude_from_queries(*field_names)
31
+ (@excluded_from_queries ||= []).concat field_names.map(&:to_sym)
32
+ end
33
+
34
+ def relation
35
+ query_field_names = field_names - (@excluded_from_queries ||= [])
36
+ Relation.new(self, query_field_names)
37
+ end
38
+
39
+ def scope(name, body)
40
+ # Body can be a Relation or a lambda that returns a relation.
41
+ define_singleton_method(name) do |*args|
42
+ body.respond_to?(:call) ? body.call(*args) : scoped.merge(body)
43
+ end
44
+ end
45
+
46
+ end
47
+
48
+ end
49
+ end
50
+
@@ -0,0 +1,42 @@
1
+ module ActiveZuora
2
+ module Subscribe
3
+
4
+ # This is meant to be included onto a SubscribeRequest class.
5
+ # Returns true/false on success.
6
+ # Result hash is stored in #result.
7
+ # If success, the subscription id and account id will be set in those objects.
8
+ # If failure, errors will be present on object.
9
+
10
+ extend ActiveSupport::Concern
11
+
12
+ included do
13
+ include Base
14
+ attr_accessor :result
15
+ end
16
+
17
+ def subscribe
18
+ self.result = self.class.connection.request(:subscribe) do |soap|
19
+ soap.body do |xml|
20
+ build_xml(xml, soap,
21
+ :namespace => soap.namespace,
22
+ :element_name => :subscribes,
23
+ :force_type => true)
24
+ end
25
+ end[:subscribe_response][:result]
26
+ if result[:success]
27
+ account.id = result[:account_id]
28
+ subscription_data.subscription.id = result[:subscription_id]
29
+ clear_changed_attributes
30
+ true
31
+ else
32
+ add_zuora_errors(result[:errors])
33
+ false
34
+ end
35
+ end
36
+
37
+ def subscribe!
38
+ raise "Could not subscribe: #{errors.full_messages.join ', '}" unless subscribe
39
+ end
40
+
41
+ end
42
+ end
@@ -0,0 +1,3 @@
1
+ module ActiveZuora
2
+ VERSION = "2.6.0"
3
+ end
@@ -0,0 +1,21 @@
1
+ module ActiveZuora
2
+ module ZObject
3
+
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ include Base
8
+ include Scoping
9
+ include HasManyAssociations
10
+ include Persistence
11
+ field :id, :string
12
+ end
13
+
14
+ def ==(another_zobject)
15
+ another_zobject.is_a?(ZObject) &&
16
+ zuora_object_name == another_zobject.zuora_object_name &&
17
+ id == another_zobject.id
18
+ end
19
+
20
+ end
21
+ end
@@ -0,0 +1,41 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'Create Account' do
4
+
5
+ integration_test do
6
+
7
+ let(:account) do
8
+ Z::Account.new name: 'Joe Customer',
9
+ currency: Tenant.currency,
10
+ bill_cycle_day: '1'
11
+ end
12
+
13
+ after(:each) do
14
+ account.delete unless account.new_record?
15
+ end
16
+
17
+ it 'can create an account' do
18
+ expect(account).to be_a_new_record
19
+ expect(account).to_not be_valid
20
+ expect(account.id).to_not be_present
21
+ expect(account.errors.full_messages).to eq ["Status can't be blank"]
22
+
23
+ now 'update account to be valid' do
24
+ account.status = 'Draft'
25
+ expect(account).to be_valid
26
+ expect(account.errors.full_messages).to be_empty
27
+ end
28
+
29
+ now 'save the account' do
30
+ expect(account.save).to be true
31
+ expect(account.id).to be_present
32
+ expect(account.errors.full_messages).to eq []
33
+ end
34
+
35
+ now 'ensure error messages are accessible' do
36
+ expect(account.update_attributes status: 'Active').to be false
37
+ expect(account.errors.full_messages).to eq ['Active account must have both sold to and bill to.']
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,39 @@
1
+ require 'spec_helper'
2
+
3
+ describe ActiveZuora::Base do
4
+ class Comment
5
+ include ActiveZuora::ZObject
6
+ field :name, :string
7
+ field :null_field, :string
8
+ end
9
+
10
+ context "#fields_order" do
11
+ let(:comment) { Comment.new :id => 'blog1', :null_field => nil, :name => 'test' }
12
+ let(:field_id) { comment.get_field(:id) }
13
+ let(:field_null) { comment.get_field(:null_field) }
14
+ let(:field_name) { comment.get_field(:name) }
15
+ let(:sorted_fields) { [field_null, field_id, field_name] }
16
+
17
+ it 'When the value of a field is null, it should be the first' do
18
+ fields1 = [field_id, field_null]
19
+ expect(fields1.sort(&comment.method(:fields_order))).to eq([field_null, field_id])
20
+
21
+ fields2 = [field_name, field_null]
22
+ expect(fields2.sort(&comment.method(:fields_order))).to eq([field_null, field_name])
23
+
24
+ fields3 = [field_id, field_name, field_null]
25
+ expect(fields3.sort(&comment.method(:fields_order))).to eq(sorted_fields)
26
+ end
27
+
28
+ it 'When the field name is id, it should be after the nil value fields but before all other fields' do
29
+ fields1 = [field_name, field_id]
30
+ expect(fields1.sort(&comment.method(:fields_order))).to eq([field_id, field_name])
31
+
32
+ fields2 = [field_null, field_id]
33
+ expect(fields2.sort(&comment.method(:fields_order))).to eq([field_null, field_id])
34
+
35
+ fields3 = [field_name, field_id, field_null]
36
+ expect(fields3.sort(&comment.method(:fields_order))).to eq(sorted_fields)
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,35 @@
1
+ require 'spec_helper'
2
+
3
+ describe "BelongsToAssociations" do
4
+
5
+ class Blog
6
+ include ActiveZuora::ZObject
7
+ end
8
+
9
+ class Comment
10
+ include ActiveZuora::Base
11
+ belongs_to :blog
12
+ end
13
+
14
+ it "should define a attribute assignment method method for the object" do
15
+ blog = Blog.new :id => "blog1"
16
+ comment = Comment.new :blog => blog
17
+ expect(comment.blog_loaded?).to be_truthy
18
+ expect(comment.blog).to eq(blog)
19
+ expect(comment.blog_id).to eq(blog.id)
20
+ comment.blog = nil
21
+ expect(comment.blog_loaded?).to be_truthy
22
+ expect(comment.blog).to be_nil
23
+ expect(comment.blog_id).to be_nil
24
+ end
25
+
26
+ it "should define a attribute assignment method for the object id" do
27
+ blog = Blog.new :id => "blog1"
28
+ comment = Comment.new :blog => blog
29
+ expect(comment.blog_loaded?).to be_truthy
30
+ comment.blog_id = "blog2"
31
+ expect(comment.blog_loaded?).to be_falsey
32
+ end
33
+
34
+ end
35
+
@@ -0,0 +1,28 @@
1
+ require 'spec_helper'
2
+
3
+ describe "ActiveZuora::CollectionProxy" do
4
+
5
+ it "should initialize" do
6
+ cp = Z::CollectionProxy.new
7
+ expect(cp).to be_empty
8
+ cp = Z::CollectionProxy.new([Z::SubscribeRequest.new])
9
+ expect(cp).not_to be_empty
10
+ end
11
+
12
+ it "should respond to enumerable methods" do
13
+ cp = Z::CollectionProxy.new([Z::SubscribeRequest.new])
14
+ cp.each do |cp|
15
+ expect(cp)
16
+ end
17
+ cp.inject do |memo,cp|
18
+ expect(memo)
19
+ expect(cp)
20
+ end
21
+ end
22
+
23
+ it "should respond to the batch_subscribe method" do
24
+ cp = Z::CollectionProxy.new([Z::SubscribeRequest.new])
25
+ expect(cp.respond_to?(:batch_subscribe)).to eq(true)
26
+ end
27
+
28
+ end
@@ -0,0 +1,66 @@
1
+ require 'spec_helper'
2
+
3
+ describe ActiveZuora::Connection do
4
+ context "custom header" do
5
+ before do
6
+ @connection = ActiveZuora::Connection.new
7
+ @stub_was_called = false
8
+ end
9
+
10
+ it "passes the regular header if not set" do
11
+ allow(Savon::SOAP::Request).to receive(:new) do |config, http, soap|
12
+ @stub_was_called = true
13
+ expect(soap.header).to eq( { "SessionHeader" => {"session" => nil} } )
14
+
15
+ double('response').as_null_object
16
+ end
17
+
18
+ @connection.request(:amend) {}
19
+
20
+ expect(@stub_was_called).to be_truthy
21
+ end
22
+
23
+ it "merges in a custom header if set" do
24
+ @connection.custom_header = {'CallOptions' => {'useSingleTransaction' => true}}
25
+ allow(Savon::SOAP::Request).to receive(:new) do |config, http, soap|
26
+ @stub_was_called = true
27
+ expect(soap.header).to eq( { "SessionHeader" => {"session" => nil}, 'CallOptions' => {'useSingleTransaction' => true} } )
28
+
29
+ double('response').as_null_object
30
+ end
31
+
32
+ @connection.request(:amend) {}
33
+
34
+ expect(@stub_was_called).to be_truthy
35
+ end
36
+ end
37
+
38
+ describe 'login' do
39
+ before do
40
+ @connection = described_class.new
41
+ end
42
+
43
+ context 'when a custom header is set' do
44
+ it 'uses the custom header' do
45
+ @connection.custom_header = { 'TestHeader' => 'Foo' }
46
+ allow(Savon::SOAP::Request).to receive(:new) do |config, http, soap|
47
+ expect(soap.header).to eq({ 'TestHeader' => 'Foo' })
48
+ double('response').as_null_object
49
+ end
50
+
51
+ @connection.login
52
+ end
53
+ end
54
+
55
+ context 'when a custom header is not set' do
56
+ it 'does not use the custom header' do
57
+ allow(Savon::SOAP::Request).to receive(:new) do |config, http, soap|
58
+ expect(soap.header).to eq({})
59
+ double('response').as_null_object
60
+ end
61
+
62
+ @connection.login
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,35 @@
1
+ require 'spec_helper'
2
+
3
+ describe ActiveZuora::DateField do
4
+ subject { described_class.new("date", described_class, {:zuora_name => "date"}) }
5
+
6
+ describe "#type_cast" do
7
+ it "returns nil if provided nil" do
8
+ expect(subject.type_cast(nil)).to eq(nil)
9
+ end
10
+
11
+ it "returns a date when given a datetime object" do
12
+ datetime = DateTime.now
13
+ expect(subject.type_cast(datetime)).to be_a(Date)
14
+ end
15
+
16
+ it "returns a date when given a date object" do
17
+ date = Date.today
18
+ expect(subject.type_cast(date)).to be_a(Date)
19
+ end
20
+ end
21
+
22
+ describe "#build_xml" do
23
+ let(:xml) { double(:xml, :tag! => nil) }
24
+ let(:soap) { double(:soap, :namespace_by_uri => nil) }
25
+ let(:options) { {} }
26
+
27
+ it "handles a nil value" do
28
+ expect { subject.build_xml(xml, soap, nil, options) }.to_not raise_error
29
+ end
30
+
31
+ it "handles a date value" do
32
+ expect { subject.build_xml(xml, soap, Date.today, options) }.to_not raise_error
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,53 @@
1
+ require 'spec_helper'
2
+
3
+ describe "HasManyRelations" do
4
+
5
+ integration_test do
6
+
7
+ before :all do
8
+ @account = Z::Account.create!(
9
+ :name => "ZObject Integration Test Account",
10
+ :status => "Draft",
11
+ :currency => Tenant.currency,
12
+ :bill_cycle_day => 1)
13
+ @billy = Z::Contact.create!(
14
+ :account => @account,
15
+ :first_name => "Billy",
16
+ :last_name => "Blanks")
17
+ @franky = Z::Contact.create!(
18
+ :account => @account,
19
+ :first_name => "Franky",
20
+ :last_name => "Funhouse")
21
+ end
22
+
23
+ after :all do
24
+ # Delete the account to cleanup in case a test failed.
25
+ @account.delete if @account
26
+ end
27
+
28
+ it "can specify conditions and order" do
29
+ Z::Account.instance_eval do
30
+ has_many :billies, :conditions => { :first_name => "Billy" }, :order => [:first_name, :desc], :class_name => 'Z::Contact'
31
+ end
32
+ expect(@account.billies.to_a).to eq([@billy])
33
+ expect(@account.billies.scope.order_attribute).to eq(:first_name)
34
+ expect(@account.billies.scope.order_direction).to eq(:desc)
35
+ end
36
+
37
+ it "can behave like an array" do
38
+ expect(@account.contacts.size).to eq(2)
39
+ expect(@account.contacts.map(&:first_name)).to match_array(%w{Billy Franky})
40
+ end
41
+
42
+ it "can respond to functions on the Relation" do
43
+ @account.contacts.unload
44
+ expect(@account.contacts.loaded?).to be_falsey
45
+ @account.contacts.reload
46
+ expect(@account.contacts.loaded?).to be_truthy
47
+ expect(@account.contacts.where(:last_name => "Funhouse").to_a).to eq([@franky])
48
+ expect(@account.contacts.loaded?).to be_truthy
49
+ expect(@account.contacts.to_a).to match_array([@billy, @franky])
50
+ end
51
+
52
+ end
53
+ end
@@ -0,0 +1,22 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'LazyAttr' do
4
+ class TestInovice
5
+ include ActiveZuora::LazyAttr
6
+ lazy_load :test_body
7
+ end
8
+
9
+ subject { TestInovice.new }
10
+
11
+ it "should fetch a lazy loaded attribute from the api" do
12
+ expect(subject).to receive(:fetch_field).with(:test_body){ 'Jesse "The Body"' }
13
+ subject.test_body
14
+ end
15
+
16
+ it "should should not refetch an attribute after it's been loaded once" do
17
+ expect(subject).to receive(:fetch_field).with(:test_body).once { 'Jesse "The Body"' }
18
+ subject.test_body
19
+ subject.test_body
20
+ end
21
+
22
+ end