calcinai / xero-php

A php library for the Xero API, with a cleaner OAuth interface and ORM-like abstraction.
MIT License
360 stars 260 forks source link

Call to Invoices returns four null invoices - may be related to new invoicing released by Xero #923

Open gurubobnz opened 4 months ago

gurubobnz commented 4 months ago

We noticed that we were getting some null object Invoices coming back from the Xero API, specifically:

$xero = Load::lib('xero')->getApplication();
$invoices = $xero->load(Invoice::class)
    ->where('Type', 'ACCREC')
    ->page(1)
    ->execute();
dd($invoices);

(don't mind the method used to load the Xero library, that is from our platform)

This returns not 100 results (the number expected on a single page), but 104. The extra four appear to be invoice objects with null properties. We started seeing this on one of our tenants as of 17/07/2024 at approx 11:54am NZST. We confirmed that it is happening on another four tenants also, with differing versions of this library.

At a glance the Xero API explorer appears to not be reporting the same, but I am confirming this.

Here is the dump that we get from the above code:

XeroPHP\Remote\Collection {#139
  #_associated_objects: null
  storage: array:104 [
    0 => XeroPHP\Models\Accounting\Invoice {#136
      #_data: array:32 [
        "Type" => null
        "Contact" => null
        "LineItems" => null
        "Date" => null
        "DueDate" => null
        "LineAmountTypes" => null
        "InvoiceNumber" => null
        "Reference" => null
        "BrandingThemeID" => null
        "Url" => null
        "CurrencyCode" => null
        "CurrencyRate" => null
        "Status" => null
        "SentToContact" => null
        "ExpectedPaymentDate" => null
        "PlannedPaymentDate" => null
        "SubTotal" => null
        "TotalTax" => null
        "Total" => null
        "TotalDiscount" => null
        "InvoiceID" => null
        "RepeatingInvoiceID" => null
        "HasAttachments" => null
        "Payments" => null
        "Prepayments" => null
        "Overpayments" => null
        "AmountDue" => null
        "AmountPaid" => null
        "FullyPaidOnDate" => null
        "AmountCredited" => null
        "UpdatedDateUTC" => null
        "CreditNotes" => null
      ]
      #_dirty: []
      #_associated_objects: []
      #_application: XeroPHP\Application {#108
        #config: array:1 [ …1]
        -transport: GuzzleHttp\Client {#119 …1}
      }
    }
    1 => XeroPHP\Models\Accounting\Invoice {#127
      #_data: array:32 [
        "Type" => null
        "Contact" => null
        "LineItems" => null
        "Date" => null
        "DueDate" => null

and so on, for the first four records, then we get normal invoices.

The timing is in line with Xero announcing their new invoicing functionality, but there is no mention of any API changes.

References:

likel commented 4 months ago

I noticed a new "pagination" key is returning.

https://github.com/XeroAPI/xero-php-oauth2/commit/f46069fe379742394b823866c549b7eda6488901#diff-fe54d6f2bad6bea431ef3bf6a810a41851f57f69c448d1bc8c609004baee70de

In Response.php if you add case pagination then it resolves the issue. There was an update that added case PageInfo a couple weeks ago, it seems like a similar issue.

parseXML/parseJSON
foreach ($sxml as $child_index => $root_child) {
            switch ($child_index) {
                case 'pagination':
                    break; // fix
                case 'PageInfo':
                    break; // 2 weeks ago fix
                case 'ErrorNumber':
gurubobnz commented 4 months ago

Yep, agreed. Can see the new element here, and the four entries (page, pageSize, pageCount, itemCount) account for the extra four blank items returned from the call.

<Response xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <Id>03f78d29-3ac5-4a44-b488-c685339a291f</Id>
  <Status>OK</Status>
  <ProviderName>Turboweb Platform</ProviderName>
  <DateTimeUTC>2024-07-18T04:15:50.360675Z</DateTimeUTC>
  <pagination>
    <page>1</page>
    <pageSize>100</pageSize>
    <pageCount>121</pageCount>
    <itemCount>12056</itemCount>
  </pagination>
  <Invoices>...</Invoices>
</Response>

I see mention of both PageInfoand paginationmentioned here: https://github.com/XeroAPI/xero-node/releases/tag/9.0.0 under "Breaking Change" with the comment "Removed PageInfo metadata object and added pagination metadata object for select Api.Accounting endpoints"

gurubobnz commented 4 months ago

Solution looks sensible for now. I've proposed a pull request for this as above https://github.com/calcinai/xero-php/pull/924