0

I'm using the Xero API to retrieve all Invoices in this month, then retrieving all CreditNotes, then I plan to allocate credits as appropriate.

Before doing that, I need to authorise all my Invoices and CreditNotes. When I get to the point of saving the updates, I'm hitting the Xeroizer::OAuth::RateLimitExceeded exception, being thrown by the validation step which seems to be individually retrieving each record via #download_complete_record! at lib/xeroizer/record/record_association_helper.rb:131.

I've tried manually setting the complete_record_downloaded flag on all the objects before saving them but then I'm getting validation errors saying the invoices have no line items, which is expected.

This is what I'm trying to do, is there a different way I should be approaching this so it doesn't try to revalidate all the records before sending the updates?

require 'xeroizer'
key = Rails.application.secrets.xero[:key]
secret = Rails.application.secrets.xero[:secret]
cert = Rails.application.secrets.xero[:cert]
xeroizer = Xeroizer::PrivateApplication.new(key, secret, cert)

issue_date = Date.new(2019,11,22)
# Retrieving this broad selection of invoices here as it's used later in this worker for other purposes
xero_all_invoices = xeroizer.Invoice.all(where: "AmountDue>0")

xero_invoices = xero_all_invoices.select{|i| i.date == issue_date && i.status == 'DRAFT'}
xeroizer.Invoice.batch_save do
  xero_invoices.each{|i| i.status = 'AUTHORISED' }
end

# At this point, the Xeroizer::OAuth::RateLimitExceeded exception is thrown.

The relevant part of the backtrace from the exception is as follows:

.../xeroizer/http.rb:175:in `handle_oauth_error!'
.../xeroizer/http.rb:124:in `http_request'
.../xeroizer/http.rb:31:in `http_get'
.../xeroizer/record/base_model.rb:152:in `find'
.../xeroizer/record/base.rb:100:in `download_complete_record!'
.../xeroizer/record/record_association_helper.rb:131:in `block in define_association_attribute'
.../xeroizer/record/base.rb:54:in `[]'
.../xeroizer/record/validators/associated_validator.rb:12:in `valid?'
.../xeroizer/record/validators/validator.rb:15:in `validate'
.../xeroizer/record/validation_helper.rb:59:in `block in valid?'
.../xeroizer/record/validation_helper.rb:58:in `each'
.../xeroizer/record/validation_helper.rb:58:in `valid?'
.../xeroizer/record/base_model.rb:161:in `each'
.../xeroizer/record/base_model.rb:161:in `all?'
.../xeroizer/record/base_model.rb:161:in `save_records'

For reference, I've asked the same question on the Xeroizer gem issues page but had no response so asking here now.

bdx
  • 3,316
  • 4
  • 32
  • 65
  • Questions seeking debugging help ("why isn't this code working?") must include the desired behavior, a specific problem or error and the shortest code necessary to reproduce it in the question itself. See: [How to create a Minimal, Reproducible Example](https://stackoverflow.com/help/minimal-reproducible-example). Your code example doesn't run. Please provide a version that actually will run, don't make us write a harness. Help us help you. – the Tin Man Nov 24 '19 at 21:30
  • I've updated the code snippet with the gem being required and the setup of the API code, however you still won't be able to run it as it requires being signed up to the Xero API, and to have a Xero account. This is not a case where I'm asking why it isn't working; I know why it isn't working, I don't know how to resolve it in the bounds of the Xeroizer gem. I want to find a way to prevent the Xeroizer gem from having to revalidate all the records it already downloaded, I'm just not sure how to do that without causing unforeseen side effects. – bdx Nov 24 '19 at 23:19
  • Add that information to the question, incorporating it where you would have put it if it'd been there initially. Don't use "edited" or "updated" tags as we can see what's changed if necessary. Trying to debug code that we can't run makes it very difficult to help you and could possibly be considered off-topic. – the Tin Man Nov 25 '19 at 04:27

1 Answers1

0

I've come to a solution for this, new working code snippet below for reference.

This may be a bit hacky as it's setting the complete_record_downloaded flag on the object which doesn't quite match the state of the object so there could be side effects for other methods I'm not aware of, but for my purposes this appears to work as intended.

The find_in_batches method retrieves the line items along with the other necessary Invoice attributes for updating them successfully so that solves the issue I was having.

After reading the Xero API documentation again I found that sending an update to an Invoice requires listing at least all the Line Item IDs otherwise they'll be removed during the update, which explains why this step was necessary.

issue_date = Date.new(2019,11,22)
# Retrieving this broad selection of invoices here as it's used later in this worker for other purposes
xero_all_invoices = []
xeroizer.Invoice.find_in_batches(where: "AmountDue>0") do |batch|
  batch.each do |invoice|
    invoice.complete_record_downloaded = true
    xero_all_invoices << invoice
  end
end

xero_invoices = xero_all_invoices.select{|i| i.date == issue_date && i.status == 'DRAFT'}
xeroizer.Invoice.batch_save do
  xero_invoices.each{|i| i.status = 'AUTHORISED' }
end
# Save successful
bdx
  • 3,316
  • 4
  • 32
  • 65