active_zuora 1.3.0 → 2.6.0

Sign up to get free protection for your applications and to get access to all the features.
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