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.
- checksums.yaml +7 -0
- data/.gitignore +5 -0
- data/.octopolo.yml +4 -0
- data/.soyuz.yml +13 -0
- data/.travis.yml +7 -0
- data/CHANGELOG.markdown +41 -0
- data/Gemfile +4 -0
- data/MIT-LICENSE +20 -0
- data/README.md +191 -0
- data/Rakefile +9 -53
- data/TODO.md +2 -0
- data/active_zuora.gemspec +25 -59
- data/lib/active_zuora.rb +44 -12
- data/lib/active_zuora/amend.rb +43 -0
- data/lib/active_zuora/base.rb +84 -0
- data/lib/active_zuora/batch_subscribe.rb +53 -0
- data/lib/active_zuora/belongs_to_associations.rb +56 -0
- data/lib/active_zuora/billing_preview.rb +49 -0
- data/lib/active_zuora/collection_proxy.rb +38 -0
- data/lib/active_zuora/connection.rb +47 -0
- data/lib/active_zuora/fields.rb +129 -0
- data/lib/active_zuora/fields/array_field_decorator.rb +28 -0
- data/lib/active_zuora/fields/boolean_field.rb +12 -0
- data/lib/active_zuora/fields/date_field.rb +18 -0
- data/lib/active_zuora/fields/date_time_field.rb +19 -0
- data/lib/active_zuora/fields/decimal_field.rb +12 -0
- data/lib/active_zuora/fields/field.rb +76 -0
- data/lib/active_zuora/fields/integer_field.rb +11 -0
- data/lib/active_zuora/fields/object_field.rb +31 -0
- data/lib/active_zuora/fields/string_field.rb +11 -0
- data/lib/active_zuora/generate.rb +43 -0
- data/lib/active_zuora/generator.rb +244 -0
- data/lib/active_zuora/has_many_associations.rb +37 -0
- data/lib/active_zuora/has_many_proxy.rb +50 -0
- data/lib/active_zuora/lazy_attr.rb +52 -0
- data/lib/active_zuora/persistence.rb +172 -0
- data/lib/active_zuora/relation.rb +260 -0
- data/lib/active_zuora/scoping.rb +50 -0
- data/lib/active_zuora/subscribe.rb +42 -0
- data/lib/active_zuora/version.rb +3 -0
- data/lib/active_zuora/z_object.rb +21 -0
- data/spec/account_integration_spec.rb +41 -0
- data/spec/base_spec.rb +39 -0
- data/spec/belongs_to_associations_spec.rb +35 -0
- data/spec/collection_proxy_spec.rb +28 -0
- data/spec/connection_spec.rb +66 -0
- data/spec/fields/date_field_spec.rb +35 -0
- data/spec/has_many_integration_spec.rb +53 -0
- data/spec/lazy_attr_spec.rb +22 -0
- data/spec/spec_helper.rb +34 -0
- data/spec/subscribe_integration_spec.rb +344 -0
- data/spec/zobject_integration_spec.rb +104 -0
- data/wsdl/zuora.wsdl +1548 -0
- metadata +141 -53
- data/LICENSE +0 -202
- data/README.rdoc +0 -15
- data/VERSION +0 -1
- data/custom_fields.yml +0 -17
- data/lib/zuora/ZUORA.rb +0 -1398
- data/lib/zuora/ZUORADriver.rb +0 -128
- data/lib/zuora/ZUORAMappingRegistry.rb +0 -1488
- data/lib/zuora/ZuoraServiceClient.rb +0 -124
- data/lib/zuora/account.rb +0 -4
- data/lib/zuora/api.rb +0 -18
- data/lib/zuora/contact.rb +0 -4
- data/lib/zuora/rate_plan.rb +0 -4
- data/lib/zuora/rate_plan_data.rb +0 -4
- data/lib/zuora/subscribe_options.rb +0 -4
- data/lib/zuora/subscribe_request.rb +0 -4
- data/lib/zuora/subscribe_with_existing_account_request.rb +0 -4
- data/lib/zuora/subscription.rb +0 -4
- data/lib/zuora/subscription_data.rb +0 -4
- data/lib/zuora/zobject.rb +0 -52
- data/lib/zuora_client.rb +0 -181
- 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,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
|
data/spec/base_spec.rb
ADDED
@@ -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
|