Preserve invoice line items if they are not sent
As a user of the API, I want to be able to update the status of an invoice without sending all of the line items along in the payload.
Currently, if I'm updating an invoice's status via the API I need to explicitly send the line items along with the request. If I do not send the line items, Xero deletes and recreates all of the line items even though they're not pertinent to the action (not updating line items, amounts, etc.).
This causes particular issues with inventory decimal precision. Every request needs to send the unitdp if you want your decimal precision for line items or amounts to remain unaltered.
# Create a new blank invoice object with the ID and sent status
invoice = xero_accounting.Invoice(invoice_id=str(ledger_ref), sent_to_contact=True)
# Add the invoice to a list
invoices = xero_accounting.Invoices([invoice])
# Update the invoice to sent
self.accounting_api.update_invoice(
xero_tenant_id=self.tenant_id,
invoice_id=str(ledger_ref),
invoices=invoices,
# unitdp=4,
)
In this case, we'd expect unit decimal precision to not change on the invoice. We could understand if amounts were being set or sent, but in this case, they are not—purely the status. Furthermore, the example Xero provides for the REST API for updating invoice status does not show this behavior.
-
kane
commented
I understand the frustration of having to resend every line item just to flip an invoice’s status, since Xero currently deletes and rebuilds the items on each update. The https://clermontcountycourt.org approach to partial updates, where unchanged fields are automatically retained, illustrates a cleaner pattern that could be applied here. Preserving the unitdp setting is especially important for inventory precision, because any inadvertent rounding can ripple through financial statements. A PATCH‑style endpoint that accepts only status while keeping the existing line‑item array would solve the problem without data loss.