Skip to content

Fix update-bank-transaction 400 when editing line items#190

Open
pedromachados wants to merge 1 commit into
XeroAPI:mainfrom
pedromachados:fix/update-bank-transaction-lineitems
Open

Fix update-bank-transaction 400 when editing line items#190
pedromachados wants to merge 1 commit into
XeroAPI:mainfrom
pedromachados:fix/update-bank-transaction-lineitems

Conversation

@pedromachados

Copy link
Copy Markdown
Contributor

Problem

Calling update-bank-transaction to edit an existing bank transaction's line items fails with:

HTTP 400 — "The document sub total does not equal the sub total of the lines"

This happens even when only a line description changes and the monetary amount is identical.

Root cause

updateBankTransaction in src/handlers/update-xero-bank-transaction.handler.ts builds the update payload by spreading the entire fetched transaction:

const bankTransaction: BankTransaction = {
  ...existingBankTransaction,   // carries read-only computed subTotal/total/totalTax
  ...
  lineItems: lineItems ? lineItems : existingBankTransaction.lineItems,
  ...
};

The spread carries Xero's read-only computed fields — subTotal, total, totalTax. When lineItems are replaced, Xero recomputes the line totals server-side, but the stale subTotal/total copied from the fetched object no longer reconcile, so the API rejects the update.

Per the Xero BankTransactions API docs, SubTotal, Total, and TotalTax are each "calculated by Xero and cannot be overridden."

Fix

Build a minimal payload containing only the editable fields plus the attributes Xero needs on update, and omit the computed totals so Xero recomputes them:

const bankTransaction: BankTransaction = {
  bankTransactionID: bankTransactionId,
  bankAccount: existingBankTransaction.bankAccount,
  lineAmountTypes: existingBankTransaction.lineAmountTypes,
  status: existingBankTransaction.status,
  currencyCode: existingBankTransaction.currencyCode,
  type: type ? BankTransaction.TypeEnum[type] : existingBankTransaction.type,
  contact: contactId ? { contactID: contactId } : existingBankTransaction.contact,
  lineItems: lineItems ? lineItems : existingBankTransaction.lineItems,
  reference: reference ? reference : existingBankTransaction.reference,
  date: date ? date : existingBankTransaction.date,
};

lineAmountTypes is preserved from the existing transaction rather than omitted: it defaults to Exclusive when absent, so dropping it could silently change the tax treatment (and therefore the recomputed totals) on inclusive-tax transactions.

Verification

  • npm run build — clean.
  • npm test — 14/14 pass.
  • Live-tested against a real AUTHORISED, tax-inclusive bank transaction: editing a line description now succeeds; the transaction's total, status, contact, and tax treatment are unchanged and the new description is persisted.

updateBankTransaction spread the entire fetched BankTransaction into the
update payload, carrying Xero's read-only computed fields (subTotal, total,
totalTax). When lineItems are replaced, Xero recomputes line totals but the
stale subTotal/total from the spread no longer match, so the API rejects the
update with HTTP 400 "The document sub total does not equal the sub total of
the lines" — even when only a line description changes.

Build a minimal payload with only editable fields plus the attributes Xero
needs on update (bankAccount, lineAmountTypes, status, currencyCode preserved
from the existing transaction), and omit the computed totals so Xero
recomputes them. Per Xero's BankTransactions API docs, subTotal/total/totalTax
are "calculated by Xero and cannot be overridden," and lineAmountTypes
defaults to Exclusive if omitted — so preserving it avoids silently changing
the tax treatment.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant