feat(transactions): move an unbooked transaction to another cash account (#1570)

A bank transaction that ingested under the wrong cash account (or with no
account at all: legacy connections, own-account transfers the backfills
deliberately skipped) surfaces under the primary account's reconciliation
and can never be matched on the account it belongs to, because
cross-account matching is deliberately blocked. There was no first-party
way to fix the binding.

New PATCH /api/transactions/[id]/cash-account moves a movable staging row
(not booked, not invoice/supplier-invoice matched, not anchored via
transaction_voucher_links) to another of the company's cash accounts,
addressed by its BAS 19xx ledger account. Cross-currency moves are
hard-rejected (the row would vanish from every report's currency scope),
and the movable gate is re-asserted atomically in the UPDATE filter
against a concurrent book/auto-match, mirroring the title route. The tvl
check runs as a pre-check query since PostgREST cannot express NOT EXISTS
in an update filter; a tvl row appearing concurrently implies the booking
flow, which sets its own transaction state.

UI: 'Flytta till annat konto' in the transaction inbox row menu (opens a
radio-list dialog of the enabled cash accounts, current one preselected
and disabled) and direct 'Flytta till {name}' items in the bank
reconciliation unmatched-row menu that PATCH and refetch the view.

New structured error codes: TRANSACTION_MOVE_BOOKED,
TRANSACTION_MOVE_UNKNOWN_ACCOUNT, TRANSACTION_MOVE_CURRENCY_MISMATCH.

Co-authored-by: Jakob Wennberg <311770904+jakobwennberg-oss@users.noreply.github.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Jakob Wennberg
2026-08-13 15:20:14 +02:00
committed by GitHub
co-authored by Jakob Wennberg Claude Fable 5
parent c420fd2aa1
commit 1eebb75269
10 changed files with 698 additions and 3 deletions
+9
View File
@@ -2710,6 +2710,13 @@
"edit_title_restore": "Restore",
"edit_title_cancel": "Cancel",
"edit_title_save": "Save",
"move_account_btn": "Move to another account",
"move_account_dialog_title": "Move to another bank account",
"move_account_dialog_description": "Choose which bank account the transaction belongs to. The move decides which bank reconciliation the transaction is counted in.",
"move_account_current": "Current account",
"move_account_currency_mismatch": "Different currency ({currency})",
"move_account_cancel": "Cancel",
"move_account_save": "Move",
"method_line": "Payment method: {method}"
},
"tx_method": {
@@ -5323,6 +5330,8 @@
"delete_failed_description": "The transaction could not be deleted. Please try again.",
"edit_title_saved": "Title updated",
"edit_title_failed": "Could not update the title",
"move_account_saved": "Transaction moved",
"move_account_failed": "Could not move the transaction",
"review_in_bookkeeping_description": "Review and post the journal entry in Bookkeeping.",
"bank_sync_attention_one": "1 bank connection needs renewal",
"bank_sync_attention_many": "{count} bank connections need renewal",
+9
View File
@@ -2710,6 +2710,13 @@
"edit_title_restore": "Återställ",
"edit_title_cancel": "Avbryt",
"edit_title_save": "Spara",
"move_account_btn": "Flytta till annat konto",
"move_account_dialog_title": "Flytta till annat bankkonto",
"move_account_dialog_description": "Välj vilket bankkonto transaktionen hör till. Flytten avgör vilken bankavstämning transaktionen räknas med i.",
"move_account_current": "Nuvarande konto",
"move_account_currency_mismatch": "Annan valuta ({currency})",
"move_account_cancel": "Avbryt",
"move_account_save": "Flytta",
"method_line": "Betalsätt: {method}"
},
"tx_method": {
@@ -5323,6 +5330,8 @@
"delete_failed_description": "Transaktionen kunde inte tas bort. Försök igen.",
"edit_title_saved": "Titeln uppdaterad",
"edit_title_failed": "Kunde inte uppdatera titeln",
"move_account_saved": "Transaktionen flyttades",
"move_account_failed": "Kunde inte flytta transaktionen",
"review_in_bookkeeping_description": "Granska och bokför verifikatet i Bokföring.",
"bank_sync_attention_one": "1 bankanslutning behöver förnyas",
"bank_sync_attention_many": "{count} bankanslutningar behöver förnyas",