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:
co-authored by
Jakob Wennberg
Claude Fable 5
parent
c420fd2aa1
commit
1eebb75269
@@ -1480,6 +1480,18 @@ export const UpdateTransactionTitleSchema = z.object({
|
||||
description: z.string().trim().min(1, 'Title cannot be empty').max(500),
|
||||
})
|
||||
|
||||
/**
|
||||
* Move an unbooked bank transaction to another of the company's cash accounts,
|
||||
* addressed by the target's BAS 19xx ledger account. Deliberately no null
|
||||
* variant: unassigning a row would just re-strand it under the primary
|
||||
* account's report (the exact symptom the move action exists to fix).
|
||||
*/
|
||||
export const MoveTransactionCashAccountSchema = z.object({
|
||||
account_number: z
|
||||
.string()
|
||||
.regex(/^19\d{2}$/, 'Expected a BAS 19xx bank account number'),
|
||||
})
|
||||
|
||||
export const BookInboxItemDirectlySchema = z.object({
|
||||
fiscal_period_id: uuid,
|
||||
entry_date: isoDate,
|
||||
|
||||
Reference in New Issue
Block a user