xero-ruby 3.1.3 → 3.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/lib/xero-ruby.rb CHANGED
@@ -18,6 +18,12 @@ require 'xero-ruby/version'
18
18
  require 'xero-ruby/configuration'
19
19
 
20
20
  # Models
21
+ require 'xero-ruby/models/app_store/plan'
22
+ require 'xero-ruby/models/app_store/price'
23
+ require 'xero-ruby/models/app_store/problem_details'
24
+ require 'xero-ruby/models/app_store/product'
25
+ require 'xero-ruby/models/app_store/subscription'
26
+ require 'xero-ruby/models/app_store/subscription_item'
21
27
  require 'xero-ruby/models/payroll_uk/account'
22
28
  require 'xero-ruby/models/payroll_uk/accounts'
23
29
  require 'xero-ruby/models/payroll_uk/address'
@@ -456,6 +462,7 @@ require 'xero-ruby/models/accounting/users'
456
462
  require 'xero-ruby/models/accounting/validation_error'
457
463
 
458
464
  # APIs
465
+ require 'xero-ruby/api/app_store_api'
459
466
  require 'xero-ruby/api/payroll_uk_api'
460
467
  require 'xero-ruby/api/payroll_nz_api'
461
468
  require 'xero-ruby/api/payroll_au_api'
@@ -0,0 +1,87 @@
1
+ =begin
2
+ #Xero AppStore API
3
+
4
+ #These endpoints are for Xero Partners to interact with the App Store Billing platform
5
+
6
+ Contact: api@xero.com
7
+ Generated by: https://openapi-generator.tech
8
+ OpenAPI Generator version: 4.3.1
9
+
10
+ =end
11
+
12
+ module XeroRuby
13
+ class AppStoreApi
14
+ attr_accessor :api_client
15
+
16
+ def initialize(api_client = ApiClient.new)
17
+ @api_client = api_client
18
+ end
19
+ # Retrieves a subscription for a given subscriptionId
20
+ # @param subscription_id [String] Unique identifier for Subscription object
21
+ # @param [Hash] opts the optional parameters
22
+ # @return [Subscription]
23
+ def get_subscription(subscription_id, opts = {})
24
+ data, _status_code, _headers = get_subscription_with_http_info(subscription_id, opts)
25
+ data
26
+ end
27
+
28
+ # Retrieves a subscription for a given subscriptionId
29
+ # @param subscription_id [String] Unique identifier for Subscription object
30
+ # @param [Hash] opts the optional parameters
31
+ # @return [Array<(Subscription, Integer, Hash)>] Subscription data, response status code and response headers
32
+ def get_subscription_with_http_info(subscription_id, options = {})
33
+ opts = options.dup
34
+ if @api_client.config.debugging
35
+ @api_client.config.logger.debug 'Calling API: AppStoreApi.get_subscription ...'
36
+ end
37
+ # verify the required parameter 'subscription_id' is set
38
+ if @api_client.config.client_side_validation && subscription_id.nil?
39
+ fail ArgumentError, "Missing the required parameter 'subscription_id' when calling AppStoreApi.get_subscription"
40
+ end
41
+ # resource path
42
+ local_var_path = '/subscriptions/{subscriptionId}'.sub('{' + 'subscriptionId' + '}', subscription_id.to_s)
43
+
44
+ # camelize keys of incoming `where` opts
45
+ opts[:'where'] = @api_client.parameterize_where(opts[:'where']) if !opts[:'where'].nil?
46
+
47
+ # query parameters
48
+ query_params = opts[:query_params] || {}
49
+
50
+ # XeroAPI's `IDs` convention openapi-generator does not snake_case properly.. manual over-riding `i_ds` malformations:
51
+ query_params[:'IDs'] = @api_client.build_collection_param(opts[:'ids'], :csv) if !opts[:'ids'].nil?
52
+ query_params[:'ContactIDs'] = @api_client.build_collection_param(opts[:'contact_ids'], :csv) if !opts[:'contact_ids'].nil?
53
+
54
+ # header parameters
55
+ header_params = opts[:header_params] || {}
56
+ # HTTP header 'Accept' (if needed)
57
+ header_params['Accept'] = @api_client.select_header_accept(['application/json'])
58
+
59
+ # form parameters
60
+ form_params = opts[:form_params] || {}
61
+
62
+ # http body (model)
63
+ post_body = opts[:body]
64
+
65
+ # return_type
66
+ return_type = opts[:return_type] || 'Subscription'
67
+
68
+ # auth_names
69
+ auth_names = opts[:auth_names] || ['OAuth2']
70
+
71
+ new_options = opts.merge(
72
+ :header_params => header_params,
73
+ :query_params => query_params,
74
+ :form_params => form_params,
75
+ :body => post_body,
76
+ :auth_names => auth_names,
77
+ :return_type => return_type
78
+ )
79
+
80
+ data, status_code, headers = @api_client.call_api(:GET, local_var_path, "AppStoreApi", new_options)
81
+ if @api_client.config.debugging
82
+ @api_client.config.logger.debug "API called: AppStoreApi#get_subscription\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"
83
+ end
84
+ return data, status_code, headers
85
+ end
86
+ end
87
+ end
@@ -29,7 +29,7 @@ module XeroRuby
29
29
  # Defines the headers to be used in HTTP requests of all API calls by default.
30
30
  #
31
31
  # @return [Hash]
32
- attr_accessor :default_headers
32
+ attr_accessor :default_headers, :grant_type
33
33
 
34
34
  # Initializes the ApiClient
35
35
  # @option config [Configuration] Configuration for initializing the object, default to Configuration.default
@@ -37,6 +37,7 @@ module XeroRuby
37
37
  @client_id = credentials[:client_id]
38
38
  @client_secret = credentials[:client_secret]
39
39
  @redirect_uri = credentials[:redirect_uri]
40
+ @grant_type = credentials[:grant_type] || 'authorization_code'
40
41
  @scopes = credentials[:scopes]
41
42
  @state = credentials[:state]
42
43
  default_config = Configuration.default.clone
@@ -56,9 +57,17 @@ module XeroRuby
56
57
  end
57
58
 
58
59
  def authorization_url
59
- url = "#{@config.login_url}?response_type=code&client_id=#{@client_id}&redirect_uri=#{@redirect_uri}&scope=#{CGI.escape(@scopes)}"
60
- url << "&state=#{@state}" if @state
61
- return url
60
+ url = URI.parse(@config.login_url)
61
+ url.query = URI.encode_www_form(
62
+ {
63
+ response_type: 'code',
64
+ client_id: @client_id,
65
+ redirect_uri: @redirect_uri,
66
+ scope: @scopes,
67
+ state: @state
68
+ }.compact
69
+ )
70
+ url.to_s
62
71
  end
63
72
 
64
73
  def accounting_api
@@ -96,6 +105,11 @@ module XeroRuby
96
105
  XeroRuby::PayrollUkApi.new(self)
97
106
  end
98
107
 
108
+ def app_store_api
109
+ @config.base_url = @config.app_store_url
110
+ XeroRuby::AppStoreApi.new(self)
111
+ end
112
+
99
113
  # Token Helpers
100
114
  def token_set
101
115
  @config.token_set
@@ -135,9 +149,18 @@ module XeroRuby
135
149
  @config.id_token = id_token
136
150
  end
137
151
 
152
+ def get_client_credentials_token
153
+ data = {
154
+ grant_type: @grant_type
155
+ }
156
+ token_set = token_request(data, '/token')
157
+
158
+ return token_set
159
+ end
160
+
138
161
  def get_token_set_from_callback(params)
139
162
  data = {
140
- grant_type: 'authorization_code',
163
+ grant_type: @grant_type,
141
164
  code: params['code'],
142
165
  redirect_uri: @redirect_uri
143
166
  }
@@ -222,6 +245,10 @@ module XeroRuby
222
245
  response[0]
223
246
  end
224
247
 
248
+ def last_connection
249
+ connections.sort { |a,b| DateTime.parse(a['updatedDateUtc']) <=> DateTime.parse(b['updatedDateUtc'])}.first
250
+ end
251
+
225
252
  def disconnect(connection_id)
226
253
  @config.base_url = 'https://api.xero.com'
227
254
  opts = { :header_params => {'Content-Type': 'application/json'}, :auth_names => ['OAuth2'] }
@@ -479,6 +506,8 @@ module XeroRuby
479
506
  XeroRuby::PayrollNz.const_get(return_type).build_from_hash(data)
480
507
  when 'PayrollUkApi'
481
508
  XeroRuby::PayrollUk.const_get(return_type).build_from_hash(data)
509
+ when 'AppStoreApi'
510
+ XeroRuby::AppStore.const_get(return_type).build_from_hash(data)
482
511
  else
483
512
  XeroRuby::Accounting.const_get(return_type).build_from_hash(data)
484
513
  end
@@ -33,6 +33,7 @@ module XeroRuby
33
33
  attr_accessor :payroll_au_url
34
34
  attr_accessor :payroll_nz_url
35
35
  attr_accessor :payroll_uk_url
36
+ attr_accessor :app_store_url
36
37
 
37
38
  # Defines API keys used with API Key authentications.
38
39
  #
@@ -149,6 +150,7 @@ module XeroRuby
149
150
  @payroll_au_url = 'https://api.xero.com/payroll.xro/1.0/'
150
151
  @payroll_nz_url = 'https://api.xero.com/payroll.xro/2.0/'
151
152
  @payroll_uk_url = 'https://api.xero.com/payroll.xro/2.0/'
153
+ @app_store_url = 'https://api.xero.com/appstore/2.0/'
152
154
  @access_token = nil
153
155
  @id_token = nil
154
156
  @api_key = {}
@@ -49,6 +49,9 @@ module XeroRuby::Accounting
49
49
  # The amount of the payment. Must be less than or equal to the outstanding amount owing on the invoice e.g. 200.00
50
50
  attr_accessor :amount
51
51
 
52
+ # The amount of the payment in the currency of the bank account.
53
+ attr_accessor :bank_amount
54
+
52
55
  # An optional description for the payment e.g. Direct Debit
53
56
  attr_accessor :reference
54
57
 
@@ -137,6 +140,7 @@ module XeroRuby::Accounting
137
140
  :'date' => :'Date',
138
141
  :'currency_rate' => :'CurrencyRate',
139
142
  :'amount' => :'Amount',
143
+ :'bank_amount' => :'BankAmount',
140
144
  :'reference' => :'Reference',
141
145
  :'is_reconciled' => :'IsReconciled',
142
146
  :'status' => :'Status',
@@ -168,6 +172,7 @@ module XeroRuby::Accounting
168
172
  :'date' => :'Date',
169
173
  :'currency_rate' => :'BigDecimal',
170
174
  :'amount' => :'BigDecimal',
175
+ :'bank_amount' => :'BigDecimal',
171
176
  :'reference' => :'String',
172
177
  :'is_reconciled' => :'Boolean',
173
178
  :'status' => :'String',
@@ -244,6 +249,10 @@ module XeroRuby::Accounting
244
249
  self.amount = attributes[:'amount']
245
250
  end
246
251
 
252
+ if attributes.key?(:'bank_amount')
253
+ self.bank_amount = attributes[:'bank_amount']
254
+ end
255
+
247
256
  if attributes.key?(:'reference')
248
257
  self.reference = attributes[:'reference']
249
258
  end
@@ -360,6 +369,7 @@ module XeroRuby::Accounting
360
369
  date == o.date &&
361
370
  currency_rate == o.currency_rate &&
362
371
  amount == o.amount &&
372
+ bank_amount == o.bank_amount &&
363
373
  reference == o.reference &&
364
374
  is_reconciled == o.is_reconciled &&
365
375
  status == o.status &&
@@ -385,7 +395,7 @@ module XeroRuby::Accounting
385
395
  # Calculates hash code according to all attributes.
386
396
  # @return [Integer] Hash code
387
397
  def hash
388
- [invoice, credit_note, prepayment, overpayment, invoice_number, credit_note_number, account, code, date, currency_rate, amount, reference, is_reconciled, status, payment_type, updated_date_utc, payment_id, batch_payment_id, bank_account_number, particulars, details, has_account, has_validation_errors, status_attribute_string, validation_errors].hash
398
+ [invoice, credit_note, prepayment, overpayment, invoice_number, credit_note_number, account, code, date, currency_rate, amount, bank_amount, reference, is_reconciled, status, payment_type, updated_date_utc, payment_id, batch_payment_id, bank_account_number, particulars, details, has_account, has_validation_errors, status_attribute_string, validation_errors].hash
389
399
  end
390
400
 
391
401
  # Builds the object from hash
@@ -122,6 +122,7 @@ module XeroRuby::Accounting
122
122
  HAWAIIANSTANDARDTIME = "HAWAIIANSTANDARDTIME".freeze
123
123
  UTC11 = "UTC11".freeze
124
124
  DATELINESTANDARDTIME = "DATELINESTANDARDTIME".freeze
125
+ EASTERISLANDSTANDARDTIME = "EASTERISLANDSTANDARDTIME".freeze
125
126
 
126
127
  # Builds the enum from string
127
128
  # @param [String] The enum value in the form of the string
@@ -0,0 +1,310 @@
1
+ =begin
2
+ #Xero AppStore API
3
+
4
+ #These endpoints are for Xero Partners to interact with the App Store Billing platform
5
+
6
+ Contact: api@xero.com
7
+ Generated by: https://openapi-generator.tech
8
+ OpenAPI Generator version: 4.3.1
9
+
10
+ =end
11
+
12
+ require 'time'
13
+ require 'date'
14
+
15
+ module XeroRuby::AppStore
16
+ require 'bigdecimal'
17
+
18
+ class Plan
19
+ # The unique identifier of the plan
20
+ attr_accessor :id
21
+
22
+ # The name of the plan. It is used in the invoice line item description.
23
+ attr_accessor :name
24
+
25
+ # Status of the plan. Available statuses are ACTIVE, PENDING_ACTIVATION.
26
+ attr_accessor :status
27
+ ACTIVE = "ACTIVE".freeze
28
+ PENDING_ACTIVATION = "PENDING_ACTIVATION".freeze
29
+
30
+ # List of the subscription items belonging to the plan. It does not include cancelled subscription items.
31
+ attr_accessor :subscription_items
32
+
33
+ class EnumAttributeValidator
34
+ attr_reader :datatype
35
+ attr_reader :allowable_values
36
+
37
+ def initialize(datatype, allowable_values)
38
+ @allowable_values = allowable_values.map do |value|
39
+ case datatype.to_s
40
+ when /Integer/i
41
+ value.to_i
42
+ when /Float/i
43
+ value.to_f
44
+ else
45
+ value
46
+ end
47
+ end
48
+ end
49
+
50
+ def valid?(value)
51
+ !value || allowable_values.include?(value)
52
+ end
53
+ end
54
+
55
+ # Attribute mapping from ruby-style variable name to JSON key.
56
+ def self.attribute_map
57
+ {
58
+ :'id' => :'id',
59
+ :'name' => :'name',
60
+ :'status' => :'status',
61
+ :'subscription_items' => :'subscriptionItems'
62
+ }
63
+ end
64
+
65
+ # Attribute type mapping.
66
+ def self.openapi_types
67
+ {
68
+ :'id' => :'String',
69
+ :'name' => :'String',
70
+ :'status' => :'String',
71
+ :'subscription_items' => :'Array<SubscriptionItem>'
72
+ }
73
+ end
74
+
75
+ # Initializes the object
76
+ # @param [Hash] attributes Model attributes in the form of hash
77
+ def initialize(attributes = {})
78
+ if (!attributes.is_a?(Hash))
79
+ fail ArgumentError, "The input argument (attributes) must be a hash in `XeroRuby::AppStore::Plan` initialize method"
80
+ end
81
+
82
+ # check to see if the attribute exists and convert string to symbol for hash key
83
+ attributes = attributes.each_with_object({}) { |(k, v), h|
84
+ if (!self.class.attribute_map.key?(k.to_sym))
85
+ fail ArgumentError, "`#{k}` is not a valid attribute in `XeroRuby::AppStore::Plan`. Please check the name to make sure it's valid. List of attributes: " + self.class.attribute_map.keys.inspect
86
+ end
87
+ h[k.to_sym] = v
88
+ }
89
+
90
+ if attributes.key?(:'id')
91
+ self.id = attributes[:'id']
92
+ end
93
+
94
+ if attributes.key?(:'name')
95
+ self.name = attributes[:'name']
96
+ end
97
+
98
+ if attributes.key?(:'status')
99
+ self.status = attributes[:'status']
100
+ end
101
+
102
+ if attributes.key?(:'subscription_items')
103
+ if (value = attributes[:'subscription_items']).is_a?(Array)
104
+ self.subscription_items = value
105
+ end
106
+ end
107
+ end
108
+
109
+ # Show invalid properties with the reasons. Usually used together with valid?
110
+ # @return Array for valid properties with the reasons
111
+ def list_invalid_properties
112
+ invalid_properties = Array.new
113
+ if @id.nil?
114
+ invalid_properties.push('invalid value for "id", id cannot be nil.')
115
+ end
116
+
117
+ if @name.nil?
118
+ invalid_properties.push('invalid value for "name", name cannot be nil.')
119
+ end
120
+
121
+ if @status.nil?
122
+ invalid_properties.push('invalid value for "status", status cannot be nil.')
123
+ end
124
+
125
+ if @subscription_items.nil?
126
+ invalid_properties.push('invalid value for "subscription_items", subscription_items cannot be nil.')
127
+ end
128
+
129
+ invalid_properties
130
+ end
131
+
132
+ # Check to see if the all the properties in the model are valid
133
+ # @return true if the model is valid
134
+ def valid?
135
+ return false if @id.nil?
136
+ return false if @name.nil?
137
+ return false if @status.nil?
138
+ status_validator = EnumAttributeValidator.new('String', ["ACTIVE", "PENDING_ACTIVATION"])
139
+ return false unless status_validator.valid?(@status)
140
+ return false if @subscription_items.nil?
141
+ true
142
+ end
143
+
144
+ # Custom attribute writer method checking allowed values (enum).
145
+ # @param [Object] status Object to be assigned
146
+ def status=(status)
147
+ validator = EnumAttributeValidator.new('String', ["ACTIVE", "PENDING_ACTIVATION"])
148
+ unless validator.valid?(status)
149
+ fail ArgumentError, "invalid value for \"status\", must be one of #{validator.allowable_values}."
150
+ end
151
+ @status = status
152
+ end
153
+
154
+ # Checks equality by comparing each attribute.
155
+ # @param [Object] Object to be compared
156
+ def ==(o)
157
+ return true if self.equal?(o)
158
+ self.class == o.class &&
159
+ id == o.id &&
160
+ name == o.name &&
161
+ status == o.status &&
162
+ subscription_items == o.subscription_items
163
+ end
164
+
165
+ # @see the `==` method
166
+ # @param [Object] Object to be compared
167
+ def eql?(o)
168
+ self == o
169
+ end
170
+
171
+ # Calculates hash code according to all attributes.
172
+ # @return [Integer] Hash code
173
+ def hash
174
+ [id, name, status, subscription_items].hash
175
+ end
176
+
177
+ # Builds the object from hash
178
+ # @param [Hash] attributes Model attributes in the form of hash
179
+ # @return [Object] Returns the model itself
180
+ def self.build_from_hash(attributes)
181
+ new.build_from_hash(attributes)
182
+ end
183
+
184
+ # Builds the object from hash
185
+ # @param [Hash] attributes Model attributes in the form of hash
186
+ # @return [Object] Returns the model itself
187
+ def build_from_hash(attributes)
188
+ return nil unless attributes.is_a?(Hash)
189
+ self.class.openapi_types.each_pair do |key, type|
190
+ if type =~ /\AArray<(.*)>/i
191
+ # check to ensure the input is an array given that the attribute
192
+ # is documented as an array but the input is not
193
+ if attributes[self.class.attribute_map[key]].is_a?(Array)
194
+ self.send("#{key}=", attributes[self.class.attribute_map[key]].map { |v| _deserialize($1, v) })
195
+ end
196
+ elsif !attributes[self.class.attribute_map[key]].nil?
197
+ self.send("#{key}=", _deserialize(type, attributes[self.class.attribute_map[key]]))
198
+ end # or else data not found in attributes(hash), not an issue as the data can be optional
199
+ end
200
+
201
+ self
202
+ end
203
+
204
+ # Deserializes the data based on type
205
+ # @param string type Data type
206
+ # @param string value Value to be deserialized
207
+ # @return [Object] Deserialized data
208
+ def _deserialize(type, value)
209
+ case type.to_sym
210
+ when :DateTime
211
+ DateTime.parse(parse_date(value))
212
+ when :Date
213
+ Date.parse(parse_date(value))
214
+ when :String
215
+ value.to_s
216
+ when :Integer
217
+ value.to_i
218
+ when :Float
219
+ value.to_f
220
+ when :BigDecimal
221
+ BigDecimal(value.to_s)
222
+ when :Boolean
223
+ if value.to_s =~ /\A(true|t|yes|y|1)\z/i
224
+ true
225
+ else
226
+ false
227
+ end
228
+ when :Object
229
+ # generic object (usually a Hash), return directly
230
+ value
231
+ when /\AArray<(?<inner_type>.+)>\z/
232
+ inner_type = Regexp.last_match[:inner_type]
233
+ value.map { |v| _deserialize(inner_type, v) }
234
+ when /\AHash<(?<k_type>.+?), (?<v_type>.+)>\z/
235
+ k_type = Regexp.last_match[:k_type]
236
+ v_type = Regexp.last_match[:v_type]
237
+ {}.tap do |hash|
238
+ value.each do |k, v|
239
+ hash[_deserialize(k_type, k)] = _deserialize(v_type, v)
240
+ end
241
+ end
242
+ else # model
243
+ XeroRuby::AppStore.const_get(type).build_from_hash(value)
244
+ end
245
+ end
246
+
247
+ # Returns the string representation of the object
248
+ # @return [String] String presentation of the object
249
+ def to_s
250
+ to_hash.to_s
251
+ end
252
+
253
+ # to_body is an alias to to_hash (backward compatibility)
254
+ # @return [Hash] Returns the object in the form of hash
255
+ def to_body
256
+ to_hash
257
+ end
258
+
259
+ # Returns the object in the form of hash
260
+ # @return [Hash] Returns the object in the form of hash
261
+ def to_hash(downcase: false)
262
+ hash = {}
263
+ self.class.attribute_map.each_pair do |attr, param|
264
+ value = self.send(attr)
265
+ next if value.nil?
266
+ key = downcase ? attr : param
267
+ hash[key] = _to_hash(value, downcase: downcase)
268
+ end
269
+ hash
270
+ end
271
+
272
+ # Returns the object in the form of hash with snake_case
273
+ def to_attributes
274
+ to_hash(downcase: true)
275
+ end
276
+
277
+ # Outputs non-array value in the form of hash
278
+ # For object, use to_hash. Otherwise, just return the value
279
+ # @param [Object] value Any valid value
280
+ # @return [Hash] Returns the value in the form of hash
281
+ def _to_hash(value, downcase: false)
282
+ if value.is_a?(Array)
283
+ value.map do |v|
284
+ v.to_hash(downcase: downcase)
285
+ end
286
+ elsif value.is_a?(Hash)
287
+ {}.tap do |hash|
288
+ value.map { |k, v| hash[k] = _to_hash(v, downcase: downcase) }
289
+ end
290
+ elsif value.respond_to? :to_hash
291
+ value.to_hash(downcase: downcase)
292
+ else
293
+ value
294
+ end
295
+ end
296
+
297
+ def parse_date(datestring)
298
+ if datestring.include?('Date')
299
+ date_pattern = /\/Date\((-?\d+)(\+\d+)?\)\//
300
+ original, date, timezone = *date_pattern.match(datestring)
301
+ date = (date.to_i / 1000)
302
+ Time.at(date).utc.strftime('%Y-%m-%dT%H:%M:%S%z').to_s
303
+ elsif /(\d\d\d\d)-(\d\d)/.match(datestring) # handles dates w/out Days: YYYY-MM*-DD
304
+ Time.parse(datestring + '-01').strftime('%Y-%m-%dT%H:%M:%S').to_s
305
+ else # handle date 'types' for small subset of payroll API's
306
+ Time.parse(datestring).strftime('%Y-%m-%dT%H:%M:%S').to_s
307
+ end
308
+ end
309
+ end
310
+ end