* feat(bank): expose bank-reported balance (booked + available) in UI, reconciliation, MCP and v1 API
The PSD2 sync has fetched the bank's reported balance for years but the
data was stranded (F7): the Bank-page source picker read a cash_accounts
column no sync ever updated (frozen at connect time), reconciliation
hard-coded external_balance to null for bank accounts, and neither MCP
nor the v1 API exposed any balance at all, so the only path to a current
bank balance was logging into the bank.
- getAccountBalance now returns booked + available from the same
quota-limited BALANCES response (previously all but one type discarded)
- every sync (manual + cron) mirrors balance, available_balance and
balance_updated_at into cash_accounts, fixing the stale picker
- new cash_accounts.available_balance column (additive migration)
- reconciliation bank kind: external_balance = bank-reported balance,
plus bank_reported_* fields and fetch timestamp in the bank block;
difference math stays movement-based and untouched
- reconciliation view shows "Saldo enligt banken ... hamtat {date}"
- MCP gnubok_list_cash_accounts returns the three balance fields; the
cash_today prompt now reports the bank's figure instead of teaching
agents to answer with the bookkept 19xx balance
- new GET /api/v1/companies/{companyId}/cash-accounts endpoint
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ewu46quXgh9LSr9UwYusxm
* fix(bank): keep external_balance null for bank sign-offs; never fabricate a zero balance; guard the mirror against stale writers
Post-review fixes from the skeptic pass + CodeRabbit on PR #2118:
- external_balance stays null for the bank reconciliation kind: sign-off
persists it into account_reconciliations and bokslutsbilagor computes
closing - external from that row, so a today-balance stored on a
balansdag sign-off printed a phantom warning-red differens in the
year-end appendix. The bank-reported figure lives only in the
timestamped bank_reported_* pair in the bank block, and only when its
fetch timestamp exists (a balance of unknown age is suppressed).
- AccountOverview no longer falls back to today's date when the balance
timestamp is missing; the line is omitted instead.
- getAccountBalance returns null on an empty BALANCES response instead
of fabricating amount 0 with a fresh timestamp; sync keeps the
previous stored value.
- updateBalancesFromSync only writes over an older-or-missing
balance_updated_at, so an older sync run finishing later cannot move
the mirrored balance backwards.
- The inline initial backfill (picker save) now mirrors fetched
balances into cash_accounts too (accounts_data is deliberately not
re-written there).
- cash_today MCP prompt mentions the gnubok_call_tool bridge for hosts
that only see the default catalog.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ewu46quXgh9LSr9UwYusxm
* fix(bank): express the stale-writer guard as two literal predicates for the schema guard
The .or() with a template literal pushed the no-phantom-columns
unresolvable-expression count over its ceiling. Same semantics, two
updates: one for rows with an older timestamp, one for rows with none.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ewu46quXgh9LSr9UwYusxm
* fix(bank): rank interimBooked (ITBD) as a booked balance type before the generic fallback
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ewu46quXgh9LSr9UwYusxm
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
60 lines
2.5 KiB
TypeScript
60 lines
2.5 KiB
TypeScript
import type { McpPrompt } from './types'
|
|
|
|
/**
|
|
* Single-action prompts. Each one is a Swedish slash-shortcut that directs
|
|
* the model to call exactly one Accounted tool and report a short answer.
|
|
*/
|
|
export const prompts: McpPrompt[] = [
|
|
{
|
|
name: 'whats_overdue',
|
|
description: 'Visa förfallna kundfakturor',
|
|
text:
|
|
'Lista mina förfallna kundfakturor. Anropa gnubok_list_invoices med status="overdue" ' +
|
|
'och svara på svenska med en kort lista: kundnamn, belopp, antal dagar förfallen. ' +
|
|
'Inga rekommendationer: bara fakta.',
|
|
},
|
|
{
|
|
name: 'cash_today',
|
|
description: 'Visa banksaldo just nu',
|
|
text:
|
|
'Hur mycket pengar har jag på företagskontot just nu? Anropa gnubok_list_cash_accounts ' +
|
|
'(syns det inte i verktygskatalogen: anropa det via gnubok_call_tool) och ' +
|
|
'rapportera bankens rapporterade saldo (balance, available_balance) per konto med tidsstämpeln ' +
|
|
'balance_updated_at. Saknas rapporterat saldo (manuellt konto eller aldrig synkat): fall tillbaka ' +
|
|
'på gnubok_get_balance_sheet för dagens datum och saldot på konto 1930, och säg att siffran är ' +
|
|
'bokförd, inte bankens. Visa även de senaste 5 transaktionerna ' +
|
|
'via gnubok_list_uncategorized_transactions (limit=5, sortera nyast först: men inkludera även ' +
|
|
'kategoriserade om verktyget tillåter). Svara kort på svenska.',
|
|
},
|
|
{
|
|
name: 'last_month_result',
|
|
description: 'Resultat förra månaden',
|
|
text:
|
|
'Visa resultaträkningen för föregående kalendermånad. Anropa gnubok_get_income_statement ' +
|
|
'med rätt datumintervall och svara på svenska med tre siffror: intäkter, kostnader, resultat. ' +
|
|
'Ingen analys.',
|
|
},
|
|
{
|
|
name: 'vat_due',
|
|
description: 'Moms att betala / återfå',
|
|
text:
|
|
'Vad är min momsskuld eller momsfordran för innevarande momsperiod? Anropa gnubok_get_vat_report ' +
|
|
'och rapportera enbart ruta 49 (att betala / att få tillbaka) samt deadline för deklarationen. ' +
|
|
'Ingen analys.',
|
|
},
|
|
{
|
|
name: 'uncategorized_count',
|
|
description: 'Okontrerade transaktioner',
|
|
text:
|
|
'Hur många banktransaktioner är okontrerade? Anropa gnubok_list_uncategorized_transactions ' +
|
|
'och svara på svenska med tre uppgifter: antal, datum för äldsta transaktion, totalbelopp. ' +
|
|
'Inga åtgärdsförslag.',
|
|
},
|
|
]
|
|
|
|
export function findPrompt(name: string): McpPrompt | null {
|
|
return prompts.find((p) => p.name === name) ?? null
|
|
}
|
|
|
|
export type { McpPrompt }
|