pyxero icon indicating copy to clipboard operation
pyxero copied to clipboard

invoice can't be saved after modification due to 'PlannedPaymentDateString'?

Open g-yorke opened this issue 6 years ago • 3 comments

Trying to save a modified invoice seems to fail because of a problem with "PlannedPaymentDateString," even though that key was not changed.

to reproduce:

from xero import Xero

x = xero.invoices.get('b7bf6764-85c5-4528-965f-fe02c5d3b9ad') this is a known open AP ID and all fields and values print as expected

x[0]['Reference'] = 'test' the change to Reference is visible when printed

xero.invoices.save(x) Traceback (most recent call last): File "", line 1, in File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/xero/basemanager.py", line 202, in wrapper raise XeroBadRequest(response) xero.exceptions.XeroBadRequest: PostDataInvalidException: The element 'PlannedPaymentDateString' was not recognised. Ensure the element name has the correct case and that there are no duplicate elements of the same name.

g-yorke avatar Oct 05 '18 22:10 g-yorke

It looks like Xero are now returning PlannedPaymentDateString (although this doesn't appear to be documented anywhere) and it's a read only field, so when you try to save the invoice PyXero sends the field back to Xero, and they return the error you're seeing.

PlannedPaymentDateString needs to be added to xero/basemanager.py NO_SEND_FIELDS tuple to stop it being sent back to Xero.

MattHealy avatar Oct 06 '18 02:10 MattHealy

Yes, poking around some ore late this morning, I found that removing the PlannedPaymentDateString k/v pair before the save worked around the problem. On this page Xero does mention the string keys:

"For some elements we also include a date string value on JSON responses to help with reading date values. e.g. DateString, DueDateString."

... but as you say, this is not documented in the Invoices object documentation proper.

g-yorke avatar Oct 06 '18 18:10 g-yorke

FWIW, we had a similar issue just recently, getting the unhelpful error:

XeroBadRequest: PostDataInvalidException: Object reference not set to an instance of an object.

Couldn't pin down exactly which field(s) caused the explosion, but a legitimate solution (IMO) is just to strip out the Contact data before sending the Invoice back. Idk why it's even there...

xero_invoice = xero.invoices.get(guid)[0]
for k, v in data.items():
    xero_invoice[k] = v
xero_invoice['Contact'] = {'ContactID': xero_invoice['Contact']['ContactID']}
xero.invoices.save(xero_invoice)

jarekwg avatar Feb 25 '19 05:02 jarekwg