active_zuora 1.5.2 → 2.0.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.
- data/Gemfile +4 -0
- data/Gemfile.lock +57 -0
- data/README.md +155 -0
- data/Rakefile +6 -22
- data/TODO.md +2 -0
- data/active_zuora.gemspec +25 -68
- data/lib/active_zuora.rb +37 -6
- data/lib/active_zuora/amend.rb +43 -0
- data/lib/active_zuora/base.rb +73 -0
- data/lib/active_zuora/belongs_to_associations.rb +56 -0
- data/lib/active_zuora/connection.rb +41 -0
- data/lib/active_zuora/fields.rb +122 -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_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 +220 -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/persistence.rb +176 -0
- data/lib/active_zuora/relation.rb +253 -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/belongs_to_associations_spec.rb +35 -0
- data/spec/has_many_integration_spec.rb +53 -0
- data/spec/spec_helper.rb +21 -0
- data/spec/subscribe_integration_spec.rb +218 -0
- data/spec/zobject_integration_spec.rb +104 -0
- data/wsdl/zuora.wsdl +1548 -0
- metadata +128 -72
- checksums.yaml +0 -7
- data/LICENSE +0 -202
- data/README.rdoc +0 -36
- data/VERSION +0 -1
- data/custom_fields.yml +0 -17
- data/lib/active_zuora/account.rb +0 -31
- data/lib/active_zuora/amendment.rb +0 -7
- data/lib/active_zuora/bill_run.rb +0 -4
- data/lib/active_zuora/contact.rb +0 -7
- data/lib/active_zuora/invoice.rb +0 -46
- data/lib/active_zuora/invoice_item.rb +0 -26
- data/lib/active_zuora/invoice_item_adjustment.rb +0 -4
- data/lib/active_zuora/invoice_payment.rb +0 -11
- data/lib/active_zuora/payment.rb +0 -18
- data/lib/active_zuora/payment_method.rb +0 -10
- data/lib/active_zuora/product.rb +0 -4
- data/lib/active_zuora/product_rate_plan.rb +0 -9
- data/lib/active_zuora/product_rate_plan_charge.rb +0 -11
- data/lib/active_zuora/product_rate_plan_charge_tier.rb +0 -7
- data/lib/active_zuora/product_rate_plan_charge_tier_data.rb +0 -4
- data/lib/active_zuora/rate_plan.rb +0 -16
- data/lib/active_zuora/rate_plan_charge.rb +0 -71
- data/lib/active_zuora/rate_plan_charge_data.rb +0 -4
- data/lib/active_zuora/rate_plan_charge_tier.rb +0 -4
- data/lib/active_zuora/rate_plan_data.rb +0 -4
- data/lib/active_zuora/refund.rb +0 -4
- data/lib/active_zuora/subscribe_options.rb +0 -4
- data/lib/active_zuora/subscribe_request.rb +0 -13
- data/lib/active_zuora/subscribe_with_existing_account_request.rb +0 -4
- data/lib/active_zuora/subscription.rb +0 -17
- data/lib/active_zuora/subscription_data.rb +0 -4
- data/lib/active_zuora/usage.rb +0 -4
- data/lib/active_zuora/zobject.rb +0 -154
- data/lib/soap/property +0 -1
- data/lib/zuora/ZUORA.rb +0 -1560
- data/lib/zuora/ZUORADriver.rb +0 -145
- data/lib/zuora/ZUORAMappingRegistry.rb +0 -1709
- data/lib/zuora/ZuoraServiceClient.rb +0 -124
- data/lib/zuora/api.rb +0 -18
- data/lib/zuora_client.rb +0 -191
- data/lib/zuora_interface.rb +0 -215
@@ -0,0 +1,220 @@
|
|
1
|
+
module ActiveZuora
|
2
|
+
class Generator
|
3
|
+
|
4
|
+
attr_reader :document, :classes
|
5
|
+
|
6
|
+
def initialize(document, options={})
|
7
|
+
# document is a parsed wsdl document.
|
8
|
+
@document = document
|
9
|
+
@classes = []
|
10
|
+
@class_nesting = options[:inside] || ActiveZuora
|
11
|
+
end
|
12
|
+
|
13
|
+
def generate_classes
|
14
|
+
|
15
|
+
# Defines the classes based on the wsdl document.
|
16
|
+
# Assumes the following namespaces in the wsdl.
|
17
|
+
# xmlns="http://schemas.xmlsoap.org/wsdl/"
|
18
|
+
# xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"
|
19
|
+
# xmlns:xs="http://www.w3.org/2001/XMLSchema"
|
20
|
+
# xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
|
21
|
+
# xmlns:zns="http://api.zuora.com/"
|
22
|
+
# xmlns:ons="http://object.api.zuora.com/"
|
23
|
+
# xmlns:fns="http://fault.api.zuora.com/"
|
24
|
+
@document.xpath('.//xs:schema[@targetNamespace]').each do |schema|
|
25
|
+
namespace = schema.attribute("targetNamespace").value
|
26
|
+
|
27
|
+
schema.xpath('.//xs:complexType[@name]').each do |complex_type|
|
28
|
+
class_name = complex_type.attribute("name").value
|
29
|
+
# Skip the zObject base class, we define our own.
|
30
|
+
next if class_name == "zObject"
|
31
|
+
|
32
|
+
zuora_class = Class.new
|
33
|
+
@class_nesting.const_set(class_name, zuora_class)
|
34
|
+
@classes << zuora_class
|
35
|
+
|
36
|
+
# Include the Base module for adding fields.
|
37
|
+
zuora_class.send :include, Base
|
38
|
+
zuora_class.namespace = namespace
|
39
|
+
|
40
|
+
# If it's a zObject, include that module as well.
|
41
|
+
if complex_type.xpath(".//xs:extension[@base='ons:zObject']").any?
|
42
|
+
zuora_class.send :include, ZObject
|
43
|
+
end
|
44
|
+
|
45
|
+
# Define the fields
|
46
|
+
complex_type.xpath('.//xs:element[@name][@type]').each do |element|
|
47
|
+
# attributes: name, type, nillable, minoccurs, maxoccurs
|
48
|
+
zuora_name = element.attribute("name").value
|
49
|
+
field_name = zuora_name.underscore
|
50
|
+
field_type = element.attribute("type").value
|
51
|
+
is_array = element_is_an_array?(element)
|
52
|
+
|
53
|
+
case field_type
|
54
|
+
when "string", "xs:string", "zns:ID", "xs:base64Binary"
|
55
|
+
zuora_class.field field_name, :string,
|
56
|
+
:zuora_name => zuora_name, :array => is_array
|
57
|
+
when "boolean", "xs:boolean"
|
58
|
+
zuora_class.field field_name, :boolean,
|
59
|
+
:zuora_name => zuora_name, :array => is_array
|
60
|
+
when "int", "short", "long", "xs:int"
|
61
|
+
zuora_class.field field_name, :integer,
|
62
|
+
:zuora_name => zuora_name, :array => is_array
|
63
|
+
when "decimal"
|
64
|
+
zuora_class.field field_name, :decimal,
|
65
|
+
:zuora_name => zuora_name, :array => is_array
|
66
|
+
when "dateTime"
|
67
|
+
zuora_class.field field_name, :datetime,
|
68
|
+
:zuora_name => zuora_name, :array => is_array
|
69
|
+
when /\A(zns:|ons:)/
|
70
|
+
zuora_class.field field_name, :object,
|
71
|
+
:zuora_name => zuora_name, :array => is_array,
|
72
|
+
:class_name => zuora_class.nested_class_name(field_type.split(':').last)
|
73
|
+
else
|
74
|
+
puts "Unkown field type: #{field_type}"
|
75
|
+
end
|
76
|
+
end # each element
|
77
|
+
|
78
|
+
end # each complexType
|
79
|
+
end # each schema
|
80
|
+
|
81
|
+
add_obvious_associations
|
82
|
+
add_extra_customizations
|
83
|
+
end
|
84
|
+
|
85
|
+
private
|
86
|
+
|
87
|
+
def add_obvious_associations
|
88
|
+
# When a zuora class has a field called InvoiceId, it's a safe
|
89
|
+
# assuption that it references the an Invoice.
|
90
|
+
# Build those associations automatically.
|
91
|
+
@classes.each do |zuora_class|
|
92
|
+
zuora_class.fields.each do |field|
|
93
|
+
# If it looks like an Id field and the name
|
94
|
+
# matches a generated ZObject class
|
95
|
+
if match = field.zuora_name.match(/\A(.+?)Id\Z/)
|
96
|
+
if zobject_class = zobject_class_with_name(match[1])
|
97
|
+
# Add a belongs to relationship.
|
98
|
+
zuora_class.belongs_to zobject_class.zuora_object_name.underscore
|
99
|
+
# If the current class is also a ZObject, add a has_many
|
100
|
+
# to the referenced class.
|
101
|
+
if zuora_class < ZObject
|
102
|
+
zobject_class.has_many zuora_class.zuora_object_name.underscore.pluralize
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def add_extra_customizations
|
111
|
+
# We can't know everything from the wsdl, like which fields are
|
112
|
+
# usable in queries. This function does some final customizations
|
113
|
+
# based on the existing Zuora documentation.
|
114
|
+
# Also, it's possible classes customized here weren't defined
|
115
|
+
# in your wsdl, so it will only customize them if they are defined.
|
116
|
+
|
117
|
+
nesting = @class_nesting
|
118
|
+
|
119
|
+
customize 'Account' do
|
120
|
+
belongs_to :bill_to, :class_name => nested_class_name('Contact') if field? :bill_to
|
121
|
+
if field? :parent_id
|
122
|
+
belongs_to :parent, :class_name => nested_class_name('Account')
|
123
|
+
has_many :children, :class_name => nested_class_name('Account'), :foreign_key => :parent_id, :inverse_of => :parent
|
124
|
+
end
|
125
|
+
belongs_to :sold_to, :class_name => nested_class_name('Contact') if field? :sold_to
|
126
|
+
validates :currency, :presence => true if field? :currency
|
127
|
+
validates :name, :presence => true if field? :name
|
128
|
+
validates :status, :presence => true if field? :status
|
129
|
+
end
|
130
|
+
|
131
|
+
customize 'Amendment' do
|
132
|
+
exclude_from_queries :rate_plan_data,
|
133
|
+
:destination_account_id, :destination_invoice_owner_id
|
134
|
+
end
|
135
|
+
|
136
|
+
customize 'AmendRequest' do
|
137
|
+
include Amend
|
138
|
+
end
|
139
|
+
|
140
|
+
customize 'Import' do
|
141
|
+
exclude_from_queries :file_content
|
142
|
+
end
|
143
|
+
|
144
|
+
customize 'Invoice' do
|
145
|
+
include Generate
|
146
|
+
exclude_from_queries :regenerate_invoice_pdf
|
147
|
+
end
|
148
|
+
|
149
|
+
customize 'InvoiceItemAdjustment' do
|
150
|
+
exclude_from_queries :customer_name, :customer_number
|
151
|
+
end
|
152
|
+
|
153
|
+
customize 'Payment' do
|
154
|
+
exclude_from_queries :applied_invoice_amount,
|
155
|
+
:gateway_option_data, :invoice_id, :invoice_number
|
156
|
+
end
|
157
|
+
|
158
|
+
customize 'PaymentMethod' do
|
159
|
+
exclude_from_queries :ach_account_number, :credit_card_number,
|
160
|
+
:credit_card_security_code, :gateway_option_data, :skip_validation
|
161
|
+
end
|
162
|
+
|
163
|
+
customize 'ProductRatePlanCharge' do
|
164
|
+
exclude_from_queries :product_rate_plan_charge_tier_data
|
165
|
+
end
|
166
|
+
|
167
|
+
customize 'Usage' do
|
168
|
+
exclude_from_queries :ancestor_account_id, :invoice_id, :invoice_number
|
169
|
+
end
|
170
|
+
|
171
|
+
customize 'RatePlanCharge' do
|
172
|
+
exclude_from_queries :rollover_balance
|
173
|
+
# Can only use overageprice or price or includedunits or
|
174
|
+
# discountamount or discountpercentage in one query.
|
175
|
+
# We'll pick price.
|
176
|
+
exclude_from_queries :overage_price, :included_units,
|
177
|
+
:discount_amount, :discount_percentage
|
178
|
+
end
|
179
|
+
|
180
|
+
customize 'Refund' do
|
181
|
+
exclude_from_queries :gateway_option_data, :payment_id
|
182
|
+
end
|
183
|
+
|
184
|
+
customize 'Subscription' do
|
185
|
+
exclude_from_queries :ancestor_account_id
|
186
|
+
belongs_to :creator_account, :class_name => nested_class_name('Account') if field? :creator_account_id
|
187
|
+
belongs_to :creator_invoice_owner, :class_name => nested_class_name('Account') if field? :creator_invoice_owner_id
|
188
|
+
belongs_to :invoice_owner, :class_name => nested_class_name('Account') if field? :invoice_owner_id
|
189
|
+
belongs_to :original, :class_name => name if field? :original_id
|
190
|
+
belongs_to :original_subscription, :class_name => name if field? :original_subscription_id
|
191
|
+
belongs_to :previous_subscription, :class_name => name if field? :previous_subscription_id
|
192
|
+
end
|
193
|
+
|
194
|
+
customize 'SubscribeRequest' do
|
195
|
+
include Subscribe
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
def customize(zuora_class_name, &block)
|
200
|
+
if @class_nesting.const_defined?(zuora_class_name)
|
201
|
+
@class_nesting.const_get(zuora_class_name).instance_eval(&block)
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
|
206
|
+
def element_is_an_array?(element)
|
207
|
+
attribute_is_more_than_one?(element.attribute("minOccurs")) ||
|
208
|
+
attribute_is_more_than_one?(element.attribute("maxOccurs"))
|
209
|
+
end
|
210
|
+
|
211
|
+
def attribute_is_more_than_one?(attribute)
|
212
|
+
attribute && ( attribute.value == "unbounded" || attribute.value.to_i > 1 )
|
213
|
+
end
|
214
|
+
|
215
|
+
def zobject_class_with_name(name)
|
216
|
+
@classes.find { |zuora_class| zuora_class.zuora_object_name == name && zuora_class < ZObject }
|
217
|
+
end
|
218
|
+
|
219
|
+
end
|
220
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module ActiveZuora
|
2
|
+
module HasManyAssociations
|
3
|
+
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
module ClassMethods
|
7
|
+
|
8
|
+
def has_many(items, options={})
|
9
|
+
class_name = options[:class_name] || nested_class_name(items.to_s.singularize.camelize)
|
10
|
+
foreign_key = options[:foreign_key] || :"#{zuora_object_name.underscore}_id"
|
11
|
+
conditions = options[:conditions]
|
12
|
+
# :order => :name
|
13
|
+
# :order => [:name, :desc]
|
14
|
+
order_attribute, order_direction = [*options[:order]]
|
15
|
+
ivar = "@#{items}"
|
16
|
+
# Define the methods on an included module, so we can override
|
17
|
+
# them using super.
|
18
|
+
generated_attribute_methods.module_eval do
|
19
|
+
define_method(items) do
|
20
|
+
if instance_variable_get(ivar)
|
21
|
+
return instance_variable_get(ivar)
|
22
|
+
else
|
23
|
+
relation = class_name.constantize.where(foreign_key => self.id)
|
24
|
+
relation = relation.merge(conditions) if conditions.present?
|
25
|
+
relation.order_attribute = order_attribute if order_attribute.present?
|
26
|
+
relation.order_direction = order_direction if order_direction.present?
|
27
|
+
proxy = HasManyProxy.new(self, relation, options)
|
28
|
+
instance_variable_set(ivar, proxy)
|
29
|
+
proxy
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module ActiveZuora
|
2
|
+
class HasManyProxy
|
3
|
+
|
4
|
+
# Wraps around the Relation representing a has_many association
|
5
|
+
# to add features like inverse_of loading.
|
6
|
+
|
7
|
+
attr_reader :scope, :owner
|
8
|
+
|
9
|
+
delegate :"==", :"===", :"=~", :inspect, :to_s, :to => :to_a
|
10
|
+
|
11
|
+
def initialize(owner, scope, options={})
|
12
|
+
@owner, @scope = owner, scope
|
13
|
+
# inverse_of by default. You can opt out with :inverse_of => false
|
14
|
+
@inverse_of = (options[:inverse_of] || owner.zuora_object_name.underscore) unless options[:inverse_of] == false
|
15
|
+
end
|
16
|
+
|
17
|
+
def to_a
|
18
|
+
if @scope.loaded? || !@inverse_of
|
19
|
+
@scope.to_a
|
20
|
+
else
|
21
|
+
@scope.to_a.each { |record| record.send("#{@inverse_of}=", owner) }
|
22
|
+
@scope.to_a
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
alias :all :to_a
|
27
|
+
|
28
|
+
def reload
|
29
|
+
# If reload is called directly on the scope, it will reload
|
30
|
+
# without our extra functionality, like inverse_of loading.
|
31
|
+
@scope.unload
|
32
|
+
to_a
|
33
|
+
end
|
34
|
+
|
35
|
+
protected
|
36
|
+
|
37
|
+
def method_missing(method, *args, &block)
|
38
|
+
# If we do anything that needs loading the scope, then we'll load it.
|
39
|
+
if Array.method_defined?(method)
|
40
|
+
to_a.send(method, *args, &block)
|
41
|
+
else
|
42
|
+
# Otherwise send all messages to the @scope.
|
43
|
+
@scope.send(method, *args, &block)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
|
@@ -0,0 +1,176 @@
|
|
1
|
+
module ActiveZuora
|
2
|
+
module Persistence
|
3
|
+
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
MAX_BATCH_SIZE = 50
|
7
|
+
|
8
|
+
def new_record?
|
9
|
+
id.blank?
|
10
|
+
end
|
11
|
+
|
12
|
+
def save
|
13
|
+
new_record? ? create : update
|
14
|
+
end
|
15
|
+
|
16
|
+
def save!
|
17
|
+
raise "Could Not Save Zuora Object: #{errors.full_messages.join ', '}" unless save
|
18
|
+
end
|
19
|
+
|
20
|
+
def update_attributes(attributes)
|
21
|
+
self.attributes = attributes
|
22
|
+
save
|
23
|
+
end
|
24
|
+
|
25
|
+
def update_attributes!(attributes)
|
26
|
+
self.attributes = attributes
|
27
|
+
save!
|
28
|
+
end
|
29
|
+
|
30
|
+
def delete
|
31
|
+
self.class.delete(id) > 0
|
32
|
+
end
|
33
|
+
|
34
|
+
def reload
|
35
|
+
raise ArgumentError.new("You can't reload a new record") if new_record?
|
36
|
+
self.untracked_attributes = self.class.find(id).attributes
|
37
|
+
self
|
38
|
+
end
|
39
|
+
|
40
|
+
def xml_field_names
|
41
|
+
# If we're rendering an existing record, always include the id.
|
42
|
+
new_record? ? super : ([:id] + super).uniq
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def create
|
48
|
+
return false unless new_record? && valid?
|
49
|
+
result = self.class.connection.request(:create) do |soap|
|
50
|
+
soap.body do |xml|
|
51
|
+
build_xml(xml, soap,
|
52
|
+
:namespace => soap.namespace,
|
53
|
+
:element_name => :zObjects,
|
54
|
+
:force_type => true)
|
55
|
+
end
|
56
|
+
end[:create_response][:result]
|
57
|
+
if result[:success]
|
58
|
+
self.id = result[:id]
|
59
|
+
clear_changed_attributes
|
60
|
+
true
|
61
|
+
else
|
62
|
+
errors.add(:base, result[:errors][:message]) if result[:errors]
|
63
|
+
false
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def update
|
68
|
+
self.class.update(self)
|
69
|
+
self.errors.blank?
|
70
|
+
end
|
71
|
+
|
72
|
+
module ClassMethods
|
73
|
+
|
74
|
+
def create(attributes={})
|
75
|
+
new(attributes).tap(&:save)
|
76
|
+
end
|
77
|
+
|
78
|
+
def create!(attributes={})
|
79
|
+
new(attributes).tap(&:save!)
|
80
|
+
end
|
81
|
+
|
82
|
+
# Takes an array of zobjects and batch saves new and updated records separately
|
83
|
+
def save(*zobjects)
|
84
|
+
new_records = 0
|
85
|
+
updated_records = 0
|
86
|
+
|
87
|
+
# Get all new objects
|
88
|
+
new_objects = zobjects.flatten.select do |zobject|
|
89
|
+
zobject.new_record? && zobject.changed.present? && zobject.valid?
|
90
|
+
end
|
91
|
+
|
92
|
+
# Get all updated objects
|
93
|
+
updated_objects = zobjects.flatten.select do |zobject|
|
94
|
+
!zobject.new_record? && zobject.changed.present? && zobject.valid?
|
95
|
+
end
|
96
|
+
|
97
|
+
# Make calls in batches of 50
|
98
|
+
new_objects.each_slice(MAX_BATCH_SIZE) do |batch|
|
99
|
+
new_records += process_save(batch, :create)
|
100
|
+
end
|
101
|
+
|
102
|
+
updated_objects.each_slice(MAX_BATCH_SIZE) do |batch|
|
103
|
+
updated_records += process_save(batch, :update)
|
104
|
+
end
|
105
|
+
|
106
|
+
new_records + updated_records
|
107
|
+
end
|
108
|
+
|
109
|
+
# For backwards compatability
|
110
|
+
def update(*zobjects)
|
111
|
+
save(zobjects)
|
112
|
+
end
|
113
|
+
|
114
|
+
def process_save(zobjects, action)
|
115
|
+
unless [:create, :update].include? action
|
116
|
+
raise "Invalid action type for saving. Must be create or update."
|
117
|
+
end
|
118
|
+
|
119
|
+
return 0 if zobjects.empty?
|
120
|
+
results = connection.request(action) do |soap|
|
121
|
+
soap.body do |xml|
|
122
|
+
zobjects.map do |zobject|
|
123
|
+
zobject.build_xml(xml, soap,
|
124
|
+
:namespace => soap.namespace,
|
125
|
+
:element_name => :zObjects,
|
126
|
+
:force_type => true,
|
127
|
+
:nil_strategy => :fields_to_nil)
|
128
|
+
end.last
|
129
|
+
end
|
130
|
+
end["#{action.to_s}_response".to_sym][:result]
|
131
|
+
results = [results] unless results.is_a?(Array)
|
132
|
+
zobjects.each_with_index do |zobject, i|
|
133
|
+
# If it's an update, grab by id, otherwise by index
|
134
|
+
if action == :update
|
135
|
+
result = results.find { |r| r[:id] == zobject.id } ||
|
136
|
+
{ :errors => { :message => "No result returned." } }
|
137
|
+
else
|
138
|
+
result = results[i] || { :errors => { :message => "No result returned." } }
|
139
|
+
end
|
140
|
+
if result[:success]
|
141
|
+
zobject.clear_changed_attributes
|
142
|
+
else
|
143
|
+
zobject.add_zuora_errors result[:errors]
|
144
|
+
end
|
145
|
+
end
|
146
|
+
# Return the count of updates that succeeded.
|
147
|
+
results.select{ |result| result[:success] }.size
|
148
|
+
end
|
149
|
+
|
150
|
+
def delete(*ids)
|
151
|
+
ids.flatten!
|
152
|
+
deleted_records = 0
|
153
|
+
ids.each_slice(MAX_BATCH_SIZE) do |batch|
|
154
|
+
deleted_records += process_delete(batch)
|
155
|
+
end
|
156
|
+
deleted_records
|
157
|
+
end
|
158
|
+
|
159
|
+
def process_delete(*ids)
|
160
|
+
ids.flatten!
|
161
|
+
results = connection.request(:delete) do |soap|
|
162
|
+
qualifier = soap.namespace_by_uri(soap.namespace)
|
163
|
+
soap.body do |xml|
|
164
|
+
xml.tag!(qualifier, :type, zuora_object_name)
|
165
|
+
ids.map { |id| xml.tag!(qualifier, :ids, id) }.last
|
166
|
+
end
|
167
|
+
end[:delete_response][:result]
|
168
|
+
results = [results] unless results.is_a?(Array)
|
169
|
+
# Return the count of deletes that succeeded.
|
170
|
+
results.select{ |result| result[:success] }.size
|
171
|
+
end
|
172
|
+
|
173
|
+
end
|
174
|
+
|
175
|
+
end
|
176
|
+
end
|