Skip to main content

Budget - Releases

← App details

Nextcloud 35

Budget 2.52.0
Release Details
UpdatedSept. 18, 2026, 11:44 a.m.
Changelog

Added

  • Import templates remember the character encoding. A statement in an encoding the importer cannot recognise on its own - an undeclared Cyrillic or Central European CSV reads as perfectly valid Western European text, just with the wrong letters - has to have its encoding picked by hand on the mapping screen, and that choice was lost on every import. A saved template now keeps it, and picking the template re-reads the file in that encoding straight away. Templates saved before this have no encoding stored and leave the picker as it is, so they cannot undo an encoding you have just chosen for the file in front of you. Contributed by @Saviq (#384)
  • Import rules can rewrite a transaction's description. A new Set Description action replaces the description a transaction arrived with - CARD PAYMENT TO TESCO STORES 2231 can become Groceries - either always or only when the description is empty. It runs on file imports, on bank sync and when rules are applied to existing transactions. Duplicate detection keeps using the description from the original file, so a statement imported again is still recognised after a rule has rewritten its descriptions. Contributed by @Saviq (#385)

  • The import review says which rows it cannot take, before you import. A file with an Account column can carry rows whose account cell is empty, and with Account for rows without one left on Skip rows without an account those rows are dropped. The review step never said so: a 75-row file whose last 29 rows had no account read as "Total 75, New 0, Duplicates 46", and the only mention of the missing 29 was a dialog after the import had already run. The reasons were there all along, the review step simply did not show them. A warning now sits above the statistics, in the same place as the direction warnings, saying how many of the file's rows will not be imported and why, with the row numbers behind each reason. Where the reason is an empty account cell it points at the fallback account select below it, which is what fixes it, and choosing an account there clears the warning and brings those rows back into the count. The row numbers also match between the review step and the dialog after the import now, the review step counted from 0 whilst the import counted from 1. Reported by @TerjeTM (#388)

  • The Budget Alerts tile can be told which categories it may alert about. Since 2.28.3 a category with no budget of its own falls back to the amount its bills and recurring income commit it to, so categories that were never budgeted against started appearing on the tile, and spending 190.00 against a 56.03 figure worked out from a bill reads as "239% over". The tile's settings, on the gear when the dashboard is unlocked, now offer Only categories with a budget I set, which leaves the derived budgets out and gives back what the tile showed before that fallback existed, and a list of every category with a budget in play that can be unticked one at a time. Rows whose budget came from a bill are marked, so it is clear which ones the checkbox covers. The filter is stored with your settings rather than with the tile, so budget alert notifications and the digest honour it as well, and the budget figures on the Budget page, the Nextcloud dashboard panel and the digest are untouched by it. With a filter on, a tile with nothing left to show stays up and says how many categories are muted rather than disappearing, which would take the gear with it. Reported by @TerjeTM (#389)

Changed

  • The mapping screen redraws as soon as you change the delimiter, the header toggle or the encoding. Changing the delimiter used to leave the columns and preview split the old way, with a note that the file would be re-parsed in the next step, and toggling Skip first row (headers) did not touch the preview at all - so neither could be checked before moving on. All three now re-read the uploaded file on the spot and redraw the column choices and the preview, keeping every column you had already picked that still exists. Picking a saved template does the same with the template's own delimiter and header setting, so its mapping lands on columns split the way it expects. Contributed by @Saviq (#383)
  • Translations. Ukrainian is now included, the Polish and Russian translations asked for in #382 are in, and German and French have been updated from Weblate.

Fixed

  • Expenses another user splits with you count towards your balance with them. When another Nextcloud user split an expense with you it showed under Shared with me as outstanding, however your contact for that person still read "Settled", opening it listed no expenses, and the totals at the top of Shared Expenses left it out. Each split is stored against the person who made it, and a contact card only ever read the splits you had made yourself. A contact linked to a Nextcloud user now also counts what that user has split with you, from your side, so their "owes you £40" is your "you owe £40", and where you have both split expenses with each other the card shows what is left once one is taken off the other. Their splits are listed in the contact's details marked split by with their name, and the payments they record show in the settlement history as payments from you. Only the person who split an expense can settle it, so Settle All and Record Payment still only reach your own splits, and are greyed out when none of yours are open. The contact has to be linked to their Nextcloud account, the same as for Shared with me. Reported by @Bow-Wow75 (#390)
  • A paid one-time bill keeps its due date. Marking a one-time bill paid cleared its next due date, and a bill created before 2.49.0 - when one-time bills gained a real Due Date - had nothing else to show, so a paid invoice read "No due date" in the list and opened with an empty Due Date beside the old Due Day and Due Month fields. The date a one-time bill was due is now kept when it is paid and the list shows it; bills paid before this release get their date back from the day and month they still hold, in the year nearest to the payment. The form no longer offers Due Day and Due Month for a one-time bill: the Due Date is its whole schedule, and it has to be filled in (#333)
  • The Bills Calendar no longer shows a bill as due for months it has moved past, or for months before it existed. Since 2.49.0 a month was struck through only when a payment was recorded against it, so a bill marked paid with Don't create any transaction - a yearly premium in February - stayed green in September as if still outstanding. Every bill was also projected back to January whatever day it was created, so a bill added on 8 September read as owed for the eight months before it, and those months inflated the monthly totals. A month the bill has moved past without a recorded payment is now struck through with a dashed line and its tooltip says no payment was recorded, and nothing is drawn before the bill's creation date unless a start date says the schedule began earlier - a bill with nothing left in the year drops out of the table rather than sitting there as a row of blanks. A payment linked from before then still shows as a paid month (#333)
  • Tab-separated CSV files can be imported. The Tab delimiter option sent the two characters \t instead of a tab, which the CSV reader refuses, so choosing it made the import fail - and a tab-separated file that was detected correctly showed a blank delimiter and was then read with commas. The option now sends a real tab, and a template saved from the old option is read as a tab too (#383)
  • The import review shows how many transactions the file holds. Total Transactions on the review step always read 0, whatever the file contained. The account page has a transaction counter with the same element id, and it sits earlier in the page, so every update meant for the import summary went to that hidden counter instead
  • Clicking quickly through months on the Budget page no longer shows another month's figures. Every month change starts its own loads of the spending and the budget amounts, and an earlier load that finished last replaced the newer figures, so June could show May's spending or May's budgets. Only the most recent load is shown now, and a budget load that fails leaves the base budgets rather than another month's. Contributed by @almeidandres (#387)
  • The dashboard follows your budget start day. With a Budget start day set, the income, expenses, savings and budget-remaining figures at the top of the dashboard still covered the calendar month, and Budget Progress set to the current budget period used the budgets of the month the period started in - a period from 28 August to 27 September was measured against August's budgets. The top figures now cover the current budget period and show its dates under their labels, and both use the budgets of the month the Budget page lists that period under, the month its 15th falls in. Envelope carryover, which the dashboard only added for whole calendar months, now counts for the budget period too. The six-month charts stay on calendar months. Contributed by @almeidandres (#386)
  • Every budget surface agrees on which month is running when you have a budget start day. A period is listed under the month its 15th falls in, so with a start day of the 10th, 5 September is still in August's period, and with the 28th, 29 September is already in October's. Budget alerts, and the Budget Health tile built on them, still used the budgets of the calendar month, the Budget page opened on the calendar month, and turning on envelope budgeting started the envelope in the calendar month too. All of them now use the period running today. The recurring-bill fallback and the "(projected)" carryover mark also treat that period as the current one, so a period that has already ended no longer borrows today's recurring figures. A category's details follow suit: This month, the trend and the monthly chart count spending per budget period instead of per calendar month, and the chart ends with the period running today. The same goes for the dashboard's Monthly Comparison tile, which now compares the running period with the one before, and for This Month Income and This Month Expenses on an account's page, and both show the dates they cover.
  • The Monthly Comparison and Weekly Spending tiles show the real figures. Both tiles looked for income and expenses at the top of the summary they load, however the summary keeps them under its totals, so they showed zeros whatever was in the accounts. They read the totals now.
  • An overdrawn envelope shows as over budget. When the overspend carried into a month is larger than that month's budget, nothing is left to spend, but the Budget page showed the row as "No budget set" with no remaining figure, and the dashboard's Budget Progress tile left it out. Both now show it as over budget, with what it owes as the remaining amount, as the alerts and reports already did.
  • The budget adjustment notice names the right month everywhere. "Budgets adjusted from ..." and its confirmation dialog read the month as midnight UTC, so anywhere west of UTC they named the month before the one being adjusted
  • The Budget page shows the right period for a start day of the 15th everywhere. The month picker's date was read as midnight UTC, which is still the 14th anywhere west of UTC, so in the Americas a budget start day of the 15th showed each month the period before the one it should
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureYjtb6oj/6u2vw+lMxUwTdqaoecbNZKr8zgforTdMu2KAUE/D7PJQiWgI+mlRDXOoDp++CZJkbkDwEIknVcN6Zl5rCfUtSvMwdVk4IvOKwG7AW2qqDhnHDplkWBwPMEFNNJdQxPnjsDTNYxTEtGnOXwl2gxc9NMIFSD3c/DeCbxzLZd61DaVpjQohgLF7EKuVeLohtjay574dEpwpXH9z50nYJ0bO65jUTxrnZmLoafqKyQRu7tqurEWjlkhUcZRBALUnDzc1KwA+7kP1K1SwVoJkiuJwqcZNju3hsz8US7leYtvEnQL0Qsp+TnCHKiGibv/G5kVVwgvGZ0ThI20UeIHQOMKDZXj+d+CKuskMLpBJTUZPJaQyTeyIfFQ858nZlHHKC1mSRno6XPO1pYQCvHBzf+TIZBtF9U7N9svhxDJ2eXRAXJbp+BrtfuVrBEFkXE/4kilamlMPdGi1nG0EkcnKB9tVaqryzKWgWb97hfuBftBulfa+kaGjJAH9ZMwf9GioTzOCSdLf32lC+XFlDFxf93nTrzfNPB3dU+v/F1ZiItBx3WvAcXbYdg2lYa8y/A8liLqYXj19o9GqDbhNFVhCVQNvfFn0nfq/otpkY6sMH+brtN4O1HQfNqOOn6Lp09HRh299sfO8kuCaQDIGfeyNb4qNNJALi6bewhAaORk=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.51.0
Release Details
UpdatedSept. 11, 2026, 1:17 p.m.
Changelog

Added

  • Accounts can be deleted in bulk. Tick the accounts you want gone and delete them in one go, from either the tile or the list view. This existed for transactions and categories but never for accounts, and the gap only really bites in the one situation that produces dozens of them at once - an import with the wrong column mapped to Account, which creates one account per distinct value in that column. Deleting those one at a time also ran into the delete endpoint's rate limit of ten calls a minute, and an account that still holds transactions costs two of them, so the clean-up stalled about five accounts in. The whole selection now goes in a single request. The destructive half is kept a separate decision: the first confirmation removes only the accounts that are already empty, and anything still holding transactions is kept back and asked about in a second dialog that names those accounts and totals their transactions, so nothing with history in it is deleted by a click meant for an empty account. Closed accounts can be selected too (#381)
  • The import preview warns when a column mapping is about to create a pile of accounts. Mapping the wrong column to Account creates one account per distinct value in it, and mapping the date column gives you one account per day. The preview did list what it was about to create, but as a comma-separated line among the statistics, which reads as a note rather than as a reason to go back. Above five new accounts it is now a proper warning, sitting above the stats where the direction warnings already sit, because it answers the same question - whether to import at all. When most of the new account names parse as dates it says so outright and points at the account column mapping, rather than leaving you to work out afterwards why you have forty accounts (#381)
  • Bulk edit can add and remove tags. Tagging a run of transactions meant opening each one in turn: the bulk editor only ever touched fields stored on the transaction row itself, and a tag is not one of them. Tags... in the bulk bar now adds and removes tags across the whole selection at once, a cross-page select all matching selection included. The two lists are deliberately separate rather than one set of checkboxes - a tag you leave unchecked is not touched either way, so adding one tag to a hundred transactions cannot quietly strip the tags those transactions already carry. Adding a tag a transaction already has does nothing, and neither does removing one it does not have, so the same change can be re-run over an overlapping selection without anything happening twice. Category tags are offered too, grouped under the category they belong to. A tag set belongs to one category, so across a selection spanning several it can only reach part of what you picked - rather than leave you to find that out afterwards, each group says how far it reaches (applies to 12 of 50), only the categories actually in your selection are offered at all, and the confirmation names any tag that fell short instead of claiming it did more. Anything the tags cannot cover is counted underneath, including split transactions, which have no category of their own once split. Removing is not restricted the same way: a transaction re-categorised after it was tagged keeps the old tag, and gating removal would leave that tag impossible to clear in bulk. Requested by @joeftiger (#379)

Fixed

  • Names with an ampersand or a quote come out right in confirmations and messages. A category called "Food & Dining" was named in its own delete confirmation as "Food &amp; Dining", and the same went for anything carrying a quote or an angle bracket - an account, a contact, a saved report. Translated text has its inserted values escaped for HTML by default, which is right for the many places that text is used as markup and wrong for the two that show it literally: the confirmations and the little messages that slide in at the top right. Both now undo that escaping, so a name reads the way it was typed. This was true of the old browser confirmations too; it is simply visible now that the dialogs are the app's own (#381)
  • Editing a reconciled transaction in the list no longer asks twice. Changing the amount, date or account of a reconciled transaction directly in the table warns you first, and that warning could appear a second time straight after you had answered it - once because opening it moved the cursor out of the cell you were editing, and once more when the table redrew behind it. Answering once is now enough (#381)
  • Confirmations stop working after a few of them in a row. Every confirmation in the app was a browser dialog, and browsers offer to switch those off: after a handful in quick succession, Chrome and Firefox add a Prevent this page from creating additional dialogs checkbox to the box, and once it is ticked every later confirmation is answered no instantly without anything being drawn. From that moment the app looked broken rather than cautious - Delete did nothing whatsoever, no dialog, no error, no message, and nothing short of reloading the page brought it back. Clearing up a handful of accounts left behind by a mis-mapped import was more than enough to trigger it, which is how this came to light: two accounts deleted fine, and every delete button after that appeared dead. Confirmations, prompts and alerts are now drawn by the app itself, so there is nothing left for a browser to suppress. They take the keyboard - Enter confirms, Escape cancels, Tab stays inside the dialog - and a confirmation for something that deletes data now says so with a red button rather than a neutral OK. Reported by @missunderstoodninja (#381)
  • Tag pickers can be reached with the keyboard. Every tag checkbox in the app was hidden outright rather than just visually, which takes it out of the tab order and out of what a screen reader can announce - the coloured badge was the only way to set a tag, and only with a mouse. The checkboxes are now hidden visually but still focusable, and a badge shows a focus ring when you tab onto it. Nothing looks different with a mouse (#379)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureomDWujOwOWa9L4Xhc5Xr+YxrNL/X4KJz7URuQ3oocoKImK3zBZp5nUdl464tQpzylxC8sTBVsN9SqEm6KKKsPGkY92c4QnEzKWsuAM1fVZDgAqU/8oCyq6pSlRTrxxmHFN+PmioiScBnhErLMyrvPWkjVSpve7kIb5v1QRqf4nqJFuxeSOJAX1JgOM1tVME5Loxrm6SFZOsXaEXpKgqGF9SSuWXPAd1qGAO+MkugHo6zEjelkCYAWzkq2/tCZHOtIExuhBUk/BuSCMd9AaYhLb2iRJVT4FYcf14uRWCdfHmbRkNuGZNV63hbwNXwvIdP0KB9ZJ3QLV82V7LFyWY+s0VfssxJnKzjm8afeKo6zxq5SeRZmTVZDAxX7+aogVVWIqB18uwCI0dYWbMZQgR6PRqig0lf8E1j6KOiMRimZeHw0mkKFDV6ytcZEHgS8PuCih1ol9XaF+tNz4QJkKu/49A23APwrCUanew/Fs0BOhH7ydCNAl7sM5xpXKx4/4hoLJrA9tzTRwQUn1dmjbRk0QjThANrvqu+m0Gz97XWEwyyj3zHQyWYNy0Ozg1W1P01U/iFGH96Nd2emV2OO63z/AAmHrGWyBVBK73VlNx1guwaf8//c6XYbrbSJdF/smvbQcMa1MikuJq4DMpItW8vmvC+YOvUycpSHDkl7Hf+TC4=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.50.1
Release Details
UpdatedSept. 10, 2026, 1:21 a.m.
Changelog

Fixed

  • Save stops working on the transaction form after the split editor has been used. Turning Split across categories on and back off - or switching the type to Transfer with it on - hid the split rows but left them sitting inside the form. A hidden field is still checked by the browser, and an empty one it cannot put on screen is one it will not report either: the form simply refused to submit, with no message, no request and no error in the console, for every transaction from then on until the page was reloaded. Firefox and Chrome at least log something; Safari says nothing at all. Putting the split editor away now empties it, and a split amount is no longer a field the browser polices - an incomplete split was already caught on save, and says what is wrong in a way you can actually see. Reported by @SGiersch (#380)
  • Adding a transaction from an account preselects that account. The Add Transaction button on an account's page was reading the account being viewed from the wrong object, so it always came through empty and the picker opened blank - on the one screen where there is no question which account you meant (#380)
  • Transfer matching finds the other half in a shared account. A transfer between an account you own and one your partner has shared with you could not be matched: the search for the opposite leg only ever looked at rows you own, and a transaction in a shared account belongs to that account's owner, so the match dialog reported nothing to match and the bulk scan skipped the pair entirely. Linking the two was already allowed - it was only finding them that was not. The match dialog, the bulk scan and bulk linking now search every account you can write to, shared ones included. Accounts shared with you read-only are left out, because linking writes to both legs and a candidate you cannot write to could never have been linked anyway. Reported by @lexiconzero (#378)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignaturebuZC6LMTRyNL1vila15DJJFe8dDZf/j3oCjxjP7KvrqebYszACpNqevFzP0b+HFTrgRwXMF7+ZnHeZDVV4l4KuZgfeI78fVJnNhQQeYNYqcIRiZZTKoqfm3zpU0OzCqWchvR7Mgslc6IIuBGjmM5EAx53O05t69k00ylo5G2YLfeMtyeg9hlqRERfuE5aMa7w5YhvBcskq9gIbtuGRU5ZfK++QikEJxZS9Quy9H7iDuuRBrPgumyJyURxaENIodcPhTuHjC/95LQWciAI6bj562mWuNglVdBEC+9+oNRN12vyMHerogSRRNpfqKwMb93Yzhlw3gkjkD9DsZvVuzuek98QAxEhTDZeEcZ5o4aAB2m+mRAmx77mj0OrfvLcyL7ekKUCr6G0/xJkU3XtEG3WDF20OupAcXsNbYBduRIoCvozx/pEGOkIipe4oQOlh6POT7MkXWfxBGJaG3N8SzmUqihyNgx8KuoxodhHsw09O8ncNlmkiBEGNn0+Hx/UXiijxE4ucigWPVSmUP6SU6F8dpjU2EU/jqbIdxPiyz3r/tt/vbVXDw41c7wd5nnkHyubljlBW6KL1uREbhrl7fdRCgjzJkPKA+fa4tdpa83af3llfzKcnyO6TXQ/nPL+xI0eLwRlXUIp4eW9xIeY0sZ3bOwjMdOemiR1Q9lGSloAZc=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.50.0
Release Details
UpdatedSept. 5, 2026, 11:16 p.m.
Changelog

Added

  • Budget alerts and forecast warnings actually notify you now. The two switches at the top of Settings → Notifications have been there since the first release and never did anything - nothing read them, and the app had no such notification to send, so the only place a budget alert ever appeared was a dashboard card you had to go and look at. Budget Alerts now sends a notification the first time a category reaches your alert threshold (80% by default) in a budget period, and a second one if that category goes on to exceed its budget. That is the most it will send per category per period, so the nightly check cannot turn into nightly noise; a category that drops back under its threshold is forgotten, so it can alert again if it climbs back. Forecast Warnings sends at most one notification a month when the six-month forecast projects your combined balance below zero, naming the month it happens and the figure it falls to. Both default to on and are switched off from those same two checkboxes

Fixed

  • The Bills Calendar never shows an occurrence as paid while the bill still says it is due. 2.49.0 placed each payment on the nearest due date, and a bill paid twice at the end of a month - or paid a few days before the next cycle - had the extra payment land on the following occurrence, so the calendar struck through September while the Bills page showed the same occurrence as upcoming. The bill already knows which occurrences are done: marking one paid moves its next due date on a cycle, so everything before that date is closed and everything from it on is still owed. Payments are now only ever placed on closed occurrences; a second payment in a month shows as that month's larger amount rather than as a month that was never paid. Reported within the hour by @TerjeTM (#375)
  • One-time bills with the same name share one calendar row. Now that paid one-time bills stay in the year's calendar, a garage that sent three invoices appeared three times, one cell each. They are folded into one row with a cell per invoice, each keeping its own amount, the way recurring bills already read (#375)
  • Exported reports come out in your language. The PDF and CSV a report exports to were written with English labels whatever language Nextcloud was set to - the exporter never asked the translator, so a German user got Total Income and Account Breakdown in an otherwise German app. Every label in the report, Year over Year and Bills Calendar exports now goes through the same translations the screen uses, month names included, and the monthly scheduled report is produced in its recipient's language rather than the server's. Labels that already exist on screen are translated straight away; the few headings that only ever appeared in the exports are new to translators and fill in as the translations arrive (#377)
  • A monthly digest can report unusual spending. Unusual-spending detection judges a month that is still in progress, so it stays quiet before the 10th - pro-rating the rent on the 2nd would flag it every time. The monthly digest is sent on the 1st, so its unusual-spending section was empty every single time it went out, and the weekly digest only filled it in on the weeks that happened to start after the 10th. The digest now asks about the period it is actually reporting on: a finished week or month, compared against the same six-month typical figure scaled to that period's length, with no early-month rule to apply because a finished period is not a partial one. That also settles a mismatch in what the digest was telling you - it reported this month's spending so far inside a summary of last week or month, and now reports the period it covers
  • The digest notification says how many categories are spending unusually. The count was being attached to the notification and then never shown, so a digest that had found something looked exactly like one that had not
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignaturekDEMKCHGsB6XHpH0lnwbdVN2PlHEz5a/0JU2HlikRqJOIHvusKOCEPzyqSYRH/8U5+wPMQcWAi6Zlb8pcjgNh3CwemL7dVDMnrV7w65ZbG5xhBtzlziNuhs1FCJzqYQshdgCJzd2xQFJYJOqTqFXqdFQK6US+0Tgm47K6ROYrFUL/9JEhdaoH3kUz8PAP2WOq+IYdRfeUBlXUslF6pbtDWQ9g6gVSTUDF1Kj0V6UU+/M+GqrHY4flUN5Q9k6lGRLri8eBRO2woA5jdLWxJ5tyonb6F9e65yjlOIYbC3QV+TaHwH5MLbj9lmkrbAjFUMaaSWQ0VuEaj8vupo46ebxm2V4dGN4oisWd0VKRmlpGpGdDLIDYT1aZwIrVIRWPIicpqiFkLdOOo+YOCIl3XHNu6lPLxdR/jNcEDORoRJq6yPVtWZTroXgXM3TznOcNLXKotj7v/o1MPxId8uMms/wiu8PRksNIlFeLnmV8czhjhI+ZLElYqwCyMJjCUZUUB3ebdvRtbDqvuJBwuYp36Oi5UKfBTXqYzbAAO8qr4nAH/gdQsA8X+YquAMuux31ilINMpOvFX71Yf7/E15pqYZfvEQS0hq1hV4xIcgVAreEOHbIIFGcVB5WdrvYNeNP366rB5WsKXUBDGFrTEIL5vtj8OHgLqVYoEgBZNg/RL9j/Fc=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.49.0
Release Details
UpdatedSept. 3, 2026, 11:53 p.m.
Changelog

Added

  • A one-time bill can be dated in the past. A bill only ever stored a day and a month, and every date it worked out from them was rolled forward past today - right for a schedule, useless for an invoice from last month, which became due next year the moment you saved it, and jumped again if you tried to edit it back. For one-time bills the schedule fields now give way to a single Due Date, taken literally: an August invoice entered in September is due in August, shows as overdue until you mark it paid, and lands in August on the Bills Calendar. The placeholder transaction a new bill pre-creates is always a scheduled one, whatever its date: with a past date it was being written as a cleared payment, booking the money as spent for a bill nobody had paid (#375)

Fixed

  • The import's fallback account is reachable when the file has its own account column. A blank account cell now falls back to the account you choose - but the select that chooses it was hidden the moment an Account column was mapped, so the fallback could never be set from the wizard and those rows still failed with "no account was chosen". On the preview step the select now stays, relabelled Account for rows without one, and is optional: leave it empty and such rows are skipped with that reason listed (#333)
  • On SQLite, a failed save now gets the unfinished-update hint too. The hint recognised MySQL's and PostgreSQL's error codes and SQLite's "no such column", but SQLite words a failed INSERT as table X has no column named Y - which is exactly the failed save the hint exists for - and that slipped through, leaving the bare SQL. Found by running the check in a browser against a dropped column (#333)
  • The Bills Calendar shows what was actually paid. Paid months were guessed in the browser from the bill's last payment date - every month up to it counted as paid - so a bill you started paying in September showed January to August paid too, and a one-time bill fell out of the calendar the moment paying it deactivated it. The cells now come from the payments recorded against each bill: a month with a payment is paid and shows the amount that actually went out, months still to come show the expected amount, and the monthly totals follow suit. A payment made a few days late counts for the month it was due, a payment with no scheduled month near it appears as an extra paid month rather than vanishing, and a bill that is inactive now but was paid this year stays in the year's picture (#375)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureUTnFglOyY//mXGi7y/LDtH4919NkTXqAr1p4PsIxsYx5fusaiKeFTWxlcugWVBcXNirEhMLHMF/hTpCv05X/jQ0yMlB2LW8Q4bUwppTjyg44BEEACZuQWr1FTs7KhmlbU/nCDKTIuC+Uk458xB8kdIiggZoDRqb4JoINSJ2tXL5KeNQgeyyq8hqOm5pwUBxlJRgx61f8EPP4+JWoAY3DWZUGJvpmk8i0VrNtxOvHT2BTdfMxLauNboowdmko+GQv3ZLEoAwP0D1UI4pjcwxcOQdAkQuM4wXwN6tywUjdmzPTmYSTxEMO1XAnc1v22KUA7bQxkHYcg5viQMbtAA459AsY2ImPJdxGyt0PbszsxOgomnZ6BHQdohkI3zbgX2XRtRc0RycVyzkDtnuk1Nr4k8nEyhimtNea3nOZ5S3yQhrC7CPqpeoXqc/gzl5b2QrO1bC07TxUIMs9knOBR/SMWsXcSq2pzYY9FCW9+XsUVQ2XKi8CQmYiAi+rO8/RNLCkyz8OHkQuMtpdmv1YI7INkGwTr0wU0TVw1bC9ozc2GWsDeJGSYJBDn43uQQ+dyCr8xMhzkURYqjcvMYsgPUjTMY2AB0mFYow2XlRK67AE9hXrLSK25TIVHBH1JMkDx65jmH5jGQwmG8vbHjIoEygsJBRvy0hmb8uK7Pq1u5OyqnI=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.48.0
Release Details
UpdatedSept. 3, 2026, 9:09 p.m.
Changelog

Added

  • Tags can be hidden once they have served their purpose. A tag for a trip you have taken or a project that has finished keeps its history, but has no business in the picker for every new transaction — and deleting it would strip it from everything it is on. Editing a tag, on the Tags page for a global tag or in the category view for a tag-set tag, now offers a Hidden checkbox. A hidden tag is no longer offered when tagging a new transaction, bill, transfer or rule action, or when linking a savings goal, and it shows dimmed with a Hidden label where tags are managed so it can be found and unhidden. Everything that already carries the tag keeps it: the transactions stay tagged, the transaction filter and reports still list it, and a hidden tag already on the item being edited stays in its form, checked, so editing something else does not strip it (#373)
  • An account can be closed. An old bank account you no longer hold can be marked closed from the Advanced section of its edit dialog. It keeps every transaction and still counts in reports, the dashboard and net worth, but it no longer appears in any picker for new activity — the transaction and quick-add forms, transfers, bills, recurring income, imports, import rules, bank-sync mappings, savings goals and pension contributions. Pickers that filter history keep listing it, so its past stays reachable, and opening an old transaction that sits in a closed account keeps that account selected, labelled (closed). The accounts page lists closed accounts in a collapsed section of their own, and the account's page shows a Closed badge and drops the reconcile and card-payment actions. Closing is refused, with the reason shown in the form, while the balance is not zero, while any transaction is dated after today, or while an active bill, transfer, recurring income, pension contribution, bank-sync mapping or import rule still pays into or out of the account — the message names each one so it can be reassigned first. The standalone quick-add page and the import's account auto-matching skip closed accounts too, the interest accrual job leaves them alone, and the public API's GET /accounts gains an additive closed field so a capture client can filter on it (#372)

Fixed

  • Restoring a backup keeps the "exclude from reports" flag. The restore rebuilt each account field by field and never copied the flag, so every restore since the option was added put excluded accounts straight back into every total, silently. The new closed flag is restored the same way (#372)
  • The account form shows the real reason when an edit is refused. A refused account update always came back as "Failed to update account", hiding the specific message — including the reload notice a stale page gets when saving a debt. Refusals that carry a reason now reach the form verbatim (#372)
  • The unfinished-update warning now checks the database itself, and names the exact fix. It used to compare the migration files on disk with the list Nextcloud had recorded as run, and that misses both ways an install can actually be broken: a migration recorded as applied whose column is nevertheless not there, and a migration file that never reached the server. The instance that prompted this had run the recommended occ app:disable && occ app:enable to the letter and still could not save a bill, because that only re-runs what is unrecorded. The check now reads the live schema and compares it with every column the app writes, lists what is missing by table and column, and - for a change that is recorded but absent - names the precise occ migrations:execute budget <version> to re-run it, with the debug toggle those commands need. A column no migration on the server adds is called out as an incomplete install instead. The warning appears on the app's pages, in the admin overview, and in the error a failed save shows, where it now bypasses the "already verified" shortcut because a save just failed. Not being able to read the schema warns about nothing, as before (#333)
  • Repair Data no longer deletes both halves of a duplicate pair, and no longer orphans what hangs off a transaction. Its duplicate cleanup removed rows straight from the database, so any splits, tags, attachments and shared-expense records on a deleted transaction were left behind with nothing to join back to - invisible, and beyond the reach of every cleanup the app has, factory reset included. It also had three detectors flagging the same rows, each free to pick a different keeper: two placeholders written by the same payment share a creation time, so which one counted as "the real payment" came down to sort order, and a pair flagged both ways had both halves deleted - the payment removed along with its duplicate. Deletions now go through the same cascade every other part of the app uses, and a row another finding is keeping is never deleted; anything left ambiguous is simply left for a second run
  • Reconciling an account no longer means ticking your way through the whole ledger. A first reconciliation has nothing earlier to anchor on, so it starts from the account's opening balance - which means every transaction since has to be ticked before the difference reaches zero. On a real account that was 860 rows at 25 to a page, against an unfiltered list that still included scheduled rows dated years ahead. Starting a session now narrows the list to the account, to transactions dated on or before the statement date, and to rows not already reconciled - those are inside the starting balance already, so ticking one would have counted it twice - and the bar offers Tick all N transactions up to \<date> to do the whole statement in one click, leaving you to untick what your bank has not taken yet. Nothing is written to the transactions until Finish, so it is a starting point to correct from. The Create adjustment button no longer appears until something has been ticked, since before that the "difference" is simply the account's entire history, and the starting balance now explains in its tooltip where its number came from. Leaving a session hands the list back unfiltered (#374)
  • Marking a bill paid without recording a transaction no longer leaves it looking due. Choosing Don't create any transaction or linking one that already existed left the pre-created row for the occurrence you had just paid sitting in the ledger, still scheduled - so the bill went on showing as upcoming - and at the same time suppressed the row for the next occurrence, so the forecast lost it. One flag was answering two different questions. Recording the payment is now about this payment alone, and whether the next occurrence is pre-created is the bill's own Create future transaction setting, which is how skipping an occurrence and editing a bill have always read it. Existing leftovers clear themselves the next time that bill is marked paid. The dialog also now says that the bill moves on to its next due date whichever option you pick (#376)
  • Rows with an empty account column are imported instead of thrown away. A file that carries its own account column had every row with that cell left blank dropped, even though the import screen had already been told which account the file belongs to - one reporter lost 14 of 27 rows that way, in silence, and only noticed because the balance was wrong. A blank cell now falls back to the account chosen for the import. A cell that names an account which cannot be resolved is still reported rather than guessed at, since that one would misfile the row (#333)
  • The importer no longer invents an account out of a file's header row. With "first row is a header" switched off, the header line is read as data - and because it holds the column titles, its account cell held the word "Account:", which the importer duly created as a real account in dollars. Only a row that would import as a transaction can name an account now, so a header line is ignored the same way the import itself ignores it. New accounts the importer creates also take your default currency rather than always US dollars (#333)
  • The import tells you why rows failed instead of pointing at the server log. A partly failed import said "%n rows could not be imported - check the server log for details" and put the actual reasons in the browser console, where nobody looks - and on an instance whose logging is misconfigured, or where the admin cannot read the log at all, there was nowhere left to find out. The reasons now open in a window as soon as the import finishes, one line per reason with the rows it applies to, so fourteen rows failing the same way read as one problem rather than fourteen (#333)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignaturewDpgdodKiAH0BJNKoHpu1H3xardvLeUHU4/1s4cGzs/N9ZfELYEXGP9FnFBY0fSJWBscyElRGGL3vR58ISgUep5I5P9aX+JA/uHMtjeyafCVQGj/YNbhZtz/hKtNb2zM+erfMrzq6pLkleaPsCFoe5tEt3ufMZKASjvCpU1R3j4Ec6bDjiom1fk90CImC26ZItTfc5Vu/dxGtACVerJ0IvZzQPvR1J2FY1xDlqCeeuapHMmB/z3V5Px9JQU0BC+nM5qF335DutR30cz0BP7ghkp7juBWtj5fBMe2bRYmqu+AOVdcbniqHtHvktQmMjv77gQzTupn8tfNtOSf4qLK5YbiqOfMXnIIai5qmrgJE1tsO17hPQmpxol9owkPC2gRa7TwHsS09K3cMrEjpKNORD5hkFlc2m9eQR2xRAu68dWQwXkhbnmu42PcpwqQsKdLhDbwBWRJHyFqsMSds4mjYhUN5+wvQbWSsQTXoO8Z9InCntaQsDxR1rTX6CWxAy0gHx+ZD0hGv0ttqWbJzEiOPrlYwLbDvserRhlotDAahPDxsdV3PEwj28+Jtv04Ie0vE/k9n56NsAFY3e8PGjJE156W6+qurFoiXi2OcJynyAmsOsoj8DTLKnMsVMVtlw16lNZZ6uAANdDUrG1QOE8F065BkQxwg69PR3qHL3jfsgY=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.47.0
Release Details
UpdatedAug. 29, 2026, 9:47 p.m.
Changelog

Added

  • The import screen can be told which character encoding a statement uses. Some files simply cannot be identified from their contents: every single-byte encoding accepts every possible byte, so an undeclared Cyrillic export is indistinguishable from a Western European one and any automatic answer is a guess. The mapping step now carries a Character Encoding picker, listing Western European, Central European, Cyrillic, Greek, Turkish, Hebrew, Japanese, Chinese and Korean options alongside Unicode, with the detected encoding named in the hint beneath it. It sits directly above the preview, so a wrong guess is visible as mojibake and correcting it redraws the columns and preview immediately. Uploads are now kept exactly as they arrived rather than converted on the way in, which is what makes the choice reversible — previously the original bytes were discarded at upload and a bad guess could not be undone (#371)

Fixed

  • A statement that isn't UTF-8 is no longer read as Latin-1 regardless. Files that aren't UTF-8 were run through a list of fallback encodings, but the first entry accepts every possible byte, so it always matched and the rest were never reached — every such upload was decoded as Latin-1 whatever it actually was, turning a Cyrillic statement into Ïÿò¸ðî÷êà and a Japanese one into ûÀ;út;àz, with no error to say anything had gone wrong. A file that declares its own encoding is now believed: OFX states it in its header and camt XML in its declaration. Anything undeclared falls back to Windows-1252 rather than ISO-8859-1 — the two agree except over the range holding the curly quotes, dashes and euro signs statements are full of. Converted XML also has its declaration corrected to match its new contents, which previously made the parser decode the file a second time and produce exactly the corruption the conversion was there to prevent. Note that an undeclared file in a non-Western encoding still can't be identified from its bytes alone — single-byte encodings are indistinguishable, and testing for the multi-byte ones proved worse than not trying, since ordinary German, Spanish and French text validates cleanly as GB18030. That case needs an encoding picker on the import screen (#371)
  • Statements written in your own language import again. A CSV, OFX or QIF holding a decent amount of non-ASCII text was refused outright as "File appears to be binary" — which took in Cyrillic, Greek, Hebrew, Arabic and CJK statements wholesale, and caught plain accented Latin too, so a French or Spanish export could trip it as easily as a Russian one. The binary check allowed the first byte of a multi-byte UTF-8 character but not the bytes that follow it, and every non-ASCII character has at least one, so roughly half the bytes of a Cyrillic file were counted as unprintable against a 10% limit. High bytes are simply what non-English text looks like, in UTF-8 and in the older 8-bit encodings banks still export, so they no longer count against a file at all; genuine binaries are caught by their null bytes and control characters, which text does not contain. Reported with a diagnosis and a fix by @ba1amut (#369)
  • "Auto-pay when due" can be switched on while editing a bill. The checkbox needs a pay-from account, and the only thing that worked that out hung off the account dropdown's own change event — but opening a bill fills that dropdown from code, which fires no such event. So every existing bill opened with auto-pay greyed out, however long it had had an account, and the only way to reach the checkbox was to re-pick the account by hand. Creating a bill was unaffected, which is why it went unnoticed. The state is now recomputed whenever the form opens (#370)
  • Editing a bill shared with you no longer strips its category and pay-from account. Sharing is granted per type, so a bill can be shared while the account it pays from is not — and both dropdowns can only list what you are allowed to see. The form silently fell back to "No specific account", and saving submitted that as no account, wiping the setting off the owner's bill; the same went for an unshared category. The real values now stay selected, shown as Unavailable (not shared with you) so it is clear why they cannot be changed, and they survive the save untouched. Auto-pay is also refused server-side when a bill would be left switched on with nothing to pay from — a pairing the create path has always rejected (#370)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignaturexHUL+LrtKQmEHZ8YQwsy+xFaIqzNZrPxOFdHD44Th6v2oSFX5rCCI2kmScHUejaVOt1t0nLiJ2qf5ZSRVvOmPPeeinPhoqGhwYlP0Nkgt8Rb0x1zPZTJj63Na8ESocx7CpajZTDxKc8pAFrQJ+H03K4UDks+/1F0qFF2NYa1soV6+c+fIuMPDaYC+DjO3aeWaJabhTUgUymMmqHLxqlhAyw+a8LJ2ABwYyT8P/rmIQ267T72D8ng0f8/ubS4mvfICaoAbtMA8H5Rnn7/gcPMDv1nJyTv97ShefnigmiykqBSWJsJQE8Ax/RYNfXWJ3Gl9uRxzXigxKYwpGtWMFnE9G2JN/eOh5oG042V5wn1QI0QcfWG2QFilp5uOD6ZVTfyPG+um2Y0FQLFe4PJnxyYpnrXmWglFFMyEVCVa0a7+AJmb7DVfjz/9vhBewTYCJ/j9XDlw8Efu28ZYWtsgZ5vZIlH4a90WalHLWHprUsNLDrUSyl+WRLTWDYDfEviRHJBCrrcz34Zyo8An0+sM9ccQalvH78w4X9PDIL5pMS90MHgyYrXVGyMPqSG65FliBn0qku7pP8wCqUabT9Ac3ofyztTlj0dy+tHyuu0OLPb+FxaLUoCgw5PaOSNSOXgDw8amDnleLNrZjvHIEsoYCS2jXtxU0rrTbmFXi4djM4jyTQ=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.46.0
Release Details
UpdatedAug. 29, 2026, 2:08 a.m.
Changelog

Added

  • A Money Flow diagram shows where the money went. Reports gains a Money Flow type that draws the period's cash as a flow diagram: income categories stream into a central Cash Flow node, which fans out into your expense categories and their subcategories, with what's left shown as a Surplus band — or a Deficit feeding in when spending exceeded income. Amounts label every node, category colors carry through, and the usual period and shared-account filters apply (#366)

Fixed

  • Bills and income shared with you can be opened again. Opening a bill your partner created failed with "Failed to load bill", and so did every action on it: editing, deleting, marking it paid or unpaid, skipping a payment, and the Record transaction repair. Sharing grants visibility, not identity, but each of those looked the bill up as the person clicking rather than as its owner, so the app approved the action and then could not find the bill to carry it out (a DoesNotExistException in the log). Bill actions now run against the bill's owner, so a shared bill behaves like one of your own, and Mark Unpaid is offered on shared bills for the first time. Shared recurring income had the identical fault and is fixed with it, and its Mark received action — which had no permission check at all, only the scoping that made it fail — now refuses a read-only share properly (#368)
  • A transfer between accounts shared with you now completes. Creating a transfer in an account owned by someone else booked both sides and then failed to join them, leaving two unconnected transactions behind every attempt and putting the raw database query on screen as the error message. Both rows belong to the account's owner, while the linking step went looking for them as the person clicking. Linking, unlinking and Create and link now work across shared accounts, and a transaction you cannot reach reports itself as not found — which also means it reaches the log, where this failure left no trace at all (#368)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
Signaturex0J8AUUfQbAJljP4bb8goctxFgu6woboHqgqhSLiZLzSNh4/bgeYYYsy4ubudGRmEAdnJZqL9XcqPKKaaVIxVXVRFVCS24iGpCdqXhCW0MMvoROv7VMao+dHMrfPhungZxdm+nKurDuI2drTpZLmbckIj6+PnjLP0Z6M+a/P7wRw/3gtdHcf1KoNmRGNIlqUUolPhYJJFQbhgsf8yg/nzDMjm0OKXYvOKWSI+GR1HFQoNSLVx9TPk2zrBOT/ARpvDEStnWWBZxhn2shkEVFNE1ntupx4AmkerIySit3CB5j4H7imaHsIYwPHDhL+MEj9afFllpMnogByvQ+nHCvJ3v7PeuNYGgQTxMvoVKpvtPDyo2610eVQDQlK8UEzmOdimk7shlkllXiE/ZEIaeFINp17VuQbYlTwuuZlNfTendUZirhPFK4xR3AL6cpTxJHq/Xc/npPYAYk8wPyYseNnFL5A3/d2UXiT/m57GQiIMkTMrayR6kYmYjGYT2EAVSRjhA0wESnCJb6jVMc6YTcBVQ3uFXnA5gR1hdulx1Qj2lRhJpBSCcXBCl/4QHDv4OIhk4Is5DWUxcw91iuaBhMCpoJLwU+kkuaibIrsiV2L3np7EeZzPtxOsRG4GyCZRyvTvCVO7HVHu///wPi1sfMH4R05Ri0AUfbqdpqPrE70mG0=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.45.0
Release Details
UpdatedAug. 29, 2026, 12:59 a.m.
Changelog

Added

  • Bi-weekly schedules can be anchored to a date. Bi-weekly income, bills and transfers used to lock onto whichever week you happened to create them in — pick "every other Friday" and the app silently decided which Friday from the creation date, with no way to say "no, the other week" (#363). Transfers were worse off still: the form only offered a day-of-month field, which means nothing to a bi-weekly schedule (#364). Income now takes a First payment date for weekly and bi-weekly frequencies, and the transfer form gains the same start-date field bills have had — the date pins both the weekday and the week, and every occurrence lands a clean 14 (or 7) days from it, whether the date you give is in the past or the future. While a start date is set the weekday field follows it and locks, so the form cannot claim a different day than the schedule runs on. Note for existing bills and transfers: a start date you set before this release only delayed the first occurrence; from now on it anchors the schedule, so a weekly or bi-weekly bill with a start date will settle onto that date's weekday and week
  • Bills can be marked unpaid. Marking a bill paid by mistake was final: the Undo button lived in a ten-second toast, and once it was gone nothing could revert the paid state — deleting the payment transaction left the bill still claiming to be paid (#365). Every payment now stores what it changed, so a Mark Unpaid action on the bill reverts the most recent one properly: the due date rolls back, a one-time bill comes back to life instead of staying vanished, a statement-amount bill gets its exact amount back (which cannot be recomputed after the fact), and the payment transactions are cleaned up — including when you already deleted one of them yourself. Auto-paid and import-matched bills get the same revert, which the toast never offered them — a payment that was linked to an imported transaction unlinks it rather than deleting money that genuinely left your bank. Recurring transfers can be reverted too, from the Transfers view. The stored revert applies to the most recent payment only, and editing the bill's amount or schedule discards it — reverting would otherwise restore values from before your edit

  • CSV files without a header row can be imported. The importer always treated the first row as a header and silently ate it — a headerless export lost its first transaction with no way to say otherwise. A First row is a header toggle (on by default, matching the old behaviour) now controls it, columns are matched by position, and blank or duplicate header cells get translated "Column N" placeholders in the mapping dropdowns instead of untranslated internal names. Saved templates keep working: they store your file's real header names where they exist, so they survive language changes and column reordering. Templates saved from files with duplicate blank headers ("Column N (2)") need their columns re-picked once. Contributed by @Saviq (#367)

  • The database-updates warning reaches the admin overview. The check that detects the app's own migrations never having run (the "Unknown column" trap, #333) now registers as a proper Nextcloud setup check, so it appears under Settings > Administration > Overview and in occ setupchecks — visible to the admin who can actually run the fix, not just to whoever next opens the app

Fixed

  • A category drill-down into subcategories now says so. Opening a parent category's transactions (from Category Details or a chart slice) applies the parent plus its subcategories, but the filter panel could only display the parent — and picking the parent to narrow down to just it did nothing. The category dropdown now shows a combined entry like "Groceries + 2 subcategories" for the applied scope, and choosing the plain parent genuinely narrows to it (#361)
  • The bills list stops fetching every dead bill. Keeping paid one-time bills reachable for Mark Unpaid meant fetching the whole bill history and discarding most of it in the browser. The server now returns active bills plus the revertible ones directly, so the payload stays small however old the install (#365)
  • A category's count badge and its panel agree on damaged rows. A row carrying both its own category and split parts (the old bulk-edit damage) was excluded from the tree's count badge but still listed in the Category Details panel — off by one on the same screen. The panel now applies the same rule; Repair Data remains the way to fix the rows themselves (#360)
  • The split flag's grey states are resolved once and for all. Two damaged states have haunted long-lived databases: rows from before the flag existed (held NULL), and rows whose restore claimed they were split while the parts never made it into the old backups (#351). A one-time update resolves every such row from the parts table — the single source of truth — and restores now do the same, so the states cannot return. This fixes three real casualties: rule runs categorize legacy transactions again (they had started skipping every pre-2026 row while reporting success), assigning a category to a damaged row now sticks instead of silently vanishing while the row stayed listed as uncategorized forever, and the Uncategorized filter no longer offers up split parents whose categorisation is exactly how such rows were created (#360)
  • Find Duplicates no longer loses a next-day duplicate at a group boundary. Groups anchor on their first transaction so distinct purchases cannot chain together — but a pair one day apart could straddle two groups and the second copy went unreported entirely. Rows near the boundary are now carried into the next group, so every pair within the window is reported together and the no-chaining rule still holds (#333)
  • A savings goal that has gone backwards shows an empty bar, not a full one. The Savings view's goal list was the last progress bar without the negative clamp the others got in v2.44.2 — withdrawals exceeding deposits painted the bar completely full
  • The Category Trends tile sticks to expense categories. It relied on a side effect of the old one-direction totals to keep income categories out; with netted figures an income category could slip into the spending list. It now filters by category type explicitly
  • The database-updates warning can no longer be silenced by a mid-deploy race. If the check ran at the exact moment app files were being replaced, a failed directory read followed by a successful one within the same page load could record the version as verified while updates were genuinely pending — permanently hiding the banner on exactly the instance it exists for. The verified marker and the pending list now come from the same scan
  • Editing a bi-weekly bill no longer silently shifts which week it falls in. The consistency check that runs on every edit recomputed the due date "from today", so changing an amount or a note in the off week flipped the schedule's parity — the bill quietly moved a week. With a start date set, the schedule now recomputes from its anchor, and an unrelated edit can never move it (#363, #364)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureV/r+TeR/H5y0TiUgo9apV0nHrv4yLWR3o2yHxeSCrwBr87AyJBO6EphcfUm/aNNDYHbJfh2Nk4ghsMvljrNWPCgMFZdwynngNS3IbrSFauamMsnuvkxDcO5h+R5aAIyBfyog9idiDesDMJF2B1dDbe3COOlxDq5i8xiiP+BGqLpoeOYZKT2dpqoaYB9j16sGk5BSE07vSFnF8kz2PGcpgExtfEqMMVCDRGQUvU02KgLqNb6oFx0abf5NhRGTpNZPMyOMwWH0CVTATrZj7r9LBp8+HQqHUjCRqPTwsYbAVBZZKYwyrtU3Wd/4VaSpKW2bMS7OWA/663hc74b0Rt/QTy0brPK2oiQyM6PisiwlZHAz6nuQWRDUiyezWVS9yLBiVDavZxby7XJAIrb49a8dSESUj7/7eRaO9xAb21oULrp39o0d0GKWBxFf2fuV/uBJ/tQh1pgj7n5PHQ01kZ3Dy1znPGH//sIfsw5nBLeKQQGZvcp4ell+s19FJr2SoKe+HgY8Wo/eCobVpai8GbpeA1HsNc7ixuKIPdxpAsY7X/mNg92GEndFExIDBkUgQfbPYd+LkmjlJdtXqluxB24WdVIVdKDJakxk860CHTUo+k7UgVroJUffjXXwXvFKQCWZG8f/5Tt4eh3QpRfaqQGWpAjQ0lw/AURkUdA0FlN4ELo=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.44.2
Release Details
UpdatedAug. 28, 2026, 3:19 p.m.
Changelog

Fixed

  • The Budget page's Spent really does net refunds now. v2.44.0 said a refund comes off what you have spent, and it did — on the budget report, the dashboard tiles, the alerts and the digest. The Budget page itself reads a different query, which kept the old one-direction sum, so the very page the issue was reported against still showed $216.90 where Category Details showed $58.29. That query now nets the same way as everywhere else. A month whose refunds exceed its spending shows the true negative figure instead of being flipped into looking like money spent, and its progress bar sits empty rather than painting full — on the dashboard's Budget Progress tile and the savings-goal tiles too, where a negative used to render as a completely full bar. Changing a category's budget period also refreshes its row with the right direction and the selected month, instead of flipping an income category's Spent to a large negative until the next reload (#361)
  • "View All Transactions" on a category lists the transactions its figures are built from. The button quietly filtered to money-out only (money-in for income categories), so an expense category's refunds were missing from the very list the netted figures above it summarise — the panel said $58.29 and the list it opened could only add up to $216.90. It also ignored the panel's period and account selection, listing everything ever recorded. It now applies no direction filter and opens scoped to the same date window and account the panel is showing (#361)
  • The transaction filters panel shows the filters that are actually applied. Arriving at the Transactions view through a category's "View All Transactions" or a chart drill-down replaced the applied filters but left the panel's controls showing whatever they held before, so the list and the dropdowns above it disagreed — and because any change to one control re-reads all of them, a stale control could silently re-apply an old filter. The panel now rewrites every control whenever the filters are set for you, clearing the ones that no longer apply (#361)
  • The last places that ignored split transactions now count them. A split carries its categories on its individual parts, and five surfaces were still reading the transaction's own category, which a split never has. Year over Year compared a year of split receipts against a year that predated splitting and called the difference a collapse. The Forecast's category trends dropped every split into Uncategorized and showed nothing against the categories the money actually went to. The count beside each category on the Categories page read 0 for a category funded entirely by splits, next to a panel listing its transactions. Find Duplicates showed a dash where the category belonged. And a CSV export with no category filter left the Category cell empty on exactly the transactions someone had taken the trouble to itemise -- it now names them, and a category is named once however many parts of the receipt went to it (#360)
  • Find Duplicates no longer chains separate purchases into one giant "duplicate" group. Each candidate was compared against the previous row added to the group rather than the first, so five identical-amount purchases a few days apart -- a regular coffee order, a repeated fare -- linked end to end into a single group spanning far more than the 3-day window, and the tool told you to delete transactions that were nothing of the sort. A row now joins a group only when it is within the window of the group's first transaction (#333)
  • Deleting a category no longer leaves split parts pointing at it. The delete guard is deliberately blind to splits (a category used only by split parts must stay deletable), but nothing cleaned those parts up afterwards, so they kept referencing a category id that no longer existed. Deleting a category -- with or without reassigning its transactions -- now degrades its split parts to uncategorized, which is what the reassignment already did for ordinary transactions. Find Duplicates also names a split Split now instead of showing a dash (#360)
  • Splits from before the split feature existed are counted once, everywhere. A transaction whose split flag was never written -- imports predating the column, and backups restored from those versions -- was in a grey state: some queries treated it as a split, others as an ordinary transaction, so depending on the screen its money was counted twice, or not at all, or it was offered up for categorisation, which is how a transaction ends up claiming a category and carrying its own breakdown. Every query pair now agrees on one rule -- a transaction with split parts counts through its parts, full stop -- covering the budget carryovers, the monthly report, Year over Year, the forecast, per-account totals, uncategorized listings and rule runs. Restoring a backup now re-marks the transactions that actually received split parts, whatever the archive claimed, and the very large id lists a restore or a year-long report can produce are processed in batches instead of one oversized query (#360)
  • The app now notices when its own database updates never ran, and says so before anything fails. If Nextcloud replaces the app's files without finishing the upgrade, the database changes that came with the new version are skipped. Nothing looks wrong -- reading data does not touch the new columns -- and then the first thing you save fails with a database error nobody can act on. Every page now checks whether any of its database updates are missing and, if so, shows a banner naming how many and the command an administrator can run to finish them. Checking costs nothing once a version has been confirmed complete, and the banner clears itself as soon as the updates are applied (#333)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureDm8DKf6I3AofLr0FMZsDKeE4q19LhQ2NgVNbRwtRNtCcfcpkF7RWros6LUOJacOmyNa9EuRDVUGQJtTGSasNt4dXxhwDjw7hDsmm2NUaTTrnoLoY32V9zyBLZqtSLb30uZTr6O8q03UGO0MsNQr5IsOcNbi7KflfjmUbYY99cIycOm/FBoLBm+LWQlDH+eQZigjqEk5GMvsLgyY2LuYQE6226WS1W96gI3neUzwICij5OWn/hdkl4axB6Y2Ei7bWofiMRSwY4oeiLF1mmgk1C4OfyoZomZEhsytxXok5wt38K4SMQBL4A+zpVoQBp0cBdFrGUynC/eNtmQjS9nsJSs0woZ3H6+QrlMCmJ+PRqSbn5kEO7PBzXMXUYNg9mqd0mUeYjH0mW1SKpF51FsBKjMHNmi1ReNqQhiRAJq+9JzyiaUuCv/gigDXOaLCR5NvRld0RbMYfnWN9XZ18k8/b+oKwzBG/oY6mqmgR0mUl24lXHK7djSHbhfmCIAG6hpOxgrL6cFguUdqNuoCGhBvUaUBJn742J4Hh4Lx4jq+zQJE1rJf4xpNhcT6VKLJNS7DrSd62oPm80FBXSu9colzmlv3C67SDYwL5TxqdM8OCsPTJvH0IWnr9R+qrrPh5MMqy3XMDyYvzDMjiK0OWmzob4ZxMCg2gi1asdtcjd5PqNgU=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.44.1
Release Details
UpdatedAug. 28, 2026, 12:44 a.m.
Changelog

Fixed

  • When the app's update has not finished, the app now says so and how to finish it. If Nextcloud updates the files but never runs the app upgrade, the migrations that add new columns never run -- the app carries on reading fine, because reads do not notice a missing column, and then the first thing you save fails. Until now that surfaced as the database's own words, "Unknown column 'amount_type'", which is accurate and no use to anyone. Any missing column or table now comes with the command that fixes it: occ app:disable budget && occ app:enable budget. Reproduced against MariaDB, where neither occ upgrade (which upgrades the server) nor occ app:update (which looks for a newer release in the app store) does anything about it (#333)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureJfhfoodWHfhncS8NhWVo/wOO4gi2kDEn4S8M8TzZg5Qfbjwxmkmh4Pn294Og1wL1uIp5gbCGyS2aIzcDN0HoEf7DhN98hxRaZ5P5/5CBFLgTGTNwJmDX9A4Xtwk81o4/3jbeLAPUJspX2OkQKGzyNtFqrCi5aDG/JF5D0Yf49WBnYG3BZp5rSaEOmrD2Scm8D3EmE5wDsIIKg+Zl1iCVHsUX/Z7TG6lVzPxeW4JVIU4NX8hhUziOOGMXthSBM5GxZX4okbtfGm9uVeUOe49rT/kXcm7mTG2Xb/4Phywh7vFqMckiOTSwP2fLttq7LFUv0XtUoaOhxjfhFJBdQIDi9qhtJRMcRvXE8kPbswzpyN9W/nC6lv44Q0Bxse967DXVQ8ZoxIWCByl6/5Z4Ooi978d0lWc/HsZYqMX5SXTb3KoALYNCG2+8WfkXwF+kZ0kPc//K6Uh/r+lgO7Gx55xaR2XkmDhClY7u/PMhLOsc0segdjc4obFyHns/iTeKJjV+aEaOvlbNq5aDKioozMZr2vQhL9XfEv4rKLq5VTxaD0s/WOv4dMJxhA/7LRpC53OlPrFN1IKPgmXUS2v2gTtP7fF9eDvZ6u66ra9zTe/j+R7y2y8mMo0zcUMnPPUxJ5fgX5saIPC2svL65fawwwghOMQTiydg6jEmbipPDU38RJQ=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.44.0
Release Details
UpdatedAug. 26, 2026, 12:34 a.m.
Changelog

Added

  • Dashboard tiles can follow your budget period. Spending by Category, Top Spending Categories and Budget Progress gain a Current budget period date range in their gear settings, which tracks the Budget start day you set in Settings. If your money arrives on the 25th, the tile now covers the 25th to the 24th like the rest of the budget surfaces do, instead of cutting your cycle in half at the month boundary. Spending by Category's header chip names the days it is actually showing — "25 Aug – 24 Sept" — rather than repeating the setting back at you. The other tiles are unchanged: a balance-history chart and the income-vs-expenses series cover a span rather than one cycle, so the option is not offered there (#333)
  • Cash Flow Forecast and Year-over-Year now actually draw. Both tiles have been in the Add Tiles menu with a card, a chart area and a working server request behind them — and no code to draw the result, so they sat blank however long you waited. Both are off by default, which is why this went unnoticed. Cash Flow Forecast now plots your projected balance month by month, starting from today's balance so each step reads as a change, with that month's income and expenses in the tooltip; choose Next 3 / 6 / 12 months in its gear settings. Year-over-Year plots income against expenses for each of the last 2, 3 or 5 years, matching the chart on the Reports page so the two cannot disagree (#333)
  • The bills tiles let you choose how far ahead to look. Upcoming Bills and Bills Due Soon now take a Look ahead setting of the next 30, 60 or 90 days. Upcoming Bills previously showed whatever came first with no horizon at all, and Bills Due Soon was fixed at 14 days. Both still include bills up to a week overdue, so an unpaid bill does not vanish from the tile that exists to chase it — Upcoming Bills previously had no such cutoff and would show a bill overdue by months right alongside this week's, and now drops anything more than seven days overdue the same way Bills Due Soon already did (#333)

Fixed

  • "Last 30 days" on a dashboard tile now means the last 30 days. It meant the month so far: on the 24th you saw 24 days, and on the 1st of a month the tile charted a single day. "Last year" behaved the same way — the year so far, so on 3 January it showed three days. This is why a tile could flatly disagree with the budget alerts sitting above it on the same screen, and it hit anyone whose spending does not line up with the calendar month hardest, because the biggest bills of the cycle fell outside the window entirely. Affects Spending by Category, Top Spending Categories and Budget Progress. "Last 90 days" and "Last 6 months" were near enough but drifted by a day around month ends — six months back from 31 March landed on 1 October — and are now exact (#333)
  • Every Date Range dropdown on the dashboard now does something. Ten tiles offered one and ignored it: you could pick a range, it saved, and the tile carried on showing its own hardcoded window. Large Transactions had no date filter whatsoever — it ranked your biggest transactions over all time — and now honours the range. Weekly Spending was pinned to the last 7 days, and its daily average divided by 7 regardless; both now follow the range you pick, and its label — which always read "This week" — now names the range it is actually showing. That default week is now an explicit Last 7 days setting rather than a hardcoded one, so it is both the tile's starting point and a choice you can change like any other range. Category Trends compared this calendar month against last, and now compares the range you chose against the equal-length stretch immediately before it, so the two figures are like for like at any range. Where a range could never apply, the dropdown is gone rather than lying: Monthly Comparison is this month against last by definition, Debt Chart is a payoff projection with no window, and Income Tracking's headline is a monthly rate that cannot vary with one (#333)
  • The Cash Flow Forecast tile was asking the server for the wrong thing. It sent a days value the forecast endpoint does not accept, so the parameter was discarded and the default horizon used every time (#333)
  • When something fails to save, the app now tells you why. Errors across the app showed a fixed message -- "Failed to create bill", "Failed to save transaction" -- whatever had actually gone wrong, so a validation problem and a database problem looked identical and neither was actionable. Where a failure comes from the database the server already attaches a short, sanitised description of it, a missing column for instance, specifically so the cause is visible to people who cannot read their server's log. Nothing in the interface was reading it. That description now appears alongside the message everywhere a save, delete or update can fail -- transactions, accounts, categories, bills, rules, pensions, assets, transfers, income and bank sync (#362)
  • Bills with a statement or minimum-payment amount explain themselves when rejected. Those amount types only work on a transfer pointing at a credit card, and the two rules enforcing that were being replaced by the generic "Failed to create bill" instead of being shown. Genuinely unexpected failures still stay generic (#362)
  • Repair Data can clear the stray categories off your split transactions. The rows the old bulk edit and the rule runs left behind are still there, each claiming a category it should never have had. Settings > Repair Data gains Split Transactions Carrying a Category, listing every one it finds with the category currently stuck to it. Repairing removes only that stray category: the split stays a split, and every part of it is left exactly as it was. Genuine splits, ordinary transactions, and a transaction explicitly marked unsplit are all left alone, and the scan drains to empty once run rather than reporting the same rows forever (#360)
  • Rules no longer break a split transaction by categorising it. A split's categories live on its parts, and its own category is deliberately left empty -- so writing one onto it produces a row that claims a category and carries its own breakdown, which every per-category total then counts twice. Bulk edit was stopped from doing this a while back, but Run rule now and Run group rules write straight to the database and went around that guard, so rules were still quietly creating the damage. A rule now leaves a split's category alone while still applying everything else it does -- vendor, notes, tags and the rest -- so splits stay covered by your rules. The preview and the results list name such a row Split instead of showing it as Uncategorized, which read as a change that was never going to happen (#360)
  • A transaction damaged by the old bulk-edit bug is no longer counted twice. Before it was fixed, "filter by Uncategorized, select all, set a category" wrote a category onto split transactions without removing the parts underneath, leaving rows that claim to be in a category and carry their own breakdown. Nothing has ever cleaned those up, so they are still sitting in databases -- and the queries behind Spending by Category, the Reports charts and the Category Details panel added up both, reporting a split receipt at its full amount plus each of its parts, and counting it as two transactions. A category could therefore show more spending than the transactions underneath it actually came to. Each transaction is now counted once, through its parts where it has them (#360)
  • Budgets count the money you spent through a split. A split transaction holds no category of its own -- its categories sit on the individual parts -- and the query behind every budget figure only ever looked at the transaction's own category. So a receipt split between Groceries and Household added nothing to either budget: the progress bars read low, remaining read high, and the budget report agreed with them. Budget alerts have counted split money since they were added and the spending charts since v2.33.0, so a category could raise an over-budget alert while the bar right next to it showed room to spare. Affects Budget Progress, Budget Breakdown and Budget Remaining on the dashboard, the Budget view, Reports > Budget and its CSV and PDF, the scheduled monthly report email, and the Unusual spending section of the digest along with its notifications. Splits restored from a backup made before v2.41.0, which lost the flag marking a transaction as split, are counted too, and a transaction damaged by the old bulk-edit bug -- which stamped a category onto a split parent without removing its parts -- now counts through its parts rather than dumping the whole receipt into the one category it was stamped with (#360)
  • A refund now comes off what you have spent. Spent on the Budget page counted only money going out, so a bill that was refunded, a returned purchase or a reimbursed expense left the category looking fully spent -- a $216.90 phone bill with $158.61 credited back read as $216.90 spent, and the bar sat at 100% over a $120 budget. It now reads $58.29, which is the figure Category Details has always shown for the same category: the two screens disagreed, and the budget was the one that was wrong. The same net figure now feeds Reports > Budget and its exports, the Budget Progress, Budget Breakdown and Budget Remaining tiles, the budget alerts -- which is what stops a category raising an over-budget alert while the bar beside it shows room to spare -- and the Unusual spending digest, where a purchase you sent back no longer reads as a spike. Income categories are measured by what came in, with anything paid back out subtracted; Reports > Budget was previously asking for money-out on those too, so an income category with a budget reported nothing against it (#361)
  • A split transaction on the dashboard names the categories you sorted it into. Recent Transactions read each row's own category, and splitting a transaction moves the categories onto its individual parts -- so however carefully a receipt had been divided up, the tile called it Uncategorized. It now names the categories the parts went to, with a coloured dot for each and the part-by-part breakdown on hover, the way the transactions list and the account register have since v2.43.1. Where the tile is too narrow for all of them the names run to an ellipsis rather than pushing the amount off the row, and a split that arrives without its parts is called a Split, which is at least true (#360)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureQHxBHmyBaONUhmqkujdb3Z0HaVDO5kl4378wYHWJgtW/QHl6D1QNcKQzzhB2nVoXZz322zCDeUae1eIk3C+EX4X5q2MolNnL9UAL0TvS0oSfQcAtWTFCAO1Z79C1uYbCxM6CUNNrGmZdoZ41ivw9OJQOICFu5nd0RHQ+w25DUCKK0SOEQXWia7LN5o0RnpTwKYxSxQHIb4dajJvbWsW+oibyBkP/yZsbfJRls3Z2zWYvEEnQhWiKTaJC4Ijfz6DgP6U/M9Z5DjhIZgyxPy5OGTOLd9aZl64K3JzcQqKDKJJ8wTDz9iUXb+bCitxDyq0chgLG4tbSyFyK7+aAcWchHZXufXDmPmAsTikDVgc6srYeKyqv2VFpa/IBA1m0GeAzN2KqIRzDbiyttRGgQQ5i2VPH4owiA8un5ak46XVpD+q5Xy/SwEZVmjCY8AZsZePmPvM9gESC+hBy6P5YuNksSar/dD++REsQCeFkCIiqf4y61wyD0WY3qHYF4yDpWzH8vVhbKSMy0x9W1JR3ZUmv0MbidSvgiOwxpPPtWVuPPRDbLKg3ENzv4bq8IK8PzR0t5jHNSFKWu7C1jrJ3gE7yoxJ5zMnsw6v3HJhedy2Jfx2C2EZsZv1XCzaXYxKBr0uaHVcOSn9/4Rn9OXf95th7bgRN6aCrU34M1ELL3RmocKs=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.43.0
Release Details
UpdatedAug. 24, 2026, 1:27 a.m.
Changelog

Added

  • Liability accounts now ask what a positive balance means instead of guessing. Editing a credit card, loan, mortgage or line of credit shows an Amount owed field that takes a plain positive number — the app adds the minus sign — with a separate This account is in credit tick for the case where you have overpaid and the lender owes you. Switching an account between a debt type and a savings type converts the figure for you and shows the resulting current balance before you save. Creating a liability works the same way. The choice is recorded with the account, so an export and restore keeps it (#353)
  • Several CSV columns can feed one text field. Banks often split what belongs together — a merchant column and a details column, say, or a reference spread over two. On the import mapping step, Description, Notes, Vendor and Reference are now checklists: tick every column that belongs in the field and the values are joined with a comma, in the order the columns appear in the file, with blank cells skipped. The same works for those four fields on OFX, QIF and camt files, and a saved import template keeps the whole selection. A single ticked column imports exactly as it always has, so re-importing an overlapping statement still recognises its transactions. Thanks to @Saviq for the feature (#355)
  • Category trees can be exported and imported. The Categories page has Export and Import buttons next to Add Category. Export downloads your whole tree as a readable JSON file; Import takes that file back, or a CSV of Parent > Child paths, shows exactly what would be created before anything is written, and leaves categories that already exist untouched while adding whatever is missing underneath them. Handy for backing up a carefully built structure, sharing it, or having a spreadsheet or an AI assistant draft one and loading it in a single step (#354)

Fixed

  • Editing a loan or credit card no longer turns your debt into an asset. Typing your statement balance as a positive number into the Opening Balance field stored it as a positive number, which the app reads as "the lender owes you this" — so a £5,000 loan quietly added £5,000 to your net worth instead of subtracting it, a £10,000 swing, and every later recalculation re-derived the wrong balance from it. Nothing on screen said so. Positive balances on a debt stay supported, because a genuine overpayment is a real thing, but the app now asks which you mean rather than reading it off the sign. If this already happened to you, Settings › Repair Data will find it: run Scan for Issues and the new Debts Recorded as Being in Credit section lists every affected account with what it reads now and what it will read afterwards — untick any you really have overpaid, and those are recorded as genuine credits and left out of future scans. Two related consequences are fixed alongside it: an account you have overpaid no longer appears in the debt payoff planner as something to pay off, and it no longer counts towards Total Liabilities on the Accounts page, where it was pulling net worth down by twice the credit (#353)
  • An account edit that does not touch the opening balance no longer rewrites the balance. Renaming an account, changing its institution or ticking a checkbox resubmitted the opening balance every time, so an unrelated edit depended on that value round-tripping through the form perfectly. It is now sent only when you actually change it (#353)
  • Reopening a split transaction no longer scrambles its parts, and saving it no longer throws them away. A split of 10 into 1, 3 and 6 came back as 1, 9.00 and 0.00 — the second part had swallowed the rest and the third was empty. The parts were always safe in the database; the editor was overwriting them as it drew them. It fills the last row automatically with whatever is left over, and it was doing that after adding each row, so every stored amount was recalculated away the moment the next row appeared. It now draws all the rows first and works out the remainder once, which is what it should have been doing. If you saved a transaction from that scrambled view, the parts you saw are what got stored — the third one was dropped for being 0.00, quietly, because the total still added up. Worth re-checking any split of three or more parts you edited recently; their categories will have been wrong in reports for the months involved. Splits of four or more parts had a second symptom — Save appeared to do nothing at all, with no message — which is fixed by the same change (#358)
  • Filtering transactions by Uncategorized no longer lists your split transactions. A split transaction has no category of its own by design — its categories live on the individual parts — and the filter was reading that as "not categorised yet", so every split you had ever made turned up in a list meant for things needing attention. Split transactions are now left out of it, and out of the dashboard's uncategorised list and the "only uncategorised transactions" option when running import rules, which read the same way. The bulk-edit consequence is the one worth knowing about: filtering by Uncategorized, selecting all and setting a category used to write that category onto the split transactions caught up in the list, after which they were counted twice in reports — once for the whole transaction and again for each of its parts. Setting a category on a split transaction is now ignored rather than obeyed; unsplitting one still assigns a category as it always has (#356)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignaturelQsdNi/Ed5bU8/Ch8iyHVXKdX+l8qhRm8fCwRYfB/ObxW6pncVobhw57Bzvu/2yio4Wb+MyJ+DZ8T75pZ9+ugVmWX+q/VSLx4PEAmnr9upL0m7AvJN33BXARoFWBzKVFHnfEy/RuYgtxnNfOmoiblZXbAeBs5zyxxeQKrYSMSHfdwdG/t9HZNFNvFEyp7k7XEU1xQ5HaAo6kResw+25vTU/lkvJNXYmNnmWr3ZxUo7qphCOw/ZJU4aMi+g8RjrWIp86biPeM8mIr57Oacrm3fIQnGTgfk7lqX5FGTjhjLTnDKin+AyFQCpkuki47leJ+W4VwS/LvObLDHn/WcYhjmkdmGXTGFZGhVYAHz3VcPklRmERDkafXZ7lPk0tWZjma/W4SCf6u8Pu3Ni5fVeZ9Zp7qiCjNomRBmMl2nlW2EC/GYJAW7c78TM1Gq9qw6EAAweO5/7JMtOMaA4Klm1XKmE6CpDmu6Ox4E0+RiaDZJ6lHnC7JcfNweMtbgZb4tK/1nAXqum2v4vIQcIDpfk2ROqxkvthclKe05z2p1oe2qg/mEWqwx51ZHR0PvMhmNYGh9VVi3F7KiT0v1K6D06CAAOJu6TeJTMKX5asGJ8K2PkVKk0E7uVWGKp7+WRBU4ILvUftG5d8Pz7ChCY35XVwknHbY/Rx7DNno+1h3YzkblIU=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.42.0
Release Details
UpdatedAug. 21, 2026, 9:23 p.m.
Changelog

Added

  • Receipts can be filed wherever you keep your app data. Uploaded receipts have always landed in Budget/Receipts/<year>/<month>/ in your Files; a new Receipts folder setting lets you point that anywhere inside your own Files instead — Applications/Budget, say, to sit alongside other apps' folders. The year and month subfolders are still created underneath, and receipts attached before the change stay exactly where they are: the app never moves or deletes your files. Applies to uploads from the web form, the API and receipt scanning alike (#352)
  • Bank statements in camt.053 XML can now be imported. Many European banks — Swiss ones in particular — export statements as ISO 20022 camt.053 (and intraday camt.052) XML rather than CSV or OFX. Drop one on the Import page and it behaves like an OFX file: every account in the statement is listed with its IBAN, auto-matched to the account of yours carrying that IBAN, and routed there. The parser reads what the payer wrote (the remittance text), who the other side was (the counterparty, which becomes the vendor), the bank's own entry text, and the transaction type code, and a batch entry such as a collective payment is split into its individual transactions with their own counterparties. Duplicate detection uses the bank's own entry reference — more reliable than the CSV content hash — except where a bank stamps the same reference on every entry, in which case the hash is used rather than collapsing the statement into one transaction. Every camt.053 schema version parses, including files with the namespace stripped (#350)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureRhkTM0z3ZXIpnFc2BJ0widME7KmhTp6jnd/kaHn42N1eiC9JQhiDUCGmqbCweHhswB3HBwwBoG37XE5L/9s97L13vmrIT+19EVx+f3o2xHXeVe0J19F0BKOxyW5mKYt7xQqo/dwCQ+qDk06kH89XPta+ppz28+qcfaEnBiEtnnzlyeOqyXgs6qWuM/sZW/WUau5dPKZxfkK57IgPaBIfx/R8cttcyokpplD5kV+rmGz8+AvAbvqcT06aGCzjQQtK4/ADbBe7PiGxy7Yy64B9LhgphkHuXqk1hzJiuC0exn+8z02QXGq5g2nDbATK6ZF6n6v6wIrSnEZtvRBvd2rloAQe5K5aiP6Ae6TPyILrunKGTL7Je1d/sqWO+103WdwcfLSI2rYHM00CUOdmxRttecjkJvc+sarc7m1M+fFIePC4SC5RlKJin/v9tUf/m+ie0+/UvqrcReF6hjCfN7jp8LBNjJQGsbpOBm+WO6v2i5GSKV/vNWLw4qln0rQXobu0jdSIhraqes84wPmF1z7U/eQorqmB9Q+ig4mfTtR3zxVfcd6vVT5fseiDTVhbaLf144zLTSxWpgVscFSQitXsVnA3FHkHuXsy8OqYeGgtQHOPjwMocSN1udnp59Wth/jd6qxj9Gf9KjFYFi/fwjc+QcvHaTuGCycDo+4xny+evpE=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.41.0
Release Details
UpdatedAug. 19, 2026, 10:30 p.m.
Changelog

Added

  • The Help & Docs page now says how to support the project. A small section with the GitHub Sponsors and PayPal links — the same ones listed on the app store — for people who installed the app and never see either. The floating help panel carries the links too. Nothing nags: it sits in Help, and the app works fully without donating
  • A recurring transfer can now pay a credit card the way the card itself would, with the amount resolved fresh at every payment. Card payments have always been representable as recurring transfers, but only at a fixed amount — useless for a bill that is different every month, which left people faking it with duplicate bills or typing the figure in by hand each time. A transfer whose destination is a credit card (or line of credit) now offers an Amount type choice mirroring what card issuers offer: Fixed amount as before; Statement balance, which pays what was owed as of the due date — everything charged since the previous due date plus any remainder an underpayment carried forward, with later charges rolling to the next statement; Current balance, which clears everything owed at the moment of payment; or Minimum payment, which pays the minimum set on the card's account (never more than is actually owed). The figure is worked out from the card's own ledger when you mark the payment made (or auto-pay makes it), so it is never stale; the amount shown on the transfer between payments is the last one resolved, and the pre-booked next occurrence carries it as the forecast estimate. Reminders, the bills calendar and auto-pay all work unchanged, because the payment is an ordinary recurring transfer. The card's own account page joins in: a Statement due day field on credit-card and line-of-credit accounts records which day of the month the payment falls due — shown on the card's page as account information in its own right — and a Set up payment button appears on a card with no payment transfer, opening the form pre-filled with the card and that due day. Once a payment transfer exists, the page shows when the next payment is due (#347)

  • Subscribing to hosted receipt scanning, and managing that subscription, now happen from the settings page. With the Otherworld relay selected as the scanning provider, the admin settings show the plans with a Subscribe button that opens Stripe checkout in a new tab — the licence key is shown once after payment, emailed as a backup, and pasted into the field above. Once a key is saved the block flips to a Manage subscription button: your server asks the relay for a billing-portal link tied to that key, so changing plan, updating the card or cancelling needs no separate account and the key itself never reaches the browser. A hand-issued key (a trial, or one minted directly) is told plainly there is no subscription behind it rather than being bounced off a portal that would refuse it (#537)

  • A CSV export of every transaction you're looking at, not just the page on screen. The account Export button built its file out of the rows the browser had already loaded, so it silently stopped at 50 — a year-end export of 800 bookings produced a file of 50 that looked complete, which is worse than an error. The export is now built on the server from the same filters the view is using, so it covers the whole result set however many pages that is. The Transactions page gains its own Export button too, which with no filters set means every booking across every account in one file: previously the only export was per-account, so a club treasurer with three accounts had to stitch three files together. Filters still apply, so you can export one category, one date range or one tag set just as easily (#344)
  • The exported CSV now says which way the money went. Amounts carry a sign — expenses negative, income positive — so the Amount column totals correctly the moment you drop it into a spreadsheet, rather than adding your outgoings to your income. The Type column reads Income and Expense instead of the stored debit and credit. Transfers between your own accounts appear as they always have, one leg of each, which now means they cancel out in the total instead of inflating both sides. The file also gained Vendor, Account, Currency, Reference, Notes and Status columns — enough to do the books from without opening the app (#344)
  • A new Income & Expenses report, for the year-end job of showing what came in and what went out. Pick it under Reports and you get two tables — income by category and expenses by category — with each side's own total and the net between them, over whatever period you select. It exports to CSV and PDF like every other report, the CSV keeping the two tables as separate labelled sections so a treasurer's spreadsheet can take them straight. Like the other reports it respects accounts and categories you've marked as excluded from reports; unlike the transaction export, which is a plain ledger of what you filtered (#344)
  • The Belarusian ruble (BYN) is now one of the currencies you can pick. It appears wherever a currency is chosen — the default in Settings, an account's currency, a manual exchange rate — and amounts are written with the symbol after the number (1,234.56 Br), as they are in Belarus. Its daily rate is fetched alongside the other fiat currencies, though the historical series is not: the 90-day history comes from the ECB reference rates, which don't cover BYN, so a converted figure for a past date falls back the same way it does for any other currency the ECB doesn't publish (#343)
  • The API can split transactions, so capture apps can categorise receipt items too. POST /api/v1/transactions/{id}/splits sets the parts of a transaction, and POST /api/v1/transactions now takes an optional splits field so a phone can record the transaction, attach the photo and set the per-item categories in a single request. /api/v1/ocr/extract additionally reports the receipt's subtotal and tax, without which a client could not make the items reconcile to the total — splits must sum exactly, and most receipts print tax on its own line. GET /api/v1/capabilities gains splits_available so a client can gate its per-item screen on a boolean rather than parsing the version. All four are additions: no existing field was renamed or removed, so clients built against the previous shape are unaffected
  • Receipts with loyalty savings can be split too. A Clubcard, coupon or multibuy line means the items on a receipt legitimately add up to more than you paid — and that gap used to make the whole receipt look misread, so it was refused for splitting and flagged with a mismatch warning. The savings are now read from the receipt and become their own line in the split, at the printed amount but negative, exactly as tax gets its own line. Four shapes now reconcile: items alone, items plus tax, items minus savings, and both together. The mismatch warning still fires when the gap is genuinely unexplained, which is the case it exists for. Two robustness details, because the reader is a vision model that occasionally slips: when it under-reads the savings by a line, the server closes the gap from the printed total so the receipt still splits rather than being refused over a saving it half-missed; and an impossible negative tax or subtotal from the reader is dropped rather than trusted into the arithmetic
  • Turn a scanned receipt into per-item splits. After a scan, if the items on the receipt add up, the scan box offers to split the transaction into one line per item so each can carry its own category — useful when one shop trip covers groceries, household and a treat. Where the receipt prints tax separately, the tax becomes its own line at the printed amount rather than being smeared across the items, so every figure still matches the receipt in your hand. The offer only appears when the arithmetic actually reconciles (items alone, or items plus tax, equalling the total); a receipt with a discount line or an unreadable item is left as a single transaction instead of producing splits that would be rejected on save. Splits carry categories, not tags — tags remain per transaction
  • Receipts are filed by month and named after the transaction. They now land in Budget/Receipts/2026/08/ rather than one folder per year, and an uploaded photo is named 2026-08-05 The Corner Deli 23.77.jpg instead of keeping whatever the camera or capture app called it (often a UUID). That sorts chronologically in the folder and makes a receipt findable by shop or amount in Nextcloud's own search. Existing receipts are left exactly where they are. A file attached from your own Files keeps its name — it's your file, and renaming it isn't ours to do
  • Receipts can now be attached while you are still adding the transaction. The Receipts section used to appear only after saving — the attach endpoints need a transaction id — so adding a purchase with its receipt meant save, reopen, attach. Files you choose (or pick from your Files) are now held and listed with an "on save" tag, then attached the moment the transaction is created. If one fails to attach, the transaction is still saved and you are told which — re-submitting would only have duplicated it
  • Scan a receipt straight into the transaction form. When your administrator has set up receipt scanning, the Add Transaction dialog gains a drop zone: drop a photo on it (or click to pick one) and the date, amount, merchant and a suggested category are filled in for you to check. The photo is attached to the transaction when you save, so a receipt is one action rather than three. The box tells you exactly which fields it filled, how many items it read, and whether those items add up to the total — nothing is saved until you press Save, so a bad read costs a retype rather than a wrong record. Scanning also works when editing an existing transaction, where it only fills fields you have left empty: a scan is a suggestion, never an overwrite. The whole section stays hidden on servers with no OCR provider configured, rather than offering a button that cannot work
  • Receipt scanning can be configured from the command line: occ budget:ocr. Run it bare to see which provider is set, whether a key is stored, and — the useful part — whether the server can actually serve a scan right now. occ budget:ocr set --provider=custom --endpoint=… --model=… changes it, and --api-key-stdin reads a key from a pipe so it never reaches your shell history. It matters that this exists rather than reaching for occ config:app:set budget ocr_…: the raw config route looks equivalent but skips the provider and URL validation, and would store your API key in plaintext, since the encryption lives in the app rather than in Nextcloud's config layer. The command takes exactly the same path as the settings page, so a rejected value changes nothing and a key is always encrypted
  • A CSV column can now be mapped to a transaction's Notes. Bank exports often carry a line of extra information — a payment reference, a booking note, the counterparty's message — that belongs in neither the description nor the reference field, and until now it was simply dropped: the only way to keep it was to edit every imported transaction by hand. Notes now sits in the column mapping alongside Description, Vendor and Reference, and whatever you point it at is stored on the transaction. It also earns its own column in the import preview whenever something is mapped into it, so you can see you picked the right column before anything is written, and it can be saved in a template like every other mapping. Over-long values are truncated to what the field accepts rather than being imported into a transaction you could no longer edit (#340)
  • The API can now read a receipt photo into a draft transaction. POST /api/v1/ocr/extract takes a photographed receipt (JPEG, PNG or WebP) and returns a draft for the user to confirm: merchant, date, printed total, line items, and — on the vision-model providers — the currency when one is legible; nothing is recorded until the client saves it through the ordinary create call, so retrying costs nothing but another scan. The reading is done by whichever OCR provider the administrator configured (below); failures carry a stable machine code (ocr_not_configured, ocr_quota_exhausted, ocr_extraction_failed) so a client reacts to what happened rather than parsing prose, and ocr_available on the new GET /capabilities reports the real state so clients hide the flow instead of hitting the error. A category is suggested by running your own categorisation rules against the extracted merchant — computed on your server, so the provider sees the image and nothing else, ever. When the line items don't add up to the printed total the draft says so rather than silently trusting either side. Documented in the REST API guide and the OpenAPI description (#533)
  • Recording a transaction over the API is now retry-safe, and can carry the receipt with it. POST /api/v1/transactions accepts an optional idempotency_key: a client that times out on mobile data cannot know whether its POST committed, so a repeat of the same key within a week answers with the transaction the first attempt recorded instead of inserting a duplicate — the single most damaging failure a capture client can produce, closed server-side. The same call now takes an optional photo part, recording the transaction and attaching the receipt in one request, plus a merchant field and a type that defaults to money-out. A new GET /transactions/recent returns the newest activity flat and merchant-first for a capture app's glanceable list. Wire field names across v1 settled on snake_case (account_id, parent_id, line_items) before anything ships against it
  • Receipt scanning can now be set up, and it is off until you do. A new Receipt scanning block in Settings → Admin Settings chooses which OCR backend reads a photographed receipt: this Nextcloud's own configured AI provider, any OpenAI-compatible endpoint — a vision model on your own network is a first-class option, not a footnote — or Otherworld's hosted relay with a license key. The choice is server-wide and an administrator's to make, because it decides who else sees your receipts. Until one is chosen the app sends receipt images nowhere at all: there is no default backend and no fallback. Your server makes the request rather than your phone or browser, so an API key never leaves the server and a backend that isn't reachable from the internet works perfectly well. Keys are stored encrypted and are never shown again after saving — leave the field blank to keep the stored one. Only the image is ever sent; account names, balances and other transactions are not. The Receipt Scanning guide sets out exactly what goes where for each option. With the API endpoint above, scanning works for capture clients as soon as a provider is configured; the scan button in the web interface arrives in the next release
  • A documented REST API, so Budget can be reached from outside the web UI. A versioned, read-and-capture API now lives at /ocs/v2.php/apps/budget/api/v1 — list your accounts and categories, browse and filter transactions, record a new one, and attach a receipt photo to it. It authenticates with an ordinary Nextcloud app password (or a token from Nextcloud's Login flow v2), so there is no separate credential to manage and revoking the entry under Settings > Security cuts off whatever was using it. That makes a phone capture app, a shell script or an n8n workflow a matter of configuration rather than code — the REST API guide has worked examples, and a machine-readable OpenAPI description ships with the app. Version 1 deliberately stops at reading and appending: editing, deleting and everything else stays in the web UI, which keeps the contract small enough to hold still. Fields will be added to it, never removed or renamed. Every amount crosses the wire as an exact decimal string ("42.50") rather than a JSON number, so a client cannot lose a penny to floating point on the way in or out. Note this is quite separate from the internal endpoints the web UI calls, which follow the database and change without notice
  • The accounts page can now be tailored to what you actually want to see. A gear button next to the tile/list switcher opens display settings for the page. Tick which attributes appear on each account — account type, institution, (masked) account number, last reconciled date, converted balance, and, on tiles, the 7-day balance trend and the status dot. Drag those same attributes into the column order you want for the list view (Alt+/Alt+ does it from the keyboard); name and balance can be moved as well, they just can't be hidden. And choose how accounts are ordered: by name, balance, type, institution, last reconciled or date added, ascending or descending. Tiles follow the same attribute order as the list columns, hiding an attribute drops its column so the rest can spread out, and everything is remembered in your browser alongside the tile/list preference
  • Categories can now be left out of budgeting without being left out of everything else. A new Exclude from budgeting checkbox sits alongside Exclude from reports on a category. Where the reports flag removes a category from all spending figures, this one is budget-only: the category keeps counting in reports, the dashboard, insights and every total, and simply drops out of the Budget page, the summary cards, budget alerts, the budget vs. actual report and envelope rollover. Meant for spending you want to see but can't sensibly budget — gifts, medical bills, home repairs — so you stop being told you're over budget on a figure you never set. Excluding a parent excludes its subcategories too, and like the reports flag it stays with the owner on a shared category
  • Select every transaction matching the current filter, not just one page. Ticking the header checkbox on the Transactions list now offers "Select all N matching transactions" when more rows match than fit on the page, so a bulk delete or edit can cover thousands of rows in one go instead of 250 at a time. The selection is dropped if you change the filter, so a mass action can never silently include rows you're no longer looking at, and bulk deletes of many rows are much faster (the account balance is recomputed once per account instead of once per row) (#336)
  • A Help & Docs page, in the app. The sidebar's Help & Docs entry used to throw you straight out to GitHub. It now opens a real page listing every guide with a one-line summary, a shortcut to the keyboard cheat sheet, the Quick Add page URL, and the System Info panel for pasting into a bug report. The floating ? button still gives you the short version for whatever page you're on, and now links through to the full page

Changed

  • A saved OFX/QIF template now remembers your field mapping as well as your account routing. These templates stored the routing only, so a bank that puts the payee in the memo had to have Description and Notes re-pointed on every single import — the choice was silently reset to the format defaults each time. Picking a saved template now restores both. Templates you saved earlier carry no mapping and are unaffected: their routing applies exactly as before and the mapping keeps the defaults (#340)
  • A reference longer than 100 characters is now refused when you type it, instead of failing when it is saved. The field was validated against a 255-character limit while the database column holds 100, so anything in between passed every check and then broke on the way to disk — a clean "too long" message is a better outcome than a server error. Nothing already stored is affected (#340)
  • A rule condition saying an import source is not something will start behaving differently on OFX and QIF imports. Because those imports never recorded a source at all, a negated Import Source condition matched every row from them; now that they do record one, it is evaluated for real. If you have a rule along the lines of source is not "Bank Sync", check it still does what you meant on your next OFX or QIF import (#338)
  • An import rule that sets notes "only if empty" no longer fires on OFX rows that carry a memo. With the memo now kept in the transaction's notes (above), the field is genuinely no longer empty on those rows, so an if empty rule correctly leaves it alone; an append rule adds to the memo rather than replacing it. Rules set to always overwrite are unaffected (#338)
  • The bill, transfer, savings goal, debt scenario, pension, asset and contact dialogs now use the same layout. Each was a narrow single-column form that had to be scrolled; they are now laid out in columns sized to what they actually hold — three for a bill (Bill, Payment, Schedule) and a debt scenario (Scenario, Payments, Debts), two for a transfer, goal, pension and asset, and a compact single column for a contact. Everything in them is visible at once, with Save and Cancel pinned below the fields. A bill's split rows span the full width of the dialog rather than being squeezed into a column, and a pension shows the pot fields or the income fields depending on its type, without leaving a gap where the other one would be
  • The four tag dialogs now match the rest. Add Tag, Edit Tag, Add Tag Set and Edit Tag Set are two-field dialogs, so they stay compact rather than being stretched into columns — but they pick up the same chrome as the bigger dialogs: a rule under the title, and Save/Cancel on a divided bar at the bottom right instead of loose against the left edge
  • The category dialog gets the same treatment. Naming fields (name, type, parent, colour) sit under Details on the left, the two exclusion options under Options on the right, and Tag Sets spans the full width below them — no scrolling, and the two checkboxes now read as ordinary checkbox rows instead of a bold heading with a stray box floating above it
  • The transaction dialog gets the same three-column desktop layout as the account dialog. Adding or editing a transaction was a 500-pixel-wide strip roughly a screen and a half tall, with a line of help text under every field restating its label. It is now laid out as Transaction (date, account, type, amount), Details (description, vendor, category, split toggle, tags) and Extras (receipts, notes, exclude from forecast), all visible at once with nothing to scroll for. Switching on Split across categories opens the split table across the full width of the dialog instead of squeezing it into a narrow column
  • The account dialog now fits on one screen. Adding or editing an account meant scrolling through roughly two screens of form in a narrow 700-pixel strip — eighteen fields, most of them empty, each with a line of help text underneath repeating what its label already said, and the Save button stranded at the very bottom. The dialog is now laid out for a desktop screen: three columns — Details, Banking, and Rates & limits with Advanced beneath it — showing every field at once with nothing to scroll for and nothing hidden. A column block with nothing to offer your account type, such as rates and limits on a Cash account, doesn't appear at all; Save and Cancel are pinned below the fields; the help text that merely restated its label is gone; and the current balance is shown as the calculated figure it is rather than a text box you can't type into. The columns reflow to two and then to a single stack on narrow windows and phones
  • The documentation has a home of its own: budget.otherworld.dev/docs. Every link that used to send you to raw Markdown files on GitHub — the in-app help panel and Help & Docs page, the README, the install guide and the app store listing — now opens the rendered site, which is searchable and readable on a phone
  • The Settings page is tidier. The Save Changes / Reset All to Defaults buttons were stranded in the middle of the page, with the Quick Add Page and System Info sections stuck below them, and Danger Zone was not the last thing on the page. Sections now run in a sensible order, with Admin Settings and Danger Zone at the end and the buttons at the very bottom. Quick Add Page and System Info have moved to the new Help & Docs page, since neither was a setting
  • The action buttons on an account row in the list view no longer sit flush against the last column

Fixed

  • The backup now actually contains your data — all of it. The export/import zip under Settings → Migration carried only categories, accounts, transactions, bills, import rules and settings; everything else silently vanished when moving servers. Reported for tags (#351), but the full list of what a migration used to lose is sobering: tags and their assignments, tag sets, transaction splits, recurring income, savings goals, assets and their value history, pensions with contributions and snapshots, per-account interest-rate history, manual exchange rates, import templates and remembered account links, saved reports, net-worth and budget history, reconciliation history, debt payoff scenarios, muted categories, shared-expense contacts with their shares and settlements — and on transactions, the links joining transfer pairs (so every transfer fell apart into an income and an expense), bill references, the split flag, and reconciliation/pension links. All of it now exports, and imports with every cross-reference remapped to the new server's ids. Old backups still import exactly as before; new backups are format 1.2.0. Deliberately still excluded, and now stated in the archive's manifest: bank-sync connections (provider agreements are instance-specific and must be re-established), shares with other users (they reference people on the old server), receipt files (stored in Nextcloud Files, not in the app), and the fetched exchange-rate cache (your manually set rates are included)
  • Marking a recurring transfer paid no longer loses the deposit half of its pre-booked transactions. When a transfer had its next occurrence pre-booked as a scheduled pair, marking it paid cleared the withdrawal leg but deleted the deposit leg — the source account paid out and the destination account never received the money, quietly understating it by one payment each cycle. Both legs of the pair are now cleared together. Payments already recorded this way are missing their deposit; the Convert to transfer action on the surviving withdrawal recreates the other half
  • Transfers no longer count as income and spending in the analysis reports. The dashboard's income and expense totals have left transfers between your own accounts out since 2.28.0, but the Reports page never got the same treatment: a £500 transfer appeared as £500 of income in Income Analysis (grouped by month, source or category) and £500 of spending in Expense Analysis (by month, vendor, account or tag) — and in the new Income & Expenses report only the incoming half was counted, overstating the net by the full amount moved. Every report view now excludes linked transfers, matching the dashboard, so shuffling money between your accounts changes no report figure. Two things are unchanged by design: a report filtered to a single account still shows that account's own transfer legs, because the money genuinely entered or left it; and only transfers the app knows to be transfers are excluded — ones created with the Transfer type, recurring transfers, and rows joined with Match transfer. Two unlinked rows entered by hand still count as ordinary income and spending (#349)
  • "Use Default Categories" failed with "A category with this name already exists" whenever any default was still present. The button seeds the whole catalogue in one go and gave up on the first name it found already taken — creating nothing at all. Easy to hit without doing anything odd: the category list shows one side at a time, so emptying the Expense view put the button on screen while the Income tree still existed in full, and pressing it failed on Income before a single expense category was created. Seeding now fills in exactly what is missing — an existing category is kept as it is, its missing subcategories are added underneath it, and everything else is created around it — so the button always finishes what it can instead of refusing the lot. A double-click while the first request was still running could also race itself into duplicates; the button now ignores the second click (#348)
  • Amounts in Kazakhstani tenge were shown with the code rather than the symbol. KZT was selectable and priced correctly, but it was missing from the front-end's symbol table, so every figure came out as KZT1,234.56 where the rest of the app would have written ₸1,234.56
  • Envelope budgets ignored everything you spent in a category's subcategories, so the whole budget rolled over untouched. The carryover looked for spending filed against the budgeted category itself and nowhere else. Budget €300 on Groceries and file the receipts under Groceries › Supermarket — the ordinary way of using subcategories — and it found nothing to subtract: July carried the full €300, August carried €600, September €900, growing by the untouched budget every month. The same screen said so in two contradictory ways, because the Groceries row itself has always added its children up: "spent €250 of €300" sat directly beside "+€300 carried". An envelope now covers the whole branch — the category and everything filed underneath it — so the amount carried forward is the leftover you'd work out by hand. A subcategory with its own envelope still keeps its own chain and is left out of its parent's rather than counted twice. Subcategories stay out of a parent's envelope when you've excluded them from budgeting or from reports, when they budget on a different period (a quarterly amount can't be added to a monthly envelope), or when they're income categories — and so does anything filed underneath those. Budget alerts and the budget-vs-actual report read the same corrected figure. Nothing was stored wrong: the carryover is recalculated from your budgets and transactions every time it's shown, so the numbers correct themselves as soon as you update (#341)
  • Envelope budgets also ignored anything you spent in a shared account, with the same result. The two queries the carryover uses to total up spending were scoped to the accounts you own, while every other budget figure on the page is scoped to the accounts you can see. So a category you fund out of an account shared with you looked untouched to the envelope: the full budget rolled forward each month, next to a row that correctly showed the money as spent. Budget alerts had the same split — they now measure spending over the same accounts as the budget they compare it against, including their split transactions (#341)
  • A long CSV column could import a transaction you were then unable to edit. Text taken from a CSV was stored exactly as the file wrote it, with no regard for what the field can hold. A notes column over 2,000 characters — easy to hit with a bank that packs a whole payment reference into one cell — imported perfectly happily and then failed validation the moment you opened that transaction, so no change to it could be saved until you shortened the note by hand. Over-long Vendor and Reference values were worse on MySQL and PostgreSQL: the row was rejected outright and counted as an error rather than imported. Imported text is now truncated to the field's limit, exactly as OFX and QIF imports already were, and leading or trailing whitespace is stripped rather than stored (#340)
  • "Check the server log for details" pointed at a log with nothing in it. When rows failed to import the warning told you to look in the server log, but the import never wrote there — the only record was in the browser's developer console, which is not where anybody was being sent. Failed rows, unresolvable accounts and balance recalculation failures are now logged properly with the row number and the underlying error (#340)
  • The column mapping step never highlighted the columns you had mapped. Each mapped column was supposed to be marked in the preview table underneath; the highlight was looked up by column position while the mapping holds column names, so it silently matched nothing and no column was ever highlighted for any ordinary CSV (#340)
  • A transaction added "today" could be filed as a future payment and left out of the account balance. Whether a date counts as future was decided using the server's calendar, but the date comes from yours — the web form pre-fills your device's date, and a capture app sends the phone's. Whenever your local date ran ahead of the server's, everything you recorded was quietly marked scheduled, and scheduled transactions are deliberately excluded from the balance: you added a purchase and the balance did not move. On a UTC-hosted Nextcloud that is the hour after midnight for anyone in British Summer Time, and most of the working day for anyone in Australia or New Zealand. The date is now judged in your own timezone (the one Nextcloud already knows from your session), falling back to the instance's configured timezone, so today is today wherever you are — while genuinely future-dated payments are still scheduled and still stay out of the balance until their date arrives. Transactions already misfiled this way corrected themselves within a few hours through the existing scheduled-transaction job; nothing was lost
  • QIF import has never worked: it reported rows in the preview and then imported none of them. A QIF file's accounts are matched to yours by an identifier the QIF parser never actually produced, so every account in the file was skipped — the import finished reporting success, with zero transactions added and no error to explain it. Underneath that, the parser had no notion of where it was in the file: an !Account header block was read as though it were a transaction (importing a row dated with the account's description), and because a real Quicken export opens with its category list, that whole list was read as an extra account containing one bogus transaction per category. Accounts are now identified by their name in the file, !Account blocks set the account's name, type and description as they should, and the sections that never held transactions — the category list, classes, memorised payees, security prices — are skipped instead of being imported as data. A file that does not name its accounts shows them as Account 1, Account 2 in file order. Dates are also read properly now: Quicken pads them to a fixed width (12/ 4'98), which nothing recognised, and a date that cannot exist — a 13th month — was passed to the database as text rather than being rejected (#338)
  • Import rules could not match on "Import Source" for OFX, QIF or any non-CSV import. Only CSV imports recorded where a transaction came from, so a rule condition on Import Source was silently false for every OFX and QIF row — and, because an unknown field inverts under a NOT, a rule saying source is not … fired on all of them instead. OFX and QIF imports now record OFX Import and QIF Import, joining the existing CSV Import, Bank Sync and Toshl, and the values are listed in the rules guide. Note the source describes how a transaction arrived and is not stored on it, so this criterion still matches nothing when a rule is re-run over existing transactions — the guide now says so (#338)
  • The column mapping did nothing at all on OFX and QIF imports, and the memo was thrown away. Every field in the mapping step could be changed and none of them had any effect — the import silently ignored the mapping and always took the description from the OFX name field. Banks that put the real payee in the memo instead (a common Canadian pattern) had no way to import a usable description, and the memo itself was parsed, shown in the preview, and then discarded rather than saved anywhere. Worse, a statement whose entries carry only a memo and no name imported with a completely blank description. Now: Description, Notes, Vendor and Reference can each be pointed at any field the file actually contains, the memo is kept in the transaction's notes by default, and a missing name falls back to the memo instead of importing nothing. Date, amount and type come from the file's structure and are no longer offered as mappable, along with the income/expense, account and currency columns that these formats never had — those dropdowns are gone rather than left on screen doing nothing (#338)
  • The import preview showed every amount as a plain positive number, whichever way the row was going. The preview is sent each amount unsigned with the direction alongside it, and it drew the number while ignoring the direction — so a statement of nothing but expenses previewed as a column of figures indistinguishable from income, and the step whose whole purpose is to be checked before anything is written could not show the one thing most worth checking. Amounts in the preview are now signed and coloured: an expense reads -€91.29 in red, income €500.00 in green, and the column is right-aligned so the figures line up. What was imported was correct all along — only the preview was silent about it (#339)
  • A negative amount written any way other than a leading hyphen imported as income. Only -1234.56 was understood; every other notation had its sign thrown away with the currency symbols. That covers a trailing minus (1.234,56-, as written by a number of German and mainframe exports), brackets ((1,234.56), the accounting convention several US and UK banks follow), and a typographic minus or dash in place of an ASCII hyphen. A trailing minus was the worst of the three: left on the end of the number it also pushed the decimal separator out of place, so 91,29- imported as income of 9,129.00 — a hundred times the real figure, on the wrong side of the ledger. All three now import as expenses, and a lone - in an amount column still means "nothing here" rather than a negative. If you have already imported a file with trailing minuses, re-importing it will add the corrected rows rather than recognising them as duplicates, because the rows that went in were keyed on the wrong amount (#339)
  • Dialogs on the Assets, Pensions, Savings Goals, Debt Payoff, Tags and Import pages opened behind the sidebar. Fourteen dialogs — including Add Asset, Add Pension, New Scenario and Add Savings Goal — were written inside the page content area, which Nextcloud paints as its own layer. A dialog can never rise above the sidebar from in there, however high its own stacking order is set, so it appeared cut off behind the app navigation. They now sit alongside the dialogs that always worked, and cover the whole window like the rest
  • The remove button on a split row sat under the Description box instead of beside it. The row's Description input was written without its closing bracket, so the browser swallowed the tag that should have ended the field and folded the remove button into it — the row's fourth column stayed empty and the ✕ dropped onto its own line. It now sits at the end of the row where it belongs
  • A mapped Type column is no longer ignored, so unsigned exports stop importing as all income. Mapping a Type column (Expense/Income, Debit/Credit, DR/CR, Withdrawal/Deposit, …) had no effect: the direction was always taken from the sign of the amount. Files that write every amount as a positive number and state the direction in a separate column — Nextcloud Tables exports, and a number of banks and budgeting apps — therefore imported every single row as income, quietly moving the balance the wrong way by twice the amount. The mapped column now decides the direction; rows where it is blank or unrecognized still fall back to the sign (#333)
  • The import preview now warns before a batch goes in the wrong direction. Two new warnings appear above the preview summary: one when a mapped Type column is blank or unrecognized on some rows (naming how many), and one when nearly every row would be booked as income into an account whose history is nearly all expenses, or the reverse. Neither blocks the import (#333)
  • Every transaction showing "Unknown Account" after restoring a backup. Restoring a backup gives every account a new id, but a page that was already open kept the old ones, so nothing in the ledger could be matched to an account and the whole Account column read Unknown Account — with nothing in the browser console to explain it. The same happened in any second tab left open during a restore. The transaction list now notices that it is holding a stale account list and refreshes it by itself, and a restore finishes reloading its data before reporting success (#333)
  • A failed accounts request no longer blanks the Category column too. If the accounts request failed while the app was loading, the rest of the load was abandoned as well, so both the Account and Category columns fell back to Unknown Account and Uncategorized behind a generic "Failed to load data" message. The two lists now load independently, and the message names which one failed and says to reload the page when an expired session is the cause (#333)
  • Select all now counts during reconciliation. In a reconciliation session, the header select-all checkbox ticked the row checkboxes visually but the Ticked total and Difference didn't move, and the ticks never reached the server — so they were also silently lost when leaving and resuming the session. Select all now registers every row it ticks (or unticks) with the session exactly like a manual tick, and no longer wipes ticks made on other pages of the list (#337)
  • Deleting an account that still has transactions now offers to delete them too, instead of failing with an unhelpful message. The delete failed with "Failed to delete account: Failed to delete account" — the real reason (the account still has transactions) was being replaced by a generic message on its way to the browser. The prompt now says how many transactions the account has and offers to remove them along with it, which makes a bad import easy to undo; decline and nothing is deleted. Transfers pointing at the deleted transactions are unlinked, leaving the counterpart in the other account intact (#336)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureBbOGARv5bo0EfD87OHApDK4LSAVbklBnbu7Q0XNAXlA/b120kU9X1ByNzLNwChmoeOLSrKp+saviED0SZkaaD2VdC6KM+2NghhWl/8RsDzdjLnUS5mbhQ04KOXOClJ1iHzwKIRJvAkStGLPAP/McI7ol6QLHi3ABWXWDlBcT6bGKDC6v7cmbh9jOeoys4phwH0uJE9pOVlQg7SfHGd/VJKr6pcScapT9P5dOBj878vpqjYSc3KIFvQ5OfA9C836sCseYxi9jM8YPoaw+LzTfX5/t80Fv5I2woXsvXnwtjijARCotyD1uZ9QMAy7M5LLkEm6yUGjJYrEBMBpc3h8fiC7muLojTK+J9O7zk7oYNN8D6Q2YqdJ3e84cEagzf83gbKicTPX4kJ9C8bvUQzK5roVtgFwat/Ndu9c2uK/rwOUVmDKPHdzt3/SQQAl9712dX7lZTJVN9r3dm87AL1nfaJghemZOfQdcQwFkahMlHZOm+B0xKrSUqQWyfbw4xezPvVZEudqpPIhQ0lIlFro93ziB7KBUJvaJCx0UNMFr2Z4zCDY64wKLaq1sgSm8HQ4QxSdL1+bPWgTG+BVzchvbx6Cmh7DHmXTAr5XGPzEczdMWY0t16uZ4ZzftT5Ss+S/NKpV37SiFKPOKWzou4BFGU9qwl0DeYKy4E+/EDMX0W80=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.40.0
Release Details
UpdatedJuly 26, 2026, 9:40 p.m.
Changelog

Added

  • Keyboard shortcuts. Budget can now be driven from the keyboard. Press ? anywhere for a cheat sheet. Globally, / (or Ctrl/Cmd+K) focuses search and g then a letter jumps to any page in the sidebar (g d Dashboard, g t Transactions, and so on — every page has a letter). Any dialog now closes with Esc, traps Tab inside itself, focuses its first field on open, and saves with Enter. On the Transactions list, j/k move a row cursor, e (or Enter) edits the highlighted row, and x selects it. Shortcuts stay out of the way while you're typing in a field
  • Export and import your import rules as a file. New Export and Import buttons on the Rules page: Export downloads every rule you own as a single JSON file (a lightweight backup, or a way to move your rule set to another instance without a full data export); Import reads such a file back in and creates the rules. A rule referencing a category or account that doesn't exist on the target instance is rejected and reported rather than mis-filed. Rules shared with you are left out of the export, and rules remain part of the full data export too (#318)
  • Import rules can now be shared. Rules join the list of things you can share with another Nextcloud user (alongside accounts, categories, bills, income and goals) — pick which rules to share, read-only or read/write, from a share's Configure panel. Shared rules show a Shared badge on the Rules page, can be run and (with write) edited by the recipient, and run during their imports too; only the owner can delete one. A shared rule's set category/set account action only takes effect for the recipient when that category/account is also shared with them, so a transaction is never filed under something they can't see (#320)
  • Import rules can now match on the account. A new Account condition scopes a rule to a specific bank account (with NOT for "any account except this one"), and a companion Account Type condition matches by kind of account (checking, savings, credit card, …). Both work when importing into an account and when running rules over existing transactions (#322)
  • Tag sets now work on shared categories. Opening a category shared with you shows its tag sets; with write access you can add, edit and delete tag sets and tags on it just like your own categories, and read-only shares show them without edit controls. Previously any tag-set action on a shared category failed (#328)
  • Bulk edit can now clear a transaction's category. The Bulk Edit Transactions dialog's Category dropdown gained an Uncategorized option alongside Don't change, so you can un-categorize many transactions at once (#332)
  • Deleting a category that still has transactions now offers to reassign them. Instead of blocking with "reassign or delete them first", the delete prompt offers to move the category's transactions — and any in its subcategories — to Uncategorized and remove it in one step (#332)

Fixed

  • The browser Back button now moves between pages inside Budget. Switching pages (Dashboard, Transactions, Accounts, …) records a history entry and updates the address bar, so Back and Forward step through the pages you visited in the app instead of jumping straight out to whatever you were looking at before you opened Budget. The current page also survives a refresh, and links that deep-link into a page (e.g. from search) still work.
  • Bills with "Auto-pay when due" turned off could still auto-pay themselves. The auto-pay flag (and the other bill toggles) could be read as on when it arrived as text rather than a true/false value — the classic (bool)"false" trap — so a bill created or restored with auto-pay off could still be auto-paid. All bill toggles are now parsed strictly as booleans on create, edit and import (#335)
  • Cryptocurrency accounts and their transactions now keep full precision. Amounts were capped at 2 decimal places on entry and storage, so e.g. 0.00012345 BTC was rounded to 0.00. Account balances, transactions and splits now accept and store up to 8 decimals, following each currency's native precision (BTC 8dp, XRP 6dp, JOD 3dp, and so on); fiat currencies are unchanged and still 2dp. Amounts on bills, recurring income and savings goals denominated in crypto are not yet covered (#331)
  • Shared categories keep the owner's order, and editors can reorder them. Recipients saw shared categories in an arbitrary order and couldn't move them; they now appear in the owner's order, and a write-share recipient can drag to reorder (the new order applies for the owner and everyone it's shared with). Reordering no longer silently fails when sort positions collide — the whole sibling group is renumbered on each move (#328)
  • Shared categories now open for the recipient instead of doing nothing. A read-only shared category couldn't be selected in the list at all, and even when reached its detail/recent-transactions/spending endpoints returned 404 (they looked the category up under the viewer, so one owned by someone else was never found). Clicking a shared category now opens a read-only view showing the owner's transactions and analytics for it (#328)
  • Recording a bill's payment failed when the bill used a shared account. A bill can point at an account owned by another user — a partner's shared account — but marking it paid, and the one-click Record transaction repair, threw "Failed to record payment" (a DoesNotExistException in the log) because the transaction was booked against the person clicking rather than the account's owner. Bill payments are now recorded against the account owner, so a share recipient can mark shared bills paid; a bill whose account was since deleted now shows an actionable message instead of the generic failure (#334)
  • A one-time bill marked paid without a recorded transaction could not be reached to fix it. After a one-time bill is marked paid it deactivates and drops off the Bills list, yet it still appears in the Payments without a recorded transaction card telling you to assign an account first — with no way to open it. That prompt is now an Assign an account button that opens the bill for editing (#333)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureTlx5adQ84X1cU4v1VoYON+yY22etMZSb58OURK5dpJ/bpQdLjdhL6stjRFGshNhEHr1Ra/KTZs7/uCZLyvq+M0XBYGD+voy+pwmXwa6Wylyi99fJ2UhiXPHxKiExVq1EJY/PA7LcHAQy639r04gbQ4Q/BvDrOZYWAZuYCLrZrZFclfoIlzf/Ra5SFuCuWguuOd79cU/tXViv8xntJBIcIXoN58cadHF5iTo3Mt2XO7sNsUs7A8+1HDXsUldblvmLFFpH9ubJdYVDKqdzA104yRb0uPH08Zd6+y764r+uIsahSB/RwF3kJ20gcv5nurCaf9FvsI06PiyQnR73jMzlnoAaWxnSPZwGDa+gvQ/t56H+m+A9DlvVgnxexUa0C+Ga7cphcgVKWPWaRZFQzeofrcJ66wAH9uh338pw2R2Lq5F+s2NCOKuKo6uXocpf+VZ9GTsfRIrDEGL+4FwkFkxd0tHUBoohsOhROk/tXphvl/mIh5m4m3pRsjm7GviZASYoTXJe+kdclUUzpFMuXGrOFjSXCd1Plk2XsDMiHBzPEXAkaPlL9hdluXiuCCXrUYIF+S/U60qB1MuWRlwzTH80RovEgvyKGwZtzlDPtNLF0hM79iABKE5UgP1km9MRm7dyDWQDdogfWq+Oy97EJH8TDtYvuO2I79lQnppc9WrYB5E=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.39.1
Release Details
UpdatedJuly 11, 2026, 10:22 p.m.
Changelog

Fixed

  • Share recipients saw wrong dashboard totals. For a user whose accounts are all shared from someone else, the Income/Expenses This Month cards counted transactions in the owner's "Exclude from reports" categories — the exclusion list was built only from the viewer's own categories, so the owner's internal-transfer legs inflated the recipient's income and expenses while the owner's own dashboard was correct. Shared categories now keep their owner's exclusion for every viewer, and per-viewer "Hide from my reports" mutes are honored by these totals as well (#326)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignaturePTjw+Z1r+sKWQmZSlNfYPSTl5PFejqjMEgNyvQR1FXSKor9zNXxtxcAM0eYYthPn9YEprCKS9V6NC699ZbeWK6WbdRtprmP+rsvCifpjQyVtPDGLJ11LWzLVgw84pTHcolsdY756JO6KWW8hxp63bq3s4QE4rs3RTCEyHSpzpZ1pXSydTCTvheL1M/rtg3XyKpzBkoOqGh39Dnh9TH7JQt+cCB8VD84aeHcsvnxUkQJU3AmZwYGcP8wSNeLmDjt1S9yCv2h8NAReLQeTMbmdzNJtioLLiifkedz5bEgjVximgqI99mmV+8uhRBY0keT1hWXR6En4IrRkiJwlEyNZRHkukMa9jNmoNVvoRYCuQOVZ1wWGtkS8MCz5Ig63yPijEMh1bqnoi3+WA1g8s23dJVIziAHSKl0F+V7DKThsw2jBouMZeZ7bG0nMS9bFLcndAm1MbpWyuZATotUExNeYhEZEIwUOuF+esV5lnDoHTf0i/q6OJGa4hPPiNTE/rH4PS3Z4pdEZ4V9YhxYfsSs/9y+Y7xg/ZQWnLq2YVsTR7V8FgQwU4Bi8OGLsfbYZhSaUnHv60ObUB2U4WkD1mZZqDHKJXAIgVGulvHFAkXQVeGpRqbUCQNvgiVU8hfRaRmEr/y9Usub/3srDJn7qybeAxfOxA7rL+AlakEZBECHPJlY=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.39.0
Release Details
UpdatedJuly 11, 2026, 12:57 a.m.
Changelog

Added

  • The Bills page now flags payments without a recorded transaction. A warning card lists bills that were marked paid in the last 60 days without a transaction being created or linked — the situation where the app balance silently detaches from the bank. Each entry has a one-click Record transaction repair that books the missing payment (dated the day it was marked paid, both legs for transfers, splits applied). Deliberate skips via the Skip button are not flagged (#274)
  • QAR (Qatari Riyal) and JOD (Jordanian Dinar) are now available as account currencies. JOD amounts use the currency's native 3 decimal places. Automatic exchange rates cover both. Requested in #321

Fixed

  • Editing a monthly recurring income never saved the changes — the app showed "Income saved successfully" but the Expected Day (and every other field) kept its old value. Any update whose payload contained an empty field (a monthly income always sends its yearly-only "expected month" as empty) reloaded the entity mid-save and threw away the edits. Thanks to @redsteadz for the fix (#324, #325)
  • The "Exclude from forecast" checkbox on a transaction appeared unticked whenever the edit dialog was reopened, and saving the transaction again then really did reset the flag. The flag was stored correctly (including when set by an import rule) but the transaction list never sent it back to the browser, so the dialog always showed — and re-saved — it as off (#326)
  • Income/Expenses This Month (and the other report summary totals) deducted transactions in "Exclude from reports" categories without converting them to the base currency, so on multi-currency setups the deduction was applied at the wrong rate — and for a single selected account the deduction wrongly included every other account's excluded transactions too (#326)
  • Imports no longer bring in flagged duplicates by default. The preview's "Show duplicates" checkbox — on by default — secretly doubled as the skip-duplicates switch, so every import ran with duplicate-skipping off and rows flagged Duplicate were imported anyway. It is now purely a display filter; a new explicit "Import flagged duplicates too" option (off by default, resets each import) covers the deliberate re-import case. The preview's per-row checkboxes, which were never actually read by the import, are gone, and the New Transactions count no longer includes flagged duplicates (#327)
  • Marking a bill paid no longer suggests unrelated transactions as "existing" matches. The Existing Transaction Found dialog offered any unlinked same-day debit as a candidate — cigarettes could be presented as a "match" for a mortgage — steering people into marking bills paid without recording the payment, the classic source of app-vs-bank balance drift. Candidates now must match the bill by amount or name, a weak match is never pre-selected (the safe default is creating the transaction), and the "Don't create any transaction" option now states — and warns after — that the account balance will not reflect the payment (#274)
  • Overdue bills no longer double-book when marked paid. The scheduled placeholder pre-created for the next occurrence was written as an ordinary cleared transaction whenever the advanced due date was not in the future, so it counted toward the balance immediately — alongside the actual payment. Next-occurrence placeholders are now always scheduled, regardless of date
  • Restoring a backup preserves every bill setting. The data import dropped most bill fields: custom recurrence patterns (restored bills then advanced one day at a time instead of quarterly/etc.), transfer destination and description pattern, auto-pay, reminder days, tags, split templates, start/end dates, remaining payments, forecast exclusion and the future-transaction opt-out

Changed

  • The Match transfer dialog now also lists candidates from accounts in a different currency (any amount, within the date window), so cross-currency transfer pairs — e.g. imported from CSV — can finally be linked by hand. Automatic matching after imports is unchanged and still only links exact same-currency amounts (#326)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignaturegJm3RDjkvl1EBICN6Us5TsX5SdQbSGnRHvRIZmLsYaclkDVqW/mYCBjVgwjU50ifkv72zl3kxf5a8S3yxpo2WX6cnhkyyibLhs5Uzdrj9Egw47yYgMun8WH4647Y0uGP7QrX3Yf51SO7Ve+JWgdMRX+hWvG4K9hxUgAwWR3AmTYRsRXpmsNrOr97q2SPC3V0g9bAARDeSeWDGQ8SR05+OMIrQRj0Ct56fC1cTNWzHpPT+Qs17SJJcUUnK3tJWsM3wvGiwk62YMBy1cv1jx3JkOXnYvsa8bpSG3sL7aqr05QkAkvL9sSGxka6mDrC3CN1LHlwwQjPjWwoX9YDtOI04j0JPd0SzlhMYILaZNyouhoNTuY5YhDIG4aLjg737AAEBHgU3jvpWxaM8Oz2+9he9LkAJW6qA9DuzB/FmDNKxyJTmQ6S0LZ21d+Hkr0LD/2uKRSywlRBld+UNCWby8YrgIkyGomPH1rjDG28y1ApiqSozetcjSvDYwqULM2mLXU9OjD9a8UJk8B1R4Xd0TqgMmDCaAZrTdRLYYdTZEEaFbnDkbm8p4z2q+UGfn/UCNEOkg5pbu1WAsRubIKkPzNTz7gTSLI9u+qJfvoZg9c3Ae1OhXWDD9k/2Z+pCrbJhu8yDX+2JukXoAxNS+bnxaDxdoxRzIM+9jcbb0eyG3wJuLk=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.38.0
Release Details
UpdatedJuly 7, 2026, 1:07 a.m.
Changelog

Fixed

  • The account selector saved in the gear settings of insight tiles (Monthly Comparison, Large Transactions, Weekly Spending, Year-over-Year) was silently ignored — the tiles always showed all-accounts data. The saved account now actually scopes the tile's numbers
  • Importing transactions that trigger the Auto-Link as Transfer rule action no longer shows "Cannot use object of type Transaction as array" on the import screen. The import itself always completed — the error came from the transfer-linking step afterwards, which also means those transfers were never actually linked (#314)
  • The Recent Transactions dashboard tile now honors its "Rows to show" setting above 8 — the display respected the setting but the data fetch was hardcoded to 8 rows, so values of 9–20 silently showed only 8

Added

  • Edit auto-categorization rules as JSON. The rule editor gains a Builder / JSON toggle. The JSON view shows the raw rule structure — editable and paste-friendly — checked when you save, and switching back to Builder repopulates the visual widgets. A Copy JSON button makes it easy to move a rule between instances (category/account IDs are instance-specific, as noted in the view). Requested in #318

  • Hide shared categories from your own reports. Categories shared with you gain a per-viewer "Hide from my reports" toggle on the Categories page. Unlike the owner's "Exclude from reports" flag — which stays owner-only because it changes every viewer's reports at once — this only affects your own reports and dashboards; the owner and other viewers see no difference. Applied at the SQL layer through the same choke points as the owner flag, so every report and insight tile honors it consistently

  • "Exclude shared accounts" on the remaining dashboard tiles. The per-tile toggle added in v2.37 now also covers Budget Progress, Monthly Comparison, Large Transactions, Weekly Spending, Category Trends, Cash Flow Forecast and Year-over-Year (shown in the gear menu when you have shared accounts). Bills, income and pension tiles are deliberately not included — they show entity data, not account aggregates

  • Clickable spending charts. Clicking a slice (or bar) on the Spending by Category dashboard tile or the Reports page pie chart jumps to the transaction list filtered to that category, scoped to the chart's date range and account. Tiles set to "top-level only" include the subcategories in the filter so the listed transactions match the clicked amount (#317)

  • Per-bill opt-out of pre-created transactions. The "Create future transaction for this bill" checkbox is now a persistent bill setting instead of a one-shot option at creation. Bills with it unticked never get a scheduled placeholder — not at creation, not after marking paid, not after skipping — and toggling it on an existing bill adds or removes the pending placeholder immediately. Previously the checkbox only affected the moment a bill was created, while every payment re-enabled pre-booking unconditionally, so unticking it never actually opted a bill out (#311)

  • Convert a transaction into a transfer. The Match transfer dialog gains a "No match? Create the other side" section: pick one of your accounts and the app creates the opposite transaction there and links the pair as a transfer. Until now the dialog could only link two existing transactions, which left no way to correctly book payments to accounts that have nothing to import — e.g. a loan tracked as its own account (#313)

Changed

  • Scheduled (future-dated) transactions now show a Scheduled badge in the main transaction list, with a tooltip explaining they are not counted until they occur. Previously only the account detail view had the badge and the main list showed scheduled rows in italics alone, which made a bill's pre-created next occurrence easy to mistake for a duplicate booking (#311)
  • The transaction list Total no longer includes scheduled transactions — they are placeholders for money that has not moved yet (#311)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
Signatures/wP/jWqAxqTStZPLKWl/5nyJk/xpeAom+Kp7KakVOdJmzhNv/Z6KM/CUUOrGem4Qj5G1OEZ2tNrPkTneCVvfFU2S5aoayMDgcRaGquqwZisM/4a0KV9Husjq8mV0RVoqco16HBH8PUY+kYsbeWRcSp2q38Zq99L04zb1x5XY1rGe5YdP4/IydUoMpyzTtsGF00Tj6OUAMvlDTnJqCcetscuXX8yo33xm0dUfLxjZD2f9hsn8UTCwNN7v1+yBhwNN4jJsfyGTN+92XV2YDhRCfVWq/3bGqphHo+nYQvbyjndJRcaAwybOquX6MH7+wpDa5wpvNw9xzc2sYNm2FM08SYep3cX7uoXngifGZu2FBqyNHQ198dqEwqJbEVv2DrK5cAnQkbSS1glYYney/uXAlsqLEinHirrShNYRoq+ZEkxUhpdung3zSWwPe0Fd/mWh2chHiTV20A2tCrv7FRuRadpf75bq+y0xuIglVZQy5E1dT2nk3lPUUwB01w/ggmwrJ91hOchPoyoRoDhoBNxZJs903bQejWR/MdZ9pbXVmwxj1EOq8oWfWeQ5B+OEz/LbcplibODsNv6IUIYU++gxK8d2XCVzBgV2ayMqsRxFDxItgluqDcu4oTW8mh3A4z33PvbeCFFMsj2bKFbOslmuT2ZiVl58oTaQRTh61xeKEA=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.37.0
Release Details
UpdatedJune 27, 2026, 11:16 p.m.
Changelog

Added

  • Exclude shared accounts from reports. When other people have shared accounts with you, the Reports page gains an "Exclude shared accounts" toggle so you can see just your own accounts' figures. The same option is available per-tile (in the gear menu) on the account-based dashboard cards — Income vs Expenses, Spending by Category, Top Spending Categories and Recent Transactions. It's off by default (shared accounts are included, as before) and only appears when you actually have shared accounts. Note: a transfer between one of your accounts and a shared account can only be partly seen when shared accounts are excluded, so income/expense totals may be slightly overstated in that case.

Fixed

  • Saving share settings failed with "Some entities do not belong to you" (HTTP 400) when the "Auto-share new" toggle was enabled for a type, or after using Select All — the auto-share toggle (which shares the same data-type as the entity checkboxes) was being collected as a phantom entity and sent as a null id. Entity selection is now scoped precisely, so share settings save correctly with auto-share on (#306)

Changed

  • The Categories page now also lists categories that have been shared with you, shown read-only with a "Shared · <owner>" badge. Previously it showed only your own categories, so anyone using a budget made up entirely of shared categories saw an empty page even though the categories worked everywhere else (#306)
  • Categories shared with you at Edit permission are now editable — rename them and change their colour straight from the Categories page (they carry a "Shared (editable) · <owner>" badge). Read-only shares stay read-only, and a category's type, parent, budget, report visibility and deletion all remain owner-only (#306)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureFqJ17XG/szTfkAMsF+oCODYGClVjdeGArgFi3SrgeGhg4CFFzIVO98XEnYhxeCnwOcYGivzy0uhe60/Vv7kgml+lIVvRL1EZOxvjOES2KksQ50fqxGZSNz3EL54EA6R3Yvo6uLFBM9cbK0mmY5H+4i3UozKhKwzRa6PJLIZzpBsjtprJXHojWsQMR5KY7WDDbb9yD32uYzMnrXMxOiQ2PZGtG7aIhLS6DzC7Mtp/oLUgyRqBWoYMUWWLLi1qyeOr4/8Tdm9H5I36oxeoX2ZQlVuprpRjDPW5EITrljbyuIPy3CdAFn5tvvt8rkurEgCtPAaMv7gSXRZto6rJJqS4woUqX310+J0re9qa53Ls0J7Kezo5WpENoaFsvT6McjVG/4k6k4YN1/l74p97fFfR+1T2kC5VptpwVz4GZ2aSF9t226Sdkft7sv72aC3oQpa4PN3PIWj113aN2X5nnCGiD+NUW282/yAdacvMWVgB+t+Rbm0FIyWtGnbw0dKAlY3CAmQoBvqX9f2vqn1OFDxJhejg/i7+FAWQD83LIk6u2kNg/N4e2+hgLtO45wd5MU6TLXXTrb1mlikbbiP80Rla1p50fScosYTCqjJfz2lh5U6D2h/nquGHHvhf4R9q7eSkykmELHZUKiUyYlrLrOfiuxGRqaWSQWp9hm0CUog1HBE=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.36.0
Release Details
UpdatedJune 27, 2026, 1:15 p.m.
Changelog

Added

  • Auto-share new entities. Each person you share with now has an "Auto-share new" toggle per entity type (accounts, categories, bills, recurring income, savings goals) in their sharing settings. Turn it on and anything you create from then on is shared with them automatically, at the permission you choose — no more sharing each new bill or category by hand (#306)

Fixed

  • Code-integrity "Some files have not passed the integrity check" errors reporting FILE_MISSING for js/.htaccess and vendor/tecnickcom/tcpdf/tools/.htaccess. The app no longer ships any .htaccess files — the Nextcloud App Store strips them from the published archive, which left the signature expecting files that were no longer present. Neither file was needed (the JS one only set a redundant cache header) (#307)
  • Deprecation warning in the Nextcloud log — the notifier now throws UnknownNotificationException instead of InvalidArgumentException for unrecognised notifications, as required by Nextcloud 30+ (#308)
  • Reports and the dashboard summary were empty when a single account flagged "Exclude from reports" was the only account selected. Accounts flagged out of reports are now only dropped from the all-accounts views; explicitly selecting one shows its data as normal (#309)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureYxqf1NnAucAiXFVdwVmQJPaPUyuExQ8t/dwv4tDVpFb1kXDtGcIWoAdspiDz+HwdyPe+ul+/2GcDWiLPTF3TvIHwIaV+h+guDRYBEHMY95+Hy5W0BSuwBC7gto5dfsZEhL5xj5OsRIYrY/Fo8Tqj99kVzDK560o9NgI6Bp6ZkQpbwPRbTnbxUX27oF0oDjrg1ArS4IiE4ghZW1ct74Mlv4uoeg5zaVQlucrZK+rBJXixtpDnImHLPMkTvd+1bmkQTFtvArS1A37YkXkLKrKn4pzWvwv/q46ddih1NXBC7o6UoBwP1pWB1OxgNq3/98OdWyPs4GLumMmRdg+7PbY95Go97lBbNc/1mrBB9qQPXirFxYHMZWVDSRHSNRJ9cSMnZA/YzsVeOZOVkIwJWXhC5YGAEN8nq8HKIMBHzmi6UYdGM2VvGPmNZ+K3wlGMIkKlVfWfIJ7XIOCe6OLvQbwR/ATZ7pUyOE+AR21uu27zWGJ4iB4y/eCfCSE8vIxyPW7L0dwkzxU13iNNNxAUQgbNrs8EiQBLQlTCaBWCWp296Dds5nEGMEilQKX9vEXAhY9KRG5dzJjoZhZ14tWA3Hjp+5/Gs2AM4Bh3Rp1OGdhfQhFDmt/2GXcL16lfDcX28K1ub4FPYE8MEz6qDmLhqqwv9FeXQQbT/ZKdQn8NwuOlGFE=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.35.1
Release Details
UpdatedJune 25, 2026, 3:28 p.m.
Changelog

Fixed

  • Categories marked "Exclude from reports" are now consistently excluded everywhere, including the Income vs Expenses trend, Category Trends, Top Spending Categories and the monthly spending chart — not just the dashboard summary. Exclusion is now applied in the database query itself, so reports and dashboard insight tiles can no longer disagree about which categories count (#219)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignaturebX/9kwpiVjwDj0f2eU5xNE7zUpt8T/nkGCFg9HnDQoKynM7c1KaXhbh4isVQBbgy5kPGXSDP7DRfuSTYY5/M3PSv1JE8gOk/9lz2AGmTqlXrf4Kgq9oARAGcVHXB955dLvDkj6Vrk7zZ9cwrjq4aMBu02dW8ZgyAHStXybiWmkAbIxK768MHM4n5FXTRFw3P/ELVlDjCxgIpxVxD5EZaaA+n7RrjN9MRY2R8/GN7Og7yijcmnutMWtna4K19B9c3ShcfUkrwotvCUz3c+K10VQSfzUpN6RoindDB0j716jUZQ6IKzXBNNRiOjQ6N6s1MlmKwjyFyw0PY509hJY+dtjBEQBbFjK0pw7ZElfW4zDWteDzWRm7M1VjzUlRgPLsg7CJ980Rg8suZAMh3UH251vymCH0ykpMYqK1qiWDurz5GWdaDov6Z0YkQPQLnszzPa60kbO9VUHrYnG+6+KA6GoPW0EHFEqaUxXv+mRLr8Pm8BhjCiDghO7mlHZFN95hN5gkNyBdIPA9JmXAdnkrJBSQaDvZdejDwFJL+T+PgA2f9JomB8BQ/WkZ4uukyKUUFYToOhntQTe7dfE+I4VsD6BycbY7smaY/xGx6EvyXfntpYkgR7Fe2rYKaxBrcRcnhTmQBeLLz85M7fLKVjME72niQdRIZRaMZ+OmpCxKK2qU=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.35.0
Release Details
UpdatedJune 25, 2026, 12:36 a.m.
Changelog

Added

  • Pensions revamp. You can now record a contribution as a transfer from a bank account — the matching withdrawal is created automatically and kept out of your spending — and record withdrawals/drawdown back into an account (#304). Scheduled (recurring) contributions (monthly/quarterly/yearly) can post automatically or on demand (#251). DC pensions gained a configurable projection target with a progress indicator and a "today's money" (inflation-adjusted) view on the growth chart, plus an optional Pension Projection dashboard card. Bank legs that fund a pension show a Pension badge in the transaction list.

Fixed

  • Background-job "class does not exist" log spam that could appear after updating PHP/Nextcloud/the app: the app's autoloader is no longer "authoritative", so it falls back to PSR-4 and self-heals if PHP's cached class map is stale after an update (#305)
  • Newly-added dashboard widgets now load their data immediately instead of staying empty until the page is refreshed.
  • The pension detail panel's balance history and activity are no longer broken — those views called endpoints that didn't exist; they now show a proper balance chart and a merged timeline of contributions, withdrawals and balance updates, each removable (#251)
  • Editing a split transaction with three or more parts no longer zeroes or overwrites the other splits. The last split row is now a read-only "remaining" amount (transaction total minus the other parts), and the dialog blocks saving until the parts add up (#303)
  • Spending-anomaly notifications no longer crash with "The arguments array must contain 1 items, 0 given" — a stray % in the notification text made Nextcloud's translation layer fail, spamming the log every time notifications were rendered (#305)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureF/7pZ4sNzjJuqXXZoHmO+9OmUzkQz6ZDke3vkONfZ2uGfzBpwpDSIiGlfNv6gt40Ho8NTPNd0JuM+ESRohLlPAAftFoF+L4h+asH5s/lncoxgTZevEFl7NE14s+sPVdGdZqXGi0b3mohB+f1jOudpVbgB0bmCDvnZMEKiMSjB7XwH9iQqzu/8WyQNd28w+Bz2TbyAfu2PCtdD6jsmVCbvtCkmEdKOVJzRWuExH+vwvZ0ltX3mtorPl6HEzqKJWoDYG3tdbpSwml6w9F3qj8naVZ3tZYBrfvwABHoMD1LYpYwRss5C9UpJvu6UFfKQ4Xso1tBu5U+tYlAPKLbQ5J70o0C1aP66R+FvL8RlMHpY93duR32qZkT/6xV0NYQpd9xzXoLbB5YkZJuBLV8m3oP9k/pNEy8vwF5Kkb+/6zrJt4aSH/iiAqBoqvuT1itwScYsNpGHXWOrGHioCKiGkcMvamfr7her1fQ42wNiVIVWKaxNtjeYrVjmHCtWA2awjv3XRfcXdcL/4stuDpXxQ0Dnv2S/Ey9ZbGbqpc0DNyPZfKie5/QK5OnHPW9F8nHUsEhxDLbNezo11fKm1ykE0ja4nTZFKL3ml2D4aRDMYQe35MWJvW/fLcNW7dYOV969ZI52G8jTIUI/YphcNfCNK24fVkljrcBSybr8WavbELxVR0=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.34.0
Release Details
UpdatedJune 24, 2026, 12:34 p.m.
Changelog

Added

  • The transaction list filters now include a Reconciled filter (All / Reconciled / Not reconciled), so you can quickly see which transactions still need reconciling (#301)
  • A Budget alert threshold setting controls when a category appears on the Budget Alerts tile (default 80% of budget). Set it to 100% to be alerted only when a category actually goes over budget, rather than when it's merely approaching or fully used (#293)

Fixed

  • Creating a category (or account) no longer fails with "Unknown column 'excluded_from_reports'" on instances where an earlier upgrade was interrupted or restored from a mid-upgrade backup. A self-healing migration re-adds the affected columns automatically on update (#302)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
Signaturey+Qi2+U6CexZu8i+0DGrbLXwFbp+cHLVW62WRSfrovEAuJrnZy8paqAacEaE570GoHVd1b23Yihz4oDfOYStLASDVFk7xhVrarnlIqv4EH+Jyw0IR2iaLR+IvhJmSZc9N5nQ42i2z8UYetvQo0znzzNPmpT2FEJB1Sty9kCfHL7HiisG4hYwJp528McMVXgCYfn/XOZUQzOVY6rvis1hP8CiFbE4UMUQj/SgDpRjimcRCZy8fsRLgZHcfO2+BKYCSt5lqLDJSzsmewBFNMVWDdtZwPUxqyK8xaTwSnwWNBNXBRg5ZcDLJhhIJtk9cEezVTdJBZTw3wx7iCztR9RFQi9CZsRz9U9S4jLEdcV8m6OTa8XG22s2ZHt+I+hisGtlC1TOQ5fpPfSe9onWdA8jgC68RAFeOLJ+KmSkLQN1bbr9gUw47oB09Yd9sEtUDcFapfv+x9Zl3/s4ExwO6xDS/bwmRyZ/fq1z2jhVu/lMFd//+9ciOrCdty1p7440JVs/sx71Qcc0mRhZsMtIRYyBD2EFceUHx8cQCtOLL99+JtGkTakCMCwIxghuGoXnrq+9mRWjgROn1ysGEHDUyC8ZKCJ5f8TXOllqX2g+2fyOpFzHR66oP7lPwI5y3eW4VYJGT/lQzTavAtU148X2XaBUz+XA8Djuco3CCuGJuT9FhSU=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.33.1
Release Details
UpdatedJune 18, 2026, 3:03 p.m.
Changelog

Fixed

  • On some installs an earlier update was recorded as applied but didn't fully run (an interrupted upgrade, or a database restored from a backup taken mid-upgrade), leaving the excluded_from_forecast column missing — so every new transaction failed with "Unknown column 'excluded_from_forecast'". A migration now re-adds the column automatically on update. (Also surfaced by the new database-error detail field added in 2.32.0.) (#289)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignaturewGNDwrdOGHhLxiEiJQDsZrcL4BFQbGBTjeDU/3VJql8bIeDBHITKzJ3HH47kV1bFmsZ35q0o7xh/r4q6Kj9/SXM8gQCTxEtQ0q80MS85LGy5+9dUtJ0yBvrLfE6kwpNPDH+kqwBVcAGxmLr9vYau5uTFGdeB0WZ3gmesUvT5kuZfdREwJDQ19QWR40pJjHRcWqM5KnXCT1/wq7btWj9s/Vf9GVQvo85g9R7adODG1PVBr4gM6R9nTgsrn+60BJvNNO5f3W3wbuzvqaJhtVdknB9Z8fc7Vbq6mh6TgSPBmXgiK2VdCAWPaW2EmpVL8iwgOGazPGSajPkMZNNZDhzDNEpLcveJl61g/x5dVAxOevwFnN4CaX5c/YYppjcqtoWyYgoTNMv3enF3///tD0wS68iQzcU5UNmsOOKsAUVvRnf/oOX2b13NfsKPONAxcu4Q/UG8ybPqYwXT+T6Vs+IRmoLJLnOs/BUgbqmmRIG1Wfs2BusDFKNHHWoW1Z5t+GDLGx2cyNci7+rKPRh2seML8iPrt9lNv2M5NjzIJ9Wm0Xt0FKpIetR4gDpLSRvBtINaQ0jVuYVixt1yDKMUfE6GH4sNW9rNi2ZoKptz2MIxouBmLNXezA5Y0gvIlgA11Bi0YBrKPUAtmxNl8Jyxhle2Ll5bZbsupMy1otRB/+NGEOs=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.33.0
Release Details
UpdatedJune 18, 2026, 12:52 a.m.
Changelog

Added

  • Run reports on multiple accounts at once: the report Account filter is now a checklist — pick any set of accounts (e.g. all your credit cards, or all your checking accounts) or "All Accounts". Applies across the summary, spending, income, cash-flow, category-by-month and year-over-year reports and their CSV/PDF exports (#299)
  • Saved reports: save a report's settings (type, period, selected accounts, tags and options) under a name and re-run it later from the "Saved Reports" picker in the Reports view. The period is stored as the chosen preset (e.g. "Last 3 months") so a saved report always shows up-to-date data (#299)
  • Dashboard tiles that can be scoped to a specific account (Spending by Category, Income vs Expenses, Net Worth History, Recent Transactions, and the other account-aware widgets) now show a small label in their header naming the account they're analyzing — the account you picked in the tile's settings, or "All accounts" (#296)

Fixed

  • The Reports period selector didn't drive the report on reopen: the dropdown kept your last choice (e.g. "Last Year") but the report always reverted to "Last 3 Months", and clicking "Generate Report" used the reverted range instead of the shown period — you had to switch the dropdown away and back. The report now always matches the period shown in the selector (custom ranges are preserved) (#300)
  • The Quick Add Transaction dashboard widget couldn't be used on mobile — the lower fields and the "Add Transaction" button were clipped off the bottom of the tile, so a transaction could never be submitted. Its form is now condensed (each label sits beside its field with tighter spacing) so the whole form fits the tile, and it falls back to scrolling within the tile if it's resized very small (#298)
  • Editing a split transaction's amount (e.g. inline in the transaction list) left its splits at the old amounts, so they no longer summed to the transaction total. The splits are now rescaled proportionally to the new amount (the last split absorbs any rounding remainder)
  • In the edit-transaction dialog, changing one split amount now adjusts another split so the parts keep summing to the transaction total, instead of silently drifting out of balance
  • Split transactions weren't counted toward category budgets or spending. When a single transaction was split across categories (e.g. one $1,000 payment split into rent, parking and a deposit), each of those categories showed $0 spent. Split allocations now count toward category spending everywhere it's shown — the Budget view, the Spending by Category chart, and reports (#297)
  • Large amounts (e.g. values over 100,000) on the dashboard hero tiles (Net Worth, Income/Expenses This Month, Net Savings, Cash Flow) wrapped onto a second line, splitting the number mid-digits. The amount now stays on one line and its font scales down to fit narrow tiles instead of wrapping (#295)
  • The "Asset Value History" dashboard tile (and "Net Worth History") showed its empty-state message anchored near the bottom of the tile instead of vertically centered. When there's no data the message now fills and centers within the chart area (#294)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
Signaturejj+nUiPNSYYgtQ/7XYIkJNFo8vWIHaX28Q0XTtpN6RWmrW8qrJBIs2jTaaHwebC7SB5f7GP6vQxghh9+nCWfA+KlTKbm8YJg6yzah9xdTLo/JcUhTOinlH9yYoXxMiIY9EVwQLsPmef4sprTsS9oqBeSgZ7S8WRJYnxjAuljee9q0Sfai9AK+RQzBk6kgENhCAVt95ooZ3H5ukfFBSb/kyXa3IU+ngu6g5B9DgiJfBduecdkLEfc0dhYKelUyNaZa61qoG865podTGJFCFqzoSnlCXgRcJqJHjhdTERIeu/nHQAL/PhaPy0OSWK8l+kyrGveMEKDM6LvQ0Eo6B9Ul0ORobundabEat67f/hqaTmnDldOkkEm5a0WAYeQvYeeZCNLtiF26pWk66v6eQhXsrT6IwcJ/gxaC6oS8URm5yYub2iW9nVq6uZXRMJavJr8CmYl7MSqQRVvFKGlwHvD7X+YfEs+htKGYM017iWdICfQv/wbGi5JzIxqdm7QKrV9EGxgl4GFWvY/cyGZt4awfhoy4RljlFtsfJ02askgVFUloVGKOWeqZ5NbqXMDC+UonPONQ/RPM64u0L3NdVvmcXOwA8RBHCg1qgEiVkDBSsJyhK55+1J7Yn5fIC2emSU0BXOdzSFgg3BgUbYJQHgH30AwNf1iagO/WBOYDSu4jqs=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.32.0
Release Details
UpdatedJune 17, 2026, 3:02 p.m.
Changelog

Added

  • Category by Month report: a new report (Reports → Category by Month) showing income and expenses per category broken down by month, with a column per month and an overall total. Categories are listed alphabetically with sub-categories grouped under their parents, and parent rows include the totals of their sub-categories; a toggle switches to sorting by total instead. Defaults to year-to-date, follows the report date-range and account filters, and exports to CSV and PDF (#288)

Changed

  • API errors caused by the database now include the underlying driver message (e.g. a missing column) in a separate detail field of the error response, visible in the browser's network tab. The user-facing message is unchanged; this makes problems diagnosable on managed Nextcloud instances where admins can't read the server log. The executed SQL and any bound values are stripped from the detail (#289)

Fixed

  • The dashboard "Budget Alerts" tile showed a red "exceeded" alert (with "0% over") for a category whose spending exactly equalled its budget. Spending that fully uses the budget without going over is now treated as a "100% used" warning, not an over-budget alert; only spending that actually exceeds the budget shows as exceeded (#293)
  • PDF reports rendered non-Latin characters (Polish, Cyrillic, etc.) in account/category names as "?". The PDF exports used a built-in font limited to Western European characters; they now use an embedded Unicode font (DejaVu Sans), so names display correctly. Applies to the budget report, bills-calendar and year-over-year PDFs (#292)
  • Marking a recurring transfer as paid showed a success message but created no account entries. The Transfers screen was only updating the transfer's "last paid" date instead of calling the mark-paid action, so no transactions were recorded; it now creates the paired transfer transactions like the Bills screen does (#291)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureNKgPUY81JziKewMWFs4QeLNIwZ8JqGBZ6wvFlsItL4R47yoDLAn4+I1T/pwgEOi7KR2lCUFBckiAdI78FONIy+JyCFhY0w4WcGEltsQdsytRMQYAggOWw+OlYvlDMPI6zoMoRfVcIvC3d+4pUrP91cJIVwi+bu5OIYO0C7ErDFCyvMlHK+ifsGvBluQJ377z8wnBUQIWSfudOuXewIyBHCF1QXsRXsVe0CIGWPNnT3ibuwxjm92a4vzwqdTEYy2qQwzPgYWPhgZofSdEN6j08iuwUzM0i9yXWd0IVpRNLb8RIo9lTzhJsjolrNFGZd0iiQk5A/4NQ6VOLKItVhwXJKOZk7KzyYTZmEki+PaeHKSEjEzwYNqv2tL4VPrBjyq5Y3bRTnYS3uBBCOnkWwn6ozQ4PitvSgPpcqciCtrP1hYAa0oQ7FsP8+BVsepO8gn8+lIcVjx7mW+YvufESAyFRXgAy61QBNjcd34vtoEfLqhdP4f37gZ/jdmCicDQ3sLw/eUIL98BylXmNvOge43vnYuRgGl9gBO11ENaP3EhqhqsrVr5Gyu07MGlMhCRlBn21fRN5sMORHFNx6pL/DcpwC0xtpfWEtHTCcEcLvArqfSiQSMrJaDvqftcQNMWYt4hGZKMVR7SYZsAragHUiMfvWDu1mW7HLNsW8PwySZDrHA=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.31.0
Release Details
UpdatedJune 14, 2026, 7:05 p.m.
Changelog

Added

  • Exclude an account from totals: a per-account "Exclude from reports, dashboard & forecast" option (in the account's edit dialog) keeps the account fully tracked but leaves its transactions and balance out of every "all accounts" aggregation — reports, the dashboard, forecast, net worth, total balance and category budgets. The account still appears in your accounts list (with an "Excluded" badge) and on its own detail page, and selecting it explicitly in a report still works (#286)

Fixed

  • The account detail page's overview tiles only counted the transactions on the visible page (e.g. "50" for an account with 1,603). "Total Transactions", "This Month Income", "This Month Expenses" and "Avg. Transaction" are now aggregated server-side over the whole account, so they're correct regardless of paging (#285)
  • The dashboard spending chart's "Total Spending" figure (and each category's percentage) only summed the top 10 categories shown in the chart. It now reflects spending across all categories
  • The CSV import preview's "Auto-categorized" count was estimated from a 50-row sample and could be wrong for larger imports; it's now counted over the full file on the server
  • Editing an existing bill failed with "Failed to update bill" — saving the edit dialog (whether or not anything changed) returned a 400 error. The bill's start-date column, added with the limited-term bills feature, was missing from the list of updatable columns, so the always-sent start date was rejected before the save could run. Bills now save correctly, with a test guarding every persisted column (#284)
  • Opening an account's detail page returned a 500 error (the reconciliation-history request failed). The reconciliation controller was missing a trait it relied on, so it couldn't be constructed and every reconciliation endpoint failed; the account page surfaced it via the history sidebar. Now fixed and covered by tests (#283)
  • Starting an account reconciliation failed with a confusing "The string did not match the expected pattern" message (most visibly on Safari). The root cause was the reconciliation controller failing to construct (the #283 fix above resolves it); on top of that, the reconciliation screens now read error responses defensively, so any failure shows a clear message with the HTTP status instead of an opaque JSON-parsing error (#287)
  • The Budget Overview dashboard widget (and the digest, spending-anomaly and bill-reminder notifications) always showed amounts in US dollars regardless of your configured currency. The server-side amount formatter was reading the wrong settings key and falling back to USD; it now uses your default currency
  • The Budget Overview dashboard widget's "Total balance" now converts multi-currency accounts to your base currency instead of summing different currencies under one symbol (currencies without an exchange rate are excluded from the total and named)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureCseRrf2b0tfseaK8cBqqPjA8lhMT1C+aq6xVuP6vO3E6sRzawwkPNHdfK7CDaOro2TYW+agvm4g873WzOGVLIVa3FHEyFlnGRkFSwMz334bq1/Rcbw2WXdMbNUliZwdK76DNCauZ0JPz8FYIXr5cqkqbw80oHD/SWhWD5dTKRKJ2gpSvbNtXJfq32Sn04UVxrJq4StY11b5rJfCXR7P7RQxmFboIYJvhoVIfcebR+vighFLC9adkKVaF/xJ8tm1MVG6oJHJ4zKU87SV3+D8vB1xpxeWo2xRwseYSwg8Nk3ik6iXkcf4cHTACrCGyHhOXgCmltGkJ441alZ8kzOQCDe6Vw3Rx+zzgducfZGOQJPuIYcrpyZAAgN51xtDQJTWJNoT9jBrUmEv0r/ftZWj8QYnesnl8HgXUQPdLCsCaloLpISXkt7KzlHYlt4PgdMphbDBnuMROrXZtTeIwDCzwGAkatsK+l8HnM+FbMlpfszT7Ki1z2HYX/d+74aLRxkNUClx3fsQsxOtd0RxK9+/JPHW+W5Sv5kWbRSfiUrslL+pT7R15L9x4t3nFK8VUUEZSDcNynhSHxCVqrqOsV3mZ12eutyvQEPpN56qyLkaZmcoxOlOD2v4BKba8pBAL6YW05jx8hBWg9m0zAg4h3/qoA6zLDRrVfHi+LvUiiE1YDWs=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.30.2
Release Details
UpdatedJune 13, 2026, 6:03 p.m.
Changelog

Fixed

  • Dropdowns in the transaction list (the column-configuration gear menu and the in-cell category/tag/account editors) were cut off when the table had only a few rows, because the table area was shorter than the dropdowns. The transaction table now fills the available height, so every dropdown has room to open in full (#280)
  • The Tags column couldn't be shown/hidden — the Show/Hide Columns menu was missing a Tags entry, and the column wasn't wired into the visibility logic. Tags can now be toggled like the other columns (#281)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureRXpaKwi4ViRdeYM6mjC3JtrlDOFrm03LMBFc2gQMktdYfBEoyMrW3YBp+DPKezxnLOmETNnqjXAI+oswcQLQMkRbAcjuD1dpBBZi7x8kmvtc0lZUcrKRw2QKUzDD5luZaN7JE14o393XlPFxdqkaUbJvWTltA5xK/XO2H72GyvEO7/7de7HCcP2G4XTK5kGSeP3PHRNQ5MjiB49QlM7D95p7Od374Fbr0k52h0sWFHSA14LgJSyPXCgHxxJMqVy7O76LlS1Iedg8B4TFBbTJZVol/8emaHjBHvEwVVzSIIkr9wdtZ60aqrEhJfTqaRwdGS0ks53VE2ROoE829Jnc3Xkz4Xxc0WEqH5a4vxbUWnA8NbuaFNAsUcfXW+0TDTUeLT34IV8c6GZkwn0z4a1parjkif0yyEolfPhNomKX/JMl74aSG5i2BkKyDH3OXMg9oC0/czhOIxluUuFCwWJyd6cBOGd6r/R382SMMe+mCHDpuBxIY12gRo4bzcAfmYMQ3e6rrtgpFwxBllUaK8lC+yPy9x9502QHhZem922Tz7HokfuXuFxh1x9Z6doBSvoZOe2H2PIKRupmFf4I9epoRYdDQZjatpZpN3+oZnz6DmY7f9+g3gaZ7Dl9dkPydm96203Pox5SGz9vhOQaXeOIw+l+rLnXnbodzB3eyqz11Ig=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.28.3
Release Details
UpdatedJune 12, 2026, 1:14 a.m.
Changelog

Security

  • The recurring-income update endpoint no longer passes the raw request body through to the entity layer — a crafted payload could previously set internal fields such as the owning user (mass assignment, integrity only — no data disclosure). Update keys are now allowlisted like the other endpoints

Fixed

  • Auto-derived recurring budgets (#269) are now consistent across all surfaces: the dashboard "Budget Remaining" hero, Budget Progress/Breakdown widgets, Budget Health score, and budget alerts now apply the same recurring fallback as the Budget view — a category funded only by recurring bills can now trigger alerts and is counted in headline totals
  • Auto-derived budgets now respect bill start/end dates: a bill that hasn't started (or has ended) no longer counts toward today's budget, avoiding double-counting during a planned cost change (#268)
  • Recurring income summaries (Income view header, dashboard Income Tracking widget): semi-monthly income was counted at half its value, and a one-time income at full value every month until received
  • Transfers page monthly total: semi-monthly and semi-annual transfers were converted incorrectly
  • Live forecast cache: cache invalidation never matched the stored key (changes such as toggling "exclude from forecast" appeared to do nothing for up to 5 minutes), and the cache key ignored shared-account visibility, letting a share-restricted viewer briefly see the owner's totals
  • Editing a bill's amount without updating its split template is now rejected when the stored splits no longer match (the payment would have silently imported unsplit and uncategorized); setting a split template via the API now clears the bill-level category, matching creation
  • Multi-account import partial failures (e.g. a deleted destination account) are now reported in the UI instead of masquerading as a full success
  • Import preview now also flags repeated bank transaction IDs for accounts that will be created by the import
  • Long OFX FITID hashing threshold raised so every previously-imported FITID keeps its exact ID (re-import dedup continuity)
  • Auto-derived category budgets (#269) now handle every supported frequency correctly: semi-annual bills were over-counted 6×, semi-monthly halved, custom-schedule bills counted every month, and one-time bills inflated the budget monthly until marked paid (now excluded). Frequency math is delegated to the shared calculator, which also gained the missing semi-monthly conversion
  • Auto-derived budgets no longer apply to past months — they reflect today's recurring bills/income and were rewriting history (including overriding explicitly-zeroed snapshot budgets)
  • Multi-account import: an invalid destination account mid-import no longer aborts the batch, and deferred balance recomputes now always run for already-imported rows
  • Bank sync: the post-import balance recompute now keys on transaction creation, not the import counter, so a row persisted just before a non-fatal error still gets its balance update
  • The scheduled-transactions background job now recomputes balances from the ledger (it was the last remaining hand-computed balance delta, and could race concurrent imports)
  • Import preview now flags a repeated bank transaction ID (OFX FITID) within one file as the duplicate it is, matching what import actually does; per-account preview counts include rows that will import with skip-duplicates off
  • Marking a bill paid by linking an existing transaction now warns if the link silently failed (no money movement recorded)
  • Extremely long OFX FITIDs are hashed to stay within the import-ID column
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
Signaturefa7u8mWcwya82OCYZOh+XZFPRJH94oqiBM5WUtEtvU3Dh6Lq+pMs8A7e2aCOa0Y6AbwWH7TF6ZRtwanfSh2PjQMwAaDFlR5anBdAvr89L/fn3eK0uSrZetqNGmAT7Itlc0mT5KowbTvtWDRdK46oR4jjqgXKay6JeO7caGbAcKmyfhJARbfTXsb5etz/yhMX72X33ayUYtCo8nQrtxLTGO5AAPIcFbq1pa3W3d1SHuQ7Ibksv3WXrZe79ngT4pQpGp6xtz3ervqo86vrI8qH8DDg6g9IJE8D1iseOiVzRv/KI/N06LnY0OvUHNZwGrJph5Jh3BrYg2/5rSYzEP5VzaGyZm+AS0DO1bXf9BC5OqbRl3s/FsM+4UgowriYD0S2Zwc4/2j/W3mDRjOdGf0MJxd8SOxv7uW2P5JL0TImjA7mTgppSipw1ShGTl8BU7q11cCtFmuCmwGfvPlRLQtMqEdr93gNkY84rAja08K9Ro1/ySZtrEWVRh/lYzQqmpazsjlw1V4x+KYtn65LHr9Zxd46ToleV5kv1tEZJ1u7nFXeNnrfThyz78EqvLbVxzcqphrfrImGOD9/VhUwryM58KtVz7+tXmLjn3SsSmM8sz9DEljbEKK4zTV9mQgIxviGwzNuIGEFD+HaW6HRIsAzRNtXow5oT7Kgpqa3BnJ3HxM=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.28.2
Release Details
UpdatedJune 11, 2026, 6:33 p.m.
Changelog

Fixed

  • Dashboard could render half-empty (hero tiles only, widget grid invisible): a Chart.js resize on a hidden tile's detached canvas threw during initialization, and the widget grid was never revealed. Chart resizing now skips detached canvases and the grid is revealed before the resize pass. Likely also behind "nothing happens" reports after certain actions (#273)
  • Dashboard tiles with a saved account selection pointing at a deleted account (e.g. after factory reset + import re-numbered accounts) no longer error with 404s and stay empty — stale selections fall back to all accounts
  • Account balances are now derived from the ledger instead of running deltas — the root cause behind every historical balance-discrepancy report (#3, #89, #124, #163, #187, #194, #274). The stored balance was a running total that each transaction code path adjusted by hand; any missed or mis-signed delta corrupted it permanently. Every transaction create/update/delete (and retroactive rule run, repair action, import and bank sync) now recomputes balance = opening balance + net of non-scheduled transactions, making drift impossible and self-healing past inconsistencies on the next write. A one-time migration backfills the opening balance so displayed balances do not change on upgrade (#274)
  • Marking a bill as paid now warns loudly when no transaction was recorded (bill without an account, or transaction creation failed) — previously the bill was advanced silently and the account balance never reflected the payment, drifting from the real bank balance every cycle (#89, #274)
  • The app's own export→import now preserves transaction status (scheduled transactions no longer silently become balance-affecting after a migration) and restores the opening-balance invariant for imported accounts
  • "Skip Duplicate Transactions" off is now honored: previously rows whose import ID already existed were still rejected deeper in the stack (duplicate-ID guard + unique index), so parts of the batch silently failed to import. Intentional duplicates now get a uniquified import ID and the entire batch imports (#275)
  • Import duplicate detection no longer gives false positives for legitimately identical rows — e.g. two same-priced purchases on the same day with the same description. Identical rows within one file now import as distinct transactions (occurrence-aware import IDs), while re-importing the same statement still skips everything it already imported. Re-importing an older statement also recovers transactions the previous logic wrongly skipped (#276)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
Signaturekx2VkgWxozCE2LPp/nzgQQiqFxk/83sOdycv738Ly/uEwn/MhxF/kNtBlP4DMQbhmtkcHdt+kDIlQK1S5q1WHJWZQxjLc/ZCkj/ZEPkNBrDhHwdQCRh4TsRVJyfrIxXUTOCAKJLYk+0DXlnJB3kMhR81adns3wWNH9RkC4b62k3gXtzMR4n+jz/QJDGEAOXRpDUzxEm2TKqFot6sGRt3u0+rVo0bng6nogDJha0APeFI5Ujt+3mECw9MlxNt9nKbQlIGjAnraLVUFz0bXNLK7dbBS3PSzjLsUxhoNhAqMivfHEfLViOvIlCFNHzoWGxFnHK0flI2zJXUlOnaidOEyfhZWbqNpHZL4RZLIZWYQaztJgATNsK+L5aO0Md+Np1hgE8jkdY90gugiV06JqoPEWqCo/qSyaO9N3xYpeXrwfiL37JJqkigwg69RZN3OD1DfBT8ue7QlhT93dfg+39ERzbVY9QBu0gT+bwIs8tyE1MVXOaSjHKUkHab5dpGU3NQhvu/E1CO1BWA3dYvUUqvrvXKB96gm7IqNQEAkRi4JJHDPGtgzjERM+k8z/JA2xeJmPp7V3TZ/1WiKOoKMPz88soCJBMuj/LWnSpekLAGo4RJDy1JBlOm835e3ieJFVHwIwqG9YP7oRB/puFvYV6aaEXCnSkUcZV+z+2NXmHB8KM=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.28.1
Release Details
UpdatedJune 8, 2026, 12:13 p.m.
Changelog

Fixed

  • Install/upgrade aborted on Nextcloud 32 and earlier with "Primary index name on oc_budget_import_templates is too long". The budget_import_templates migration created its primary key without an explicit name, so Nextcloud derived a default name and hit the Oracle-compatibility identifier limit (the unprefixed table name is exactly 23 characters). The primary key now has an explicit short name. Thanks to @TheUnderdev for the report and fix (#272)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureXdUz/Pc10uA7L3R+vTa/cI52W9X8nDyH33zElCWeS/xWeYgonfr0GwLhn4ywE7rtUQF8e1Y8GhETbSd60otnPduP+4rXp7+5+b+iMTa3qfYi6gAd3Y1YJJrZqK0yx2Fdqld/nhQLfFpVkUSQl/JQ78RZanEh779Af5RejNl7lolRlJYg7ZNrLrFasWrpyrLNsg4+Tf74/vMpKWDXf0FEIqjnXZ0LKJm7Yjig4uazy+a5vDcDOrfq6fLU56d9ML/jBJK+9A2loT3I5HP7H2cngdLpwk6+MNLiYQDsdNzLGJJK9TK4hn0Cj+AV80mAQ45beagh4H0SmEoDTPvR/hC7LLlU5rtioE1Rg1tCvlZfHBuPcH9LZMq11Q3HVbZnvzkTdG3lKQlKeFhP86QOIjiAg1Frm0yuOt4nMSdG36N+k1C5szF7HrCoH+u1XgdY6fKI6WW71RkqXJ2IhwOorxcijLVQc2l3wyDLqoQrHtJA2yWGsI9NXlq+d5ZLJ03T7xvcLBPgSDTz91KqBABqJYRdCGhzAuQPe9M814mDu5XgdoCJNUKNrAl6YGvLvJXyj5j8I09qImqsQx09AmEBxi8YTZDbxuO8U/g3yKO14aBgGu3Z+v8+h6xyqJyNsPEbHHxpjfSbwAF/9FlvjA64nOTqPam3fPOjZAdqne5bgf05gFY=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.28.0
Release Details
UpdatedJune 7, 2026, 9:59 p.m.
Changelog

Added

  • Shared savings goals — share a savings goal with another Nextcloud user. Recipients see a "Shared" badge and can view progress; with write permission they can edit the goal and add money, while only the owner can delete it (#255)
  • Auto-derived budgets from recurring items — a (sub-)category with no manually-set budget now shows its committed recurring total (active recurring bills + recurring income, normalized to the budget period) as an automatic budget limit, marked "auto". Typing a value always overrides it (#269)
  • Exclude extraordinary/one-time items from the forecast — a per-transaction "exclude from forecast" flag (with a "No forecast" list badge), the same flag on recurring bills/income (propagated to generated transactions), and a matching import-rule action. Flagged amounts still affect your balance but are kept out of the projection averages (#270)
  • Reusable CSV import templates — save column mappings and import options and reapply them to future imports (#247)
  • OFX/QIF import account routing — route multi-account OFX/QIF files to the right Budget accounts, remembered across subsequent imports
  • Bank sync: pending transactions — option to import not-yet-posted (pending) transactions, automatically reconciled when they clear (#257)
  • Bill start dates — a bill only occurs on or after its start date, making it easy to change a recurring cost mid-year by ending one bill and starting another (#268)
  • "Shared with me" expenses view — recipients can now see expenses that have been shared with them (#248)
  • Dashboard period indicator — chart tiles now show a read-only indicator of the period they cover (#250)

Fixed

  • Dashboard now collapses to a single full-width column on phones, independent of your configured desktop column count (#249)
  • "Excluded from reports" categories no longer appear in the Budget view (#266, #267)
  • Category spending chart shows income as positive with the correct label (#265)
  • Tag-linked savings goals now sum net realized contributions (credits minus debits, excluding scheduled) (#264)
  • Recurring income description is now persisted on create (#263)
  • Transfers are now excluded from dashboard income/expense totals (#262)
  • Account Breakdown report now uses each account's own currency instead of a single assumed one (#256)
  • Fixed a PageController crash (TypeError) on unauthenticated requests (#259)
  • Quick Add date field normalization on iOS (#235)

Docs

  • Documented the standalone Quick Add page and the iOS home-screen workaround
  • Noted that GoCardless no longer accepts new bank-sync sign-ups; EU/UK self-hosters without an existing account are pointed to manual import (#271)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureiQMjVEdG/FWcc56MAPwvDd04E0ERl5pUWkrRWtdYdgbboBj0+7YAo+rDODFz5qC3EPqWBr7XRkjXOfvn9+m61v0w88Qy8SZQIZRHTAwRJuK5jDQbpfce5dropQgKW8btEIzI3BPE+DFBIDeV+qLNQEYT25ApMkUAz44PumVV0sJMibCGo0JBgIxHCPyem1NNjYaX3qQDt41eg8I5rH8wLCWGa7lNTtGyp8vaJ4ck0sh4J9sPuVzMdJoXQDHfGe5S8YY3GTwgvwyloNJQAFO+SQzm5WX6mC/IKAfpxwG82cQAEMm6B4geyHwaYGSFDEgrBuHOZj2fQmvQgzoarRN+U76bOhjQI0IqU76Pno3qM17eF+UKW8peDiqFBXpepGYfDoeyjQsF2GqxIK3C0bNUR5bp9RjNxkWckwvS2ihvP/2rg4lr05MuDDmIdBYG9Ny+PT9dEWBssQkXzIVX28Ox6P8xkorH0n5EoSRl3j+KMXbM34QteNMt1+jgsHAxcS8H57CwV3MC0uqZnhxUu/LbwIGHzvKbC6vN3F/3l6F+35rWM7UaQhdvr2W/1q5Swj5F2sp2Bq5jgrxbWIuUB9+pzftASgVUEmtd6blOUlJuuJj1wmaIrA9jx21+Bg8t/OmrQqB97ZHzint0WTdo7KTOviKZGnoZVXeoQthPmSyW7Wc=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath

Nextcloud 34

Budget 2.52.0
Release Details
UpdatedSept. 18, 2026, 11:44 a.m.
Changelog

Added

  • Import templates remember the character encoding. A statement in an encoding the importer cannot recognise on its own - an undeclared Cyrillic or Central European CSV reads as perfectly valid Western European text, just with the wrong letters - has to have its encoding picked by hand on the mapping screen, and that choice was lost on every import. A saved template now keeps it, and picking the template re-reads the file in that encoding straight away. Templates saved before this have no encoding stored and leave the picker as it is, so they cannot undo an encoding you have just chosen for the file in front of you. Contributed by @Saviq (#384)
  • Import rules can rewrite a transaction's description. A new Set Description action replaces the description a transaction arrived with - CARD PAYMENT TO TESCO STORES 2231 can become Groceries - either always or only when the description is empty. It runs on file imports, on bank sync and when rules are applied to existing transactions. Duplicate detection keeps using the description from the original file, so a statement imported again is still recognised after a rule has rewritten its descriptions. Contributed by @Saviq (#385)

  • The import review says which rows it cannot take, before you import. A file with an Account column can carry rows whose account cell is empty, and with Account for rows without one left on Skip rows without an account those rows are dropped. The review step never said so: a 75-row file whose last 29 rows had no account read as "Total 75, New 0, Duplicates 46", and the only mention of the missing 29 was a dialog after the import had already run. The reasons were there all along, the review step simply did not show them. A warning now sits above the statistics, in the same place as the direction warnings, saying how many of the file's rows will not be imported and why, with the row numbers behind each reason. Where the reason is an empty account cell it points at the fallback account select below it, which is what fixes it, and choosing an account there clears the warning and brings those rows back into the count. The row numbers also match between the review step and the dialog after the import now, the review step counted from 0 whilst the import counted from 1. Reported by @TerjeTM (#388)

  • The Budget Alerts tile can be told which categories it may alert about. Since 2.28.3 a category with no budget of its own falls back to the amount its bills and recurring income commit it to, so categories that were never budgeted against started appearing on the tile, and spending 190.00 against a 56.03 figure worked out from a bill reads as "239% over". The tile's settings, on the gear when the dashboard is unlocked, now offer Only categories with a budget I set, which leaves the derived budgets out and gives back what the tile showed before that fallback existed, and a list of every category with a budget in play that can be unticked one at a time. Rows whose budget came from a bill are marked, so it is clear which ones the checkbox covers. The filter is stored with your settings rather than with the tile, so budget alert notifications and the digest honour it as well, and the budget figures on the Budget page, the Nextcloud dashboard panel and the digest are untouched by it. With a filter on, a tile with nothing left to show stays up and says how many categories are muted rather than disappearing, which would take the gear with it. Reported by @TerjeTM (#389)

Changed

  • The mapping screen redraws as soon as you change the delimiter, the header toggle or the encoding. Changing the delimiter used to leave the columns and preview split the old way, with a note that the file would be re-parsed in the next step, and toggling Skip first row (headers) did not touch the preview at all - so neither could be checked before moving on. All three now re-read the uploaded file on the spot and redraw the column choices and the preview, keeping every column you had already picked that still exists. Picking a saved template does the same with the template's own delimiter and header setting, so its mapping lands on columns split the way it expects. Contributed by @Saviq (#383)
  • Translations. Ukrainian is now included, the Polish and Russian translations asked for in #382 are in, and German and French have been updated from Weblate.

Fixed

  • Expenses another user splits with you count towards your balance with them. When another Nextcloud user split an expense with you it showed under Shared with me as outstanding, however your contact for that person still read "Settled", opening it listed no expenses, and the totals at the top of Shared Expenses left it out. Each split is stored against the person who made it, and a contact card only ever read the splits you had made yourself. A contact linked to a Nextcloud user now also counts what that user has split with you, from your side, so their "owes you £40" is your "you owe £40", and where you have both split expenses with each other the card shows what is left once one is taken off the other. Their splits are listed in the contact's details marked split by with their name, and the payments they record show in the settlement history as payments from you. Only the person who split an expense can settle it, so Settle All and Record Payment still only reach your own splits, and are greyed out when none of yours are open. The contact has to be linked to their Nextcloud account, the same as for Shared with me. Reported by @Bow-Wow75 (#390)
  • A paid one-time bill keeps its due date. Marking a one-time bill paid cleared its next due date, and a bill created before 2.49.0 - when one-time bills gained a real Due Date - had nothing else to show, so a paid invoice read "No due date" in the list and opened with an empty Due Date beside the old Due Day and Due Month fields. The date a one-time bill was due is now kept when it is paid and the list shows it; bills paid before this release get their date back from the day and month they still hold, in the year nearest to the payment. The form no longer offers Due Day and Due Month for a one-time bill: the Due Date is its whole schedule, and it has to be filled in (#333)
  • The Bills Calendar no longer shows a bill as due for months it has moved past, or for months before it existed. Since 2.49.0 a month was struck through only when a payment was recorded against it, so a bill marked paid with Don't create any transaction - a yearly premium in February - stayed green in September as if still outstanding. Every bill was also projected back to January whatever day it was created, so a bill added on 8 September read as owed for the eight months before it, and those months inflated the monthly totals. A month the bill has moved past without a recorded payment is now struck through with a dashed line and its tooltip says no payment was recorded, and nothing is drawn before the bill's creation date unless a start date says the schedule began earlier - a bill with nothing left in the year drops out of the table rather than sitting there as a row of blanks. A payment linked from before then still shows as a paid month (#333)
  • Tab-separated CSV files can be imported. The Tab delimiter option sent the two characters \t instead of a tab, which the CSV reader refuses, so choosing it made the import fail - and a tab-separated file that was detected correctly showed a blank delimiter and was then read with commas. The option now sends a real tab, and a template saved from the old option is read as a tab too (#383)
  • The import review shows how many transactions the file holds. Total Transactions on the review step always read 0, whatever the file contained. The account page has a transaction counter with the same element id, and it sits earlier in the page, so every update meant for the import summary went to that hidden counter instead
  • Clicking quickly through months on the Budget page no longer shows another month's figures. Every month change starts its own loads of the spending and the budget amounts, and an earlier load that finished last replaced the newer figures, so June could show May's spending or May's budgets. Only the most recent load is shown now, and a budget load that fails leaves the base budgets rather than another month's. Contributed by @almeidandres (#387)
  • The dashboard follows your budget start day. With a Budget start day set, the income, expenses, savings and budget-remaining figures at the top of the dashboard still covered the calendar month, and Budget Progress set to the current budget period used the budgets of the month the period started in - a period from 28 August to 27 September was measured against August's budgets. The top figures now cover the current budget period and show its dates under their labels, and both use the budgets of the month the Budget page lists that period under, the month its 15th falls in. Envelope carryover, which the dashboard only added for whole calendar months, now counts for the budget period too. The six-month charts stay on calendar months. Contributed by @almeidandres (#386)
  • Every budget surface agrees on which month is running when you have a budget start day. A period is listed under the month its 15th falls in, so with a start day of the 10th, 5 September is still in August's period, and with the 28th, 29 September is already in October's. Budget alerts, and the Budget Health tile built on them, still used the budgets of the calendar month, the Budget page opened on the calendar month, and turning on envelope budgeting started the envelope in the calendar month too. All of them now use the period running today. The recurring-bill fallback and the "(projected)" carryover mark also treat that period as the current one, so a period that has already ended no longer borrows today's recurring figures. A category's details follow suit: This month, the trend and the monthly chart count spending per budget period instead of per calendar month, and the chart ends with the period running today. The same goes for the dashboard's Monthly Comparison tile, which now compares the running period with the one before, and for This Month Income and This Month Expenses on an account's page, and both show the dates they cover.
  • The Monthly Comparison and Weekly Spending tiles show the real figures. Both tiles looked for income and expenses at the top of the summary they load, however the summary keeps them under its totals, so they showed zeros whatever was in the accounts. They read the totals now.
  • An overdrawn envelope shows as over budget. When the overspend carried into a month is larger than that month's budget, nothing is left to spend, but the Budget page showed the row as "No budget set" with no remaining figure, and the dashboard's Budget Progress tile left it out. Both now show it as over budget, with what it owes as the remaining amount, as the alerts and reports already did.
  • The budget adjustment notice names the right month everywhere. "Budgets adjusted from ..." and its confirmation dialog read the month as midnight UTC, so anywhere west of UTC they named the month before the one being adjusted
  • The Budget page shows the right period for a start day of the 15th everywhere. The month picker's date was read as midnight UTC, which is still the 14th anywhere west of UTC, so in the Americas a budget start day of the 15th showed each month the period before the one it should
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureYjtb6oj/6u2vw+lMxUwTdqaoecbNZKr8zgforTdMu2KAUE/D7PJQiWgI+mlRDXOoDp++CZJkbkDwEIknVcN6Zl5rCfUtSvMwdVk4IvOKwG7AW2qqDhnHDplkWBwPMEFNNJdQxPnjsDTNYxTEtGnOXwl2gxc9NMIFSD3c/DeCbxzLZd61DaVpjQohgLF7EKuVeLohtjay574dEpwpXH9z50nYJ0bO65jUTxrnZmLoafqKyQRu7tqurEWjlkhUcZRBALUnDzc1KwA+7kP1K1SwVoJkiuJwqcZNju3hsz8US7leYtvEnQL0Qsp+TnCHKiGibv/G5kVVwgvGZ0ThI20UeIHQOMKDZXj+d+CKuskMLpBJTUZPJaQyTeyIfFQ858nZlHHKC1mSRno6XPO1pYQCvHBzf+TIZBtF9U7N9svhxDJ2eXRAXJbp+BrtfuVrBEFkXE/4kilamlMPdGi1nG0EkcnKB9tVaqryzKWgWb97hfuBftBulfa+kaGjJAH9ZMwf9GioTzOCSdLf32lC+XFlDFxf93nTrzfNPB3dU+v/F1ZiItBx3WvAcXbYdg2lYa8y/A8liLqYXj19o9GqDbhNFVhCVQNvfFn0nfq/otpkY6sMH+brtN4O1HQfNqOOn6Lp09HRh299sfO8kuCaQDIGfeyNb4qNNJALi6bewhAaORk=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.51.0
Release Details
UpdatedSept. 11, 2026, 1:17 p.m.
Changelog

Added

  • Accounts can be deleted in bulk. Tick the accounts you want gone and delete them in one go, from either the tile or the list view. This existed for transactions and categories but never for accounts, and the gap only really bites in the one situation that produces dozens of them at once - an import with the wrong column mapped to Account, which creates one account per distinct value in that column. Deleting those one at a time also ran into the delete endpoint's rate limit of ten calls a minute, and an account that still holds transactions costs two of them, so the clean-up stalled about five accounts in. The whole selection now goes in a single request. The destructive half is kept a separate decision: the first confirmation removes only the accounts that are already empty, and anything still holding transactions is kept back and asked about in a second dialog that names those accounts and totals their transactions, so nothing with history in it is deleted by a click meant for an empty account. Closed accounts can be selected too (#381)
  • The import preview warns when a column mapping is about to create a pile of accounts. Mapping the wrong column to Account creates one account per distinct value in it, and mapping the date column gives you one account per day. The preview did list what it was about to create, but as a comma-separated line among the statistics, which reads as a note rather than as a reason to go back. Above five new accounts it is now a proper warning, sitting above the stats where the direction warnings already sit, because it answers the same question - whether to import at all. When most of the new account names parse as dates it says so outright and points at the account column mapping, rather than leaving you to work out afterwards why you have forty accounts (#381)
  • Bulk edit can add and remove tags. Tagging a run of transactions meant opening each one in turn: the bulk editor only ever touched fields stored on the transaction row itself, and a tag is not one of them. Tags... in the bulk bar now adds and removes tags across the whole selection at once, a cross-page select all matching selection included. The two lists are deliberately separate rather than one set of checkboxes - a tag you leave unchecked is not touched either way, so adding one tag to a hundred transactions cannot quietly strip the tags those transactions already carry. Adding a tag a transaction already has does nothing, and neither does removing one it does not have, so the same change can be re-run over an overlapping selection without anything happening twice. Category tags are offered too, grouped under the category they belong to. A tag set belongs to one category, so across a selection spanning several it can only reach part of what you picked - rather than leave you to find that out afterwards, each group says how far it reaches (applies to 12 of 50), only the categories actually in your selection are offered at all, and the confirmation names any tag that fell short instead of claiming it did more. Anything the tags cannot cover is counted underneath, including split transactions, which have no category of their own once split. Removing is not restricted the same way: a transaction re-categorised after it was tagged keeps the old tag, and gating removal would leave that tag impossible to clear in bulk. Requested by @joeftiger (#379)

Fixed

  • Names with an ampersand or a quote come out right in confirmations and messages. A category called "Food & Dining" was named in its own delete confirmation as "Food &amp; Dining", and the same went for anything carrying a quote or an angle bracket - an account, a contact, a saved report. Translated text has its inserted values escaped for HTML by default, which is right for the many places that text is used as markup and wrong for the two that show it literally: the confirmations and the little messages that slide in at the top right. Both now undo that escaping, so a name reads the way it was typed. This was true of the old browser confirmations too; it is simply visible now that the dialogs are the app's own (#381)
  • Editing a reconciled transaction in the list no longer asks twice. Changing the amount, date or account of a reconciled transaction directly in the table warns you first, and that warning could appear a second time straight after you had answered it - once because opening it moved the cursor out of the cell you were editing, and once more when the table redrew behind it. Answering once is now enough (#381)
  • Confirmations stop working after a few of them in a row. Every confirmation in the app was a browser dialog, and browsers offer to switch those off: after a handful in quick succession, Chrome and Firefox add a Prevent this page from creating additional dialogs checkbox to the box, and once it is ticked every later confirmation is answered no instantly without anything being drawn. From that moment the app looked broken rather than cautious - Delete did nothing whatsoever, no dialog, no error, no message, and nothing short of reloading the page brought it back. Clearing up a handful of accounts left behind by a mis-mapped import was more than enough to trigger it, which is how this came to light: two accounts deleted fine, and every delete button after that appeared dead. Confirmations, prompts and alerts are now drawn by the app itself, so there is nothing left for a browser to suppress. They take the keyboard - Enter confirms, Escape cancels, Tab stays inside the dialog - and a confirmation for something that deletes data now says so with a red button rather than a neutral OK. Reported by @missunderstoodninja (#381)
  • Tag pickers can be reached with the keyboard. Every tag checkbox in the app was hidden outright rather than just visually, which takes it out of the tab order and out of what a screen reader can announce - the coloured badge was the only way to set a tag, and only with a mouse. The checkboxes are now hidden visually but still focusable, and a badge shows a focus ring when you tab onto it. Nothing looks different with a mouse (#379)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureomDWujOwOWa9L4Xhc5Xr+YxrNL/X4KJz7URuQ3oocoKImK3zBZp5nUdl464tQpzylxC8sTBVsN9SqEm6KKKsPGkY92c4QnEzKWsuAM1fVZDgAqU/8oCyq6pSlRTrxxmHFN+PmioiScBnhErLMyrvPWkjVSpve7kIb5v1QRqf4nqJFuxeSOJAX1JgOM1tVME5Loxrm6SFZOsXaEXpKgqGF9SSuWXPAd1qGAO+MkugHo6zEjelkCYAWzkq2/tCZHOtIExuhBUk/BuSCMd9AaYhLb2iRJVT4FYcf14uRWCdfHmbRkNuGZNV63hbwNXwvIdP0KB9ZJ3QLV82V7LFyWY+s0VfssxJnKzjm8afeKo6zxq5SeRZmTVZDAxX7+aogVVWIqB18uwCI0dYWbMZQgR6PRqig0lf8E1j6KOiMRimZeHw0mkKFDV6ytcZEHgS8PuCih1ol9XaF+tNz4QJkKu/49A23APwrCUanew/Fs0BOhH7ydCNAl7sM5xpXKx4/4hoLJrA9tzTRwQUn1dmjbRk0QjThANrvqu+m0Gz97XWEwyyj3zHQyWYNy0Ozg1W1P01U/iFGH96Nd2emV2OO63z/AAmHrGWyBVBK73VlNx1guwaf8//c6XYbrbSJdF/smvbQcMa1MikuJq4DMpItW8vmvC+YOvUycpSHDkl7Hf+TC4=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.50.1
Release Details
UpdatedSept. 10, 2026, 1:21 a.m.
Changelog

Fixed

  • Save stops working on the transaction form after the split editor has been used. Turning Split across categories on and back off - or switching the type to Transfer with it on - hid the split rows but left them sitting inside the form. A hidden field is still checked by the browser, and an empty one it cannot put on screen is one it will not report either: the form simply refused to submit, with no message, no request and no error in the console, for every transaction from then on until the page was reloaded. Firefox and Chrome at least log something; Safari says nothing at all. Putting the split editor away now empties it, and a split amount is no longer a field the browser polices - an incomplete split was already caught on save, and says what is wrong in a way you can actually see. Reported by @SGiersch (#380)
  • Adding a transaction from an account preselects that account. The Add Transaction button on an account's page was reading the account being viewed from the wrong object, so it always came through empty and the picker opened blank - on the one screen where there is no question which account you meant (#380)
  • Transfer matching finds the other half in a shared account. A transfer between an account you own and one your partner has shared with you could not be matched: the search for the opposite leg only ever looked at rows you own, and a transaction in a shared account belongs to that account's owner, so the match dialog reported nothing to match and the bulk scan skipped the pair entirely. Linking the two was already allowed - it was only finding them that was not. The match dialog, the bulk scan and bulk linking now search every account you can write to, shared ones included. Accounts shared with you read-only are left out, because linking writes to both legs and a candidate you cannot write to could never have been linked anyway. Reported by @lexiconzero (#378)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignaturebuZC6LMTRyNL1vila15DJJFe8dDZf/j3oCjxjP7KvrqebYszACpNqevFzP0b+HFTrgRwXMF7+ZnHeZDVV4l4KuZgfeI78fVJnNhQQeYNYqcIRiZZTKoqfm3zpU0OzCqWchvR7Mgslc6IIuBGjmM5EAx53O05t69k00ylo5G2YLfeMtyeg9hlqRERfuE5aMa7w5YhvBcskq9gIbtuGRU5ZfK++QikEJxZS9Quy9H7iDuuRBrPgumyJyURxaENIodcPhTuHjC/95LQWciAI6bj562mWuNglVdBEC+9+oNRN12vyMHerogSRRNpfqKwMb93Yzhlw3gkjkD9DsZvVuzuek98QAxEhTDZeEcZ5o4aAB2m+mRAmx77mj0OrfvLcyL7ekKUCr6G0/xJkU3XtEG3WDF20OupAcXsNbYBduRIoCvozx/pEGOkIipe4oQOlh6POT7MkXWfxBGJaG3N8SzmUqihyNgx8KuoxodhHsw09O8ncNlmkiBEGNn0+Hx/UXiijxE4ucigWPVSmUP6SU6F8dpjU2EU/jqbIdxPiyz3r/tt/vbVXDw41c7wd5nnkHyubljlBW6KL1uREbhrl7fdRCgjzJkPKA+fa4tdpa83af3llfzKcnyO6TXQ/nPL+xI0eLwRlXUIp4eW9xIeY0sZ3bOwjMdOemiR1Q9lGSloAZc=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.50.0
Release Details
UpdatedSept. 5, 2026, 11:16 p.m.
Changelog

Added

  • Budget alerts and forecast warnings actually notify you now. The two switches at the top of Settings → Notifications have been there since the first release and never did anything - nothing read them, and the app had no such notification to send, so the only place a budget alert ever appeared was a dashboard card you had to go and look at. Budget Alerts now sends a notification the first time a category reaches your alert threshold (80% by default) in a budget period, and a second one if that category goes on to exceed its budget. That is the most it will send per category per period, so the nightly check cannot turn into nightly noise; a category that drops back under its threshold is forgotten, so it can alert again if it climbs back. Forecast Warnings sends at most one notification a month when the six-month forecast projects your combined balance below zero, naming the month it happens and the figure it falls to. Both default to on and are switched off from those same two checkboxes

Fixed

  • The Bills Calendar never shows an occurrence as paid while the bill still says it is due. 2.49.0 placed each payment on the nearest due date, and a bill paid twice at the end of a month - or paid a few days before the next cycle - had the extra payment land on the following occurrence, so the calendar struck through September while the Bills page showed the same occurrence as upcoming. The bill already knows which occurrences are done: marking one paid moves its next due date on a cycle, so everything before that date is closed and everything from it on is still owed. Payments are now only ever placed on closed occurrences; a second payment in a month shows as that month's larger amount rather than as a month that was never paid. Reported within the hour by @TerjeTM (#375)
  • One-time bills with the same name share one calendar row. Now that paid one-time bills stay in the year's calendar, a garage that sent three invoices appeared three times, one cell each. They are folded into one row with a cell per invoice, each keeping its own amount, the way recurring bills already read (#375)
  • Exported reports come out in your language. The PDF and CSV a report exports to were written with English labels whatever language Nextcloud was set to - the exporter never asked the translator, so a German user got Total Income and Account Breakdown in an otherwise German app. Every label in the report, Year over Year and Bills Calendar exports now goes through the same translations the screen uses, month names included, and the monthly scheduled report is produced in its recipient's language rather than the server's. Labels that already exist on screen are translated straight away; the few headings that only ever appeared in the exports are new to translators and fill in as the translations arrive (#377)
  • A monthly digest can report unusual spending. Unusual-spending detection judges a month that is still in progress, so it stays quiet before the 10th - pro-rating the rent on the 2nd would flag it every time. The monthly digest is sent on the 1st, so its unusual-spending section was empty every single time it went out, and the weekly digest only filled it in on the weeks that happened to start after the 10th. The digest now asks about the period it is actually reporting on: a finished week or month, compared against the same six-month typical figure scaled to that period's length, with no early-month rule to apply because a finished period is not a partial one. That also settles a mismatch in what the digest was telling you - it reported this month's spending so far inside a summary of last week or month, and now reports the period it covers
  • The digest notification says how many categories are spending unusually. The count was being attached to the notification and then never shown, so a digest that had found something looked exactly like one that had not
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignaturekDEMKCHGsB6XHpH0lnwbdVN2PlHEz5a/0JU2HlikRqJOIHvusKOCEPzyqSYRH/8U5+wPMQcWAi6Zlb8pcjgNh3CwemL7dVDMnrV7w65ZbG5xhBtzlziNuhs1FCJzqYQshdgCJzd2xQFJYJOqTqFXqdFQK6US+0Tgm47K6ROYrFUL/9JEhdaoH3kUz8PAP2WOq+IYdRfeUBlXUslF6pbtDWQ9g6gVSTUDF1Kj0V6UU+/M+GqrHY4flUN5Q9k6lGRLri8eBRO2woA5jdLWxJ5tyonb6F9e65yjlOIYbC3QV+TaHwH5MLbj9lmkrbAjFUMaaSWQ0VuEaj8vupo46ebxm2V4dGN4oisWd0VKRmlpGpGdDLIDYT1aZwIrVIRWPIicpqiFkLdOOo+YOCIl3XHNu6lPLxdR/jNcEDORoRJq6yPVtWZTroXgXM3TznOcNLXKotj7v/o1MPxId8uMms/wiu8PRksNIlFeLnmV8czhjhI+ZLElYqwCyMJjCUZUUB3ebdvRtbDqvuJBwuYp36Oi5UKfBTXqYzbAAO8qr4nAH/gdQsA8X+YquAMuux31ilINMpOvFX71Yf7/E15pqYZfvEQS0hq1hV4xIcgVAreEOHbIIFGcVB5WdrvYNeNP366rB5WsKXUBDGFrTEIL5vtj8OHgLqVYoEgBZNg/RL9j/Fc=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.49.0
Release Details
UpdatedSept. 3, 2026, 11:53 p.m.
Changelog

Added

  • A one-time bill can be dated in the past. A bill only ever stored a day and a month, and every date it worked out from them was rolled forward past today - right for a schedule, useless for an invoice from last month, which became due next year the moment you saved it, and jumped again if you tried to edit it back. For one-time bills the schedule fields now give way to a single Due Date, taken literally: an August invoice entered in September is due in August, shows as overdue until you mark it paid, and lands in August on the Bills Calendar. The placeholder transaction a new bill pre-creates is always a scheduled one, whatever its date: with a past date it was being written as a cleared payment, booking the money as spent for a bill nobody had paid (#375)

Fixed

  • The import's fallback account is reachable when the file has its own account column. A blank account cell now falls back to the account you choose - but the select that chooses it was hidden the moment an Account column was mapped, so the fallback could never be set from the wizard and those rows still failed with "no account was chosen". On the preview step the select now stays, relabelled Account for rows without one, and is optional: leave it empty and such rows are skipped with that reason listed (#333)
  • On SQLite, a failed save now gets the unfinished-update hint too. The hint recognised MySQL's and PostgreSQL's error codes and SQLite's "no such column", but SQLite words a failed INSERT as table X has no column named Y - which is exactly the failed save the hint exists for - and that slipped through, leaving the bare SQL. Found by running the check in a browser against a dropped column (#333)
  • The Bills Calendar shows what was actually paid. Paid months were guessed in the browser from the bill's last payment date - every month up to it counted as paid - so a bill you started paying in September showed January to August paid too, and a one-time bill fell out of the calendar the moment paying it deactivated it. The cells now come from the payments recorded against each bill: a month with a payment is paid and shows the amount that actually went out, months still to come show the expected amount, and the monthly totals follow suit. A payment made a few days late counts for the month it was due, a payment with no scheduled month near it appears as an extra paid month rather than vanishing, and a bill that is inactive now but was paid this year stays in the year's picture (#375)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureUTnFglOyY//mXGi7y/LDtH4919NkTXqAr1p4PsIxsYx5fusaiKeFTWxlcugWVBcXNirEhMLHMF/hTpCv05X/jQ0yMlB2LW8Q4bUwppTjyg44BEEACZuQWr1FTs7KhmlbU/nCDKTIuC+Uk458xB8kdIiggZoDRqb4JoINSJ2tXL5KeNQgeyyq8hqOm5pwUBxlJRgx61f8EPP4+JWoAY3DWZUGJvpmk8i0VrNtxOvHT2BTdfMxLauNboowdmko+GQv3ZLEoAwP0D1UI4pjcwxcOQdAkQuM4wXwN6tywUjdmzPTmYSTxEMO1XAnc1v22KUA7bQxkHYcg5viQMbtAA459AsY2ImPJdxGyt0PbszsxOgomnZ6BHQdohkI3zbgX2XRtRc0RycVyzkDtnuk1Nr4k8nEyhimtNea3nOZ5S3yQhrC7CPqpeoXqc/gzl5b2QrO1bC07TxUIMs9knOBR/SMWsXcSq2pzYY9FCW9+XsUVQ2XKi8CQmYiAi+rO8/RNLCkyz8OHkQuMtpdmv1YI7INkGwTr0wU0TVw1bC9ozc2GWsDeJGSYJBDn43uQQ+dyCr8xMhzkURYqjcvMYsgPUjTMY2AB0mFYow2XlRK67AE9hXrLSK25TIVHBH1JMkDx65jmH5jGQwmG8vbHjIoEygsJBRvy0hmb8uK7Pq1u5OyqnI=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.48.0
Release Details
UpdatedSept. 3, 2026, 9:09 p.m.
Changelog

Added

  • Tags can be hidden once they have served their purpose. A tag for a trip you have taken or a project that has finished keeps its history, but has no business in the picker for every new transaction — and deleting it would strip it from everything it is on. Editing a tag, on the Tags page for a global tag or in the category view for a tag-set tag, now offers a Hidden checkbox. A hidden tag is no longer offered when tagging a new transaction, bill, transfer or rule action, or when linking a savings goal, and it shows dimmed with a Hidden label where tags are managed so it can be found and unhidden. Everything that already carries the tag keeps it: the transactions stay tagged, the transaction filter and reports still list it, and a hidden tag already on the item being edited stays in its form, checked, so editing something else does not strip it (#373)
  • An account can be closed. An old bank account you no longer hold can be marked closed from the Advanced section of its edit dialog. It keeps every transaction and still counts in reports, the dashboard and net worth, but it no longer appears in any picker for new activity — the transaction and quick-add forms, transfers, bills, recurring income, imports, import rules, bank-sync mappings, savings goals and pension contributions. Pickers that filter history keep listing it, so its past stays reachable, and opening an old transaction that sits in a closed account keeps that account selected, labelled (closed). The accounts page lists closed accounts in a collapsed section of their own, and the account's page shows a Closed badge and drops the reconcile and card-payment actions. Closing is refused, with the reason shown in the form, while the balance is not zero, while any transaction is dated after today, or while an active bill, transfer, recurring income, pension contribution, bank-sync mapping or import rule still pays into or out of the account — the message names each one so it can be reassigned first. The standalone quick-add page and the import's account auto-matching skip closed accounts too, the interest accrual job leaves them alone, and the public API's GET /accounts gains an additive closed field so a capture client can filter on it (#372)

Fixed

  • Restoring a backup keeps the "exclude from reports" flag. The restore rebuilt each account field by field and never copied the flag, so every restore since the option was added put excluded accounts straight back into every total, silently. The new closed flag is restored the same way (#372)
  • The account form shows the real reason when an edit is refused. A refused account update always came back as "Failed to update account", hiding the specific message — including the reload notice a stale page gets when saving a debt. Refusals that carry a reason now reach the form verbatim (#372)
  • The unfinished-update warning now checks the database itself, and names the exact fix. It used to compare the migration files on disk with the list Nextcloud had recorded as run, and that misses both ways an install can actually be broken: a migration recorded as applied whose column is nevertheless not there, and a migration file that never reached the server. The instance that prompted this had run the recommended occ app:disable && occ app:enable to the letter and still could not save a bill, because that only re-runs what is unrecorded. The check now reads the live schema and compares it with every column the app writes, lists what is missing by table and column, and - for a change that is recorded but absent - names the precise occ migrations:execute budget <version> to re-run it, with the debug toggle those commands need. A column no migration on the server adds is called out as an incomplete install instead. The warning appears on the app's pages, in the admin overview, and in the error a failed save shows, where it now bypasses the "already verified" shortcut because a save just failed. Not being able to read the schema warns about nothing, as before (#333)
  • Repair Data no longer deletes both halves of a duplicate pair, and no longer orphans what hangs off a transaction. Its duplicate cleanup removed rows straight from the database, so any splits, tags, attachments and shared-expense records on a deleted transaction were left behind with nothing to join back to - invisible, and beyond the reach of every cleanup the app has, factory reset included. It also had three detectors flagging the same rows, each free to pick a different keeper: two placeholders written by the same payment share a creation time, so which one counted as "the real payment" came down to sort order, and a pair flagged both ways had both halves deleted - the payment removed along with its duplicate. Deletions now go through the same cascade every other part of the app uses, and a row another finding is keeping is never deleted; anything left ambiguous is simply left for a second run
  • Reconciling an account no longer means ticking your way through the whole ledger. A first reconciliation has nothing earlier to anchor on, so it starts from the account's opening balance - which means every transaction since has to be ticked before the difference reaches zero. On a real account that was 860 rows at 25 to a page, against an unfiltered list that still included scheduled rows dated years ahead. Starting a session now narrows the list to the account, to transactions dated on or before the statement date, and to rows not already reconciled - those are inside the starting balance already, so ticking one would have counted it twice - and the bar offers Tick all N transactions up to \<date> to do the whole statement in one click, leaving you to untick what your bank has not taken yet. Nothing is written to the transactions until Finish, so it is a starting point to correct from. The Create adjustment button no longer appears until something has been ticked, since before that the "difference" is simply the account's entire history, and the starting balance now explains in its tooltip where its number came from. Leaving a session hands the list back unfiltered (#374)
  • Marking a bill paid without recording a transaction no longer leaves it looking due. Choosing Don't create any transaction or linking one that already existed left the pre-created row for the occurrence you had just paid sitting in the ledger, still scheduled - so the bill went on showing as upcoming - and at the same time suppressed the row for the next occurrence, so the forecast lost it. One flag was answering two different questions. Recording the payment is now about this payment alone, and whether the next occurrence is pre-created is the bill's own Create future transaction setting, which is how skipping an occurrence and editing a bill have always read it. Existing leftovers clear themselves the next time that bill is marked paid. The dialog also now says that the bill moves on to its next due date whichever option you pick (#376)
  • Rows with an empty account column are imported instead of thrown away. A file that carries its own account column had every row with that cell left blank dropped, even though the import screen had already been told which account the file belongs to - one reporter lost 14 of 27 rows that way, in silence, and only noticed because the balance was wrong. A blank cell now falls back to the account chosen for the import. A cell that names an account which cannot be resolved is still reported rather than guessed at, since that one would misfile the row (#333)
  • The importer no longer invents an account out of a file's header row. With "first row is a header" switched off, the header line is read as data - and because it holds the column titles, its account cell held the word "Account:", which the importer duly created as a real account in dollars. Only a row that would import as a transaction can name an account now, so a header line is ignored the same way the import itself ignores it. New accounts the importer creates also take your default currency rather than always US dollars (#333)
  • The import tells you why rows failed instead of pointing at the server log. A partly failed import said "%n rows could not be imported - check the server log for details" and put the actual reasons in the browser console, where nobody looks - and on an instance whose logging is misconfigured, or where the admin cannot read the log at all, there was nowhere left to find out. The reasons now open in a window as soon as the import finishes, one line per reason with the rows it applies to, so fourteen rows failing the same way read as one problem rather than fourteen (#333)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignaturewDpgdodKiAH0BJNKoHpu1H3xardvLeUHU4/1s4cGzs/N9ZfELYEXGP9FnFBY0fSJWBscyElRGGL3vR58ISgUep5I5P9aX+JA/uHMtjeyafCVQGj/YNbhZtz/hKtNb2zM+erfMrzq6pLkleaPsCFoe5tEt3ufMZKASjvCpU1R3j4Ec6bDjiom1fk90CImC26ZItTfc5Vu/dxGtACVerJ0IvZzQPvR1J2FY1xDlqCeeuapHMmB/z3V5Px9JQU0BC+nM5qF335DutR30cz0BP7ghkp7juBWtj5fBMe2bRYmqu+AOVdcbniqHtHvktQmMjv77gQzTupn8tfNtOSf4qLK5YbiqOfMXnIIai5qmrgJE1tsO17hPQmpxol9owkPC2gRa7TwHsS09K3cMrEjpKNORD5hkFlc2m9eQR2xRAu68dWQwXkhbnmu42PcpwqQsKdLhDbwBWRJHyFqsMSds4mjYhUN5+wvQbWSsQTXoO8Z9InCntaQsDxR1rTX6CWxAy0gHx+ZD0hGv0ttqWbJzEiOPrlYwLbDvserRhlotDAahPDxsdV3PEwj28+Jtv04Ie0vE/k9n56NsAFY3e8PGjJE156W6+qurFoiXi2OcJynyAmsOsoj8DTLKnMsVMVtlw16lNZZ6uAANdDUrG1QOE8F065BkQxwg69PR3qHL3jfsgY=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.47.0
Release Details
UpdatedAug. 29, 2026, 9:47 p.m.
Changelog

Added

  • The import screen can be told which character encoding a statement uses. Some files simply cannot be identified from their contents: every single-byte encoding accepts every possible byte, so an undeclared Cyrillic export is indistinguishable from a Western European one and any automatic answer is a guess. The mapping step now carries a Character Encoding picker, listing Western European, Central European, Cyrillic, Greek, Turkish, Hebrew, Japanese, Chinese and Korean options alongside Unicode, with the detected encoding named in the hint beneath it. It sits directly above the preview, so a wrong guess is visible as mojibake and correcting it redraws the columns and preview immediately. Uploads are now kept exactly as they arrived rather than converted on the way in, which is what makes the choice reversible — previously the original bytes were discarded at upload and a bad guess could not be undone (#371)

Fixed

  • A statement that isn't UTF-8 is no longer read as Latin-1 regardless. Files that aren't UTF-8 were run through a list of fallback encodings, but the first entry accepts every possible byte, so it always matched and the rest were never reached — every such upload was decoded as Latin-1 whatever it actually was, turning a Cyrillic statement into Ïÿò¸ðî÷êà and a Japanese one into ûÀ;út;àz, with no error to say anything had gone wrong. A file that declares its own encoding is now believed: OFX states it in its header and camt XML in its declaration. Anything undeclared falls back to Windows-1252 rather than ISO-8859-1 — the two agree except over the range holding the curly quotes, dashes and euro signs statements are full of. Converted XML also has its declaration corrected to match its new contents, which previously made the parser decode the file a second time and produce exactly the corruption the conversion was there to prevent. Note that an undeclared file in a non-Western encoding still can't be identified from its bytes alone — single-byte encodings are indistinguishable, and testing for the multi-byte ones proved worse than not trying, since ordinary German, Spanish and French text validates cleanly as GB18030. That case needs an encoding picker on the import screen (#371)
  • Statements written in your own language import again. A CSV, OFX or QIF holding a decent amount of non-ASCII text was refused outright as "File appears to be binary" — which took in Cyrillic, Greek, Hebrew, Arabic and CJK statements wholesale, and caught plain accented Latin too, so a French or Spanish export could trip it as easily as a Russian one. The binary check allowed the first byte of a multi-byte UTF-8 character but not the bytes that follow it, and every non-ASCII character has at least one, so roughly half the bytes of a Cyrillic file were counted as unprintable against a 10% limit. High bytes are simply what non-English text looks like, in UTF-8 and in the older 8-bit encodings banks still export, so they no longer count against a file at all; genuine binaries are caught by their null bytes and control characters, which text does not contain. Reported with a diagnosis and a fix by @ba1amut (#369)
  • "Auto-pay when due" can be switched on while editing a bill. The checkbox needs a pay-from account, and the only thing that worked that out hung off the account dropdown's own change event — but opening a bill fills that dropdown from code, which fires no such event. So every existing bill opened with auto-pay greyed out, however long it had had an account, and the only way to reach the checkbox was to re-pick the account by hand. Creating a bill was unaffected, which is why it went unnoticed. The state is now recomputed whenever the form opens (#370)
  • Editing a bill shared with you no longer strips its category and pay-from account. Sharing is granted per type, so a bill can be shared while the account it pays from is not — and both dropdowns can only list what you are allowed to see. The form silently fell back to "No specific account", and saving submitted that as no account, wiping the setting off the owner's bill; the same went for an unshared category. The real values now stay selected, shown as Unavailable (not shared with you) so it is clear why they cannot be changed, and they survive the save untouched. Auto-pay is also refused server-side when a bill would be left switched on with nothing to pay from — a pairing the create path has always rejected (#370)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignaturexHUL+LrtKQmEHZ8YQwsy+xFaIqzNZrPxOFdHD44Th6v2oSFX5rCCI2kmScHUejaVOt1t0nLiJ2qf5ZSRVvOmPPeeinPhoqGhwYlP0Nkgt8Rb0x1zPZTJj63Na8ESocx7CpajZTDxKc8pAFrQJ+H03K4UDks+/1F0qFF2NYa1soV6+c+fIuMPDaYC+DjO3aeWaJabhTUgUymMmqHLxqlhAyw+a8LJ2ABwYyT8P/rmIQ267T72D8ng0f8/ubS4mvfICaoAbtMA8H5Rnn7/gcPMDv1nJyTv97ShefnigmiykqBSWJsJQE8Ax/RYNfXWJ3Gl9uRxzXigxKYwpGtWMFnE9G2JN/eOh5oG042V5wn1QI0QcfWG2QFilp5uOD6ZVTfyPG+um2Y0FQLFe4PJnxyYpnrXmWglFFMyEVCVa0a7+AJmb7DVfjz/9vhBewTYCJ/j9XDlw8Efu28ZYWtsgZ5vZIlH4a90WalHLWHprUsNLDrUSyl+WRLTWDYDfEviRHJBCrrcz34Zyo8An0+sM9ccQalvH78w4X9PDIL5pMS90MHgyYrXVGyMPqSG65FliBn0qku7pP8wCqUabT9Ac3ofyztTlj0dy+tHyuu0OLPb+FxaLUoCgw5PaOSNSOXgDw8amDnleLNrZjvHIEsoYCS2jXtxU0rrTbmFXi4djM4jyTQ=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.46.0
Release Details
UpdatedAug. 29, 2026, 2:08 a.m.
Changelog

Added

  • A Money Flow diagram shows where the money went. Reports gains a Money Flow type that draws the period's cash as a flow diagram: income categories stream into a central Cash Flow node, which fans out into your expense categories and their subcategories, with what's left shown as a Surplus band — or a Deficit feeding in when spending exceeded income. Amounts label every node, category colors carry through, and the usual period and shared-account filters apply (#366)

Fixed

  • Bills and income shared with you can be opened again. Opening a bill your partner created failed with "Failed to load bill", and so did every action on it: editing, deleting, marking it paid or unpaid, skipping a payment, and the Record transaction repair. Sharing grants visibility, not identity, but each of those looked the bill up as the person clicking rather than as its owner, so the app approved the action and then could not find the bill to carry it out (a DoesNotExistException in the log). Bill actions now run against the bill's owner, so a shared bill behaves like one of your own, and Mark Unpaid is offered on shared bills for the first time. Shared recurring income had the identical fault and is fixed with it, and its Mark received action — which had no permission check at all, only the scoping that made it fail — now refuses a read-only share properly (#368)
  • A transfer between accounts shared with you now completes. Creating a transfer in an account owned by someone else booked both sides and then failed to join them, leaving two unconnected transactions behind every attempt and putting the raw database query on screen as the error message. Both rows belong to the account's owner, while the linking step went looking for them as the person clicking. Linking, unlinking and Create and link now work across shared accounts, and a transaction you cannot reach reports itself as not found — which also means it reaches the log, where this failure left no trace at all (#368)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
Signaturex0J8AUUfQbAJljP4bb8goctxFgu6woboHqgqhSLiZLzSNh4/bgeYYYsy4ubudGRmEAdnJZqL9XcqPKKaaVIxVXVRFVCS24iGpCdqXhCW0MMvoROv7VMao+dHMrfPhungZxdm+nKurDuI2drTpZLmbckIj6+PnjLP0Z6M+a/P7wRw/3gtdHcf1KoNmRGNIlqUUolPhYJJFQbhgsf8yg/nzDMjm0OKXYvOKWSI+GR1HFQoNSLVx9TPk2zrBOT/ARpvDEStnWWBZxhn2shkEVFNE1ntupx4AmkerIySit3CB5j4H7imaHsIYwPHDhL+MEj9afFllpMnogByvQ+nHCvJ3v7PeuNYGgQTxMvoVKpvtPDyo2610eVQDQlK8UEzmOdimk7shlkllXiE/ZEIaeFINp17VuQbYlTwuuZlNfTendUZirhPFK4xR3AL6cpTxJHq/Xc/npPYAYk8wPyYseNnFL5A3/d2UXiT/m57GQiIMkTMrayR6kYmYjGYT2EAVSRjhA0wESnCJb6jVMc6YTcBVQ3uFXnA5gR1hdulx1Qj2lRhJpBSCcXBCl/4QHDv4OIhk4Is5DWUxcw91iuaBhMCpoJLwU+kkuaibIrsiV2L3np7EeZzPtxOsRG4GyCZRyvTvCVO7HVHu///wPi1sfMH4R05Ri0AUfbqdpqPrE70mG0=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.45.0
Release Details
UpdatedAug. 29, 2026, 12:59 a.m.
Changelog

Added

  • Bi-weekly schedules can be anchored to a date. Bi-weekly income, bills and transfers used to lock onto whichever week you happened to create them in — pick "every other Friday" and the app silently decided which Friday from the creation date, with no way to say "no, the other week" (#363). Transfers were worse off still: the form only offered a day-of-month field, which means nothing to a bi-weekly schedule (#364). Income now takes a First payment date for weekly and bi-weekly frequencies, and the transfer form gains the same start-date field bills have had — the date pins both the weekday and the week, and every occurrence lands a clean 14 (or 7) days from it, whether the date you give is in the past or the future. While a start date is set the weekday field follows it and locks, so the form cannot claim a different day than the schedule runs on. Note for existing bills and transfers: a start date you set before this release only delayed the first occurrence; from now on it anchors the schedule, so a weekly or bi-weekly bill with a start date will settle onto that date's weekday and week
  • Bills can be marked unpaid. Marking a bill paid by mistake was final: the Undo button lived in a ten-second toast, and once it was gone nothing could revert the paid state — deleting the payment transaction left the bill still claiming to be paid (#365). Every payment now stores what it changed, so a Mark Unpaid action on the bill reverts the most recent one properly: the due date rolls back, a one-time bill comes back to life instead of staying vanished, a statement-amount bill gets its exact amount back (which cannot be recomputed after the fact), and the payment transactions are cleaned up — including when you already deleted one of them yourself. Auto-paid and import-matched bills get the same revert, which the toast never offered them — a payment that was linked to an imported transaction unlinks it rather than deleting money that genuinely left your bank. Recurring transfers can be reverted too, from the Transfers view. The stored revert applies to the most recent payment only, and editing the bill's amount or schedule discards it — reverting would otherwise restore values from before your edit

  • CSV files without a header row can be imported. The importer always treated the first row as a header and silently ate it — a headerless export lost its first transaction with no way to say otherwise. A First row is a header toggle (on by default, matching the old behaviour) now controls it, columns are matched by position, and blank or duplicate header cells get translated "Column N" placeholders in the mapping dropdowns instead of untranslated internal names. Saved templates keep working: they store your file's real header names where they exist, so they survive language changes and column reordering. Templates saved from files with duplicate blank headers ("Column N (2)") need their columns re-picked once. Contributed by @Saviq (#367)

  • The database-updates warning reaches the admin overview. The check that detects the app's own migrations never having run (the "Unknown column" trap, #333) now registers as a proper Nextcloud setup check, so it appears under Settings > Administration > Overview and in occ setupchecks — visible to the admin who can actually run the fix, not just to whoever next opens the app

Fixed

  • A category drill-down into subcategories now says so. Opening a parent category's transactions (from Category Details or a chart slice) applies the parent plus its subcategories, but the filter panel could only display the parent — and picking the parent to narrow down to just it did nothing. The category dropdown now shows a combined entry like "Groceries + 2 subcategories" for the applied scope, and choosing the plain parent genuinely narrows to it (#361)
  • The bills list stops fetching every dead bill. Keeping paid one-time bills reachable for Mark Unpaid meant fetching the whole bill history and discarding most of it in the browser. The server now returns active bills plus the revertible ones directly, so the payload stays small however old the install (#365)
  • A category's count badge and its panel agree on damaged rows. A row carrying both its own category and split parts (the old bulk-edit damage) was excluded from the tree's count badge but still listed in the Category Details panel — off by one on the same screen. The panel now applies the same rule; Repair Data remains the way to fix the rows themselves (#360)
  • The split flag's grey states are resolved once and for all. Two damaged states have haunted long-lived databases: rows from before the flag existed (held NULL), and rows whose restore claimed they were split while the parts never made it into the old backups (#351). A one-time update resolves every such row from the parts table — the single source of truth — and restores now do the same, so the states cannot return. This fixes three real casualties: rule runs categorize legacy transactions again (they had started skipping every pre-2026 row while reporting success), assigning a category to a damaged row now sticks instead of silently vanishing while the row stayed listed as uncategorized forever, and the Uncategorized filter no longer offers up split parents whose categorisation is exactly how such rows were created (#360)
  • Find Duplicates no longer loses a next-day duplicate at a group boundary. Groups anchor on their first transaction so distinct purchases cannot chain together — but a pair one day apart could straddle two groups and the second copy went unreported entirely. Rows near the boundary are now carried into the next group, so every pair within the window is reported together and the no-chaining rule still holds (#333)
  • A savings goal that has gone backwards shows an empty bar, not a full one. The Savings view's goal list was the last progress bar without the negative clamp the others got in v2.44.2 — withdrawals exceeding deposits painted the bar completely full
  • The Category Trends tile sticks to expense categories. It relied on a side effect of the old one-direction totals to keep income categories out; with netted figures an income category could slip into the spending list. It now filters by category type explicitly
  • The database-updates warning can no longer be silenced by a mid-deploy race. If the check ran at the exact moment app files were being replaced, a failed directory read followed by a successful one within the same page load could record the version as verified while updates were genuinely pending — permanently hiding the banner on exactly the instance it exists for. The verified marker and the pending list now come from the same scan
  • Editing a bi-weekly bill no longer silently shifts which week it falls in. The consistency check that runs on every edit recomputed the due date "from today", so changing an amount or a note in the off week flipped the schedule's parity — the bill quietly moved a week. With a start date set, the schedule now recomputes from its anchor, and an unrelated edit can never move it (#363, #364)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureV/r+TeR/H5y0TiUgo9apV0nHrv4yLWR3o2yHxeSCrwBr87AyJBO6EphcfUm/aNNDYHbJfh2Nk4ghsMvljrNWPCgMFZdwynngNS3IbrSFauamMsnuvkxDcO5h+R5aAIyBfyog9idiDesDMJF2B1dDbe3COOlxDq5i8xiiP+BGqLpoeOYZKT2dpqoaYB9j16sGk5BSE07vSFnF8kz2PGcpgExtfEqMMVCDRGQUvU02KgLqNb6oFx0abf5NhRGTpNZPMyOMwWH0CVTATrZj7r9LBp8+HQqHUjCRqPTwsYbAVBZZKYwyrtU3Wd/4VaSpKW2bMS7OWA/663hc74b0Rt/QTy0brPK2oiQyM6PisiwlZHAz6nuQWRDUiyezWVS9yLBiVDavZxby7XJAIrb49a8dSESUj7/7eRaO9xAb21oULrp39o0d0GKWBxFf2fuV/uBJ/tQh1pgj7n5PHQ01kZ3Dy1znPGH//sIfsw5nBLeKQQGZvcp4ell+s19FJr2SoKe+HgY8Wo/eCobVpai8GbpeA1HsNc7ixuKIPdxpAsY7X/mNg92GEndFExIDBkUgQfbPYd+LkmjlJdtXqluxB24WdVIVdKDJakxk860CHTUo+k7UgVroJUffjXXwXvFKQCWZG8f/5Tt4eh3QpRfaqQGWpAjQ0lw/AURkUdA0FlN4ELo=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.44.2
Release Details
UpdatedAug. 28, 2026, 3:19 p.m.
Changelog

Fixed

  • The Budget page's Spent really does net refunds now. v2.44.0 said a refund comes off what you have spent, and it did — on the budget report, the dashboard tiles, the alerts and the digest. The Budget page itself reads a different query, which kept the old one-direction sum, so the very page the issue was reported against still showed $216.90 where Category Details showed $58.29. That query now nets the same way as everywhere else. A month whose refunds exceed its spending shows the true negative figure instead of being flipped into looking like money spent, and its progress bar sits empty rather than painting full — on the dashboard's Budget Progress tile and the savings-goal tiles too, where a negative used to render as a completely full bar. Changing a category's budget period also refreshes its row with the right direction and the selected month, instead of flipping an income category's Spent to a large negative until the next reload (#361)
  • "View All Transactions" on a category lists the transactions its figures are built from. The button quietly filtered to money-out only (money-in for income categories), so an expense category's refunds were missing from the very list the netted figures above it summarise — the panel said $58.29 and the list it opened could only add up to $216.90. It also ignored the panel's period and account selection, listing everything ever recorded. It now applies no direction filter and opens scoped to the same date window and account the panel is showing (#361)
  • The transaction filters panel shows the filters that are actually applied. Arriving at the Transactions view through a category's "View All Transactions" or a chart drill-down replaced the applied filters but left the panel's controls showing whatever they held before, so the list and the dropdowns above it disagreed — and because any change to one control re-reads all of them, a stale control could silently re-apply an old filter. The panel now rewrites every control whenever the filters are set for you, clearing the ones that no longer apply (#361)
  • The last places that ignored split transactions now count them. A split carries its categories on its individual parts, and five surfaces were still reading the transaction's own category, which a split never has. Year over Year compared a year of split receipts against a year that predated splitting and called the difference a collapse. The Forecast's category trends dropped every split into Uncategorized and showed nothing against the categories the money actually went to. The count beside each category on the Categories page read 0 for a category funded entirely by splits, next to a panel listing its transactions. Find Duplicates showed a dash where the category belonged. And a CSV export with no category filter left the Category cell empty on exactly the transactions someone had taken the trouble to itemise -- it now names them, and a category is named once however many parts of the receipt went to it (#360)
  • Find Duplicates no longer chains separate purchases into one giant "duplicate" group. Each candidate was compared against the previous row added to the group rather than the first, so five identical-amount purchases a few days apart -- a regular coffee order, a repeated fare -- linked end to end into a single group spanning far more than the 3-day window, and the tool told you to delete transactions that were nothing of the sort. A row now joins a group only when it is within the window of the group's first transaction (#333)
  • Deleting a category no longer leaves split parts pointing at it. The delete guard is deliberately blind to splits (a category used only by split parts must stay deletable), but nothing cleaned those parts up afterwards, so they kept referencing a category id that no longer existed. Deleting a category -- with or without reassigning its transactions -- now degrades its split parts to uncategorized, which is what the reassignment already did for ordinary transactions. Find Duplicates also names a split Split now instead of showing a dash (#360)
  • Splits from before the split feature existed are counted once, everywhere. A transaction whose split flag was never written -- imports predating the column, and backups restored from those versions -- was in a grey state: some queries treated it as a split, others as an ordinary transaction, so depending on the screen its money was counted twice, or not at all, or it was offered up for categorisation, which is how a transaction ends up claiming a category and carrying its own breakdown. Every query pair now agrees on one rule -- a transaction with split parts counts through its parts, full stop -- covering the budget carryovers, the monthly report, Year over Year, the forecast, per-account totals, uncategorized listings and rule runs. Restoring a backup now re-marks the transactions that actually received split parts, whatever the archive claimed, and the very large id lists a restore or a year-long report can produce are processed in batches instead of one oversized query (#360)
  • The app now notices when its own database updates never ran, and says so before anything fails. If Nextcloud replaces the app's files without finishing the upgrade, the database changes that came with the new version are skipped. Nothing looks wrong -- reading data does not touch the new columns -- and then the first thing you save fails with a database error nobody can act on. Every page now checks whether any of its database updates are missing and, if so, shows a banner naming how many and the command an administrator can run to finish them. Checking costs nothing once a version has been confirmed complete, and the banner clears itself as soon as the updates are applied (#333)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureDm8DKf6I3AofLr0FMZsDKeE4q19LhQ2NgVNbRwtRNtCcfcpkF7RWros6LUOJacOmyNa9EuRDVUGQJtTGSasNt4dXxhwDjw7hDsmm2NUaTTrnoLoY32V9zyBLZqtSLb30uZTr6O8q03UGO0MsNQr5IsOcNbi7KflfjmUbYY99cIycOm/FBoLBm+LWQlDH+eQZigjqEk5GMvsLgyY2LuYQE6226WS1W96gI3neUzwICij5OWn/hdkl4axB6Y2Ei7bWofiMRSwY4oeiLF1mmgk1C4OfyoZomZEhsytxXok5wt38K4SMQBL4A+zpVoQBp0cBdFrGUynC/eNtmQjS9nsJSs0woZ3H6+QrlMCmJ+PRqSbn5kEO7PBzXMXUYNg9mqd0mUeYjH0mW1SKpF51FsBKjMHNmi1ReNqQhiRAJq+9JzyiaUuCv/gigDXOaLCR5NvRld0RbMYfnWN9XZ18k8/b+oKwzBG/oY6mqmgR0mUl24lXHK7djSHbhfmCIAG6hpOxgrL6cFguUdqNuoCGhBvUaUBJn742J4Hh4Lx4jq+zQJE1rJf4xpNhcT6VKLJNS7DrSd62oPm80FBXSu9colzmlv3C67SDYwL5TxqdM8OCsPTJvH0IWnr9R+qrrPh5MMqy3XMDyYvzDMjiK0OWmzob4ZxMCg2gi1asdtcjd5PqNgU=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.44.1
Release Details
UpdatedAug. 28, 2026, 12:44 a.m.
Changelog

Fixed

  • When the app's update has not finished, the app now says so and how to finish it. If Nextcloud updates the files but never runs the app upgrade, the migrations that add new columns never run -- the app carries on reading fine, because reads do not notice a missing column, and then the first thing you save fails. Until now that surfaced as the database's own words, "Unknown column 'amount_type'", which is accurate and no use to anyone. Any missing column or table now comes with the command that fixes it: occ app:disable budget && occ app:enable budget. Reproduced against MariaDB, where neither occ upgrade (which upgrades the server) nor occ app:update (which looks for a newer release in the app store) does anything about it (#333)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureJfhfoodWHfhncS8NhWVo/wOO4gi2kDEn4S8M8TzZg5Qfbjwxmkmh4Pn294Og1wL1uIp5gbCGyS2aIzcDN0HoEf7DhN98hxRaZ5P5/5CBFLgTGTNwJmDX9A4Xtwk81o4/3jbeLAPUJspX2OkQKGzyNtFqrCi5aDG/JF5D0Yf49WBnYG3BZp5rSaEOmrD2Scm8D3EmE5wDsIIKg+Zl1iCVHsUX/Z7TG6lVzPxeW4JVIU4NX8hhUziOOGMXthSBM5GxZX4okbtfGm9uVeUOe49rT/kXcm7mTG2Xb/4Phywh7vFqMckiOTSwP2fLttq7LFUv0XtUoaOhxjfhFJBdQIDi9qhtJRMcRvXE8kPbswzpyN9W/nC6lv44Q0Bxse967DXVQ8ZoxIWCByl6/5Z4Ooi978d0lWc/HsZYqMX5SXTb3KoALYNCG2+8WfkXwF+kZ0kPc//K6Uh/r+lgO7Gx55xaR2XkmDhClY7u/PMhLOsc0segdjc4obFyHns/iTeKJjV+aEaOvlbNq5aDKioozMZr2vQhL9XfEv4rKLq5VTxaD0s/WOv4dMJxhA/7LRpC53OlPrFN1IKPgmXUS2v2gTtP7fF9eDvZ6u66ra9zTe/j+R7y2y8mMo0zcUMnPPUxJ5fgX5saIPC2svL65fawwwghOMQTiydg6jEmbipPDU38RJQ=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.44.0
Release Details
UpdatedAug. 26, 2026, 12:34 a.m.
Changelog

Added

  • Dashboard tiles can follow your budget period. Spending by Category, Top Spending Categories and Budget Progress gain a Current budget period date range in their gear settings, which tracks the Budget start day you set in Settings. If your money arrives on the 25th, the tile now covers the 25th to the 24th like the rest of the budget surfaces do, instead of cutting your cycle in half at the month boundary. Spending by Category's header chip names the days it is actually showing — "25 Aug – 24 Sept" — rather than repeating the setting back at you. The other tiles are unchanged: a balance-history chart and the income-vs-expenses series cover a span rather than one cycle, so the option is not offered there (#333)
  • Cash Flow Forecast and Year-over-Year now actually draw. Both tiles have been in the Add Tiles menu with a card, a chart area and a working server request behind them — and no code to draw the result, so they sat blank however long you waited. Both are off by default, which is why this went unnoticed. Cash Flow Forecast now plots your projected balance month by month, starting from today's balance so each step reads as a change, with that month's income and expenses in the tooltip; choose Next 3 / 6 / 12 months in its gear settings. Year-over-Year plots income against expenses for each of the last 2, 3 or 5 years, matching the chart on the Reports page so the two cannot disagree (#333)
  • The bills tiles let you choose how far ahead to look. Upcoming Bills and Bills Due Soon now take a Look ahead setting of the next 30, 60 or 90 days. Upcoming Bills previously showed whatever came first with no horizon at all, and Bills Due Soon was fixed at 14 days. Both still include bills up to a week overdue, so an unpaid bill does not vanish from the tile that exists to chase it — Upcoming Bills previously had no such cutoff and would show a bill overdue by months right alongside this week's, and now drops anything more than seven days overdue the same way Bills Due Soon already did (#333)

Fixed

  • "Last 30 days" on a dashboard tile now means the last 30 days. It meant the month so far: on the 24th you saw 24 days, and on the 1st of a month the tile charted a single day. "Last year" behaved the same way — the year so far, so on 3 January it showed three days. This is why a tile could flatly disagree with the budget alerts sitting above it on the same screen, and it hit anyone whose spending does not line up with the calendar month hardest, because the biggest bills of the cycle fell outside the window entirely. Affects Spending by Category, Top Spending Categories and Budget Progress. "Last 90 days" and "Last 6 months" were near enough but drifted by a day around month ends — six months back from 31 March landed on 1 October — and are now exact (#333)
  • Every Date Range dropdown on the dashboard now does something. Ten tiles offered one and ignored it: you could pick a range, it saved, and the tile carried on showing its own hardcoded window. Large Transactions had no date filter whatsoever — it ranked your biggest transactions over all time — and now honours the range. Weekly Spending was pinned to the last 7 days, and its daily average divided by 7 regardless; both now follow the range you pick, and its label — which always read "This week" — now names the range it is actually showing. That default week is now an explicit Last 7 days setting rather than a hardcoded one, so it is both the tile's starting point and a choice you can change like any other range. Category Trends compared this calendar month against last, and now compares the range you chose against the equal-length stretch immediately before it, so the two figures are like for like at any range. Where a range could never apply, the dropdown is gone rather than lying: Monthly Comparison is this month against last by definition, Debt Chart is a payoff projection with no window, and Income Tracking's headline is a monthly rate that cannot vary with one (#333)
  • The Cash Flow Forecast tile was asking the server for the wrong thing. It sent a days value the forecast endpoint does not accept, so the parameter was discarded and the default horizon used every time (#333)
  • When something fails to save, the app now tells you why. Errors across the app showed a fixed message -- "Failed to create bill", "Failed to save transaction" -- whatever had actually gone wrong, so a validation problem and a database problem looked identical and neither was actionable. Where a failure comes from the database the server already attaches a short, sanitised description of it, a missing column for instance, specifically so the cause is visible to people who cannot read their server's log. Nothing in the interface was reading it. That description now appears alongside the message everywhere a save, delete or update can fail -- transactions, accounts, categories, bills, rules, pensions, assets, transfers, income and bank sync (#362)
  • Bills with a statement or minimum-payment amount explain themselves when rejected. Those amount types only work on a transfer pointing at a credit card, and the two rules enforcing that were being replaced by the generic "Failed to create bill" instead of being shown. Genuinely unexpected failures still stay generic (#362)
  • Repair Data can clear the stray categories off your split transactions. The rows the old bulk edit and the rule runs left behind are still there, each claiming a category it should never have had. Settings > Repair Data gains Split Transactions Carrying a Category, listing every one it finds with the category currently stuck to it. Repairing removes only that stray category: the split stays a split, and every part of it is left exactly as it was. Genuine splits, ordinary transactions, and a transaction explicitly marked unsplit are all left alone, and the scan drains to empty once run rather than reporting the same rows forever (#360)
  • Rules no longer break a split transaction by categorising it. A split's categories live on its parts, and its own category is deliberately left empty -- so writing one onto it produces a row that claims a category and carries its own breakdown, which every per-category total then counts twice. Bulk edit was stopped from doing this a while back, but Run rule now and Run group rules write straight to the database and went around that guard, so rules were still quietly creating the damage. A rule now leaves a split's category alone while still applying everything else it does -- vendor, notes, tags and the rest -- so splits stay covered by your rules. The preview and the results list name such a row Split instead of showing it as Uncategorized, which read as a change that was never going to happen (#360)
  • A transaction damaged by the old bulk-edit bug is no longer counted twice. Before it was fixed, "filter by Uncategorized, select all, set a category" wrote a category onto split transactions without removing the parts underneath, leaving rows that claim to be in a category and carry their own breakdown. Nothing has ever cleaned those up, so they are still sitting in databases -- and the queries behind Spending by Category, the Reports charts and the Category Details panel added up both, reporting a split receipt at its full amount plus each of its parts, and counting it as two transactions. A category could therefore show more spending than the transactions underneath it actually came to. Each transaction is now counted once, through its parts where it has them (#360)
  • Budgets count the money you spent through a split. A split transaction holds no category of its own -- its categories sit on the individual parts -- and the query behind every budget figure only ever looked at the transaction's own category. So a receipt split between Groceries and Household added nothing to either budget: the progress bars read low, remaining read high, and the budget report agreed with them. Budget alerts have counted split money since they were added and the spending charts since v2.33.0, so a category could raise an over-budget alert while the bar right next to it showed room to spare. Affects Budget Progress, Budget Breakdown and Budget Remaining on the dashboard, the Budget view, Reports > Budget and its CSV and PDF, the scheduled monthly report email, and the Unusual spending section of the digest along with its notifications. Splits restored from a backup made before v2.41.0, which lost the flag marking a transaction as split, are counted too, and a transaction damaged by the old bulk-edit bug -- which stamped a category onto a split parent without removing its parts -- now counts through its parts rather than dumping the whole receipt into the one category it was stamped with (#360)
  • A refund now comes off what you have spent. Spent on the Budget page counted only money going out, so a bill that was refunded, a returned purchase or a reimbursed expense left the category looking fully spent -- a $216.90 phone bill with $158.61 credited back read as $216.90 spent, and the bar sat at 100% over a $120 budget. It now reads $58.29, which is the figure Category Details has always shown for the same category: the two screens disagreed, and the budget was the one that was wrong. The same net figure now feeds Reports > Budget and its exports, the Budget Progress, Budget Breakdown and Budget Remaining tiles, the budget alerts -- which is what stops a category raising an over-budget alert while the bar beside it shows room to spare -- and the Unusual spending digest, where a purchase you sent back no longer reads as a spike. Income categories are measured by what came in, with anything paid back out subtracted; Reports > Budget was previously asking for money-out on those too, so an income category with a budget reported nothing against it (#361)
  • A split transaction on the dashboard names the categories you sorted it into. Recent Transactions read each row's own category, and splitting a transaction moves the categories onto its individual parts -- so however carefully a receipt had been divided up, the tile called it Uncategorized. It now names the categories the parts went to, with a coloured dot for each and the part-by-part breakdown on hover, the way the transactions list and the account register have since v2.43.1. Where the tile is too narrow for all of them the names run to an ellipsis rather than pushing the amount off the row, and a split that arrives without its parts is called a Split, which is at least true (#360)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureQHxBHmyBaONUhmqkujdb3Z0HaVDO5kl4378wYHWJgtW/QHl6D1QNcKQzzhB2nVoXZz322zCDeUae1eIk3C+EX4X5q2MolNnL9UAL0TvS0oSfQcAtWTFCAO1Z79C1uYbCxM6CUNNrGmZdoZ41ivw9OJQOICFu5nd0RHQ+w25DUCKK0SOEQXWia7LN5o0RnpTwKYxSxQHIb4dajJvbWsW+oibyBkP/yZsbfJRls3Z2zWYvEEnQhWiKTaJC4Ijfz6DgP6U/M9Z5DjhIZgyxPy5OGTOLd9aZl64K3JzcQqKDKJJ8wTDz9iUXb+bCitxDyq0chgLG4tbSyFyK7+aAcWchHZXufXDmPmAsTikDVgc6srYeKyqv2VFpa/IBA1m0GeAzN2KqIRzDbiyttRGgQQ5i2VPH4owiA8un5ak46XVpD+q5Xy/SwEZVmjCY8AZsZePmPvM9gESC+hBy6P5YuNksSar/dD++REsQCeFkCIiqf4y61wyD0WY3qHYF4yDpWzH8vVhbKSMy0x9W1JR3ZUmv0MbidSvgiOwxpPPtWVuPPRDbLKg3ENzv4bq8IK8PzR0t5jHNSFKWu7C1jrJ3gE7yoxJ5zMnsw6v3HJhedy2Jfx2C2EZsZv1XCzaXYxKBr0uaHVcOSn9/4Rn9OXf95th7bgRN6aCrU34M1ELL3RmocKs=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.43.0
Release Details
UpdatedAug. 24, 2026, 1:27 a.m.
Changelog

Added

  • Liability accounts now ask what a positive balance means instead of guessing. Editing a credit card, loan, mortgage or line of credit shows an Amount owed field that takes a plain positive number — the app adds the minus sign — with a separate This account is in credit tick for the case where you have overpaid and the lender owes you. Switching an account between a debt type and a savings type converts the figure for you and shows the resulting current balance before you save. Creating a liability works the same way. The choice is recorded with the account, so an export and restore keeps it (#353)
  • Several CSV columns can feed one text field. Banks often split what belongs together — a merchant column and a details column, say, or a reference spread over two. On the import mapping step, Description, Notes, Vendor and Reference are now checklists: tick every column that belongs in the field and the values are joined with a comma, in the order the columns appear in the file, with blank cells skipped. The same works for those four fields on OFX, QIF and camt files, and a saved import template keeps the whole selection. A single ticked column imports exactly as it always has, so re-importing an overlapping statement still recognises its transactions. Thanks to @Saviq for the feature (#355)
  • Category trees can be exported and imported. The Categories page has Export and Import buttons next to Add Category. Export downloads your whole tree as a readable JSON file; Import takes that file back, or a CSV of Parent > Child paths, shows exactly what would be created before anything is written, and leaves categories that already exist untouched while adding whatever is missing underneath them. Handy for backing up a carefully built structure, sharing it, or having a spreadsheet or an AI assistant draft one and loading it in a single step (#354)

Fixed

  • Editing a loan or credit card no longer turns your debt into an asset. Typing your statement balance as a positive number into the Opening Balance field stored it as a positive number, which the app reads as "the lender owes you this" — so a £5,000 loan quietly added £5,000 to your net worth instead of subtracting it, a £10,000 swing, and every later recalculation re-derived the wrong balance from it. Nothing on screen said so. Positive balances on a debt stay supported, because a genuine overpayment is a real thing, but the app now asks which you mean rather than reading it off the sign. If this already happened to you, Settings › Repair Data will find it: run Scan for Issues and the new Debts Recorded as Being in Credit section lists every affected account with what it reads now and what it will read afterwards — untick any you really have overpaid, and those are recorded as genuine credits and left out of future scans. Two related consequences are fixed alongside it: an account you have overpaid no longer appears in the debt payoff planner as something to pay off, and it no longer counts towards Total Liabilities on the Accounts page, where it was pulling net worth down by twice the credit (#353)
  • An account edit that does not touch the opening balance no longer rewrites the balance. Renaming an account, changing its institution or ticking a checkbox resubmitted the opening balance every time, so an unrelated edit depended on that value round-tripping through the form perfectly. It is now sent only when you actually change it (#353)
  • Reopening a split transaction no longer scrambles its parts, and saving it no longer throws them away. A split of 10 into 1, 3 and 6 came back as 1, 9.00 and 0.00 — the second part had swallowed the rest and the third was empty. The parts were always safe in the database; the editor was overwriting them as it drew them. It fills the last row automatically with whatever is left over, and it was doing that after adding each row, so every stored amount was recalculated away the moment the next row appeared. It now draws all the rows first and works out the remainder once, which is what it should have been doing. If you saved a transaction from that scrambled view, the parts you saw are what got stored — the third one was dropped for being 0.00, quietly, because the total still added up. Worth re-checking any split of three or more parts you edited recently; their categories will have been wrong in reports for the months involved. Splits of four or more parts had a second symptom — Save appeared to do nothing at all, with no message — which is fixed by the same change (#358)
  • Filtering transactions by Uncategorized no longer lists your split transactions. A split transaction has no category of its own by design — its categories live on the individual parts — and the filter was reading that as "not categorised yet", so every split you had ever made turned up in a list meant for things needing attention. Split transactions are now left out of it, and out of the dashboard's uncategorised list and the "only uncategorised transactions" option when running import rules, which read the same way. The bulk-edit consequence is the one worth knowing about: filtering by Uncategorized, selecting all and setting a category used to write that category onto the split transactions caught up in the list, after which they were counted twice in reports — once for the whole transaction and again for each of its parts. Setting a category on a split transaction is now ignored rather than obeyed; unsplitting one still assigns a category as it always has (#356)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignaturelQsdNi/Ed5bU8/Ch8iyHVXKdX+l8qhRm8fCwRYfB/ObxW6pncVobhw57Bzvu/2yio4Wb+MyJ+DZ8T75pZ9+ugVmWX+q/VSLx4PEAmnr9upL0m7AvJN33BXARoFWBzKVFHnfEy/RuYgtxnNfOmoiblZXbAeBs5zyxxeQKrYSMSHfdwdG/t9HZNFNvFEyp7k7XEU1xQ5HaAo6kResw+25vTU/lkvJNXYmNnmWr3ZxUo7qphCOw/ZJU4aMi+g8RjrWIp86biPeM8mIr57Oacrm3fIQnGTgfk7lqX5FGTjhjLTnDKin+AyFQCpkuki47leJ+W4VwS/LvObLDHn/WcYhjmkdmGXTGFZGhVYAHz3VcPklRmERDkafXZ7lPk0tWZjma/W4SCf6u8Pu3Ni5fVeZ9Zp7qiCjNomRBmMl2nlW2EC/GYJAW7c78TM1Gq9qw6EAAweO5/7JMtOMaA4Klm1XKmE6CpDmu6Ox4E0+RiaDZJ6lHnC7JcfNweMtbgZb4tK/1nAXqum2v4vIQcIDpfk2ROqxkvthclKe05z2p1oe2qg/mEWqwx51ZHR0PvMhmNYGh9VVi3F7KiT0v1K6D06CAAOJu6TeJTMKX5asGJ8K2PkVKk0E7uVWGKp7+WRBU4ILvUftG5d8Pz7ChCY35XVwknHbY/Rx7DNno+1h3YzkblIU=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.42.0
Release Details
UpdatedAug. 21, 2026, 9:23 p.m.
Changelog

Added

  • Receipts can be filed wherever you keep your app data. Uploaded receipts have always landed in Budget/Receipts/<year>/<month>/ in your Files; a new Receipts folder setting lets you point that anywhere inside your own Files instead — Applications/Budget, say, to sit alongside other apps' folders. The year and month subfolders are still created underneath, and receipts attached before the change stay exactly where they are: the app never moves or deletes your files. Applies to uploads from the web form, the API and receipt scanning alike (#352)
  • Bank statements in camt.053 XML can now be imported. Many European banks — Swiss ones in particular — export statements as ISO 20022 camt.053 (and intraday camt.052) XML rather than CSV or OFX. Drop one on the Import page and it behaves like an OFX file: every account in the statement is listed with its IBAN, auto-matched to the account of yours carrying that IBAN, and routed there. The parser reads what the payer wrote (the remittance text), who the other side was (the counterparty, which becomes the vendor), the bank's own entry text, and the transaction type code, and a batch entry such as a collective payment is split into its individual transactions with their own counterparties. Duplicate detection uses the bank's own entry reference — more reliable than the CSV content hash — except where a bank stamps the same reference on every entry, in which case the hash is used rather than collapsing the statement into one transaction. Every camt.053 schema version parses, including files with the namespace stripped (#350)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureRhkTM0z3ZXIpnFc2BJ0widME7KmhTp6jnd/kaHn42N1eiC9JQhiDUCGmqbCweHhswB3HBwwBoG37XE5L/9s97L13vmrIT+19EVx+f3o2xHXeVe0J19F0BKOxyW5mKYt7xQqo/dwCQ+qDk06kH89XPta+ppz28+qcfaEnBiEtnnzlyeOqyXgs6qWuM/sZW/WUau5dPKZxfkK57IgPaBIfx/R8cttcyokpplD5kV+rmGz8+AvAbvqcT06aGCzjQQtK4/ADbBe7PiGxy7Yy64B9LhgphkHuXqk1hzJiuC0exn+8z02QXGq5g2nDbATK6ZF6n6v6wIrSnEZtvRBvd2rloAQe5K5aiP6Ae6TPyILrunKGTL7Je1d/sqWO+103WdwcfLSI2rYHM00CUOdmxRttecjkJvc+sarc7m1M+fFIePC4SC5RlKJin/v9tUf/m+ie0+/UvqrcReF6hjCfN7jp8LBNjJQGsbpOBm+WO6v2i5GSKV/vNWLw4qln0rQXobu0jdSIhraqes84wPmF1z7U/eQorqmB9Q+ig4mfTtR3zxVfcd6vVT5fseiDTVhbaLf144zLTSxWpgVscFSQitXsVnA3FHkHuXsy8OqYeGgtQHOPjwMocSN1udnp59Wth/jd6qxj9Gf9KjFYFi/fwjc+QcvHaTuGCycDo+4xny+evpE=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.41.0
Release Details
UpdatedAug. 19, 2026, 10:30 p.m.
Changelog

Added

  • The Help & Docs page now says how to support the project. A small section with the GitHub Sponsors and PayPal links — the same ones listed on the app store — for people who installed the app and never see either. The floating help panel carries the links too. Nothing nags: it sits in Help, and the app works fully without donating
  • A recurring transfer can now pay a credit card the way the card itself would, with the amount resolved fresh at every payment. Card payments have always been representable as recurring transfers, but only at a fixed amount — useless for a bill that is different every month, which left people faking it with duplicate bills or typing the figure in by hand each time. A transfer whose destination is a credit card (or line of credit) now offers an Amount type choice mirroring what card issuers offer: Fixed amount as before; Statement balance, which pays what was owed as of the due date — everything charged since the previous due date plus any remainder an underpayment carried forward, with later charges rolling to the next statement; Current balance, which clears everything owed at the moment of payment; or Minimum payment, which pays the minimum set on the card's account (never more than is actually owed). The figure is worked out from the card's own ledger when you mark the payment made (or auto-pay makes it), so it is never stale; the amount shown on the transfer between payments is the last one resolved, and the pre-booked next occurrence carries it as the forecast estimate. Reminders, the bills calendar and auto-pay all work unchanged, because the payment is an ordinary recurring transfer. The card's own account page joins in: a Statement due day field on credit-card and line-of-credit accounts records which day of the month the payment falls due — shown on the card's page as account information in its own right — and a Set up payment button appears on a card with no payment transfer, opening the form pre-filled with the card and that due day. Once a payment transfer exists, the page shows when the next payment is due (#347)

  • Subscribing to hosted receipt scanning, and managing that subscription, now happen from the settings page. With the Otherworld relay selected as the scanning provider, the admin settings show the plans with a Subscribe button that opens Stripe checkout in a new tab — the licence key is shown once after payment, emailed as a backup, and pasted into the field above. Once a key is saved the block flips to a Manage subscription button: your server asks the relay for a billing-portal link tied to that key, so changing plan, updating the card or cancelling needs no separate account and the key itself never reaches the browser. A hand-issued key (a trial, or one minted directly) is told plainly there is no subscription behind it rather than being bounced off a portal that would refuse it (#537)

  • A CSV export of every transaction you're looking at, not just the page on screen. The account Export button built its file out of the rows the browser had already loaded, so it silently stopped at 50 — a year-end export of 800 bookings produced a file of 50 that looked complete, which is worse than an error. The export is now built on the server from the same filters the view is using, so it covers the whole result set however many pages that is. The Transactions page gains its own Export button too, which with no filters set means every booking across every account in one file: previously the only export was per-account, so a club treasurer with three accounts had to stitch three files together. Filters still apply, so you can export one category, one date range or one tag set just as easily (#344)
  • The exported CSV now says which way the money went. Amounts carry a sign — expenses negative, income positive — so the Amount column totals correctly the moment you drop it into a spreadsheet, rather than adding your outgoings to your income. The Type column reads Income and Expense instead of the stored debit and credit. Transfers between your own accounts appear as they always have, one leg of each, which now means they cancel out in the total instead of inflating both sides. The file also gained Vendor, Account, Currency, Reference, Notes and Status columns — enough to do the books from without opening the app (#344)
  • A new Income & Expenses report, for the year-end job of showing what came in and what went out. Pick it under Reports and you get two tables — income by category and expenses by category — with each side's own total and the net between them, over whatever period you select. It exports to CSV and PDF like every other report, the CSV keeping the two tables as separate labelled sections so a treasurer's spreadsheet can take them straight. Like the other reports it respects accounts and categories you've marked as excluded from reports; unlike the transaction export, which is a plain ledger of what you filtered (#344)
  • The Belarusian ruble (BYN) is now one of the currencies you can pick. It appears wherever a currency is chosen — the default in Settings, an account's currency, a manual exchange rate — and amounts are written with the symbol after the number (1,234.56 Br), as they are in Belarus. Its daily rate is fetched alongside the other fiat currencies, though the historical series is not: the 90-day history comes from the ECB reference rates, which don't cover BYN, so a converted figure for a past date falls back the same way it does for any other currency the ECB doesn't publish (#343)
  • The API can split transactions, so capture apps can categorise receipt items too. POST /api/v1/transactions/{id}/splits sets the parts of a transaction, and POST /api/v1/transactions now takes an optional splits field so a phone can record the transaction, attach the photo and set the per-item categories in a single request. /api/v1/ocr/extract additionally reports the receipt's subtotal and tax, without which a client could not make the items reconcile to the total — splits must sum exactly, and most receipts print tax on its own line. GET /api/v1/capabilities gains splits_available so a client can gate its per-item screen on a boolean rather than parsing the version. All four are additions: no existing field was renamed or removed, so clients built against the previous shape are unaffected
  • Receipts with loyalty savings can be split too. A Clubcard, coupon or multibuy line means the items on a receipt legitimately add up to more than you paid — and that gap used to make the whole receipt look misread, so it was refused for splitting and flagged with a mismatch warning. The savings are now read from the receipt and become their own line in the split, at the printed amount but negative, exactly as tax gets its own line. Four shapes now reconcile: items alone, items plus tax, items minus savings, and both together. The mismatch warning still fires when the gap is genuinely unexplained, which is the case it exists for. Two robustness details, because the reader is a vision model that occasionally slips: when it under-reads the savings by a line, the server closes the gap from the printed total so the receipt still splits rather than being refused over a saving it half-missed; and an impossible negative tax or subtotal from the reader is dropped rather than trusted into the arithmetic
  • Turn a scanned receipt into per-item splits. After a scan, if the items on the receipt add up, the scan box offers to split the transaction into one line per item so each can carry its own category — useful when one shop trip covers groceries, household and a treat. Where the receipt prints tax separately, the tax becomes its own line at the printed amount rather than being smeared across the items, so every figure still matches the receipt in your hand. The offer only appears when the arithmetic actually reconciles (items alone, or items plus tax, equalling the total); a receipt with a discount line or an unreadable item is left as a single transaction instead of producing splits that would be rejected on save. Splits carry categories, not tags — tags remain per transaction
  • Receipts are filed by month and named after the transaction. They now land in Budget/Receipts/2026/08/ rather than one folder per year, and an uploaded photo is named 2026-08-05 The Corner Deli 23.77.jpg instead of keeping whatever the camera or capture app called it (often a UUID). That sorts chronologically in the folder and makes a receipt findable by shop or amount in Nextcloud's own search. Existing receipts are left exactly where they are. A file attached from your own Files keeps its name — it's your file, and renaming it isn't ours to do
  • Receipts can now be attached while you are still adding the transaction. The Receipts section used to appear only after saving — the attach endpoints need a transaction id — so adding a purchase with its receipt meant save, reopen, attach. Files you choose (or pick from your Files) are now held and listed with an "on save" tag, then attached the moment the transaction is created. If one fails to attach, the transaction is still saved and you are told which — re-submitting would only have duplicated it
  • Scan a receipt straight into the transaction form. When your administrator has set up receipt scanning, the Add Transaction dialog gains a drop zone: drop a photo on it (or click to pick one) and the date, amount, merchant and a suggested category are filled in for you to check. The photo is attached to the transaction when you save, so a receipt is one action rather than three. The box tells you exactly which fields it filled, how many items it read, and whether those items add up to the total — nothing is saved until you press Save, so a bad read costs a retype rather than a wrong record. Scanning also works when editing an existing transaction, where it only fills fields you have left empty: a scan is a suggestion, never an overwrite. The whole section stays hidden on servers with no OCR provider configured, rather than offering a button that cannot work
  • Receipt scanning can be configured from the command line: occ budget:ocr. Run it bare to see which provider is set, whether a key is stored, and — the useful part — whether the server can actually serve a scan right now. occ budget:ocr set --provider=custom --endpoint=… --model=… changes it, and --api-key-stdin reads a key from a pipe so it never reaches your shell history. It matters that this exists rather than reaching for occ config:app:set budget ocr_…: the raw config route looks equivalent but skips the provider and URL validation, and would store your API key in plaintext, since the encryption lives in the app rather than in Nextcloud's config layer. The command takes exactly the same path as the settings page, so a rejected value changes nothing and a key is always encrypted
  • A CSV column can now be mapped to a transaction's Notes. Bank exports often carry a line of extra information — a payment reference, a booking note, the counterparty's message — that belongs in neither the description nor the reference field, and until now it was simply dropped: the only way to keep it was to edit every imported transaction by hand. Notes now sits in the column mapping alongside Description, Vendor and Reference, and whatever you point it at is stored on the transaction. It also earns its own column in the import preview whenever something is mapped into it, so you can see you picked the right column before anything is written, and it can be saved in a template like every other mapping. Over-long values are truncated to what the field accepts rather than being imported into a transaction you could no longer edit (#340)
  • The API can now read a receipt photo into a draft transaction. POST /api/v1/ocr/extract takes a photographed receipt (JPEG, PNG or WebP) and returns a draft for the user to confirm: merchant, date, printed total, line items, and — on the vision-model providers — the currency when one is legible; nothing is recorded until the client saves it through the ordinary create call, so retrying costs nothing but another scan. The reading is done by whichever OCR provider the administrator configured (below); failures carry a stable machine code (ocr_not_configured, ocr_quota_exhausted, ocr_extraction_failed) so a client reacts to what happened rather than parsing prose, and ocr_available on the new GET /capabilities reports the real state so clients hide the flow instead of hitting the error. A category is suggested by running your own categorisation rules against the extracted merchant — computed on your server, so the provider sees the image and nothing else, ever. When the line items don't add up to the printed total the draft says so rather than silently trusting either side. Documented in the REST API guide and the OpenAPI description (#533)
  • Recording a transaction over the API is now retry-safe, and can carry the receipt with it. POST /api/v1/transactions accepts an optional idempotency_key: a client that times out on mobile data cannot know whether its POST committed, so a repeat of the same key within a week answers with the transaction the first attempt recorded instead of inserting a duplicate — the single most damaging failure a capture client can produce, closed server-side. The same call now takes an optional photo part, recording the transaction and attaching the receipt in one request, plus a merchant field and a type that defaults to money-out. A new GET /transactions/recent returns the newest activity flat and merchant-first for a capture app's glanceable list. Wire field names across v1 settled on snake_case (account_id, parent_id, line_items) before anything ships against it
  • Receipt scanning can now be set up, and it is off until you do. A new Receipt scanning block in Settings → Admin Settings chooses which OCR backend reads a photographed receipt: this Nextcloud's own configured AI provider, any OpenAI-compatible endpoint — a vision model on your own network is a first-class option, not a footnote — or Otherworld's hosted relay with a license key. The choice is server-wide and an administrator's to make, because it decides who else sees your receipts. Until one is chosen the app sends receipt images nowhere at all: there is no default backend and no fallback. Your server makes the request rather than your phone or browser, so an API key never leaves the server and a backend that isn't reachable from the internet works perfectly well. Keys are stored encrypted and are never shown again after saving — leave the field blank to keep the stored one. Only the image is ever sent; account names, balances and other transactions are not. The Receipt Scanning guide sets out exactly what goes where for each option. With the API endpoint above, scanning works for capture clients as soon as a provider is configured; the scan button in the web interface arrives in the next release
  • A documented REST API, so Budget can be reached from outside the web UI. A versioned, read-and-capture API now lives at /ocs/v2.php/apps/budget/api/v1 — list your accounts and categories, browse and filter transactions, record a new one, and attach a receipt photo to it. It authenticates with an ordinary Nextcloud app password (or a token from Nextcloud's Login flow v2), so there is no separate credential to manage and revoking the entry under Settings > Security cuts off whatever was using it. That makes a phone capture app, a shell script or an n8n workflow a matter of configuration rather than code — the REST API guide has worked examples, and a machine-readable OpenAPI description ships with the app. Version 1 deliberately stops at reading and appending: editing, deleting and everything else stays in the web UI, which keeps the contract small enough to hold still. Fields will be added to it, never removed or renamed. Every amount crosses the wire as an exact decimal string ("42.50") rather than a JSON number, so a client cannot lose a penny to floating point on the way in or out. Note this is quite separate from the internal endpoints the web UI calls, which follow the database and change without notice
  • The accounts page can now be tailored to what you actually want to see. A gear button next to the tile/list switcher opens display settings for the page. Tick which attributes appear on each account — account type, institution, (masked) account number, last reconciled date, converted balance, and, on tiles, the 7-day balance trend and the status dot. Drag those same attributes into the column order you want for the list view (Alt+/Alt+ does it from the keyboard); name and balance can be moved as well, they just can't be hidden. And choose how accounts are ordered: by name, balance, type, institution, last reconciled or date added, ascending or descending. Tiles follow the same attribute order as the list columns, hiding an attribute drops its column so the rest can spread out, and everything is remembered in your browser alongside the tile/list preference
  • Categories can now be left out of budgeting without being left out of everything else. A new Exclude from budgeting checkbox sits alongside Exclude from reports on a category. Where the reports flag removes a category from all spending figures, this one is budget-only: the category keeps counting in reports, the dashboard, insights and every total, and simply drops out of the Budget page, the summary cards, budget alerts, the budget vs. actual report and envelope rollover. Meant for spending you want to see but can't sensibly budget — gifts, medical bills, home repairs — so you stop being told you're over budget on a figure you never set. Excluding a parent excludes its subcategories too, and like the reports flag it stays with the owner on a shared category
  • Select every transaction matching the current filter, not just one page. Ticking the header checkbox on the Transactions list now offers "Select all N matching transactions" when more rows match than fit on the page, so a bulk delete or edit can cover thousands of rows in one go instead of 250 at a time. The selection is dropped if you change the filter, so a mass action can never silently include rows you're no longer looking at, and bulk deletes of many rows are much faster (the account balance is recomputed once per account instead of once per row) (#336)
  • A Help & Docs page, in the app. The sidebar's Help & Docs entry used to throw you straight out to GitHub. It now opens a real page listing every guide with a one-line summary, a shortcut to the keyboard cheat sheet, the Quick Add page URL, and the System Info panel for pasting into a bug report. The floating ? button still gives you the short version for whatever page you're on, and now links through to the full page

Changed

  • A saved OFX/QIF template now remembers your field mapping as well as your account routing. These templates stored the routing only, so a bank that puts the payee in the memo had to have Description and Notes re-pointed on every single import — the choice was silently reset to the format defaults each time. Picking a saved template now restores both. Templates you saved earlier carry no mapping and are unaffected: their routing applies exactly as before and the mapping keeps the defaults (#340)
  • A reference longer than 100 characters is now refused when you type it, instead of failing when it is saved. The field was validated against a 255-character limit while the database column holds 100, so anything in between passed every check and then broke on the way to disk — a clean "too long" message is a better outcome than a server error. Nothing already stored is affected (#340)
  • A rule condition saying an import source is not something will start behaving differently on OFX and QIF imports. Because those imports never recorded a source at all, a negated Import Source condition matched every row from them; now that they do record one, it is evaluated for real. If you have a rule along the lines of source is not "Bank Sync", check it still does what you meant on your next OFX or QIF import (#338)
  • An import rule that sets notes "only if empty" no longer fires on OFX rows that carry a memo. With the memo now kept in the transaction's notes (above), the field is genuinely no longer empty on those rows, so an if empty rule correctly leaves it alone; an append rule adds to the memo rather than replacing it. Rules set to always overwrite are unaffected (#338)
  • The bill, transfer, savings goal, debt scenario, pension, asset and contact dialogs now use the same layout. Each was a narrow single-column form that had to be scrolled; they are now laid out in columns sized to what they actually hold — three for a bill (Bill, Payment, Schedule) and a debt scenario (Scenario, Payments, Debts), two for a transfer, goal, pension and asset, and a compact single column for a contact. Everything in them is visible at once, with Save and Cancel pinned below the fields. A bill's split rows span the full width of the dialog rather than being squeezed into a column, and a pension shows the pot fields or the income fields depending on its type, without leaving a gap where the other one would be
  • The four tag dialogs now match the rest. Add Tag, Edit Tag, Add Tag Set and Edit Tag Set are two-field dialogs, so they stay compact rather than being stretched into columns — but they pick up the same chrome as the bigger dialogs: a rule under the title, and Save/Cancel on a divided bar at the bottom right instead of loose against the left edge
  • The category dialog gets the same treatment. Naming fields (name, type, parent, colour) sit under Details on the left, the two exclusion options under Options on the right, and Tag Sets spans the full width below them — no scrolling, and the two checkboxes now read as ordinary checkbox rows instead of a bold heading with a stray box floating above it
  • The transaction dialog gets the same three-column desktop layout as the account dialog. Adding or editing a transaction was a 500-pixel-wide strip roughly a screen and a half tall, with a line of help text under every field restating its label. It is now laid out as Transaction (date, account, type, amount), Details (description, vendor, category, split toggle, tags) and Extras (receipts, notes, exclude from forecast), all visible at once with nothing to scroll for. Switching on Split across categories opens the split table across the full width of the dialog instead of squeezing it into a narrow column
  • The account dialog now fits on one screen. Adding or editing an account meant scrolling through roughly two screens of form in a narrow 700-pixel strip — eighteen fields, most of them empty, each with a line of help text underneath repeating what its label already said, and the Save button stranded at the very bottom. The dialog is now laid out for a desktop screen: three columns — Details, Banking, and Rates & limits with Advanced beneath it — showing every field at once with nothing to scroll for and nothing hidden. A column block with nothing to offer your account type, such as rates and limits on a Cash account, doesn't appear at all; Save and Cancel are pinned below the fields; the help text that merely restated its label is gone; and the current balance is shown as the calculated figure it is rather than a text box you can't type into. The columns reflow to two and then to a single stack on narrow windows and phones
  • The documentation has a home of its own: budget.otherworld.dev/docs. Every link that used to send you to raw Markdown files on GitHub — the in-app help panel and Help & Docs page, the README, the install guide and the app store listing — now opens the rendered site, which is searchable and readable on a phone
  • The Settings page is tidier. The Save Changes / Reset All to Defaults buttons were stranded in the middle of the page, with the Quick Add Page and System Info sections stuck below them, and Danger Zone was not the last thing on the page. Sections now run in a sensible order, with Admin Settings and Danger Zone at the end and the buttons at the very bottom. Quick Add Page and System Info have moved to the new Help & Docs page, since neither was a setting
  • The action buttons on an account row in the list view no longer sit flush against the last column

Fixed

  • The backup now actually contains your data — all of it. The export/import zip under Settings → Migration carried only categories, accounts, transactions, bills, import rules and settings; everything else silently vanished when moving servers. Reported for tags (#351), but the full list of what a migration used to lose is sobering: tags and their assignments, tag sets, transaction splits, recurring income, savings goals, assets and their value history, pensions with contributions and snapshots, per-account interest-rate history, manual exchange rates, import templates and remembered account links, saved reports, net-worth and budget history, reconciliation history, debt payoff scenarios, muted categories, shared-expense contacts with their shares and settlements — and on transactions, the links joining transfer pairs (so every transfer fell apart into an income and an expense), bill references, the split flag, and reconciliation/pension links. All of it now exports, and imports with every cross-reference remapped to the new server's ids. Old backups still import exactly as before; new backups are format 1.2.0. Deliberately still excluded, and now stated in the archive's manifest: bank-sync connections (provider agreements are instance-specific and must be re-established), shares with other users (they reference people on the old server), receipt files (stored in Nextcloud Files, not in the app), and the fetched exchange-rate cache (your manually set rates are included)
  • Marking a recurring transfer paid no longer loses the deposit half of its pre-booked transactions. When a transfer had its next occurrence pre-booked as a scheduled pair, marking it paid cleared the withdrawal leg but deleted the deposit leg — the source account paid out and the destination account never received the money, quietly understating it by one payment each cycle. Both legs of the pair are now cleared together. Payments already recorded this way are missing their deposit; the Convert to transfer action on the surviving withdrawal recreates the other half
  • Transfers no longer count as income and spending in the analysis reports. The dashboard's income and expense totals have left transfers between your own accounts out since 2.28.0, but the Reports page never got the same treatment: a £500 transfer appeared as £500 of income in Income Analysis (grouped by month, source or category) and £500 of spending in Expense Analysis (by month, vendor, account or tag) — and in the new Income & Expenses report only the incoming half was counted, overstating the net by the full amount moved. Every report view now excludes linked transfers, matching the dashboard, so shuffling money between your accounts changes no report figure. Two things are unchanged by design: a report filtered to a single account still shows that account's own transfer legs, because the money genuinely entered or left it; and only transfers the app knows to be transfers are excluded — ones created with the Transfer type, recurring transfers, and rows joined with Match transfer. Two unlinked rows entered by hand still count as ordinary income and spending (#349)
  • "Use Default Categories" failed with "A category with this name already exists" whenever any default was still present. The button seeds the whole catalogue in one go and gave up on the first name it found already taken — creating nothing at all. Easy to hit without doing anything odd: the category list shows one side at a time, so emptying the Expense view put the button on screen while the Income tree still existed in full, and pressing it failed on Income before a single expense category was created. Seeding now fills in exactly what is missing — an existing category is kept as it is, its missing subcategories are added underneath it, and everything else is created around it — so the button always finishes what it can instead of refusing the lot. A double-click while the first request was still running could also race itself into duplicates; the button now ignores the second click (#348)
  • Amounts in Kazakhstani tenge were shown with the code rather than the symbol. KZT was selectable and priced correctly, but it was missing from the front-end's symbol table, so every figure came out as KZT1,234.56 where the rest of the app would have written ₸1,234.56
  • Envelope budgets ignored everything you spent in a category's subcategories, so the whole budget rolled over untouched. The carryover looked for spending filed against the budgeted category itself and nowhere else. Budget €300 on Groceries and file the receipts under Groceries › Supermarket — the ordinary way of using subcategories — and it found nothing to subtract: July carried the full €300, August carried €600, September €900, growing by the untouched budget every month. The same screen said so in two contradictory ways, because the Groceries row itself has always added its children up: "spent €250 of €300" sat directly beside "+€300 carried". An envelope now covers the whole branch — the category and everything filed underneath it — so the amount carried forward is the leftover you'd work out by hand. A subcategory with its own envelope still keeps its own chain and is left out of its parent's rather than counted twice. Subcategories stay out of a parent's envelope when you've excluded them from budgeting or from reports, when they budget on a different period (a quarterly amount can't be added to a monthly envelope), or when they're income categories — and so does anything filed underneath those. Budget alerts and the budget-vs-actual report read the same corrected figure. Nothing was stored wrong: the carryover is recalculated from your budgets and transactions every time it's shown, so the numbers correct themselves as soon as you update (#341)
  • Envelope budgets also ignored anything you spent in a shared account, with the same result. The two queries the carryover uses to total up spending were scoped to the accounts you own, while every other budget figure on the page is scoped to the accounts you can see. So a category you fund out of an account shared with you looked untouched to the envelope: the full budget rolled forward each month, next to a row that correctly showed the money as spent. Budget alerts had the same split — they now measure spending over the same accounts as the budget they compare it against, including their split transactions (#341)
  • A long CSV column could import a transaction you were then unable to edit. Text taken from a CSV was stored exactly as the file wrote it, with no regard for what the field can hold. A notes column over 2,000 characters — easy to hit with a bank that packs a whole payment reference into one cell — imported perfectly happily and then failed validation the moment you opened that transaction, so no change to it could be saved until you shortened the note by hand. Over-long Vendor and Reference values were worse on MySQL and PostgreSQL: the row was rejected outright and counted as an error rather than imported. Imported text is now truncated to the field's limit, exactly as OFX and QIF imports already were, and leading or trailing whitespace is stripped rather than stored (#340)
  • "Check the server log for details" pointed at a log with nothing in it. When rows failed to import the warning told you to look in the server log, but the import never wrote there — the only record was in the browser's developer console, which is not where anybody was being sent. Failed rows, unresolvable accounts and balance recalculation failures are now logged properly with the row number and the underlying error (#340)
  • The column mapping step never highlighted the columns you had mapped. Each mapped column was supposed to be marked in the preview table underneath; the highlight was looked up by column position while the mapping holds column names, so it silently matched nothing and no column was ever highlighted for any ordinary CSV (#340)
  • A transaction added "today" could be filed as a future payment and left out of the account balance. Whether a date counts as future was decided using the server's calendar, but the date comes from yours — the web form pre-fills your device's date, and a capture app sends the phone's. Whenever your local date ran ahead of the server's, everything you recorded was quietly marked scheduled, and scheduled transactions are deliberately excluded from the balance: you added a purchase and the balance did not move. On a UTC-hosted Nextcloud that is the hour after midnight for anyone in British Summer Time, and most of the working day for anyone in Australia or New Zealand. The date is now judged in your own timezone (the one Nextcloud already knows from your session), falling back to the instance's configured timezone, so today is today wherever you are — while genuinely future-dated payments are still scheduled and still stay out of the balance until their date arrives. Transactions already misfiled this way corrected themselves within a few hours through the existing scheduled-transaction job; nothing was lost
  • QIF import has never worked: it reported rows in the preview and then imported none of them. A QIF file's accounts are matched to yours by an identifier the QIF parser never actually produced, so every account in the file was skipped — the import finished reporting success, with zero transactions added and no error to explain it. Underneath that, the parser had no notion of where it was in the file: an !Account header block was read as though it were a transaction (importing a row dated with the account's description), and because a real Quicken export opens with its category list, that whole list was read as an extra account containing one bogus transaction per category. Accounts are now identified by their name in the file, !Account blocks set the account's name, type and description as they should, and the sections that never held transactions — the category list, classes, memorised payees, security prices — are skipped instead of being imported as data. A file that does not name its accounts shows them as Account 1, Account 2 in file order. Dates are also read properly now: Quicken pads them to a fixed width (12/ 4'98), which nothing recognised, and a date that cannot exist — a 13th month — was passed to the database as text rather than being rejected (#338)
  • Import rules could not match on "Import Source" for OFX, QIF or any non-CSV import. Only CSV imports recorded where a transaction came from, so a rule condition on Import Source was silently false for every OFX and QIF row — and, because an unknown field inverts under a NOT, a rule saying source is not … fired on all of them instead. OFX and QIF imports now record OFX Import and QIF Import, joining the existing CSV Import, Bank Sync and Toshl, and the values are listed in the rules guide. Note the source describes how a transaction arrived and is not stored on it, so this criterion still matches nothing when a rule is re-run over existing transactions — the guide now says so (#338)
  • The column mapping did nothing at all on OFX and QIF imports, and the memo was thrown away. Every field in the mapping step could be changed and none of them had any effect — the import silently ignored the mapping and always took the description from the OFX name field. Banks that put the real payee in the memo instead (a common Canadian pattern) had no way to import a usable description, and the memo itself was parsed, shown in the preview, and then discarded rather than saved anywhere. Worse, a statement whose entries carry only a memo and no name imported with a completely blank description. Now: Description, Notes, Vendor and Reference can each be pointed at any field the file actually contains, the memo is kept in the transaction's notes by default, and a missing name falls back to the memo instead of importing nothing. Date, amount and type come from the file's structure and are no longer offered as mappable, along with the income/expense, account and currency columns that these formats never had — those dropdowns are gone rather than left on screen doing nothing (#338)
  • The import preview showed every amount as a plain positive number, whichever way the row was going. The preview is sent each amount unsigned with the direction alongside it, and it drew the number while ignoring the direction — so a statement of nothing but expenses previewed as a column of figures indistinguishable from income, and the step whose whole purpose is to be checked before anything is written could not show the one thing most worth checking. Amounts in the preview are now signed and coloured: an expense reads -€91.29 in red, income €500.00 in green, and the column is right-aligned so the figures line up. What was imported was correct all along — only the preview was silent about it (#339)
  • A negative amount written any way other than a leading hyphen imported as income. Only -1234.56 was understood; every other notation had its sign thrown away with the currency symbols. That covers a trailing minus (1.234,56-, as written by a number of German and mainframe exports), brackets ((1,234.56), the accounting convention several US and UK banks follow), and a typographic minus or dash in place of an ASCII hyphen. A trailing minus was the worst of the three: left on the end of the number it also pushed the decimal separator out of place, so 91,29- imported as income of 9,129.00 — a hundred times the real figure, on the wrong side of the ledger. All three now import as expenses, and a lone - in an amount column still means "nothing here" rather than a negative. If you have already imported a file with trailing minuses, re-importing it will add the corrected rows rather than recognising them as duplicates, because the rows that went in were keyed on the wrong amount (#339)
  • Dialogs on the Assets, Pensions, Savings Goals, Debt Payoff, Tags and Import pages opened behind the sidebar. Fourteen dialogs — including Add Asset, Add Pension, New Scenario and Add Savings Goal — were written inside the page content area, which Nextcloud paints as its own layer. A dialog can never rise above the sidebar from in there, however high its own stacking order is set, so it appeared cut off behind the app navigation. They now sit alongside the dialogs that always worked, and cover the whole window like the rest
  • The remove button on a split row sat under the Description box instead of beside it. The row's Description input was written without its closing bracket, so the browser swallowed the tag that should have ended the field and folded the remove button into it — the row's fourth column stayed empty and the ✕ dropped onto its own line. It now sits at the end of the row where it belongs
  • A mapped Type column is no longer ignored, so unsigned exports stop importing as all income. Mapping a Type column (Expense/Income, Debit/Credit, DR/CR, Withdrawal/Deposit, …) had no effect: the direction was always taken from the sign of the amount. Files that write every amount as a positive number and state the direction in a separate column — Nextcloud Tables exports, and a number of banks and budgeting apps — therefore imported every single row as income, quietly moving the balance the wrong way by twice the amount. The mapped column now decides the direction; rows where it is blank or unrecognized still fall back to the sign (#333)
  • The import preview now warns before a batch goes in the wrong direction. Two new warnings appear above the preview summary: one when a mapped Type column is blank or unrecognized on some rows (naming how many), and one when nearly every row would be booked as income into an account whose history is nearly all expenses, or the reverse. Neither blocks the import (#333)
  • Every transaction showing "Unknown Account" after restoring a backup. Restoring a backup gives every account a new id, but a page that was already open kept the old ones, so nothing in the ledger could be matched to an account and the whole Account column read Unknown Account — with nothing in the browser console to explain it. The same happened in any second tab left open during a restore. The transaction list now notices that it is holding a stale account list and refreshes it by itself, and a restore finishes reloading its data before reporting success (#333)
  • A failed accounts request no longer blanks the Category column too. If the accounts request failed while the app was loading, the rest of the load was abandoned as well, so both the Account and Category columns fell back to Unknown Account and Uncategorized behind a generic "Failed to load data" message. The two lists now load independently, and the message names which one failed and says to reload the page when an expired session is the cause (#333)
  • Select all now counts during reconciliation. In a reconciliation session, the header select-all checkbox ticked the row checkboxes visually but the Ticked total and Difference didn't move, and the ticks never reached the server — so they were also silently lost when leaving and resuming the session. Select all now registers every row it ticks (or unticks) with the session exactly like a manual tick, and no longer wipes ticks made on other pages of the list (#337)
  • Deleting an account that still has transactions now offers to delete them too, instead of failing with an unhelpful message. The delete failed with "Failed to delete account: Failed to delete account" — the real reason (the account still has transactions) was being replaced by a generic message on its way to the browser. The prompt now says how many transactions the account has and offers to remove them along with it, which makes a bad import easy to undo; decline and nothing is deleted. Transfers pointing at the deleted transactions are unlinked, leaving the counterpart in the other account intact (#336)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureBbOGARv5bo0EfD87OHApDK4LSAVbklBnbu7Q0XNAXlA/b120kU9X1ByNzLNwChmoeOLSrKp+saviED0SZkaaD2VdC6KM+2NghhWl/8RsDzdjLnUS5mbhQ04KOXOClJ1iHzwKIRJvAkStGLPAP/McI7ol6QLHi3ABWXWDlBcT6bGKDC6v7cmbh9jOeoys4phwH0uJE9pOVlQg7SfHGd/VJKr6pcScapT9P5dOBj878vpqjYSc3KIFvQ5OfA9C836sCseYxi9jM8YPoaw+LzTfX5/t80Fv5I2woXsvXnwtjijARCotyD1uZ9QMAy7M5LLkEm6yUGjJYrEBMBpc3h8fiC7muLojTK+J9O7zk7oYNN8D6Q2YqdJ3e84cEagzf83gbKicTPX4kJ9C8bvUQzK5roVtgFwat/Ndu9c2uK/rwOUVmDKPHdzt3/SQQAl9712dX7lZTJVN9r3dm87AL1nfaJghemZOfQdcQwFkahMlHZOm+B0xKrSUqQWyfbw4xezPvVZEudqpPIhQ0lIlFro93ziB7KBUJvaJCx0UNMFr2Z4zCDY64wKLaq1sgSm8HQ4QxSdL1+bPWgTG+BVzchvbx6Cmh7DHmXTAr5XGPzEczdMWY0t16uZ4ZzftT5Ss+S/NKpV37SiFKPOKWzou4BFGU9qwl0DeYKy4E+/EDMX0W80=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.40.0
Release Details
UpdatedJuly 26, 2026, 9:40 p.m.
Changelog

Added

  • Keyboard shortcuts. Budget can now be driven from the keyboard. Press ? anywhere for a cheat sheet. Globally, / (or Ctrl/Cmd+K) focuses search and g then a letter jumps to any page in the sidebar (g d Dashboard, g t Transactions, and so on — every page has a letter). Any dialog now closes with Esc, traps Tab inside itself, focuses its first field on open, and saves with Enter. On the Transactions list, j/k move a row cursor, e (or Enter) edits the highlighted row, and x selects it. Shortcuts stay out of the way while you're typing in a field
  • Export and import your import rules as a file. New Export and Import buttons on the Rules page: Export downloads every rule you own as a single JSON file (a lightweight backup, or a way to move your rule set to another instance without a full data export); Import reads such a file back in and creates the rules. A rule referencing a category or account that doesn't exist on the target instance is rejected and reported rather than mis-filed. Rules shared with you are left out of the export, and rules remain part of the full data export too (#318)
  • Import rules can now be shared. Rules join the list of things you can share with another Nextcloud user (alongside accounts, categories, bills, income and goals) — pick which rules to share, read-only or read/write, from a share's Configure panel. Shared rules show a Shared badge on the Rules page, can be run and (with write) edited by the recipient, and run during their imports too; only the owner can delete one. A shared rule's set category/set account action only takes effect for the recipient when that category/account is also shared with them, so a transaction is never filed under something they can't see (#320)
  • Import rules can now match on the account. A new Account condition scopes a rule to a specific bank account (with NOT for "any account except this one"), and a companion Account Type condition matches by kind of account (checking, savings, credit card, …). Both work when importing into an account and when running rules over existing transactions (#322)
  • Tag sets now work on shared categories. Opening a category shared with you shows its tag sets; with write access you can add, edit and delete tag sets and tags on it just like your own categories, and read-only shares show them without edit controls. Previously any tag-set action on a shared category failed (#328)
  • Bulk edit can now clear a transaction's category. The Bulk Edit Transactions dialog's Category dropdown gained an Uncategorized option alongside Don't change, so you can un-categorize many transactions at once (#332)
  • Deleting a category that still has transactions now offers to reassign them. Instead of blocking with "reassign or delete them first", the delete prompt offers to move the category's transactions — and any in its subcategories — to Uncategorized and remove it in one step (#332)

Fixed

  • The browser Back button now moves between pages inside Budget. Switching pages (Dashboard, Transactions, Accounts, …) records a history entry and updates the address bar, so Back and Forward step through the pages you visited in the app instead of jumping straight out to whatever you were looking at before you opened Budget. The current page also survives a refresh, and links that deep-link into a page (e.g. from search) still work.
  • Bills with "Auto-pay when due" turned off could still auto-pay themselves. The auto-pay flag (and the other bill toggles) could be read as on when it arrived as text rather than a true/false value — the classic (bool)"false" trap — so a bill created or restored with auto-pay off could still be auto-paid. All bill toggles are now parsed strictly as booleans on create, edit and import (#335)
  • Cryptocurrency accounts and their transactions now keep full precision. Amounts were capped at 2 decimal places on entry and storage, so e.g. 0.00012345 BTC was rounded to 0.00. Account balances, transactions and splits now accept and store up to 8 decimals, following each currency's native precision (BTC 8dp, XRP 6dp, JOD 3dp, and so on); fiat currencies are unchanged and still 2dp. Amounts on bills, recurring income and savings goals denominated in crypto are not yet covered (#331)
  • Shared categories keep the owner's order, and editors can reorder them. Recipients saw shared categories in an arbitrary order and couldn't move them; they now appear in the owner's order, and a write-share recipient can drag to reorder (the new order applies for the owner and everyone it's shared with). Reordering no longer silently fails when sort positions collide — the whole sibling group is renumbered on each move (#328)
  • Shared categories now open for the recipient instead of doing nothing. A read-only shared category couldn't be selected in the list at all, and even when reached its detail/recent-transactions/spending endpoints returned 404 (they looked the category up under the viewer, so one owned by someone else was never found). Clicking a shared category now opens a read-only view showing the owner's transactions and analytics for it (#328)
  • Recording a bill's payment failed when the bill used a shared account. A bill can point at an account owned by another user — a partner's shared account — but marking it paid, and the one-click Record transaction repair, threw "Failed to record payment" (a DoesNotExistException in the log) because the transaction was booked against the person clicking rather than the account's owner. Bill payments are now recorded against the account owner, so a share recipient can mark shared bills paid; a bill whose account was since deleted now shows an actionable message instead of the generic failure (#334)
  • A one-time bill marked paid without a recorded transaction could not be reached to fix it. After a one-time bill is marked paid it deactivates and drops off the Bills list, yet it still appears in the Payments without a recorded transaction card telling you to assign an account first — with no way to open it. That prompt is now an Assign an account button that opens the bill for editing (#333)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureTlx5adQ84X1cU4v1VoYON+yY22etMZSb58OURK5dpJ/bpQdLjdhL6stjRFGshNhEHr1Ra/KTZs7/uCZLyvq+M0XBYGD+voy+pwmXwa6Wylyi99fJ2UhiXPHxKiExVq1EJY/PA7LcHAQy639r04gbQ4Q/BvDrOZYWAZuYCLrZrZFclfoIlzf/Ra5SFuCuWguuOd79cU/tXViv8xntJBIcIXoN58cadHF5iTo3Mt2XO7sNsUs7A8+1HDXsUldblvmLFFpH9ubJdYVDKqdzA104yRb0uPH08Zd6+y764r+uIsahSB/RwF3kJ20gcv5nurCaf9FvsI06PiyQnR73jMzlnoAaWxnSPZwGDa+gvQ/t56H+m+A9DlvVgnxexUa0C+Ga7cphcgVKWPWaRZFQzeofrcJ66wAH9uh338pw2R2Lq5F+s2NCOKuKo6uXocpf+VZ9GTsfRIrDEGL+4FwkFkxd0tHUBoohsOhROk/tXphvl/mIh5m4m3pRsjm7GviZASYoTXJe+kdclUUzpFMuXGrOFjSXCd1Plk2XsDMiHBzPEXAkaPlL9hdluXiuCCXrUYIF+S/U60qB1MuWRlwzTH80RovEgvyKGwZtzlDPtNLF0hM79iABKE5UgP1km9MRm7dyDWQDdogfWq+Oy97EJH8TDtYvuO2I79lQnppc9WrYB5E=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.39.1
Release Details
UpdatedJuly 11, 2026, 10:22 p.m.
Changelog

Fixed

  • Share recipients saw wrong dashboard totals. For a user whose accounts are all shared from someone else, the Income/Expenses This Month cards counted transactions in the owner's "Exclude from reports" categories — the exclusion list was built only from the viewer's own categories, so the owner's internal-transfer legs inflated the recipient's income and expenses while the owner's own dashboard was correct. Shared categories now keep their owner's exclusion for every viewer, and per-viewer "Hide from my reports" mutes are honored by these totals as well (#326)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignaturePTjw+Z1r+sKWQmZSlNfYPSTl5PFejqjMEgNyvQR1FXSKor9zNXxtxcAM0eYYthPn9YEprCKS9V6NC699ZbeWK6WbdRtprmP+rsvCifpjQyVtPDGLJ11LWzLVgw84pTHcolsdY756JO6KWW8hxp63bq3s4QE4rs3RTCEyHSpzpZ1pXSydTCTvheL1M/rtg3XyKpzBkoOqGh39Dnh9TH7JQt+cCB8VD84aeHcsvnxUkQJU3AmZwYGcP8wSNeLmDjt1S9yCv2h8NAReLQeTMbmdzNJtioLLiifkedz5bEgjVximgqI99mmV+8uhRBY0keT1hWXR6En4IrRkiJwlEyNZRHkukMa9jNmoNVvoRYCuQOVZ1wWGtkS8MCz5Ig63yPijEMh1bqnoi3+WA1g8s23dJVIziAHSKl0F+V7DKThsw2jBouMZeZ7bG0nMS9bFLcndAm1MbpWyuZATotUExNeYhEZEIwUOuF+esV5lnDoHTf0i/q6OJGa4hPPiNTE/rH4PS3Z4pdEZ4V9YhxYfsSs/9y+Y7xg/ZQWnLq2YVsTR7V8FgQwU4Bi8OGLsfbYZhSaUnHv60ObUB2U4WkD1mZZqDHKJXAIgVGulvHFAkXQVeGpRqbUCQNvgiVU8hfRaRmEr/y9Usub/3srDJn7qybeAxfOxA7rL+AlakEZBECHPJlY=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.39.0
Release Details
UpdatedJuly 11, 2026, 12:57 a.m.
Changelog

Added

  • The Bills page now flags payments without a recorded transaction. A warning card lists bills that were marked paid in the last 60 days without a transaction being created or linked — the situation where the app balance silently detaches from the bank. Each entry has a one-click Record transaction repair that books the missing payment (dated the day it was marked paid, both legs for transfers, splits applied). Deliberate skips via the Skip button are not flagged (#274)
  • QAR (Qatari Riyal) and JOD (Jordanian Dinar) are now available as account currencies. JOD amounts use the currency's native 3 decimal places. Automatic exchange rates cover both. Requested in #321

Fixed

  • Editing a monthly recurring income never saved the changes — the app showed "Income saved successfully" but the Expected Day (and every other field) kept its old value. Any update whose payload contained an empty field (a monthly income always sends its yearly-only "expected month" as empty) reloaded the entity mid-save and threw away the edits. Thanks to @redsteadz for the fix (#324, #325)
  • The "Exclude from forecast" checkbox on a transaction appeared unticked whenever the edit dialog was reopened, and saving the transaction again then really did reset the flag. The flag was stored correctly (including when set by an import rule) but the transaction list never sent it back to the browser, so the dialog always showed — and re-saved — it as off (#326)
  • Income/Expenses This Month (and the other report summary totals) deducted transactions in "Exclude from reports" categories without converting them to the base currency, so on multi-currency setups the deduction was applied at the wrong rate — and for a single selected account the deduction wrongly included every other account's excluded transactions too (#326)
  • Imports no longer bring in flagged duplicates by default. The preview's "Show duplicates" checkbox — on by default — secretly doubled as the skip-duplicates switch, so every import ran with duplicate-skipping off and rows flagged Duplicate were imported anyway. It is now purely a display filter; a new explicit "Import flagged duplicates too" option (off by default, resets each import) covers the deliberate re-import case. The preview's per-row checkboxes, which were never actually read by the import, are gone, and the New Transactions count no longer includes flagged duplicates (#327)
  • Marking a bill paid no longer suggests unrelated transactions as "existing" matches. The Existing Transaction Found dialog offered any unlinked same-day debit as a candidate — cigarettes could be presented as a "match" for a mortgage — steering people into marking bills paid without recording the payment, the classic source of app-vs-bank balance drift. Candidates now must match the bill by amount or name, a weak match is never pre-selected (the safe default is creating the transaction), and the "Don't create any transaction" option now states — and warns after — that the account balance will not reflect the payment (#274)
  • Overdue bills no longer double-book when marked paid. The scheduled placeholder pre-created for the next occurrence was written as an ordinary cleared transaction whenever the advanced due date was not in the future, so it counted toward the balance immediately — alongside the actual payment. Next-occurrence placeholders are now always scheduled, regardless of date
  • Restoring a backup preserves every bill setting. The data import dropped most bill fields: custom recurrence patterns (restored bills then advanced one day at a time instead of quarterly/etc.), transfer destination and description pattern, auto-pay, reminder days, tags, split templates, start/end dates, remaining payments, forecast exclusion and the future-transaction opt-out

Changed

  • The Match transfer dialog now also lists candidates from accounts in a different currency (any amount, within the date window), so cross-currency transfer pairs — e.g. imported from CSV — can finally be linked by hand. Automatic matching after imports is unchanged and still only links exact same-currency amounts (#326)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignaturegJm3RDjkvl1EBICN6Us5TsX5SdQbSGnRHvRIZmLsYaclkDVqW/mYCBjVgwjU50ifkv72zl3kxf5a8S3yxpo2WX6cnhkyyibLhs5Uzdrj9Egw47yYgMun8WH4647Y0uGP7QrX3Yf51SO7Ve+JWgdMRX+hWvG4K9hxUgAwWR3AmTYRsRXpmsNrOr97q2SPC3V0g9bAARDeSeWDGQ8SR05+OMIrQRj0Ct56fC1cTNWzHpPT+Qs17SJJcUUnK3tJWsM3wvGiwk62YMBy1cv1jx3JkOXnYvsa8bpSG3sL7aqr05QkAkvL9sSGxka6mDrC3CN1LHlwwQjPjWwoX9YDtOI04j0JPd0SzlhMYILaZNyouhoNTuY5YhDIG4aLjg737AAEBHgU3jvpWxaM8Oz2+9he9LkAJW6qA9DuzB/FmDNKxyJTmQ6S0LZ21d+Hkr0LD/2uKRSywlRBld+UNCWby8YrgIkyGomPH1rjDG28y1ApiqSozetcjSvDYwqULM2mLXU9OjD9a8UJk8B1R4Xd0TqgMmDCaAZrTdRLYYdTZEEaFbnDkbm8p4z2q+UGfn/UCNEOkg5pbu1WAsRubIKkPzNTz7gTSLI9u+qJfvoZg9c3Ae1OhXWDD9k/2Z+pCrbJhu8yDX+2JukXoAxNS+bnxaDxdoxRzIM+9jcbb0eyG3wJuLk=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.38.0
Release Details
UpdatedJuly 7, 2026, 1:07 a.m.
Changelog

Fixed

  • The account selector saved in the gear settings of insight tiles (Monthly Comparison, Large Transactions, Weekly Spending, Year-over-Year) was silently ignored — the tiles always showed all-accounts data. The saved account now actually scopes the tile's numbers
  • Importing transactions that trigger the Auto-Link as Transfer rule action no longer shows "Cannot use object of type Transaction as array" on the import screen. The import itself always completed — the error came from the transfer-linking step afterwards, which also means those transfers were never actually linked (#314)
  • The Recent Transactions dashboard tile now honors its "Rows to show" setting above 8 — the display respected the setting but the data fetch was hardcoded to 8 rows, so values of 9–20 silently showed only 8

Added

  • Edit auto-categorization rules as JSON. The rule editor gains a Builder / JSON toggle. The JSON view shows the raw rule structure — editable and paste-friendly — checked when you save, and switching back to Builder repopulates the visual widgets. A Copy JSON button makes it easy to move a rule between instances (category/account IDs are instance-specific, as noted in the view). Requested in #318

  • Hide shared categories from your own reports. Categories shared with you gain a per-viewer "Hide from my reports" toggle on the Categories page. Unlike the owner's "Exclude from reports" flag — which stays owner-only because it changes every viewer's reports at once — this only affects your own reports and dashboards; the owner and other viewers see no difference. Applied at the SQL layer through the same choke points as the owner flag, so every report and insight tile honors it consistently

  • "Exclude shared accounts" on the remaining dashboard tiles. The per-tile toggle added in v2.37 now also covers Budget Progress, Monthly Comparison, Large Transactions, Weekly Spending, Category Trends, Cash Flow Forecast and Year-over-Year (shown in the gear menu when you have shared accounts). Bills, income and pension tiles are deliberately not included — they show entity data, not account aggregates

  • Clickable spending charts. Clicking a slice (or bar) on the Spending by Category dashboard tile or the Reports page pie chart jumps to the transaction list filtered to that category, scoped to the chart's date range and account. Tiles set to "top-level only" include the subcategories in the filter so the listed transactions match the clicked amount (#317)

  • Per-bill opt-out of pre-created transactions. The "Create future transaction for this bill" checkbox is now a persistent bill setting instead of a one-shot option at creation. Bills with it unticked never get a scheduled placeholder — not at creation, not after marking paid, not after skipping — and toggling it on an existing bill adds or removes the pending placeholder immediately. Previously the checkbox only affected the moment a bill was created, while every payment re-enabled pre-booking unconditionally, so unticking it never actually opted a bill out (#311)

  • Convert a transaction into a transfer. The Match transfer dialog gains a "No match? Create the other side" section: pick one of your accounts and the app creates the opposite transaction there and links the pair as a transfer. Until now the dialog could only link two existing transactions, which left no way to correctly book payments to accounts that have nothing to import — e.g. a loan tracked as its own account (#313)

Changed

  • Scheduled (future-dated) transactions now show a Scheduled badge in the main transaction list, with a tooltip explaining they are not counted until they occur. Previously only the account detail view had the badge and the main list showed scheduled rows in italics alone, which made a bill's pre-created next occurrence easy to mistake for a duplicate booking (#311)
  • The transaction list Total no longer includes scheduled transactions — they are placeholders for money that has not moved yet (#311)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
Signatures/wP/jWqAxqTStZPLKWl/5nyJk/xpeAom+Kp7KakVOdJmzhNv/Z6KM/CUUOrGem4Qj5G1OEZ2tNrPkTneCVvfFU2S5aoayMDgcRaGquqwZisM/4a0KV9Husjq8mV0RVoqco16HBH8PUY+kYsbeWRcSp2q38Zq99L04zb1x5XY1rGe5YdP4/IydUoMpyzTtsGF00Tj6OUAMvlDTnJqCcetscuXX8yo33xm0dUfLxjZD2f9hsn8UTCwNN7v1+yBhwNN4jJsfyGTN+92XV2YDhRCfVWq/3bGqphHo+nYQvbyjndJRcaAwybOquX6MH7+wpDa5wpvNw9xzc2sYNm2FM08SYep3cX7uoXngifGZu2FBqyNHQ198dqEwqJbEVv2DrK5cAnQkbSS1glYYney/uXAlsqLEinHirrShNYRoq+ZEkxUhpdung3zSWwPe0Fd/mWh2chHiTV20A2tCrv7FRuRadpf75bq+y0xuIglVZQy5E1dT2nk3lPUUwB01w/ggmwrJ91hOchPoyoRoDhoBNxZJs903bQejWR/MdZ9pbXVmwxj1EOq8oWfWeQ5B+OEz/LbcplibODsNv6IUIYU++gxK8d2XCVzBgV2ayMqsRxFDxItgluqDcu4oTW8mh3A4z33PvbeCFFMsj2bKFbOslmuT2ZiVl58oTaQRTh61xeKEA=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.37.0
Release Details
UpdatedJune 27, 2026, 11:16 p.m.
Changelog

Added

  • Exclude shared accounts from reports. When other people have shared accounts with you, the Reports page gains an "Exclude shared accounts" toggle so you can see just your own accounts' figures. The same option is available per-tile (in the gear menu) on the account-based dashboard cards — Income vs Expenses, Spending by Category, Top Spending Categories and Recent Transactions. It's off by default (shared accounts are included, as before) and only appears when you actually have shared accounts. Note: a transfer between one of your accounts and a shared account can only be partly seen when shared accounts are excluded, so income/expense totals may be slightly overstated in that case.

Fixed

  • Saving share settings failed with "Some entities do not belong to you" (HTTP 400) when the "Auto-share new" toggle was enabled for a type, or after using Select All — the auto-share toggle (which shares the same data-type as the entity checkboxes) was being collected as a phantom entity and sent as a null id. Entity selection is now scoped precisely, so share settings save correctly with auto-share on (#306)

Changed

  • The Categories page now also lists categories that have been shared with you, shown read-only with a "Shared · <owner>" badge. Previously it showed only your own categories, so anyone using a budget made up entirely of shared categories saw an empty page even though the categories worked everywhere else (#306)
  • Categories shared with you at Edit permission are now editable — rename them and change their colour straight from the Categories page (they carry a "Shared (editable) · <owner>" badge). Read-only shares stay read-only, and a category's type, parent, budget, report visibility and deletion all remain owner-only (#306)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureFqJ17XG/szTfkAMsF+oCODYGClVjdeGArgFi3SrgeGhg4CFFzIVO98XEnYhxeCnwOcYGivzy0uhe60/Vv7kgml+lIVvRL1EZOxvjOES2KksQ50fqxGZSNz3EL54EA6R3Yvo6uLFBM9cbK0mmY5H+4i3UozKhKwzRa6PJLIZzpBsjtprJXHojWsQMR5KY7WDDbb9yD32uYzMnrXMxOiQ2PZGtG7aIhLS6DzC7Mtp/oLUgyRqBWoYMUWWLLi1qyeOr4/8Tdm9H5I36oxeoX2ZQlVuprpRjDPW5EITrljbyuIPy3CdAFn5tvvt8rkurEgCtPAaMv7gSXRZto6rJJqS4woUqX310+J0re9qa53Ls0J7Kezo5WpENoaFsvT6McjVG/4k6k4YN1/l74p97fFfR+1T2kC5VptpwVz4GZ2aSF9t226Sdkft7sv72aC3oQpa4PN3PIWj113aN2X5nnCGiD+NUW282/yAdacvMWVgB+t+Rbm0FIyWtGnbw0dKAlY3CAmQoBvqX9f2vqn1OFDxJhejg/i7+FAWQD83LIk6u2kNg/N4e2+hgLtO45wd5MU6TLXXTrb1mlikbbiP80Rla1p50fScosYTCqjJfz2lh5U6D2h/nquGHHvhf4R9q7eSkykmELHZUKiUyYlrLrOfiuxGRqaWSQWp9hm0CUog1HBE=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.36.0
Release Details
UpdatedJune 27, 2026, 1:15 p.m.
Changelog

Added

  • Auto-share new entities. Each person you share with now has an "Auto-share new" toggle per entity type (accounts, categories, bills, recurring income, savings goals) in their sharing settings. Turn it on and anything you create from then on is shared with them automatically, at the permission you choose — no more sharing each new bill or category by hand (#306)

Fixed

  • Code-integrity "Some files have not passed the integrity check" errors reporting FILE_MISSING for js/.htaccess and vendor/tecnickcom/tcpdf/tools/.htaccess. The app no longer ships any .htaccess files — the Nextcloud App Store strips them from the published archive, which left the signature expecting files that were no longer present. Neither file was needed (the JS one only set a redundant cache header) (#307)
  • Deprecation warning in the Nextcloud log — the notifier now throws UnknownNotificationException instead of InvalidArgumentException for unrecognised notifications, as required by Nextcloud 30+ (#308)
  • Reports and the dashboard summary were empty when a single account flagged "Exclude from reports" was the only account selected. Accounts flagged out of reports are now only dropped from the all-accounts views; explicitly selecting one shows its data as normal (#309)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureYxqf1NnAucAiXFVdwVmQJPaPUyuExQ8t/dwv4tDVpFb1kXDtGcIWoAdspiDz+HwdyPe+ul+/2GcDWiLPTF3TvIHwIaV+h+guDRYBEHMY95+Hy5W0BSuwBC7gto5dfsZEhL5xj5OsRIYrY/Fo8Tqj99kVzDK560o9NgI6Bp6ZkQpbwPRbTnbxUX27oF0oDjrg1ArS4IiE4ghZW1ct74Mlv4uoeg5zaVQlucrZK+rBJXixtpDnImHLPMkTvd+1bmkQTFtvArS1A37YkXkLKrKn4pzWvwv/q46ddih1NXBC7o6UoBwP1pWB1OxgNq3/98OdWyPs4GLumMmRdg+7PbY95Go97lBbNc/1mrBB9qQPXirFxYHMZWVDSRHSNRJ9cSMnZA/YzsVeOZOVkIwJWXhC5YGAEN8nq8HKIMBHzmi6UYdGM2VvGPmNZ+K3wlGMIkKlVfWfIJ7XIOCe6OLvQbwR/ATZ7pUyOE+AR21uu27zWGJ4iB4y/eCfCSE8vIxyPW7L0dwkzxU13iNNNxAUQgbNrs8EiQBLQlTCaBWCWp296Dds5nEGMEilQKX9vEXAhY9KRG5dzJjoZhZ14tWA3Hjp+5/Gs2AM4Bh3Rp1OGdhfQhFDmt/2GXcL16lfDcX28K1ub4FPYE8MEz6qDmLhqqwv9FeXQQbT/ZKdQn8NwuOlGFE=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.35.1
Release Details
UpdatedJune 25, 2026, 3:28 p.m.
Changelog

Fixed

  • Categories marked "Exclude from reports" are now consistently excluded everywhere, including the Income vs Expenses trend, Category Trends, Top Spending Categories and the monthly spending chart — not just the dashboard summary. Exclusion is now applied in the database query itself, so reports and dashboard insight tiles can no longer disagree about which categories count (#219)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignaturebX/9kwpiVjwDj0f2eU5xNE7zUpt8T/nkGCFg9HnDQoKynM7c1KaXhbh4isVQBbgy5kPGXSDP7DRfuSTYY5/M3PSv1JE8gOk/9lz2AGmTqlXrf4Kgq9oARAGcVHXB955dLvDkj6Vrk7zZ9cwrjq4aMBu02dW8ZgyAHStXybiWmkAbIxK768MHM4n5FXTRFw3P/ELVlDjCxgIpxVxD5EZaaA+n7RrjN9MRY2R8/GN7Og7yijcmnutMWtna4K19B9c3ShcfUkrwotvCUz3c+K10VQSfzUpN6RoindDB0j716jUZQ6IKzXBNNRiOjQ6N6s1MlmKwjyFyw0PY509hJY+dtjBEQBbFjK0pw7ZElfW4zDWteDzWRm7M1VjzUlRgPLsg7CJ980Rg8suZAMh3UH251vymCH0ykpMYqK1qiWDurz5GWdaDov6Z0YkQPQLnszzPa60kbO9VUHrYnG+6+KA6GoPW0EHFEqaUxXv+mRLr8Pm8BhjCiDghO7mlHZFN95hN5gkNyBdIPA9JmXAdnkrJBSQaDvZdejDwFJL+T+PgA2f9JomB8BQ/WkZ4uukyKUUFYToOhntQTe7dfE+I4VsD6BycbY7smaY/xGx6EvyXfntpYkgR7Fe2rYKaxBrcRcnhTmQBeLLz85M7fLKVjME72niQdRIZRaMZ+OmpCxKK2qU=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.35.0
Release Details
UpdatedJune 25, 2026, 12:36 a.m.
Changelog

Added

  • Pensions revamp. You can now record a contribution as a transfer from a bank account — the matching withdrawal is created automatically and kept out of your spending — and record withdrawals/drawdown back into an account (#304). Scheduled (recurring) contributions (monthly/quarterly/yearly) can post automatically or on demand (#251). DC pensions gained a configurable projection target with a progress indicator and a "today's money" (inflation-adjusted) view on the growth chart, plus an optional Pension Projection dashboard card. Bank legs that fund a pension show a Pension badge in the transaction list.

Fixed

  • Background-job "class does not exist" log spam that could appear after updating PHP/Nextcloud/the app: the app's autoloader is no longer "authoritative", so it falls back to PSR-4 and self-heals if PHP's cached class map is stale after an update (#305)
  • Newly-added dashboard widgets now load their data immediately instead of staying empty until the page is refreshed.
  • The pension detail panel's balance history and activity are no longer broken — those views called endpoints that didn't exist; they now show a proper balance chart and a merged timeline of contributions, withdrawals and balance updates, each removable (#251)
  • Editing a split transaction with three or more parts no longer zeroes or overwrites the other splits. The last split row is now a read-only "remaining" amount (transaction total minus the other parts), and the dialog blocks saving until the parts add up (#303)
  • Spending-anomaly notifications no longer crash with "The arguments array must contain 1 items, 0 given" — a stray % in the notification text made Nextcloud's translation layer fail, spamming the log every time notifications were rendered (#305)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureF/7pZ4sNzjJuqXXZoHmO+9OmUzkQz6ZDke3vkONfZ2uGfzBpwpDSIiGlfNv6gt40Ho8NTPNd0JuM+ESRohLlPAAftFoF+L4h+asH5s/lncoxgTZevEFl7NE14s+sPVdGdZqXGi0b3mohB+f1jOudpVbgB0bmCDvnZMEKiMSjB7XwH9iQqzu/8WyQNd28w+Bz2TbyAfu2PCtdD6jsmVCbvtCkmEdKOVJzRWuExH+vwvZ0ltX3mtorPl6HEzqKJWoDYG3tdbpSwml6w9F3qj8naVZ3tZYBrfvwABHoMD1LYpYwRss5C9UpJvu6UFfKQ4Xso1tBu5U+tYlAPKLbQ5J70o0C1aP66R+FvL8RlMHpY93duR32qZkT/6xV0NYQpd9xzXoLbB5YkZJuBLV8m3oP9k/pNEy8vwF5Kkb+/6zrJt4aSH/iiAqBoqvuT1itwScYsNpGHXWOrGHioCKiGkcMvamfr7her1fQ42wNiVIVWKaxNtjeYrVjmHCtWA2awjv3XRfcXdcL/4stuDpXxQ0Dnv2S/Ey9ZbGbqpc0DNyPZfKie5/QK5OnHPW9F8nHUsEhxDLbNezo11fKm1ykE0ja4nTZFKL3ml2D4aRDMYQe35MWJvW/fLcNW7dYOV969ZI52G8jTIUI/YphcNfCNK24fVkljrcBSybr8WavbELxVR0=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.34.0
Release Details
UpdatedJune 24, 2026, 12:34 p.m.
Changelog

Added

  • The transaction list filters now include a Reconciled filter (All / Reconciled / Not reconciled), so you can quickly see which transactions still need reconciling (#301)
  • A Budget alert threshold setting controls when a category appears on the Budget Alerts tile (default 80% of budget). Set it to 100% to be alerted only when a category actually goes over budget, rather than when it's merely approaching or fully used (#293)

Fixed

  • Creating a category (or account) no longer fails with "Unknown column 'excluded_from_reports'" on instances where an earlier upgrade was interrupted or restored from a mid-upgrade backup. A self-healing migration re-adds the affected columns automatically on update (#302)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
Signaturey+Qi2+U6CexZu8i+0DGrbLXwFbp+cHLVW62WRSfrovEAuJrnZy8paqAacEaE570GoHVd1b23Yihz4oDfOYStLASDVFk7xhVrarnlIqv4EH+Jyw0IR2iaLR+IvhJmSZc9N5nQ42i2z8UYetvQo0znzzNPmpT2FEJB1Sty9kCfHL7HiisG4hYwJp528McMVXgCYfn/XOZUQzOVY6rvis1hP8CiFbE4UMUQj/SgDpRjimcRCZy8fsRLgZHcfO2+BKYCSt5lqLDJSzsmewBFNMVWDdtZwPUxqyK8xaTwSnwWNBNXBRg5ZcDLJhhIJtk9cEezVTdJBZTw3wx7iCztR9RFQi9CZsRz9U9S4jLEdcV8m6OTa8XG22s2ZHt+I+hisGtlC1TOQ5fpPfSe9onWdA8jgC68RAFeOLJ+KmSkLQN1bbr9gUw47oB09Yd9sEtUDcFapfv+x9Zl3/s4ExwO6xDS/bwmRyZ/fq1z2jhVu/lMFd//+9ciOrCdty1p7440JVs/sx71Qcc0mRhZsMtIRYyBD2EFceUHx8cQCtOLL99+JtGkTakCMCwIxghuGoXnrq+9mRWjgROn1ysGEHDUyC8ZKCJ5f8TXOllqX2g+2fyOpFzHR66oP7lPwI5y3eW4VYJGT/lQzTavAtU148X2XaBUz+XA8Djuco3CCuGJuT9FhSU=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.33.1
Release Details
UpdatedJune 18, 2026, 3:03 p.m.
Changelog

Fixed

  • On some installs an earlier update was recorded as applied but didn't fully run (an interrupted upgrade, or a database restored from a backup taken mid-upgrade), leaving the excluded_from_forecast column missing — so every new transaction failed with "Unknown column 'excluded_from_forecast'". A migration now re-adds the column automatically on update. (Also surfaced by the new database-error detail field added in 2.32.0.) (#289)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignaturewGNDwrdOGHhLxiEiJQDsZrcL4BFQbGBTjeDU/3VJql8bIeDBHITKzJ3HH47kV1bFmsZ35q0o7xh/r4q6Kj9/SXM8gQCTxEtQ0q80MS85LGy5+9dUtJ0yBvrLfE6kwpNPDH+kqwBVcAGxmLr9vYau5uTFGdeB0WZ3gmesUvT5kuZfdREwJDQ19QWR40pJjHRcWqM5KnXCT1/wq7btWj9s/Vf9GVQvo85g9R7adODG1PVBr4gM6R9nTgsrn+60BJvNNO5f3W3wbuzvqaJhtVdknB9Z8fc7Vbq6mh6TgSPBmXgiK2VdCAWPaW2EmpVL8iwgOGazPGSajPkMZNNZDhzDNEpLcveJl61g/x5dVAxOevwFnN4CaX5c/YYppjcqtoWyYgoTNMv3enF3///tD0wS68iQzcU5UNmsOOKsAUVvRnf/oOX2b13NfsKPONAxcu4Q/UG8ybPqYwXT+T6Vs+IRmoLJLnOs/BUgbqmmRIG1Wfs2BusDFKNHHWoW1Z5t+GDLGx2cyNci7+rKPRh2seML8iPrt9lNv2M5NjzIJ9Wm0Xt0FKpIetR4gDpLSRvBtINaQ0jVuYVixt1yDKMUfE6GH4sNW9rNi2ZoKptz2MIxouBmLNXezA5Y0gvIlgA11Bi0YBrKPUAtmxNl8Jyxhle2Ll5bZbsupMy1otRB/+NGEOs=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.33.0
Release Details
UpdatedJune 18, 2026, 12:52 a.m.
Changelog

Added

  • Run reports on multiple accounts at once: the report Account filter is now a checklist — pick any set of accounts (e.g. all your credit cards, or all your checking accounts) or "All Accounts". Applies across the summary, spending, income, cash-flow, category-by-month and year-over-year reports and their CSV/PDF exports (#299)
  • Saved reports: save a report's settings (type, period, selected accounts, tags and options) under a name and re-run it later from the "Saved Reports" picker in the Reports view. The period is stored as the chosen preset (e.g. "Last 3 months") so a saved report always shows up-to-date data (#299)
  • Dashboard tiles that can be scoped to a specific account (Spending by Category, Income vs Expenses, Net Worth History, Recent Transactions, and the other account-aware widgets) now show a small label in their header naming the account they're analyzing — the account you picked in the tile's settings, or "All accounts" (#296)

Fixed

  • The Reports period selector didn't drive the report on reopen: the dropdown kept your last choice (e.g. "Last Year") but the report always reverted to "Last 3 Months", and clicking "Generate Report" used the reverted range instead of the shown period — you had to switch the dropdown away and back. The report now always matches the period shown in the selector (custom ranges are preserved) (#300)
  • The Quick Add Transaction dashboard widget couldn't be used on mobile — the lower fields and the "Add Transaction" button were clipped off the bottom of the tile, so a transaction could never be submitted. Its form is now condensed (each label sits beside its field with tighter spacing) so the whole form fits the tile, and it falls back to scrolling within the tile if it's resized very small (#298)
  • Editing a split transaction's amount (e.g. inline in the transaction list) left its splits at the old amounts, so they no longer summed to the transaction total. The splits are now rescaled proportionally to the new amount (the last split absorbs any rounding remainder)
  • In the edit-transaction dialog, changing one split amount now adjusts another split so the parts keep summing to the transaction total, instead of silently drifting out of balance
  • Split transactions weren't counted toward category budgets or spending. When a single transaction was split across categories (e.g. one $1,000 payment split into rent, parking and a deposit), each of those categories showed $0 spent. Split allocations now count toward category spending everywhere it's shown — the Budget view, the Spending by Category chart, and reports (#297)
  • Large amounts (e.g. values over 100,000) on the dashboard hero tiles (Net Worth, Income/Expenses This Month, Net Savings, Cash Flow) wrapped onto a second line, splitting the number mid-digits. The amount now stays on one line and its font scales down to fit narrow tiles instead of wrapping (#295)
  • The "Asset Value History" dashboard tile (and "Net Worth History") showed its empty-state message anchored near the bottom of the tile instead of vertically centered. When there's no data the message now fills and centers within the chart area (#294)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
Signaturejj+nUiPNSYYgtQ/7XYIkJNFo8vWIHaX28Q0XTtpN6RWmrW8qrJBIs2jTaaHwebC7SB5f7GP6vQxghh9+nCWfA+KlTKbm8YJg6yzah9xdTLo/JcUhTOinlH9yYoXxMiIY9EVwQLsPmef4sprTsS9oqBeSgZ7S8WRJYnxjAuljee9q0Sfai9AK+RQzBk6kgENhCAVt95ooZ3H5ukfFBSb/kyXa3IU+ngu6g5B9DgiJfBduecdkLEfc0dhYKelUyNaZa61qoG865podTGJFCFqzoSnlCXgRcJqJHjhdTERIeu/nHQAL/PhaPy0OSWK8l+kyrGveMEKDM6LvQ0Eo6B9Ul0ORobundabEat67f/hqaTmnDldOkkEm5a0WAYeQvYeeZCNLtiF26pWk66v6eQhXsrT6IwcJ/gxaC6oS8URm5yYub2iW9nVq6uZXRMJavJr8CmYl7MSqQRVvFKGlwHvD7X+YfEs+htKGYM017iWdICfQv/wbGi5JzIxqdm7QKrV9EGxgl4GFWvY/cyGZt4awfhoy4RljlFtsfJ02askgVFUloVGKOWeqZ5NbqXMDC+UonPONQ/RPM64u0L3NdVvmcXOwA8RBHCg1qgEiVkDBSsJyhK55+1J7Yn5fIC2emSU0BXOdzSFgg3BgUbYJQHgH30AwNf1iagO/WBOYDSu4jqs=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.32.0
Release Details
UpdatedJune 17, 2026, 3:02 p.m.
Changelog

Added

  • Category by Month report: a new report (Reports → Category by Month) showing income and expenses per category broken down by month, with a column per month and an overall total. Categories are listed alphabetically with sub-categories grouped under their parents, and parent rows include the totals of their sub-categories; a toggle switches to sorting by total instead. Defaults to year-to-date, follows the report date-range and account filters, and exports to CSV and PDF (#288)

Changed

  • API errors caused by the database now include the underlying driver message (e.g. a missing column) in a separate detail field of the error response, visible in the browser's network tab. The user-facing message is unchanged; this makes problems diagnosable on managed Nextcloud instances where admins can't read the server log. The executed SQL and any bound values are stripped from the detail (#289)

Fixed

  • The dashboard "Budget Alerts" tile showed a red "exceeded" alert (with "0% over") for a category whose spending exactly equalled its budget. Spending that fully uses the budget without going over is now treated as a "100% used" warning, not an over-budget alert; only spending that actually exceeds the budget shows as exceeded (#293)
  • PDF reports rendered non-Latin characters (Polish, Cyrillic, etc.) in account/category names as "?". The PDF exports used a built-in font limited to Western European characters; they now use an embedded Unicode font (DejaVu Sans), so names display correctly. Applies to the budget report, bills-calendar and year-over-year PDFs (#292)
  • Marking a recurring transfer as paid showed a success message but created no account entries. The Transfers screen was only updating the transfer's "last paid" date instead of calling the mark-paid action, so no transactions were recorded; it now creates the paired transfer transactions like the Bills screen does (#291)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureNKgPUY81JziKewMWFs4QeLNIwZ8JqGBZ6wvFlsItL4R47yoDLAn4+I1T/pwgEOi7KR2lCUFBckiAdI78FONIy+JyCFhY0w4WcGEltsQdsytRMQYAggOWw+OlYvlDMPI6zoMoRfVcIvC3d+4pUrP91cJIVwi+bu5OIYO0C7ErDFCyvMlHK+ifsGvBluQJ377z8wnBUQIWSfudOuXewIyBHCF1QXsRXsVe0CIGWPNnT3ibuwxjm92a4vzwqdTEYy2qQwzPgYWPhgZofSdEN6j08iuwUzM0i9yXWd0IVpRNLb8RIo9lTzhJsjolrNFGZd0iiQk5A/4NQ6VOLKItVhwXJKOZk7KzyYTZmEki+PaeHKSEjEzwYNqv2tL4VPrBjyq5Y3bRTnYS3uBBCOnkWwn6ozQ4PitvSgPpcqciCtrP1hYAa0oQ7FsP8+BVsepO8gn8+lIcVjx7mW+YvufESAyFRXgAy61QBNjcd34vtoEfLqhdP4f37gZ/jdmCicDQ3sLw/eUIL98BylXmNvOge43vnYuRgGl9gBO11ENaP3EhqhqsrVr5Gyu07MGlMhCRlBn21fRN5sMORHFNx6pL/DcpwC0xtpfWEtHTCcEcLvArqfSiQSMrJaDvqftcQNMWYt4hGZKMVR7SYZsAragHUiMfvWDu1mW7HLNsW8PwySZDrHA=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.31.0
Release Details
UpdatedJune 14, 2026, 7:05 p.m.
Changelog

Added

  • Exclude an account from totals: a per-account "Exclude from reports, dashboard & forecast" option (in the account's edit dialog) keeps the account fully tracked but leaves its transactions and balance out of every "all accounts" aggregation — reports, the dashboard, forecast, net worth, total balance and category budgets. The account still appears in your accounts list (with an "Excluded" badge) and on its own detail page, and selecting it explicitly in a report still works (#286)

Fixed

  • The account detail page's overview tiles only counted the transactions on the visible page (e.g. "50" for an account with 1,603). "Total Transactions", "This Month Income", "This Month Expenses" and "Avg. Transaction" are now aggregated server-side over the whole account, so they're correct regardless of paging (#285)
  • The dashboard spending chart's "Total Spending" figure (and each category's percentage) only summed the top 10 categories shown in the chart. It now reflects spending across all categories
  • The CSV import preview's "Auto-categorized" count was estimated from a 50-row sample and could be wrong for larger imports; it's now counted over the full file on the server
  • Editing an existing bill failed with "Failed to update bill" — saving the edit dialog (whether or not anything changed) returned a 400 error. The bill's start-date column, added with the limited-term bills feature, was missing from the list of updatable columns, so the always-sent start date was rejected before the save could run. Bills now save correctly, with a test guarding every persisted column (#284)
  • Opening an account's detail page returned a 500 error (the reconciliation-history request failed). The reconciliation controller was missing a trait it relied on, so it couldn't be constructed and every reconciliation endpoint failed; the account page surfaced it via the history sidebar. Now fixed and covered by tests (#283)
  • Starting an account reconciliation failed with a confusing "The string did not match the expected pattern" message (most visibly on Safari). The root cause was the reconciliation controller failing to construct (the #283 fix above resolves it); on top of that, the reconciliation screens now read error responses defensively, so any failure shows a clear message with the HTTP status instead of an opaque JSON-parsing error (#287)
  • The Budget Overview dashboard widget (and the digest, spending-anomaly and bill-reminder notifications) always showed amounts in US dollars regardless of your configured currency. The server-side amount formatter was reading the wrong settings key and falling back to USD; it now uses your default currency
  • The Budget Overview dashboard widget's "Total balance" now converts multi-currency accounts to your base currency instead of summing different currencies under one symbol (currencies without an exchange rate are excluded from the total and named)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureCseRrf2b0tfseaK8cBqqPjA8lhMT1C+aq6xVuP6vO3E6sRzawwkPNHdfK7CDaOro2TYW+agvm4g873WzOGVLIVa3FHEyFlnGRkFSwMz334bq1/Rcbw2WXdMbNUliZwdK76DNCauZ0JPz8FYIXr5cqkqbw80oHD/SWhWD5dTKRKJ2gpSvbNtXJfq32Sn04UVxrJq4StY11b5rJfCXR7P7RQxmFboIYJvhoVIfcebR+vighFLC9adkKVaF/xJ8tm1MVG6oJHJ4zKU87SV3+D8vB1xpxeWo2xRwseYSwg8Nk3ik6iXkcf4cHTACrCGyHhOXgCmltGkJ441alZ8kzOQCDe6Vw3Rx+zzgducfZGOQJPuIYcrpyZAAgN51xtDQJTWJNoT9jBrUmEv0r/ftZWj8QYnesnl8HgXUQPdLCsCaloLpISXkt7KzlHYlt4PgdMphbDBnuMROrXZtTeIwDCzwGAkatsK+l8HnM+FbMlpfszT7Ki1z2HYX/d+74aLRxkNUClx3fsQsxOtd0RxK9+/JPHW+W5Sv5kWbRSfiUrslL+pT7R15L9x4t3nFK8VUUEZSDcNynhSHxCVqrqOsV3mZ12eutyvQEPpN56qyLkaZmcoxOlOD2v4BKba8pBAL6YW05jx8hBWg9m0zAg4h3/qoA6zLDRrVfHi+LvUiiE1YDWs=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.30.2
Release Details
UpdatedJune 13, 2026, 6:03 p.m.
Changelog

Fixed

  • Dropdowns in the transaction list (the column-configuration gear menu and the in-cell category/tag/account editors) were cut off when the table had only a few rows, because the table area was shorter than the dropdowns. The transaction table now fills the available height, so every dropdown has room to open in full (#280)
  • The Tags column couldn't be shown/hidden — the Show/Hide Columns menu was missing a Tags entry, and the column wasn't wired into the visibility logic. Tags can now be toggled like the other columns (#281)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureRXpaKwi4ViRdeYM6mjC3JtrlDOFrm03LMBFc2gQMktdYfBEoyMrW3YBp+DPKezxnLOmETNnqjXAI+oswcQLQMkRbAcjuD1dpBBZi7x8kmvtc0lZUcrKRw2QKUzDD5luZaN7JE14o393XlPFxdqkaUbJvWTltA5xK/XO2H72GyvEO7/7de7HCcP2G4XTK5kGSeP3PHRNQ5MjiB49QlM7D95p7Od374Fbr0k52h0sWFHSA14LgJSyPXCgHxxJMqVy7O76LlS1Iedg8B4TFBbTJZVol/8emaHjBHvEwVVzSIIkr9wdtZ60aqrEhJfTqaRwdGS0ks53VE2ROoE829Jnc3Xkz4Xxc0WEqH5a4vxbUWnA8NbuaFNAsUcfXW+0TDTUeLT34IV8c6GZkwn0z4a1parjkif0yyEolfPhNomKX/JMl74aSG5i2BkKyDH3OXMg9oC0/czhOIxluUuFCwWJyd6cBOGd6r/R382SMMe+mCHDpuBxIY12gRo4bzcAfmYMQ3e6rrtgpFwxBllUaK8lC+yPy9x9502QHhZem922Tz7HokfuXuFxh1x9Z6doBSvoZOe2H2PIKRupmFf4I9epoRYdDQZjatpZpN3+oZnz6DmY7f9+g3gaZ7Dl9dkPydm96203Pox5SGz9vhOQaXeOIw+l+rLnXnbodzB3eyqz11Ig=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.28.3
Release Details
UpdatedJune 12, 2026, 1:14 a.m.
Changelog

Security

  • The recurring-income update endpoint no longer passes the raw request body through to the entity layer — a crafted payload could previously set internal fields such as the owning user (mass assignment, integrity only — no data disclosure). Update keys are now allowlisted like the other endpoints

Fixed

  • Auto-derived recurring budgets (#269) are now consistent across all surfaces: the dashboard "Budget Remaining" hero, Budget Progress/Breakdown widgets, Budget Health score, and budget alerts now apply the same recurring fallback as the Budget view — a category funded only by recurring bills can now trigger alerts and is counted in headline totals
  • Auto-derived budgets now respect bill start/end dates: a bill that hasn't started (or has ended) no longer counts toward today's budget, avoiding double-counting during a planned cost change (#268)
  • Recurring income summaries (Income view header, dashboard Income Tracking widget): semi-monthly income was counted at half its value, and a one-time income at full value every month until received
  • Transfers page monthly total: semi-monthly and semi-annual transfers were converted incorrectly
  • Live forecast cache: cache invalidation never matched the stored key (changes such as toggling "exclude from forecast" appeared to do nothing for up to 5 minutes), and the cache key ignored shared-account visibility, letting a share-restricted viewer briefly see the owner's totals
  • Editing a bill's amount without updating its split template is now rejected when the stored splits no longer match (the payment would have silently imported unsplit and uncategorized); setting a split template via the API now clears the bill-level category, matching creation
  • Multi-account import partial failures (e.g. a deleted destination account) are now reported in the UI instead of masquerading as a full success
  • Import preview now also flags repeated bank transaction IDs for accounts that will be created by the import
  • Long OFX FITID hashing threshold raised so every previously-imported FITID keeps its exact ID (re-import dedup continuity)
  • Auto-derived category budgets (#269) now handle every supported frequency correctly: semi-annual bills were over-counted 6×, semi-monthly halved, custom-schedule bills counted every month, and one-time bills inflated the budget monthly until marked paid (now excluded). Frequency math is delegated to the shared calculator, which also gained the missing semi-monthly conversion
  • Auto-derived budgets no longer apply to past months — they reflect today's recurring bills/income and were rewriting history (including overriding explicitly-zeroed snapshot budgets)
  • Multi-account import: an invalid destination account mid-import no longer aborts the batch, and deferred balance recomputes now always run for already-imported rows
  • Bank sync: the post-import balance recompute now keys on transaction creation, not the import counter, so a row persisted just before a non-fatal error still gets its balance update
  • The scheduled-transactions background job now recomputes balances from the ledger (it was the last remaining hand-computed balance delta, and could race concurrent imports)
  • Import preview now flags a repeated bank transaction ID (OFX FITID) within one file as the duplicate it is, matching what import actually does; per-account preview counts include rows that will import with skip-duplicates off
  • Marking a bill paid by linking an existing transaction now warns if the link silently failed (no money movement recorded)
  • Extremely long OFX FITIDs are hashed to stay within the import-ID column
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
Signaturefa7u8mWcwya82OCYZOh+XZFPRJH94oqiBM5WUtEtvU3Dh6Lq+pMs8A7e2aCOa0Y6AbwWH7TF6ZRtwanfSh2PjQMwAaDFlR5anBdAvr89L/fn3eK0uSrZetqNGmAT7Itlc0mT5KowbTvtWDRdK46oR4jjqgXKay6JeO7caGbAcKmyfhJARbfTXsb5etz/yhMX72X33ayUYtCo8nQrtxLTGO5AAPIcFbq1pa3W3d1SHuQ7Ibksv3WXrZe79ngT4pQpGp6xtz3ervqo86vrI8qH8DDg6g9IJE8D1iseOiVzRv/KI/N06LnY0OvUHNZwGrJph5Jh3BrYg2/5rSYzEP5VzaGyZm+AS0DO1bXf9BC5OqbRl3s/FsM+4UgowriYD0S2Zwc4/2j/W3mDRjOdGf0MJxd8SOxv7uW2P5JL0TImjA7mTgppSipw1ShGTl8BU7q11cCtFmuCmwGfvPlRLQtMqEdr93gNkY84rAja08K9Ro1/ySZtrEWVRh/lYzQqmpazsjlw1V4x+KYtn65LHr9Zxd46ToleV5kv1tEZJ1u7nFXeNnrfThyz78EqvLbVxzcqphrfrImGOD9/VhUwryM58KtVz7+tXmLjn3SsSmM8sz9DEljbEKK4zTV9mQgIxviGwzNuIGEFD+HaW6HRIsAzRNtXow5oT7Kgpqa3BnJ3HxM=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.28.2
Release Details
UpdatedJune 11, 2026, 6:33 p.m.
Changelog

Fixed

  • Dashboard could render half-empty (hero tiles only, widget grid invisible): a Chart.js resize on a hidden tile's detached canvas threw during initialization, and the widget grid was never revealed. Chart resizing now skips detached canvases and the grid is revealed before the resize pass. Likely also behind "nothing happens" reports after certain actions (#273)
  • Dashboard tiles with a saved account selection pointing at a deleted account (e.g. after factory reset + import re-numbered accounts) no longer error with 404s and stay empty — stale selections fall back to all accounts
  • Account balances are now derived from the ledger instead of running deltas — the root cause behind every historical balance-discrepancy report (#3, #89, #124, #163, #187, #194, #274). The stored balance was a running total that each transaction code path adjusted by hand; any missed or mis-signed delta corrupted it permanently. Every transaction create/update/delete (and retroactive rule run, repair action, import and bank sync) now recomputes balance = opening balance + net of non-scheduled transactions, making drift impossible and self-healing past inconsistencies on the next write. A one-time migration backfills the opening balance so displayed balances do not change on upgrade (#274)
  • Marking a bill as paid now warns loudly when no transaction was recorded (bill without an account, or transaction creation failed) — previously the bill was advanced silently and the account balance never reflected the payment, drifting from the real bank balance every cycle (#89, #274)
  • The app's own export→import now preserves transaction status (scheduled transactions no longer silently become balance-affecting after a migration) and restores the opening-balance invariant for imported accounts
  • "Skip Duplicate Transactions" off is now honored: previously rows whose import ID already existed were still rejected deeper in the stack (duplicate-ID guard + unique index), so parts of the batch silently failed to import. Intentional duplicates now get a uniquified import ID and the entire batch imports (#275)
  • Import duplicate detection no longer gives false positives for legitimately identical rows — e.g. two same-priced purchases on the same day with the same description. Identical rows within one file now import as distinct transactions (occurrence-aware import IDs), while re-importing the same statement still skips everything it already imported. Re-importing an older statement also recovers transactions the previous logic wrongly skipped (#276)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
Signaturekx2VkgWxozCE2LPp/nzgQQiqFxk/83sOdycv738Ly/uEwn/MhxF/kNtBlP4DMQbhmtkcHdt+kDIlQK1S5q1WHJWZQxjLc/ZCkj/ZEPkNBrDhHwdQCRh4TsRVJyfrIxXUTOCAKJLYk+0DXlnJB3kMhR81adns3wWNH9RkC4b62k3gXtzMR4n+jz/QJDGEAOXRpDUzxEm2TKqFot6sGRt3u0+rVo0bng6nogDJha0APeFI5Ujt+3mECw9MlxNt9nKbQlIGjAnraLVUFz0bXNLK7dbBS3PSzjLsUxhoNhAqMivfHEfLViOvIlCFNHzoWGxFnHK0flI2zJXUlOnaidOEyfhZWbqNpHZL4RZLIZWYQaztJgATNsK+L5aO0Md+Np1hgE8jkdY90gugiV06JqoPEWqCo/qSyaO9N3xYpeXrwfiL37JJqkigwg69RZN3OD1DfBT8ue7QlhT93dfg+39ERzbVY9QBu0gT+bwIs8tyE1MVXOaSjHKUkHab5dpGU3NQhvu/E1CO1BWA3dYvUUqvrvXKB96gm7IqNQEAkRi4JJHDPGtgzjERM+k8z/JA2xeJmPp7V3TZ/1WiKOoKMPz88soCJBMuj/LWnSpekLAGo4RJDy1JBlOm835e3ieJFVHwIwqG9YP7oRB/puFvYV6aaEXCnSkUcZV+z+2NXmHB8KM=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.28.1
Release Details
UpdatedJune 8, 2026, 12:13 p.m.
Changelog

Fixed

  • Install/upgrade aborted on Nextcloud 32 and earlier with "Primary index name on oc_budget_import_templates is too long". The budget_import_templates migration created its primary key without an explicit name, so Nextcloud derived a default name and hit the Oracle-compatibility identifier limit (the unprefixed table name is exactly 23 characters). The primary key now has an explicit short name. Thanks to @TheUnderdev for the report and fix (#272)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureXdUz/Pc10uA7L3R+vTa/cI52W9X8nDyH33zElCWeS/xWeYgonfr0GwLhn4ywE7rtUQF8e1Y8GhETbSd60otnPduP+4rXp7+5+b+iMTa3qfYi6gAd3Y1YJJrZqK0yx2Fdqld/nhQLfFpVkUSQl/JQ78RZanEh779Af5RejNl7lolRlJYg7ZNrLrFasWrpyrLNsg4+Tf74/vMpKWDXf0FEIqjnXZ0LKJm7Yjig4uazy+a5vDcDOrfq6fLU56d9ML/jBJK+9A2loT3I5HP7H2cngdLpwk6+MNLiYQDsdNzLGJJK9TK4hn0Cj+AV80mAQ45beagh4H0SmEoDTPvR/hC7LLlU5rtioE1Rg1tCvlZfHBuPcH9LZMq11Q3HVbZnvzkTdG3lKQlKeFhP86QOIjiAg1Frm0yuOt4nMSdG36N+k1C5szF7HrCoH+u1XgdY6fKI6WW71RkqXJ2IhwOorxcijLVQc2l3wyDLqoQrHtJA2yWGsI9NXlq+d5ZLJ03T7xvcLBPgSDTz91KqBABqJYRdCGhzAuQPe9M814mDu5XgdoCJNUKNrAl6YGvLvJXyj5j8I09qImqsQx09AmEBxi8YTZDbxuO8U/g3yKO14aBgGu3Z+v8+h6xyqJyNsPEbHHxpjfSbwAF/9FlvjA64nOTqPam3fPOjZAdqne5bgf05gFY=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.28.0
Release Details
UpdatedJune 7, 2026, 9:59 p.m.
Changelog

Added

  • Shared savings goals — share a savings goal with another Nextcloud user. Recipients see a "Shared" badge and can view progress; with write permission they can edit the goal and add money, while only the owner can delete it (#255)
  • Auto-derived budgets from recurring items — a (sub-)category with no manually-set budget now shows its committed recurring total (active recurring bills + recurring income, normalized to the budget period) as an automatic budget limit, marked "auto". Typing a value always overrides it (#269)
  • Exclude extraordinary/one-time items from the forecast — a per-transaction "exclude from forecast" flag (with a "No forecast" list badge), the same flag on recurring bills/income (propagated to generated transactions), and a matching import-rule action. Flagged amounts still affect your balance but are kept out of the projection averages (#270)
  • Reusable CSV import templates — save column mappings and import options and reapply them to future imports (#247)
  • OFX/QIF import account routing — route multi-account OFX/QIF files to the right Budget accounts, remembered across subsequent imports
  • Bank sync: pending transactions — option to import not-yet-posted (pending) transactions, automatically reconciled when they clear (#257)
  • Bill start dates — a bill only occurs on or after its start date, making it easy to change a recurring cost mid-year by ending one bill and starting another (#268)
  • "Shared with me" expenses view — recipients can now see expenses that have been shared with them (#248)
  • Dashboard period indicator — chart tiles now show a read-only indicator of the period they cover (#250)

Fixed

  • Dashboard now collapses to a single full-width column on phones, independent of your configured desktop column count (#249)
  • "Excluded from reports" categories no longer appear in the Budget view (#266, #267)
  • Category spending chart shows income as positive with the correct label (#265)
  • Tag-linked savings goals now sum net realized contributions (credits minus debits, excluding scheduled) (#264)
  • Recurring income description is now persisted on create (#263)
  • Transfers are now excluded from dashboard income/expense totals (#262)
  • Account Breakdown report now uses each account's own currency instead of a single assumed one (#256)
  • Fixed a PageController crash (TypeError) on unauthenticated requests (#259)
  • Quick Add date field normalization on iOS (#235)

Docs

  • Documented the standalone Quick Add page and the iOS home-screen workaround
  • Noted that GoCardless no longer accepts new bank-sync sign-ups; EU/UK self-hosters without an existing account are pointed to manual import (#271)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureiQMjVEdG/FWcc56MAPwvDd04E0ERl5pUWkrRWtdYdgbboBj0+7YAo+rDODFz5qC3EPqWBr7XRkjXOfvn9+m61v0w88Qy8SZQIZRHTAwRJuK5jDQbpfce5dropQgKW8btEIzI3BPE+DFBIDeV+qLNQEYT25ApMkUAz44PumVV0sJMibCGo0JBgIxHCPyem1NNjYaX3qQDt41eg8I5rH8wLCWGa7lNTtGyp8vaJ4ck0sh4J9sPuVzMdJoXQDHfGe5S8YY3GTwgvwyloNJQAFO+SQzm5WX6mC/IKAfpxwG82cQAEMm6B4geyHwaYGSFDEgrBuHOZj2fQmvQgzoarRN+U76bOhjQI0IqU76Pno3qM17eF+UKW8peDiqFBXpepGYfDoeyjQsF2GqxIK3C0bNUR5bp9RjNxkWckwvS2ihvP/2rg4lr05MuDDmIdBYG9Ny+PT9dEWBssQkXzIVX28Ox6P8xkorH0n5EoSRl3j+KMXbM34QteNMt1+jgsHAxcS8H57CwV3MC0uqZnhxUu/LbwIGHzvKbC6vN3F/3l6F+35rWM7UaQhdvr2W/1q5Swj5F2sp2Bq5jgrxbWIuUB9+pzftASgVUEmtd6blOUlJuuJj1wmaIrA9jx21+Bg8t/OmrQqB97ZHzint0WTdo7KTOviKZGnoZVXeoQthPmSyW7Wc=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath

Nextcloud 33

Budget 2.52.0
Release Details
UpdatedSept. 18, 2026, 11:44 a.m.
Changelog

Added

  • Import templates remember the character encoding. A statement in an encoding the importer cannot recognise on its own - an undeclared Cyrillic or Central European CSV reads as perfectly valid Western European text, just with the wrong letters - has to have its encoding picked by hand on the mapping screen, and that choice was lost on every import. A saved template now keeps it, and picking the template re-reads the file in that encoding straight away. Templates saved before this have no encoding stored and leave the picker as it is, so they cannot undo an encoding you have just chosen for the file in front of you. Contributed by @Saviq (#384)
  • Import rules can rewrite a transaction's description. A new Set Description action replaces the description a transaction arrived with - CARD PAYMENT TO TESCO STORES 2231 can become Groceries - either always or only when the description is empty. It runs on file imports, on bank sync and when rules are applied to existing transactions. Duplicate detection keeps using the description from the original file, so a statement imported again is still recognised after a rule has rewritten its descriptions. Contributed by @Saviq (#385)

  • The import review says which rows it cannot take, before you import. A file with an Account column can carry rows whose account cell is empty, and with Account for rows without one left on Skip rows without an account those rows are dropped. The review step never said so: a 75-row file whose last 29 rows had no account read as "Total 75, New 0, Duplicates 46", and the only mention of the missing 29 was a dialog after the import had already run. The reasons were there all along, the review step simply did not show them. A warning now sits above the statistics, in the same place as the direction warnings, saying how many of the file's rows will not be imported and why, with the row numbers behind each reason. Where the reason is an empty account cell it points at the fallback account select below it, which is what fixes it, and choosing an account there clears the warning and brings those rows back into the count. The row numbers also match between the review step and the dialog after the import now, the review step counted from 0 whilst the import counted from 1. Reported by @TerjeTM (#388)

  • The Budget Alerts tile can be told which categories it may alert about. Since 2.28.3 a category with no budget of its own falls back to the amount its bills and recurring income commit it to, so categories that were never budgeted against started appearing on the tile, and spending 190.00 against a 56.03 figure worked out from a bill reads as "239% over". The tile's settings, on the gear when the dashboard is unlocked, now offer Only categories with a budget I set, which leaves the derived budgets out and gives back what the tile showed before that fallback existed, and a list of every category with a budget in play that can be unticked one at a time. Rows whose budget came from a bill are marked, so it is clear which ones the checkbox covers. The filter is stored with your settings rather than with the tile, so budget alert notifications and the digest honour it as well, and the budget figures on the Budget page, the Nextcloud dashboard panel and the digest are untouched by it. With a filter on, a tile with nothing left to show stays up and says how many categories are muted rather than disappearing, which would take the gear with it. Reported by @TerjeTM (#389)

Changed

  • The mapping screen redraws as soon as you change the delimiter, the header toggle or the encoding. Changing the delimiter used to leave the columns and preview split the old way, with a note that the file would be re-parsed in the next step, and toggling Skip first row (headers) did not touch the preview at all - so neither could be checked before moving on. All three now re-read the uploaded file on the spot and redraw the column choices and the preview, keeping every column you had already picked that still exists. Picking a saved template does the same with the template's own delimiter and header setting, so its mapping lands on columns split the way it expects. Contributed by @Saviq (#383)
  • Translations. Ukrainian is now included, the Polish and Russian translations asked for in #382 are in, and German and French have been updated from Weblate.

Fixed

  • Expenses another user splits with you count towards your balance with them. When another Nextcloud user split an expense with you it showed under Shared with me as outstanding, however your contact for that person still read "Settled", opening it listed no expenses, and the totals at the top of Shared Expenses left it out. Each split is stored against the person who made it, and a contact card only ever read the splits you had made yourself. A contact linked to a Nextcloud user now also counts what that user has split with you, from your side, so their "owes you £40" is your "you owe £40", and where you have both split expenses with each other the card shows what is left once one is taken off the other. Their splits are listed in the contact's details marked split by with their name, and the payments they record show in the settlement history as payments from you. Only the person who split an expense can settle it, so Settle All and Record Payment still only reach your own splits, and are greyed out when none of yours are open. The contact has to be linked to their Nextcloud account, the same as for Shared with me. Reported by @Bow-Wow75 (#390)
  • A paid one-time bill keeps its due date. Marking a one-time bill paid cleared its next due date, and a bill created before 2.49.0 - when one-time bills gained a real Due Date - had nothing else to show, so a paid invoice read "No due date" in the list and opened with an empty Due Date beside the old Due Day and Due Month fields. The date a one-time bill was due is now kept when it is paid and the list shows it; bills paid before this release get their date back from the day and month they still hold, in the year nearest to the payment. The form no longer offers Due Day and Due Month for a one-time bill: the Due Date is its whole schedule, and it has to be filled in (#333)
  • The Bills Calendar no longer shows a bill as due for months it has moved past, or for months before it existed. Since 2.49.0 a month was struck through only when a payment was recorded against it, so a bill marked paid with Don't create any transaction - a yearly premium in February - stayed green in September as if still outstanding. Every bill was also projected back to January whatever day it was created, so a bill added on 8 September read as owed for the eight months before it, and those months inflated the monthly totals. A month the bill has moved past without a recorded payment is now struck through with a dashed line and its tooltip says no payment was recorded, and nothing is drawn before the bill's creation date unless a start date says the schedule began earlier - a bill with nothing left in the year drops out of the table rather than sitting there as a row of blanks. A payment linked from before then still shows as a paid month (#333)
  • Tab-separated CSV files can be imported. The Tab delimiter option sent the two characters \t instead of a tab, which the CSV reader refuses, so choosing it made the import fail - and a tab-separated file that was detected correctly showed a blank delimiter and was then read with commas. The option now sends a real tab, and a template saved from the old option is read as a tab too (#383)
  • The import review shows how many transactions the file holds. Total Transactions on the review step always read 0, whatever the file contained. The account page has a transaction counter with the same element id, and it sits earlier in the page, so every update meant for the import summary went to that hidden counter instead
  • Clicking quickly through months on the Budget page no longer shows another month's figures. Every month change starts its own loads of the spending and the budget amounts, and an earlier load that finished last replaced the newer figures, so June could show May's spending or May's budgets. Only the most recent load is shown now, and a budget load that fails leaves the base budgets rather than another month's. Contributed by @almeidandres (#387)
  • The dashboard follows your budget start day. With a Budget start day set, the income, expenses, savings and budget-remaining figures at the top of the dashboard still covered the calendar month, and Budget Progress set to the current budget period used the budgets of the month the period started in - a period from 28 August to 27 September was measured against August's budgets. The top figures now cover the current budget period and show its dates under their labels, and both use the budgets of the month the Budget page lists that period under, the month its 15th falls in. Envelope carryover, which the dashboard only added for whole calendar months, now counts for the budget period too. The six-month charts stay on calendar months. Contributed by @almeidandres (#386)
  • Every budget surface agrees on which month is running when you have a budget start day. A period is listed under the month its 15th falls in, so with a start day of the 10th, 5 September is still in August's period, and with the 28th, 29 September is already in October's. Budget alerts, and the Budget Health tile built on them, still used the budgets of the calendar month, the Budget page opened on the calendar month, and turning on envelope budgeting started the envelope in the calendar month too. All of them now use the period running today. The recurring-bill fallback and the "(projected)" carryover mark also treat that period as the current one, so a period that has already ended no longer borrows today's recurring figures. A category's details follow suit: This month, the trend and the monthly chart count spending per budget period instead of per calendar month, and the chart ends with the period running today. The same goes for the dashboard's Monthly Comparison tile, which now compares the running period with the one before, and for This Month Income and This Month Expenses on an account's page, and both show the dates they cover.
  • The Monthly Comparison and Weekly Spending tiles show the real figures. Both tiles looked for income and expenses at the top of the summary they load, however the summary keeps them under its totals, so they showed zeros whatever was in the accounts. They read the totals now.
  • An overdrawn envelope shows as over budget. When the overspend carried into a month is larger than that month's budget, nothing is left to spend, but the Budget page showed the row as "No budget set" with no remaining figure, and the dashboard's Budget Progress tile left it out. Both now show it as over budget, with what it owes as the remaining amount, as the alerts and reports already did.
  • The budget adjustment notice names the right month everywhere. "Budgets adjusted from ..." and its confirmation dialog read the month as midnight UTC, so anywhere west of UTC they named the month before the one being adjusted
  • The Budget page shows the right period for a start day of the 15th everywhere. The month picker's date was read as midnight UTC, which is still the 14th anywhere west of UTC, so in the Americas a budget start day of the 15th showed each month the period before the one it should
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureYjtb6oj/6u2vw+lMxUwTdqaoecbNZKr8zgforTdMu2KAUE/D7PJQiWgI+mlRDXOoDp++CZJkbkDwEIknVcN6Zl5rCfUtSvMwdVk4IvOKwG7AW2qqDhnHDplkWBwPMEFNNJdQxPnjsDTNYxTEtGnOXwl2gxc9NMIFSD3c/DeCbxzLZd61DaVpjQohgLF7EKuVeLohtjay574dEpwpXH9z50nYJ0bO65jUTxrnZmLoafqKyQRu7tqurEWjlkhUcZRBALUnDzc1KwA+7kP1K1SwVoJkiuJwqcZNju3hsz8US7leYtvEnQL0Qsp+TnCHKiGibv/G5kVVwgvGZ0ThI20UeIHQOMKDZXj+d+CKuskMLpBJTUZPJaQyTeyIfFQ858nZlHHKC1mSRno6XPO1pYQCvHBzf+TIZBtF9U7N9svhxDJ2eXRAXJbp+BrtfuVrBEFkXE/4kilamlMPdGi1nG0EkcnKB9tVaqryzKWgWb97hfuBftBulfa+kaGjJAH9ZMwf9GioTzOCSdLf32lC+XFlDFxf93nTrzfNPB3dU+v/F1ZiItBx3WvAcXbYdg2lYa8y/A8liLqYXj19o9GqDbhNFVhCVQNvfFn0nfq/otpkY6sMH+brtN4O1HQfNqOOn6Lp09HRh299sfO8kuCaQDIGfeyNb4qNNJALi6bewhAaORk=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.51.0
Release Details
UpdatedSept. 11, 2026, 1:17 p.m.
Changelog

Added

  • Accounts can be deleted in bulk. Tick the accounts you want gone and delete them in one go, from either the tile or the list view. This existed for transactions and categories but never for accounts, and the gap only really bites in the one situation that produces dozens of them at once - an import with the wrong column mapped to Account, which creates one account per distinct value in that column. Deleting those one at a time also ran into the delete endpoint's rate limit of ten calls a minute, and an account that still holds transactions costs two of them, so the clean-up stalled about five accounts in. The whole selection now goes in a single request. The destructive half is kept a separate decision: the first confirmation removes only the accounts that are already empty, and anything still holding transactions is kept back and asked about in a second dialog that names those accounts and totals their transactions, so nothing with history in it is deleted by a click meant for an empty account. Closed accounts can be selected too (#381)
  • The import preview warns when a column mapping is about to create a pile of accounts. Mapping the wrong column to Account creates one account per distinct value in it, and mapping the date column gives you one account per day. The preview did list what it was about to create, but as a comma-separated line among the statistics, which reads as a note rather than as a reason to go back. Above five new accounts it is now a proper warning, sitting above the stats where the direction warnings already sit, because it answers the same question - whether to import at all. When most of the new account names parse as dates it says so outright and points at the account column mapping, rather than leaving you to work out afterwards why you have forty accounts (#381)
  • Bulk edit can add and remove tags. Tagging a run of transactions meant opening each one in turn: the bulk editor only ever touched fields stored on the transaction row itself, and a tag is not one of them. Tags... in the bulk bar now adds and removes tags across the whole selection at once, a cross-page select all matching selection included. The two lists are deliberately separate rather than one set of checkboxes - a tag you leave unchecked is not touched either way, so adding one tag to a hundred transactions cannot quietly strip the tags those transactions already carry. Adding a tag a transaction already has does nothing, and neither does removing one it does not have, so the same change can be re-run over an overlapping selection without anything happening twice. Category tags are offered too, grouped under the category they belong to. A tag set belongs to one category, so across a selection spanning several it can only reach part of what you picked - rather than leave you to find that out afterwards, each group says how far it reaches (applies to 12 of 50), only the categories actually in your selection are offered at all, and the confirmation names any tag that fell short instead of claiming it did more. Anything the tags cannot cover is counted underneath, including split transactions, which have no category of their own once split. Removing is not restricted the same way: a transaction re-categorised after it was tagged keeps the old tag, and gating removal would leave that tag impossible to clear in bulk. Requested by @joeftiger (#379)

Fixed

  • Names with an ampersand or a quote come out right in confirmations and messages. A category called "Food & Dining" was named in its own delete confirmation as "Food &amp; Dining", and the same went for anything carrying a quote or an angle bracket - an account, a contact, a saved report. Translated text has its inserted values escaped for HTML by default, which is right for the many places that text is used as markup and wrong for the two that show it literally: the confirmations and the little messages that slide in at the top right. Both now undo that escaping, so a name reads the way it was typed. This was true of the old browser confirmations too; it is simply visible now that the dialogs are the app's own (#381)
  • Editing a reconciled transaction in the list no longer asks twice. Changing the amount, date or account of a reconciled transaction directly in the table warns you first, and that warning could appear a second time straight after you had answered it - once because opening it moved the cursor out of the cell you were editing, and once more when the table redrew behind it. Answering once is now enough (#381)
  • Confirmations stop working after a few of them in a row. Every confirmation in the app was a browser dialog, and browsers offer to switch those off: after a handful in quick succession, Chrome and Firefox add a Prevent this page from creating additional dialogs checkbox to the box, and once it is ticked every later confirmation is answered no instantly without anything being drawn. From that moment the app looked broken rather than cautious - Delete did nothing whatsoever, no dialog, no error, no message, and nothing short of reloading the page brought it back. Clearing up a handful of accounts left behind by a mis-mapped import was more than enough to trigger it, which is how this came to light: two accounts deleted fine, and every delete button after that appeared dead. Confirmations, prompts and alerts are now drawn by the app itself, so there is nothing left for a browser to suppress. They take the keyboard - Enter confirms, Escape cancels, Tab stays inside the dialog - and a confirmation for something that deletes data now says so with a red button rather than a neutral OK. Reported by @missunderstoodninja (#381)
  • Tag pickers can be reached with the keyboard. Every tag checkbox in the app was hidden outright rather than just visually, which takes it out of the tab order and out of what a screen reader can announce - the coloured badge was the only way to set a tag, and only with a mouse. The checkboxes are now hidden visually but still focusable, and a badge shows a focus ring when you tab onto it. Nothing looks different with a mouse (#379)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureomDWujOwOWa9L4Xhc5Xr+YxrNL/X4KJz7URuQ3oocoKImK3zBZp5nUdl464tQpzylxC8sTBVsN9SqEm6KKKsPGkY92c4QnEzKWsuAM1fVZDgAqU/8oCyq6pSlRTrxxmHFN+PmioiScBnhErLMyrvPWkjVSpve7kIb5v1QRqf4nqJFuxeSOJAX1JgOM1tVME5Loxrm6SFZOsXaEXpKgqGF9SSuWXPAd1qGAO+MkugHo6zEjelkCYAWzkq2/tCZHOtIExuhBUk/BuSCMd9AaYhLb2iRJVT4FYcf14uRWCdfHmbRkNuGZNV63hbwNXwvIdP0KB9ZJ3QLV82V7LFyWY+s0VfssxJnKzjm8afeKo6zxq5SeRZmTVZDAxX7+aogVVWIqB18uwCI0dYWbMZQgR6PRqig0lf8E1j6KOiMRimZeHw0mkKFDV6ytcZEHgS8PuCih1ol9XaF+tNz4QJkKu/49A23APwrCUanew/Fs0BOhH7ydCNAl7sM5xpXKx4/4hoLJrA9tzTRwQUn1dmjbRk0QjThANrvqu+m0Gz97XWEwyyj3zHQyWYNy0Ozg1W1P01U/iFGH96Nd2emV2OO63z/AAmHrGWyBVBK73VlNx1guwaf8//c6XYbrbSJdF/smvbQcMa1MikuJq4DMpItW8vmvC+YOvUycpSHDkl7Hf+TC4=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.50.1
Release Details
UpdatedSept. 10, 2026, 1:21 a.m.
Changelog

Fixed

  • Save stops working on the transaction form after the split editor has been used. Turning Split across categories on and back off - or switching the type to Transfer with it on - hid the split rows but left them sitting inside the form. A hidden field is still checked by the browser, and an empty one it cannot put on screen is one it will not report either: the form simply refused to submit, with no message, no request and no error in the console, for every transaction from then on until the page was reloaded. Firefox and Chrome at least log something; Safari says nothing at all. Putting the split editor away now empties it, and a split amount is no longer a field the browser polices - an incomplete split was already caught on save, and says what is wrong in a way you can actually see. Reported by @SGiersch (#380)
  • Adding a transaction from an account preselects that account. The Add Transaction button on an account's page was reading the account being viewed from the wrong object, so it always came through empty and the picker opened blank - on the one screen where there is no question which account you meant (#380)
  • Transfer matching finds the other half in a shared account. A transfer between an account you own and one your partner has shared with you could not be matched: the search for the opposite leg only ever looked at rows you own, and a transaction in a shared account belongs to that account's owner, so the match dialog reported nothing to match and the bulk scan skipped the pair entirely. Linking the two was already allowed - it was only finding them that was not. The match dialog, the bulk scan and bulk linking now search every account you can write to, shared ones included. Accounts shared with you read-only are left out, because linking writes to both legs and a candidate you cannot write to could never have been linked anyway. Reported by @lexiconzero (#378)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignaturebuZC6LMTRyNL1vila15DJJFe8dDZf/j3oCjxjP7KvrqebYszACpNqevFzP0b+HFTrgRwXMF7+ZnHeZDVV4l4KuZgfeI78fVJnNhQQeYNYqcIRiZZTKoqfm3zpU0OzCqWchvR7Mgslc6IIuBGjmM5EAx53O05t69k00ylo5G2YLfeMtyeg9hlqRERfuE5aMa7w5YhvBcskq9gIbtuGRU5ZfK++QikEJxZS9Quy9H7iDuuRBrPgumyJyURxaENIodcPhTuHjC/95LQWciAI6bj562mWuNglVdBEC+9+oNRN12vyMHerogSRRNpfqKwMb93Yzhlw3gkjkD9DsZvVuzuek98QAxEhTDZeEcZ5o4aAB2m+mRAmx77mj0OrfvLcyL7ekKUCr6G0/xJkU3XtEG3WDF20OupAcXsNbYBduRIoCvozx/pEGOkIipe4oQOlh6POT7MkXWfxBGJaG3N8SzmUqihyNgx8KuoxodhHsw09O8ncNlmkiBEGNn0+Hx/UXiijxE4ucigWPVSmUP6SU6F8dpjU2EU/jqbIdxPiyz3r/tt/vbVXDw41c7wd5nnkHyubljlBW6KL1uREbhrl7fdRCgjzJkPKA+fa4tdpa83af3llfzKcnyO6TXQ/nPL+xI0eLwRlXUIp4eW9xIeY0sZ3bOwjMdOemiR1Q9lGSloAZc=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.50.0
Release Details
UpdatedSept. 5, 2026, 11:16 p.m.
Changelog

Added

  • Budget alerts and forecast warnings actually notify you now. The two switches at the top of Settings → Notifications have been there since the first release and never did anything - nothing read them, and the app had no such notification to send, so the only place a budget alert ever appeared was a dashboard card you had to go and look at. Budget Alerts now sends a notification the first time a category reaches your alert threshold (80% by default) in a budget period, and a second one if that category goes on to exceed its budget. That is the most it will send per category per period, so the nightly check cannot turn into nightly noise; a category that drops back under its threshold is forgotten, so it can alert again if it climbs back. Forecast Warnings sends at most one notification a month when the six-month forecast projects your combined balance below zero, naming the month it happens and the figure it falls to. Both default to on and are switched off from those same two checkboxes

Fixed

  • The Bills Calendar never shows an occurrence as paid while the bill still says it is due. 2.49.0 placed each payment on the nearest due date, and a bill paid twice at the end of a month - or paid a few days before the next cycle - had the extra payment land on the following occurrence, so the calendar struck through September while the Bills page showed the same occurrence as upcoming. The bill already knows which occurrences are done: marking one paid moves its next due date on a cycle, so everything before that date is closed and everything from it on is still owed. Payments are now only ever placed on closed occurrences; a second payment in a month shows as that month's larger amount rather than as a month that was never paid. Reported within the hour by @TerjeTM (#375)
  • One-time bills with the same name share one calendar row. Now that paid one-time bills stay in the year's calendar, a garage that sent three invoices appeared three times, one cell each. They are folded into one row with a cell per invoice, each keeping its own amount, the way recurring bills already read (#375)
  • Exported reports come out in your language. The PDF and CSV a report exports to were written with English labels whatever language Nextcloud was set to - the exporter never asked the translator, so a German user got Total Income and Account Breakdown in an otherwise German app. Every label in the report, Year over Year and Bills Calendar exports now goes through the same translations the screen uses, month names included, and the monthly scheduled report is produced in its recipient's language rather than the server's. Labels that already exist on screen are translated straight away; the few headings that only ever appeared in the exports are new to translators and fill in as the translations arrive (#377)
  • A monthly digest can report unusual spending. Unusual-spending detection judges a month that is still in progress, so it stays quiet before the 10th - pro-rating the rent on the 2nd would flag it every time. The monthly digest is sent on the 1st, so its unusual-spending section was empty every single time it went out, and the weekly digest only filled it in on the weeks that happened to start after the 10th. The digest now asks about the period it is actually reporting on: a finished week or month, compared against the same six-month typical figure scaled to that period's length, with no early-month rule to apply because a finished period is not a partial one. That also settles a mismatch in what the digest was telling you - it reported this month's spending so far inside a summary of last week or month, and now reports the period it covers
  • The digest notification says how many categories are spending unusually. The count was being attached to the notification and then never shown, so a digest that had found something looked exactly like one that had not
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignaturekDEMKCHGsB6XHpH0lnwbdVN2PlHEz5a/0JU2HlikRqJOIHvusKOCEPzyqSYRH/8U5+wPMQcWAi6Zlb8pcjgNh3CwemL7dVDMnrV7w65ZbG5xhBtzlziNuhs1FCJzqYQshdgCJzd2xQFJYJOqTqFXqdFQK6US+0Tgm47K6ROYrFUL/9JEhdaoH3kUz8PAP2WOq+IYdRfeUBlXUslF6pbtDWQ9g6gVSTUDF1Kj0V6UU+/M+GqrHY4flUN5Q9k6lGRLri8eBRO2woA5jdLWxJ5tyonb6F9e65yjlOIYbC3QV+TaHwH5MLbj9lmkrbAjFUMaaSWQ0VuEaj8vupo46ebxm2V4dGN4oisWd0VKRmlpGpGdDLIDYT1aZwIrVIRWPIicpqiFkLdOOo+YOCIl3XHNu6lPLxdR/jNcEDORoRJq6yPVtWZTroXgXM3TznOcNLXKotj7v/o1MPxId8uMms/wiu8PRksNIlFeLnmV8czhjhI+ZLElYqwCyMJjCUZUUB3ebdvRtbDqvuJBwuYp36Oi5UKfBTXqYzbAAO8qr4nAH/gdQsA8X+YquAMuux31ilINMpOvFX71Yf7/E15pqYZfvEQS0hq1hV4xIcgVAreEOHbIIFGcVB5WdrvYNeNP366rB5WsKXUBDGFrTEIL5vtj8OHgLqVYoEgBZNg/RL9j/Fc=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.49.0
Release Details
UpdatedSept. 3, 2026, 11:53 p.m.
Changelog

Added

  • A one-time bill can be dated in the past. A bill only ever stored a day and a month, and every date it worked out from them was rolled forward past today - right for a schedule, useless for an invoice from last month, which became due next year the moment you saved it, and jumped again if you tried to edit it back. For one-time bills the schedule fields now give way to a single Due Date, taken literally: an August invoice entered in September is due in August, shows as overdue until you mark it paid, and lands in August on the Bills Calendar. The placeholder transaction a new bill pre-creates is always a scheduled one, whatever its date: with a past date it was being written as a cleared payment, booking the money as spent for a bill nobody had paid (#375)

Fixed

  • The import's fallback account is reachable when the file has its own account column. A blank account cell now falls back to the account you choose - but the select that chooses it was hidden the moment an Account column was mapped, so the fallback could never be set from the wizard and those rows still failed with "no account was chosen". On the preview step the select now stays, relabelled Account for rows without one, and is optional: leave it empty and such rows are skipped with that reason listed (#333)
  • On SQLite, a failed save now gets the unfinished-update hint too. The hint recognised MySQL's and PostgreSQL's error codes and SQLite's "no such column", but SQLite words a failed INSERT as table X has no column named Y - which is exactly the failed save the hint exists for - and that slipped through, leaving the bare SQL. Found by running the check in a browser against a dropped column (#333)
  • The Bills Calendar shows what was actually paid. Paid months were guessed in the browser from the bill's last payment date - every month up to it counted as paid - so a bill you started paying in September showed January to August paid too, and a one-time bill fell out of the calendar the moment paying it deactivated it. The cells now come from the payments recorded against each bill: a month with a payment is paid and shows the amount that actually went out, months still to come show the expected amount, and the monthly totals follow suit. A payment made a few days late counts for the month it was due, a payment with no scheduled month near it appears as an extra paid month rather than vanishing, and a bill that is inactive now but was paid this year stays in the year's picture (#375)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureUTnFglOyY//mXGi7y/LDtH4919NkTXqAr1p4PsIxsYx5fusaiKeFTWxlcugWVBcXNirEhMLHMF/hTpCv05X/jQ0yMlB2LW8Q4bUwppTjyg44BEEACZuQWr1FTs7KhmlbU/nCDKTIuC+Uk458xB8kdIiggZoDRqb4JoINSJ2tXL5KeNQgeyyq8hqOm5pwUBxlJRgx61f8EPP4+JWoAY3DWZUGJvpmk8i0VrNtxOvHT2BTdfMxLauNboowdmko+GQv3ZLEoAwP0D1UI4pjcwxcOQdAkQuM4wXwN6tywUjdmzPTmYSTxEMO1XAnc1v22KUA7bQxkHYcg5viQMbtAA459AsY2ImPJdxGyt0PbszsxOgomnZ6BHQdohkI3zbgX2XRtRc0RycVyzkDtnuk1Nr4k8nEyhimtNea3nOZ5S3yQhrC7CPqpeoXqc/gzl5b2QrO1bC07TxUIMs9knOBR/SMWsXcSq2pzYY9FCW9+XsUVQ2XKi8CQmYiAi+rO8/RNLCkyz8OHkQuMtpdmv1YI7INkGwTr0wU0TVw1bC9ozc2GWsDeJGSYJBDn43uQQ+dyCr8xMhzkURYqjcvMYsgPUjTMY2AB0mFYow2XlRK67AE9hXrLSK25TIVHBH1JMkDx65jmH5jGQwmG8vbHjIoEygsJBRvy0hmb8uK7Pq1u5OyqnI=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.48.0
Release Details
UpdatedSept. 3, 2026, 9:09 p.m.
Changelog

Added

  • Tags can be hidden once they have served their purpose. A tag for a trip you have taken or a project that has finished keeps its history, but has no business in the picker for every new transaction — and deleting it would strip it from everything it is on. Editing a tag, on the Tags page for a global tag or in the category view for a tag-set tag, now offers a Hidden checkbox. A hidden tag is no longer offered when tagging a new transaction, bill, transfer or rule action, or when linking a savings goal, and it shows dimmed with a Hidden label where tags are managed so it can be found and unhidden. Everything that already carries the tag keeps it: the transactions stay tagged, the transaction filter and reports still list it, and a hidden tag already on the item being edited stays in its form, checked, so editing something else does not strip it (#373)
  • An account can be closed. An old bank account you no longer hold can be marked closed from the Advanced section of its edit dialog. It keeps every transaction and still counts in reports, the dashboard and net worth, but it no longer appears in any picker for new activity — the transaction and quick-add forms, transfers, bills, recurring income, imports, import rules, bank-sync mappings, savings goals and pension contributions. Pickers that filter history keep listing it, so its past stays reachable, and opening an old transaction that sits in a closed account keeps that account selected, labelled (closed). The accounts page lists closed accounts in a collapsed section of their own, and the account's page shows a Closed badge and drops the reconcile and card-payment actions. Closing is refused, with the reason shown in the form, while the balance is not zero, while any transaction is dated after today, or while an active bill, transfer, recurring income, pension contribution, bank-sync mapping or import rule still pays into or out of the account — the message names each one so it can be reassigned first. The standalone quick-add page and the import's account auto-matching skip closed accounts too, the interest accrual job leaves them alone, and the public API's GET /accounts gains an additive closed field so a capture client can filter on it (#372)

Fixed

  • Restoring a backup keeps the "exclude from reports" flag. The restore rebuilt each account field by field and never copied the flag, so every restore since the option was added put excluded accounts straight back into every total, silently. The new closed flag is restored the same way (#372)
  • The account form shows the real reason when an edit is refused. A refused account update always came back as "Failed to update account", hiding the specific message — including the reload notice a stale page gets when saving a debt. Refusals that carry a reason now reach the form verbatim (#372)
  • The unfinished-update warning now checks the database itself, and names the exact fix. It used to compare the migration files on disk with the list Nextcloud had recorded as run, and that misses both ways an install can actually be broken: a migration recorded as applied whose column is nevertheless not there, and a migration file that never reached the server. The instance that prompted this had run the recommended occ app:disable && occ app:enable to the letter and still could not save a bill, because that only re-runs what is unrecorded. The check now reads the live schema and compares it with every column the app writes, lists what is missing by table and column, and - for a change that is recorded but absent - names the precise occ migrations:execute budget <version> to re-run it, with the debug toggle those commands need. A column no migration on the server adds is called out as an incomplete install instead. The warning appears on the app's pages, in the admin overview, and in the error a failed save shows, where it now bypasses the "already verified" shortcut because a save just failed. Not being able to read the schema warns about nothing, as before (#333)
  • Repair Data no longer deletes both halves of a duplicate pair, and no longer orphans what hangs off a transaction. Its duplicate cleanup removed rows straight from the database, so any splits, tags, attachments and shared-expense records on a deleted transaction were left behind with nothing to join back to - invisible, and beyond the reach of every cleanup the app has, factory reset included. It also had three detectors flagging the same rows, each free to pick a different keeper: two placeholders written by the same payment share a creation time, so which one counted as "the real payment" came down to sort order, and a pair flagged both ways had both halves deleted - the payment removed along with its duplicate. Deletions now go through the same cascade every other part of the app uses, and a row another finding is keeping is never deleted; anything left ambiguous is simply left for a second run
  • Reconciling an account no longer means ticking your way through the whole ledger. A first reconciliation has nothing earlier to anchor on, so it starts from the account's opening balance - which means every transaction since has to be ticked before the difference reaches zero. On a real account that was 860 rows at 25 to a page, against an unfiltered list that still included scheduled rows dated years ahead. Starting a session now narrows the list to the account, to transactions dated on or before the statement date, and to rows not already reconciled - those are inside the starting balance already, so ticking one would have counted it twice - and the bar offers Tick all N transactions up to \<date> to do the whole statement in one click, leaving you to untick what your bank has not taken yet. Nothing is written to the transactions until Finish, so it is a starting point to correct from. The Create adjustment button no longer appears until something has been ticked, since before that the "difference" is simply the account's entire history, and the starting balance now explains in its tooltip where its number came from. Leaving a session hands the list back unfiltered (#374)
  • Marking a bill paid without recording a transaction no longer leaves it looking due. Choosing Don't create any transaction or linking one that already existed left the pre-created row for the occurrence you had just paid sitting in the ledger, still scheduled - so the bill went on showing as upcoming - and at the same time suppressed the row for the next occurrence, so the forecast lost it. One flag was answering two different questions. Recording the payment is now about this payment alone, and whether the next occurrence is pre-created is the bill's own Create future transaction setting, which is how skipping an occurrence and editing a bill have always read it. Existing leftovers clear themselves the next time that bill is marked paid. The dialog also now says that the bill moves on to its next due date whichever option you pick (#376)
  • Rows with an empty account column are imported instead of thrown away. A file that carries its own account column had every row with that cell left blank dropped, even though the import screen had already been told which account the file belongs to - one reporter lost 14 of 27 rows that way, in silence, and only noticed because the balance was wrong. A blank cell now falls back to the account chosen for the import. A cell that names an account which cannot be resolved is still reported rather than guessed at, since that one would misfile the row (#333)
  • The importer no longer invents an account out of a file's header row. With "first row is a header" switched off, the header line is read as data - and because it holds the column titles, its account cell held the word "Account:", which the importer duly created as a real account in dollars. Only a row that would import as a transaction can name an account now, so a header line is ignored the same way the import itself ignores it. New accounts the importer creates also take your default currency rather than always US dollars (#333)
  • The import tells you why rows failed instead of pointing at the server log. A partly failed import said "%n rows could not be imported - check the server log for details" and put the actual reasons in the browser console, where nobody looks - and on an instance whose logging is misconfigured, or where the admin cannot read the log at all, there was nowhere left to find out. The reasons now open in a window as soon as the import finishes, one line per reason with the rows it applies to, so fourteen rows failing the same way read as one problem rather than fourteen (#333)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignaturewDpgdodKiAH0BJNKoHpu1H3xardvLeUHU4/1s4cGzs/N9ZfELYEXGP9FnFBY0fSJWBscyElRGGL3vR58ISgUep5I5P9aX+JA/uHMtjeyafCVQGj/YNbhZtz/hKtNb2zM+erfMrzq6pLkleaPsCFoe5tEt3ufMZKASjvCpU1R3j4Ec6bDjiom1fk90CImC26ZItTfc5Vu/dxGtACVerJ0IvZzQPvR1J2FY1xDlqCeeuapHMmB/z3V5Px9JQU0BC+nM5qF335DutR30cz0BP7ghkp7juBWtj5fBMe2bRYmqu+AOVdcbniqHtHvktQmMjv77gQzTupn8tfNtOSf4qLK5YbiqOfMXnIIai5qmrgJE1tsO17hPQmpxol9owkPC2gRa7TwHsS09K3cMrEjpKNORD5hkFlc2m9eQR2xRAu68dWQwXkhbnmu42PcpwqQsKdLhDbwBWRJHyFqsMSds4mjYhUN5+wvQbWSsQTXoO8Z9InCntaQsDxR1rTX6CWxAy0gHx+ZD0hGv0ttqWbJzEiOPrlYwLbDvserRhlotDAahPDxsdV3PEwj28+Jtv04Ie0vE/k9n56NsAFY3e8PGjJE156W6+qurFoiXi2OcJynyAmsOsoj8DTLKnMsVMVtlw16lNZZ6uAANdDUrG1QOE8F065BkQxwg69PR3qHL3jfsgY=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.47.0
Release Details
UpdatedAug. 29, 2026, 9:47 p.m.
Changelog

Added

  • The import screen can be told which character encoding a statement uses. Some files simply cannot be identified from their contents: every single-byte encoding accepts every possible byte, so an undeclared Cyrillic export is indistinguishable from a Western European one and any automatic answer is a guess. The mapping step now carries a Character Encoding picker, listing Western European, Central European, Cyrillic, Greek, Turkish, Hebrew, Japanese, Chinese and Korean options alongside Unicode, with the detected encoding named in the hint beneath it. It sits directly above the preview, so a wrong guess is visible as mojibake and correcting it redraws the columns and preview immediately. Uploads are now kept exactly as they arrived rather than converted on the way in, which is what makes the choice reversible — previously the original bytes were discarded at upload and a bad guess could not be undone (#371)

Fixed

  • A statement that isn't UTF-8 is no longer read as Latin-1 regardless. Files that aren't UTF-8 were run through a list of fallback encodings, but the first entry accepts every possible byte, so it always matched and the rest were never reached — every such upload was decoded as Latin-1 whatever it actually was, turning a Cyrillic statement into Ïÿò¸ðî÷êà and a Japanese one into ûÀ;út;àz, with no error to say anything had gone wrong. A file that declares its own encoding is now believed: OFX states it in its header and camt XML in its declaration. Anything undeclared falls back to Windows-1252 rather than ISO-8859-1 — the two agree except over the range holding the curly quotes, dashes and euro signs statements are full of. Converted XML also has its declaration corrected to match its new contents, which previously made the parser decode the file a second time and produce exactly the corruption the conversion was there to prevent. Note that an undeclared file in a non-Western encoding still can't be identified from its bytes alone — single-byte encodings are indistinguishable, and testing for the multi-byte ones proved worse than not trying, since ordinary German, Spanish and French text validates cleanly as GB18030. That case needs an encoding picker on the import screen (#371)
  • Statements written in your own language import again. A CSV, OFX or QIF holding a decent amount of non-ASCII text was refused outright as "File appears to be binary" — which took in Cyrillic, Greek, Hebrew, Arabic and CJK statements wholesale, and caught plain accented Latin too, so a French or Spanish export could trip it as easily as a Russian one. The binary check allowed the first byte of a multi-byte UTF-8 character but not the bytes that follow it, and every non-ASCII character has at least one, so roughly half the bytes of a Cyrillic file were counted as unprintable against a 10% limit. High bytes are simply what non-English text looks like, in UTF-8 and in the older 8-bit encodings banks still export, so they no longer count against a file at all; genuine binaries are caught by their null bytes and control characters, which text does not contain. Reported with a diagnosis and a fix by @ba1amut (#369)
  • "Auto-pay when due" can be switched on while editing a bill. The checkbox needs a pay-from account, and the only thing that worked that out hung off the account dropdown's own change event — but opening a bill fills that dropdown from code, which fires no such event. So every existing bill opened with auto-pay greyed out, however long it had had an account, and the only way to reach the checkbox was to re-pick the account by hand. Creating a bill was unaffected, which is why it went unnoticed. The state is now recomputed whenever the form opens (#370)
  • Editing a bill shared with you no longer strips its category and pay-from account. Sharing is granted per type, so a bill can be shared while the account it pays from is not — and both dropdowns can only list what you are allowed to see. The form silently fell back to "No specific account", and saving submitted that as no account, wiping the setting off the owner's bill; the same went for an unshared category. The real values now stay selected, shown as Unavailable (not shared with you) so it is clear why they cannot be changed, and they survive the save untouched. Auto-pay is also refused server-side when a bill would be left switched on with nothing to pay from — a pairing the create path has always rejected (#370)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignaturexHUL+LrtKQmEHZ8YQwsy+xFaIqzNZrPxOFdHD44Th6v2oSFX5rCCI2kmScHUejaVOt1t0nLiJ2qf5ZSRVvOmPPeeinPhoqGhwYlP0Nkgt8Rb0x1zPZTJj63Na8ESocx7CpajZTDxKc8pAFrQJ+H03K4UDks+/1F0qFF2NYa1soV6+c+fIuMPDaYC+DjO3aeWaJabhTUgUymMmqHLxqlhAyw+a8LJ2ABwYyT8P/rmIQ267T72D8ng0f8/ubS4mvfICaoAbtMA8H5Rnn7/gcPMDv1nJyTv97ShefnigmiykqBSWJsJQE8Ax/RYNfXWJ3Gl9uRxzXigxKYwpGtWMFnE9G2JN/eOh5oG042V5wn1QI0QcfWG2QFilp5uOD6ZVTfyPG+um2Y0FQLFe4PJnxyYpnrXmWglFFMyEVCVa0a7+AJmb7DVfjz/9vhBewTYCJ/j9XDlw8Efu28ZYWtsgZ5vZIlH4a90WalHLWHprUsNLDrUSyl+WRLTWDYDfEviRHJBCrrcz34Zyo8An0+sM9ccQalvH78w4X9PDIL5pMS90MHgyYrXVGyMPqSG65FliBn0qku7pP8wCqUabT9Ac3ofyztTlj0dy+tHyuu0OLPb+FxaLUoCgw5PaOSNSOXgDw8amDnleLNrZjvHIEsoYCS2jXtxU0rrTbmFXi4djM4jyTQ=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.46.0
Release Details
UpdatedAug. 29, 2026, 2:08 a.m.
Changelog

Added

  • A Money Flow diagram shows where the money went. Reports gains a Money Flow type that draws the period's cash as a flow diagram: income categories stream into a central Cash Flow node, which fans out into your expense categories and their subcategories, with what's left shown as a Surplus band — or a Deficit feeding in when spending exceeded income. Amounts label every node, category colors carry through, and the usual period and shared-account filters apply (#366)

Fixed

  • Bills and income shared with you can be opened again. Opening a bill your partner created failed with "Failed to load bill", and so did every action on it: editing, deleting, marking it paid or unpaid, skipping a payment, and the Record transaction repair. Sharing grants visibility, not identity, but each of those looked the bill up as the person clicking rather than as its owner, so the app approved the action and then could not find the bill to carry it out (a DoesNotExistException in the log). Bill actions now run against the bill's owner, so a shared bill behaves like one of your own, and Mark Unpaid is offered on shared bills for the first time. Shared recurring income had the identical fault and is fixed with it, and its Mark received action — which had no permission check at all, only the scoping that made it fail — now refuses a read-only share properly (#368)
  • A transfer between accounts shared with you now completes. Creating a transfer in an account owned by someone else booked both sides and then failed to join them, leaving two unconnected transactions behind every attempt and putting the raw database query on screen as the error message. Both rows belong to the account's owner, while the linking step went looking for them as the person clicking. Linking, unlinking and Create and link now work across shared accounts, and a transaction you cannot reach reports itself as not found — which also means it reaches the log, where this failure left no trace at all (#368)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
Signaturex0J8AUUfQbAJljP4bb8goctxFgu6woboHqgqhSLiZLzSNh4/bgeYYYsy4ubudGRmEAdnJZqL9XcqPKKaaVIxVXVRFVCS24iGpCdqXhCW0MMvoROv7VMao+dHMrfPhungZxdm+nKurDuI2drTpZLmbckIj6+PnjLP0Z6M+a/P7wRw/3gtdHcf1KoNmRGNIlqUUolPhYJJFQbhgsf8yg/nzDMjm0OKXYvOKWSI+GR1HFQoNSLVx9TPk2zrBOT/ARpvDEStnWWBZxhn2shkEVFNE1ntupx4AmkerIySit3CB5j4H7imaHsIYwPHDhL+MEj9afFllpMnogByvQ+nHCvJ3v7PeuNYGgQTxMvoVKpvtPDyo2610eVQDQlK8UEzmOdimk7shlkllXiE/ZEIaeFINp17VuQbYlTwuuZlNfTendUZirhPFK4xR3AL6cpTxJHq/Xc/npPYAYk8wPyYseNnFL5A3/d2UXiT/m57GQiIMkTMrayR6kYmYjGYT2EAVSRjhA0wESnCJb6jVMc6YTcBVQ3uFXnA5gR1hdulx1Qj2lRhJpBSCcXBCl/4QHDv4OIhk4Is5DWUxcw91iuaBhMCpoJLwU+kkuaibIrsiV2L3np7EeZzPtxOsRG4GyCZRyvTvCVO7HVHu///wPi1sfMH4R05Ri0AUfbqdpqPrE70mG0=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.45.0
Release Details
UpdatedAug. 29, 2026, 12:59 a.m.
Changelog

Added

  • Bi-weekly schedules can be anchored to a date. Bi-weekly income, bills and transfers used to lock onto whichever week you happened to create them in — pick "every other Friday" and the app silently decided which Friday from the creation date, with no way to say "no, the other week" (#363). Transfers were worse off still: the form only offered a day-of-month field, which means nothing to a bi-weekly schedule (#364). Income now takes a First payment date for weekly and bi-weekly frequencies, and the transfer form gains the same start-date field bills have had — the date pins both the weekday and the week, and every occurrence lands a clean 14 (or 7) days from it, whether the date you give is in the past or the future. While a start date is set the weekday field follows it and locks, so the form cannot claim a different day than the schedule runs on. Note for existing bills and transfers: a start date you set before this release only delayed the first occurrence; from now on it anchors the schedule, so a weekly or bi-weekly bill with a start date will settle onto that date's weekday and week
  • Bills can be marked unpaid. Marking a bill paid by mistake was final: the Undo button lived in a ten-second toast, and once it was gone nothing could revert the paid state — deleting the payment transaction left the bill still claiming to be paid (#365). Every payment now stores what it changed, so a Mark Unpaid action on the bill reverts the most recent one properly: the due date rolls back, a one-time bill comes back to life instead of staying vanished, a statement-amount bill gets its exact amount back (which cannot be recomputed after the fact), and the payment transactions are cleaned up — including when you already deleted one of them yourself. Auto-paid and import-matched bills get the same revert, which the toast never offered them — a payment that was linked to an imported transaction unlinks it rather than deleting money that genuinely left your bank. Recurring transfers can be reverted too, from the Transfers view. The stored revert applies to the most recent payment only, and editing the bill's amount or schedule discards it — reverting would otherwise restore values from before your edit

  • CSV files without a header row can be imported. The importer always treated the first row as a header and silently ate it — a headerless export lost its first transaction with no way to say otherwise. A First row is a header toggle (on by default, matching the old behaviour) now controls it, columns are matched by position, and blank or duplicate header cells get translated "Column N" placeholders in the mapping dropdowns instead of untranslated internal names. Saved templates keep working: they store your file's real header names where they exist, so they survive language changes and column reordering. Templates saved from files with duplicate blank headers ("Column N (2)") need their columns re-picked once. Contributed by @Saviq (#367)

  • The database-updates warning reaches the admin overview. The check that detects the app's own migrations never having run (the "Unknown column" trap, #333) now registers as a proper Nextcloud setup check, so it appears under Settings > Administration > Overview and in occ setupchecks — visible to the admin who can actually run the fix, not just to whoever next opens the app

Fixed

  • A category drill-down into subcategories now says so. Opening a parent category's transactions (from Category Details or a chart slice) applies the parent plus its subcategories, but the filter panel could only display the parent — and picking the parent to narrow down to just it did nothing. The category dropdown now shows a combined entry like "Groceries + 2 subcategories" for the applied scope, and choosing the plain parent genuinely narrows to it (#361)
  • The bills list stops fetching every dead bill. Keeping paid one-time bills reachable for Mark Unpaid meant fetching the whole bill history and discarding most of it in the browser. The server now returns active bills plus the revertible ones directly, so the payload stays small however old the install (#365)
  • A category's count badge and its panel agree on damaged rows. A row carrying both its own category and split parts (the old bulk-edit damage) was excluded from the tree's count badge but still listed in the Category Details panel — off by one on the same screen. The panel now applies the same rule; Repair Data remains the way to fix the rows themselves (#360)
  • The split flag's grey states are resolved once and for all. Two damaged states have haunted long-lived databases: rows from before the flag existed (held NULL), and rows whose restore claimed they were split while the parts never made it into the old backups (#351). A one-time update resolves every such row from the parts table — the single source of truth — and restores now do the same, so the states cannot return. This fixes three real casualties: rule runs categorize legacy transactions again (they had started skipping every pre-2026 row while reporting success), assigning a category to a damaged row now sticks instead of silently vanishing while the row stayed listed as uncategorized forever, and the Uncategorized filter no longer offers up split parents whose categorisation is exactly how such rows were created (#360)
  • Find Duplicates no longer loses a next-day duplicate at a group boundary. Groups anchor on their first transaction so distinct purchases cannot chain together — but a pair one day apart could straddle two groups and the second copy went unreported entirely. Rows near the boundary are now carried into the next group, so every pair within the window is reported together and the no-chaining rule still holds (#333)
  • A savings goal that has gone backwards shows an empty bar, not a full one. The Savings view's goal list was the last progress bar without the negative clamp the others got in v2.44.2 — withdrawals exceeding deposits painted the bar completely full
  • The Category Trends tile sticks to expense categories. It relied on a side effect of the old one-direction totals to keep income categories out; with netted figures an income category could slip into the spending list. It now filters by category type explicitly
  • The database-updates warning can no longer be silenced by a mid-deploy race. If the check ran at the exact moment app files were being replaced, a failed directory read followed by a successful one within the same page load could record the version as verified while updates were genuinely pending — permanently hiding the banner on exactly the instance it exists for. The verified marker and the pending list now come from the same scan
  • Editing a bi-weekly bill no longer silently shifts which week it falls in. The consistency check that runs on every edit recomputed the due date "from today", so changing an amount or a note in the off week flipped the schedule's parity — the bill quietly moved a week. With a start date set, the schedule now recomputes from its anchor, and an unrelated edit can never move it (#363, #364)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureV/r+TeR/H5y0TiUgo9apV0nHrv4yLWR3o2yHxeSCrwBr87AyJBO6EphcfUm/aNNDYHbJfh2Nk4ghsMvljrNWPCgMFZdwynngNS3IbrSFauamMsnuvkxDcO5h+R5aAIyBfyog9idiDesDMJF2B1dDbe3COOlxDq5i8xiiP+BGqLpoeOYZKT2dpqoaYB9j16sGk5BSE07vSFnF8kz2PGcpgExtfEqMMVCDRGQUvU02KgLqNb6oFx0abf5NhRGTpNZPMyOMwWH0CVTATrZj7r9LBp8+HQqHUjCRqPTwsYbAVBZZKYwyrtU3Wd/4VaSpKW2bMS7OWA/663hc74b0Rt/QTy0brPK2oiQyM6PisiwlZHAz6nuQWRDUiyezWVS9yLBiVDavZxby7XJAIrb49a8dSESUj7/7eRaO9xAb21oULrp39o0d0GKWBxFf2fuV/uBJ/tQh1pgj7n5PHQ01kZ3Dy1znPGH//sIfsw5nBLeKQQGZvcp4ell+s19FJr2SoKe+HgY8Wo/eCobVpai8GbpeA1HsNc7ixuKIPdxpAsY7X/mNg92GEndFExIDBkUgQfbPYd+LkmjlJdtXqluxB24WdVIVdKDJakxk860CHTUo+k7UgVroJUffjXXwXvFKQCWZG8f/5Tt4eh3QpRfaqQGWpAjQ0lw/AURkUdA0FlN4ELo=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.44.2
Release Details
UpdatedAug. 28, 2026, 3:19 p.m.
Changelog

Fixed

  • The Budget page's Spent really does net refunds now. v2.44.0 said a refund comes off what you have spent, and it did — on the budget report, the dashboard tiles, the alerts and the digest. The Budget page itself reads a different query, which kept the old one-direction sum, so the very page the issue was reported against still showed $216.90 where Category Details showed $58.29. That query now nets the same way as everywhere else. A month whose refunds exceed its spending shows the true negative figure instead of being flipped into looking like money spent, and its progress bar sits empty rather than painting full — on the dashboard's Budget Progress tile and the savings-goal tiles too, where a negative used to render as a completely full bar. Changing a category's budget period also refreshes its row with the right direction and the selected month, instead of flipping an income category's Spent to a large negative until the next reload (#361)
  • "View All Transactions" on a category lists the transactions its figures are built from. The button quietly filtered to money-out only (money-in for income categories), so an expense category's refunds were missing from the very list the netted figures above it summarise — the panel said $58.29 and the list it opened could only add up to $216.90. It also ignored the panel's period and account selection, listing everything ever recorded. It now applies no direction filter and opens scoped to the same date window and account the panel is showing (#361)
  • The transaction filters panel shows the filters that are actually applied. Arriving at the Transactions view through a category's "View All Transactions" or a chart drill-down replaced the applied filters but left the panel's controls showing whatever they held before, so the list and the dropdowns above it disagreed — and because any change to one control re-reads all of them, a stale control could silently re-apply an old filter. The panel now rewrites every control whenever the filters are set for you, clearing the ones that no longer apply (#361)
  • The last places that ignored split transactions now count them. A split carries its categories on its individual parts, and five surfaces were still reading the transaction's own category, which a split never has. Year over Year compared a year of split receipts against a year that predated splitting and called the difference a collapse. The Forecast's category trends dropped every split into Uncategorized and showed nothing against the categories the money actually went to. The count beside each category on the Categories page read 0 for a category funded entirely by splits, next to a panel listing its transactions. Find Duplicates showed a dash where the category belonged. And a CSV export with no category filter left the Category cell empty on exactly the transactions someone had taken the trouble to itemise -- it now names them, and a category is named once however many parts of the receipt went to it (#360)
  • Find Duplicates no longer chains separate purchases into one giant "duplicate" group. Each candidate was compared against the previous row added to the group rather than the first, so five identical-amount purchases a few days apart -- a regular coffee order, a repeated fare -- linked end to end into a single group spanning far more than the 3-day window, and the tool told you to delete transactions that were nothing of the sort. A row now joins a group only when it is within the window of the group's first transaction (#333)
  • Deleting a category no longer leaves split parts pointing at it. The delete guard is deliberately blind to splits (a category used only by split parts must stay deletable), but nothing cleaned those parts up afterwards, so they kept referencing a category id that no longer existed. Deleting a category -- with or without reassigning its transactions -- now degrades its split parts to uncategorized, which is what the reassignment already did for ordinary transactions. Find Duplicates also names a split Split now instead of showing a dash (#360)
  • Splits from before the split feature existed are counted once, everywhere. A transaction whose split flag was never written -- imports predating the column, and backups restored from those versions -- was in a grey state: some queries treated it as a split, others as an ordinary transaction, so depending on the screen its money was counted twice, or not at all, or it was offered up for categorisation, which is how a transaction ends up claiming a category and carrying its own breakdown. Every query pair now agrees on one rule -- a transaction with split parts counts through its parts, full stop -- covering the budget carryovers, the monthly report, Year over Year, the forecast, per-account totals, uncategorized listings and rule runs. Restoring a backup now re-marks the transactions that actually received split parts, whatever the archive claimed, and the very large id lists a restore or a year-long report can produce are processed in batches instead of one oversized query (#360)
  • The app now notices when its own database updates never ran, and says so before anything fails. If Nextcloud replaces the app's files without finishing the upgrade, the database changes that came with the new version are skipped. Nothing looks wrong -- reading data does not touch the new columns -- and then the first thing you save fails with a database error nobody can act on. Every page now checks whether any of its database updates are missing and, if so, shows a banner naming how many and the command an administrator can run to finish them. Checking costs nothing once a version has been confirmed complete, and the banner clears itself as soon as the updates are applied (#333)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureDm8DKf6I3AofLr0FMZsDKeE4q19LhQ2NgVNbRwtRNtCcfcpkF7RWros6LUOJacOmyNa9EuRDVUGQJtTGSasNt4dXxhwDjw7hDsmm2NUaTTrnoLoY32V9zyBLZqtSLb30uZTr6O8q03UGO0MsNQr5IsOcNbi7KflfjmUbYY99cIycOm/FBoLBm+LWQlDH+eQZigjqEk5GMvsLgyY2LuYQE6226WS1W96gI3neUzwICij5OWn/hdkl4axB6Y2Ei7bWofiMRSwY4oeiLF1mmgk1C4OfyoZomZEhsytxXok5wt38K4SMQBL4A+zpVoQBp0cBdFrGUynC/eNtmQjS9nsJSs0woZ3H6+QrlMCmJ+PRqSbn5kEO7PBzXMXUYNg9mqd0mUeYjH0mW1SKpF51FsBKjMHNmi1ReNqQhiRAJq+9JzyiaUuCv/gigDXOaLCR5NvRld0RbMYfnWN9XZ18k8/b+oKwzBG/oY6mqmgR0mUl24lXHK7djSHbhfmCIAG6hpOxgrL6cFguUdqNuoCGhBvUaUBJn742J4Hh4Lx4jq+zQJE1rJf4xpNhcT6VKLJNS7DrSd62oPm80FBXSu9colzmlv3C67SDYwL5TxqdM8OCsPTJvH0IWnr9R+qrrPh5MMqy3XMDyYvzDMjiK0OWmzob4ZxMCg2gi1asdtcjd5PqNgU=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.44.1
Release Details
UpdatedAug. 28, 2026, 12:44 a.m.
Changelog

Fixed

  • When the app's update has not finished, the app now says so and how to finish it. If Nextcloud updates the files but never runs the app upgrade, the migrations that add new columns never run -- the app carries on reading fine, because reads do not notice a missing column, and then the first thing you save fails. Until now that surfaced as the database's own words, "Unknown column 'amount_type'", which is accurate and no use to anyone. Any missing column or table now comes with the command that fixes it: occ app:disable budget && occ app:enable budget. Reproduced against MariaDB, where neither occ upgrade (which upgrades the server) nor occ app:update (which looks for a newer release in the app store) does anything about it (#333)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureJfhfoodWHfhncS8NhWVo/wOO4gi2kDEn4S8M8TzZg5Qfbjwxmkmh4Pn294Og1wL1uIp5gbCGyS2aIzcDN0HoEf7DhN98hxRaZ5P5/5CBFLgTGTNwJmDX9A4Xtwk81o4/3jbeLAPUJspX2OkQKGzyNtFqrCi5aDG/JF5D0Yf49WBnYG3BZp5rSaEOmrD2Scm8D3EmE5wDsIIKg+Zl1iCVHsUX/Z7TG6lVzPxeW4JVIU4NX8hhUziOOGMXthSBM5GxZX4okbtfGm9uVeUOe49rT/kXcm7mTG2Xb/4Phywh7vFqMckiOTSwP2fLttq7LFUv0XtUoaOhxjfhFJBdQIDi9qhtJRMcRvXE8kPbswzpyN9W/nC6lv44Q0Bxse967DXVQ8ZoxIWCByl6/5Z4Ooi978d0lWc/HsZYqMX5SXTb3KoALYNCG2+8WfkXwF+kZ0kPc//K6Uh/r+lgO7Gx55xaR2XkmDhClY7u/PMhLOsc0segdjc4obFyHns/iTeKJjV+aEaOvlbNq5aDKioozMZr2vQhL9XfEv4rKLq5VTxaD0s/WOv4dMJxhA/7LRpC53OlPrFN1IKPgmXUS2v2gTtP7fF9eDvZ6u66ra9zTe/j+R7y2y8mMo0zcUMnPPUxJ5fgX5saIPC2svL65fawwwghOMQTiydg6jEmbipPDU38RJQ=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.44.0
Release Details
UpdatedAug. 26, 2026, 12:34 a.m.
Changelog

Added

  • Dashboard tiles can follow your budget period. Spending by Category, Top Spending Categories and Budget Progress gain a Current budget period date range in their gear settings, which tracks the Budget start day you set in Settings. If your money arrives on the 25th, the tile now covers the 25th to the 24th like the rest of the budget surfaces do, instead of cutting your cycle in half at the month boundary. Spending by Category's header chip names the days it is actually showing — "25 Aug – 24 Sept" — rather than repeating the setting back at you. The other tiles are unchanged: a balance-history chart and the income-vs-expenses series cover a span rather than one cycle, so the option is not offered there (#333)
  • Cash Flow Forecast and Year-over-Year now actually draw. Both tiles have been in the Add Tiles menu with a card, a chart area and a working server request behind them — and no code to draw the result, so they sat blank however long you waited. Both are off by default, which is why this went unnoticed. Cash Flow Forecast now plots your projected balance month by month, starting from today's balance so each step reads as a change, with that month's income and expenses in the tooltip; choose Next 3 / 6 / 12 months in its gear settings. Year-over-Year plots income against expenses for each of the last 2, 3 or 5 years, matching the chart on the Reports page so the two cannot disagree (#333)
  • The bills tiles let you choose how far ahead to look. Upcoming Bills and Bills Due Soon now take a Look ahead setting of the next 30, 60 or 90 days. Upcoming Bills previously showed whatever came first with no horizon at all, and Bills Due Soon was fixed at 14 days. Both still include bills up to a week overdue, so an unpaid bill does not vanish from the tile that exists to chase it — Upcoming Bills previously had no such cutoff and would show a bill overdue by months right alongside this week's, and now drops anything more than seven days overdue the same way Bills Due Soon already did (#333)

Fixed

  • "Last 30 days" on a dashboard tile now means the last 30 days. It meant the month so far: on the 24th you saw 24 days, and on the 1st of a month the tile charted a single day. "Last year" behaved the same way — the year so far, so on 3 January it showed three days. This is why a tile could flatly disagree with the budget alerts sitting above it on the same screen, and it hit anyone whose spending does not line up with the calendar month hardest, because the biggest bills of the cycle fell outside the window entirely. Affects Spending by Category, Top Spending Categories and Budget Progress. "Last 90 days" and "Last 6 months" were near enough but drifted by a day around month ends — six months back from 31 March landed on 1 October — and are now exact (#333)
  • Every Date Range dropdown on the dashboard now does something. Ten tiles offered one and ignored it: you could pick a range, it saved, and the tile carried on showing its own hardcoded window. Large Transactions had no date filter whatsoever — it ranked your biggest transactions over all time — and now honours the range. Weekly Spending was pinned to the last 7 days, and its daily average divided by 7 regardless; both now follow the range you pick, and its label — which always read "This week" — now names the range it is actually showing. That default week is now an explicit Last 7 days setting rather than a hardcoded one, so it is both the tile's starting point and a choice you can change like any other range. Category Trends compared this calendar month against last, and now compares the range you chose against the equal-length stretch immediately before it, so the two figures are like for like at any range. Where a range could never apply, the dropdown is gone rather than lying: Monthly Comparison is this month against last by definition, Debt Chart is a payoff projection with no window, and Income Tracking's headline is a monthly rate that cannot vary with one (#333)
  • The Cash Flow Forecast tile was asking the server for the wrong thing. It sent a days value the forecast endpoint does not accept, so the parameter was discarded and the default horizon used every time (#333)
  • When something fails to save, the app now tells you why. Errors across the app showed a fixed message -- "Failed to create bill", "Failed to save transaction" -- whatever had actually gone wrong, so a validation problem and a database problem looked identical and neither was actionable. Where a failure comes from the database the server already attaches a short, sanitised description of it, a missing column for instance, specifically so the cause is visible to people who cannot read their server's log. Nothing in the interface was reading it. That description now appears alongside the message everywhere a save, delete or update can fail -- transactions, accounts, categories, bills, rules, pensions, assets, transfers, income and bank sync (#362)
  • Bills with a statement or minimum-payment amount explain themselves when rejected. Those amount types only work on a transfer pointing at a credit card, and the two rules enforcing that were being replaced by the generic "Failed to create bill" instead of being shown. Genuinely unexpected failures still stay generic (#362)
  • Repair Data can clear the stray categories off your split transactions. The rows the old bulk edit and the rule runs left behind are still there, each claiming a category it should never have had. Settings > Repair Data gains Split Transactions Carrying a Category, listing every one it finds with the category currently stuck to it. Repairing removes only that stray category: the split stays a split, and every part of it is left exactly as it was. Genuine splits, ordinary transactions, and a transaction explicitly marked unsplit are all left alone, and the scan drains to empty once run rather than reporting the same rows forever (#360)
  • Rules no longer break a split transaction by categorising it. A split's categories live on its parts, and its own category is deliberately left empty -- so writing one onto it produces a row that claims a category and carries its own breakdown, which every per-category total then counts twice. Bulk edit was stopped from doing this a while back, but Run rule now and Run group rules write straight to the database and went around that guard, so rules were still quietly creating the damage. A rule now leaves a split's category alone while still applying everything else it does -- vendor, notes, tags and the rest -- so splits stay covered by your rules. The preview and the results list name such a row Split instead of showing it as Uncategorized, which read as a change that was never going to happen (#360)
  • A transaction damaged by the old bulk-edit bug is no longer counted twice. Before it was fixed, "filter by Uncategorized, select all, set a category" wrote a category onto split transactions without removing the parts underneath, leaving rows that claim to be in a category and carry their own breakdown. Nothing has ever cleaned those up, so they are still sitting in databases -- and the queries behind Spending by Category, the Reports charts and the Category Details panel added up both, reporting a split receipt at its full amount plus each of its parts, and counting it as two transactions. A category could therefore show more spending than the transactions underneath it actually came to. Each transaction is now counted once, through its parts where it has them (#360)
  • Budgets count the money you spent through a split. A split transaction holds no category of its own -- its categories sit on the individual parts -- and the query behind every budget figure only ever looked at the transaction's own category. So a receipt split between Groceries and Household added nothing to either budget: the progress bars read low, remaining read high, and the budget report agreed with them. Budget alerts have counted split money since they were added and the spending charts since v2.33.0, so a category could raise an over-budget alert while the bar right next to it showed room to spare. Affects Budget Progress, Budget Breakdown and Budget Remaining on the dashboard, the Budget view, Reports > Budget and its CSV and PDF, the scheduled monthly report email, and the Unusual spending section of the digest along with its notifications. Splits restored from a backup made before v2.41.0, which lost the flag marking a transaction as split, are counted too, and a transaction damaged by the old bulk-edit bug -- which stamped a category onto a split parent without removing its parts -- now counts through its parts rather than dumping the whole receipt into the one category it was stamped with (#360)
  • A refund now comes off what you have spent. Spent on the Budget page counted only money going out, so a bill that was refunded, a returned purchase or a reimbursed expense left the category looking fully spent -- a $216.90 phone bill with $158.61 credited back read as $216.90 spent, and the bar sat at 100% over a $120 budget. It now reads $58.29, which is the figure Category Details has always shown for the same category: the two screens disagreed, and the budget was the one that was wrong. The same net figure now feeds Reports > Budget and its exports, the Budget Progress, Budget Breakdown and Budget Remaining tiles, the budget alerts -- which is what stops a category raising an over-budget alert while the bar beside it shows room to spare -- and the Unusual spending digest, where a purchase you sent back no longer reads as a spike. Income categories are measured by what came in, with anything paid back out subtracted; Reports > Budget was previously asking for money-out on those too, so an income category with a budget reported nothing against it (#361)
  • A split transaction on the dashboard names the categories you sorted it into. Recent Transactions read each row's own category, and splitting a transaction moves the categories onto its individual parts -- so however carefully a receipt had been divided up, the tile called it Uncategorized. It now names the categories the parts went to, with a coloured dot for each and the part-by-part breakdown on hover, the way the transactions list and the account register have since v2.43.1. Where the tile is too narrow for all of them the names run to an ellipsis rather than pushing the amount off the row, and a split that arrives without its parts is called a Split, which is at least true (#360)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureQHxBHmyBaONUhmqkujdb3Z0HaVDO5kl4378wYHWJgtW/QHl6D1QNcKQzzhB2nVoXZz322zCDeUae1eIk3C+EX4X5q2MolNnL9UAL0TvS0oSfQcAtWTFCAO1Z79C1uYbCxM6CUNNrGmZdoZ41ivw9OJQOICFu5nd0RHQ+w25DUCKK0SOEQXWia7LN5o0RnpTwKYxSxQHIb4dajJvbWsW+oibyBkP/yZsbfJRls3Z2zWYvEEnQhWiKTaJC4Ijfz6DgP6U/M9Z5DjhIZgyxPy5OGTOLd9aZl64K3JzcQqKDKJJ8wTDz9iUXb+bCitxDyq0chgLG4tbSyFyK7+aAcWchHZXufXDmPmAsTikDVgc6srYeKyqv2VFpa/IBA1m0GeAzN2KqIRzDbiyttRGgQQ5i2VPH4owiA8un5ak46XVpD+q5Xy/SwEZVmjCY8AZsZePmPvM9gESC+hBy6P5YuNksSar/dD++REsQCeFkCIiqf4y61wyD0WY3qHYF4yDpWzH8vVhbKSMy0x9W1JR3ZUmv0MbidSvgiOwxpPPtWVuPPRDbLKg3ENzv4bq8IK8PzR0t5jHNSFKWu7C1jrJ3gE7yoxJ5zMnsw6v3HJhedy2Jfx2C2EZsZv1XCzaXYxKBr0uaHVcOSn9/4Rn9OXf95th7bgRN6aCrU34M1ELL3RmocKs=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.43.0
Release Details
UpdatedAug. 24, 2026, 1:27 a.m.
Changelog

Added

  • Liability accounts now ask what a positive balance means instead of guessing. Editing a credit card, loan, mortgage or line of credit shows an Amount owed field that takes a plain positive number — the app adds the minus sign — with a separate This account is in credit tick for the case where you have overpaid and the lender owes you. Switching an account between a debt type and a savings type converts the figure for you and shows the resulting current balance before you save. Creating a liability works the same way. The choice is recorded with the account, so an export and restore keeps it (#353)
  • Several CSV columns can feed one text field. Banks often split what belongs together — a merchant column and a details column, say, or a reference spread over two. On the import mapping step, Description, Notes, Vendor and Reference are now checklists: tick every column that belongs in the field and the values are joined with a comma, in the order the columns appear in the file, with blank cells skipped. The same works for those four fields on OFX, QIF and camt files, and a saved import template keeps the whole selection. A single ticked column imports exactly as it always has, so re-importing an overlapping statement still recognises its transactions. Thanks to @Saviq for the feature (#355)
  • Category trees can be exported and imported. The Categories page has Export and Import buttons next to Add Category. Export downloads your whole tree as a readable JSON file; Import takes that file back, or a CSV of Parent > Child paths, shows exactly what would be created before anything is written, and leaves categories that already exist untouched while adding whatever is missing underneath them. Handy for backing up a carefully built structure, sharing it, or having a spreadsheet or an AI assistant draft one and loading it in a single step (#354)

Fixed

  • Editing a loan or credit card no longer turns your debt into an asset. Typing your statement balance as a positive number into the Opening Balance field stored it as a positive number, which the app reads as "the lender owes you this" — so a £5,000 loan quietly added £5,000 to your net worth instead of subtracting it, a £10,000 swing, and every later recalculation re-derived the wrong balance from it. Nothing on screen said so. Positive balances on a debt stay supported, because a genuine overpayment is a real thing, but the app now asks which you mean rather than reading it off the sign. If this already happened to you, Settings › Repair Data will find it: run Scan for Issues and the new Debts Recorded as Being in Credit section lists every affected account with what it reads now and what it will read afterwards — untick any you really have overpaid, and those are recorded as genuine credits and left out of future scans. Two related consequences are fixed alongside it: an account you have overpaid no longer appears in the debt payoff planner as something to pay off, and it no longer counts towards Total Liabilities on the Accounts page, where it was pulling net worth down by twice the credit (#353)
  • An account edit that does not touch the opening balance no longer rewrites the balance. Renaming an account, changing its institution or ticking a checkbox resubmitted the opening balance every time, so an unrelated edit depended on that value round-tripping through the form perfectly. It is now sent only when you actually change it (#353)
  • Reopening a split transaction no longer scrambles its parts, and saving it no longer throws them away. A split of 10 into 1, 3 and 6 came back as 1, 9.00 and 0.00 — the second part had swallowed the rest and the third was empty. The parts were always safe in the database; the editor was overwriting them as it drew them. It fills the last row automatically with whatever is left over, and it was doing that after adding each row, so every stored amount was recalculated away the moment the next row appeared. It now draws all the rows first and works out the remainder once, which is what it should have been doing. If you saved a transaction from that scrambled view, the parts you saw are what got stored — the third one was dropped for being 0.00, quietly, because the total still added up. Worth re-checking any split of three or more parts you edited recently; their categories will have been wrong in reports for the months involved. Splits of four or more parts had a second symptom — Save appeared to do nothing at all, with no message — which is fixed by the same change (#358)
  • Filtering transactions by Uncategorized no longer lists your split transactions. A split transaction has no category of its own by design — its categories live on the individual parts — and the filter was reading that as "not categorised yet", so every split you had ever made turned up in a list meant for things needing attention. Split transactions are now left out of it, and out of the dashboard's uncategorised list and the "only uncategorised transactions" option when running import rules, which read the same way. The bulk-edit consequence is the one worth knowing about: filtering by Uncategorized, selecting all and setting a category used to write that category onto the split transactions caught up in the list, after which they were counted twice in reports — once for the whole transaction and again for each of its parts. Setting a category on a split transaction is now ignored rather than obeyed; unsplitting one still assigns a category as it always has (#356)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignaturelQsdNi/Ed5bU8/Ch8iyHVXKdX+l8qhRm8fCwRYfB/ObxW6pncVobhw57Bzvu/2yio4Wb+MyJ+DZ8T75pZ9+ugVmWX+q/VSLx4PEAmnr9upL0m7AvJN33BXARoFWBzKVFHnfEy/RuYgtxnNfOmoiblZXbAeBs5zyxxeQKrYSMSHfdwdG/t9HZNFNvFEyp7k7XEU1xQ5HaAo6kResw+25vTU/lkvJNXYmNnmWr3ZxUo7qphCOw/ZJU4aMi+g8RjrWIp86biPeM8mIr57Oacrm3fIQnGTgfk7lqX5FGTjhjLTnDKin+AyFQCpkuki47leJ+W4VwS/LvObLDHn/WcYhjmkdmGXTGFZGhVYAHz3VcPklRmERDkafXZ7lPk0tWZjma/W4SCf6u8Pu3Ni5fVeZ9Zp7qiCjNomRBmMl2nlW2EC/GYJAW7c78TM1Gq9qw6EAAweO5/7JMtOMaA4Klm1XKmE6CpDmu6Ox4E0+RiaDZJ6lHnC7JcfNweMtbgZb4tK/1nAXqum2v4vIQcIDpfk2ROqxkvthclKe05z2p1oe2qg/mEWqwx51ZHR0PvMhmNYGh9VVi3F7KiT0v1K6D06CAAOJu6TeJTMKX5asGJ8K2PkVKk0E7uVWGKp7+WRBU4ILvUftG5d8Pz7ChCY35XVwknHbY/Rx7DNno+1h3YzkblIU=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.42.0
Release Details
UpdatedAug. 21, 2026, 9:23 p.m.
Changelog

Added

  • Receipts can be filed wherever you keep your app data. Uploaded receipts have always landed in Budget/Receipts/<year>/<month>/ in your Files; a new Receipts folder setting lets you point that anywhere inside your own Files instead — Applications/Budget, say, to sit alongside other apps' folders. The year and month subfolders are still created underneath, and receipts attached before the change stay exactly where they are: the app never moves or deletes your files. Applies to uploads from the web form, the API and receipt scanning alike (#352)
  • Bank statements in camt.053 XML can now be imported. Many European banks — Swiss ones in particular — export statements as ISO 20022 camt.053 (and intraday camt.052) XML rather than CSV or OFX. Drop one on the Import page and it behaves like an OFX file: every account in the statement is listed with its IBAN, auto-matched to the account of yours carrying that IBAN, and routed there. The parser reads what the payer wrote (the remittance text), who the other side was (the counterparty, which becomes the vendor), the bank's own entry text, and the transaction type code, and a batch entry such as a collective payment is split into its individual transactions with their own counterparties. Duplicate detection uses the bank's own entry reference — more reliable than the CSV content hash — except where a bank stamps the same reference on every entry, in which case the hash is used rather than collapsing the statement into one transaction. Every camt.053 schema version parses, including files with the namespace stripped (#350)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureRhkTM0z3ZXIpnFc2BJ0widME7KmhTp6jnd/kaHn42N1eiC9JQhiDUCGmqbCweHhswB3HBwwBoG37XE5L/9s97L13vmrIT+19EVx+f3o2xHXeVe0J19F0BKOxyW5mKYt7xQqo/dwCQ+qDk06kH89XPta+ppz28+qcfaEnBiEtnnzlyeOqyXgs6qWuM/sZW/WUau5dPKZxfkK57IgPaBIfx/R8cttcyokpplD5kV+rmGz8+AvAbvqcT06aGCzjQQtK4/ADbBe7PiGxy7Yy64B9LhgphkHuXqk1hzJiuC0exn+8z02QXGq5g2nDbATK6ZF6n6v6wIrSnEZtvRBvd2rloAQe5K5aiP6Ae6TPyILrunKGTL7Je1d/sqWO+103WdwcfLSI2rYHM00CUOdmxRttecjkJvc+sarc7m1M+fFIePC4SC5RlKJin/v9tUf/m+ie0+/UvqrcReF6hjCfN7jp8LBNjJQGsbpOBm+WO6v2i5GSKV/vNWLw4qln0rQXobu0jdSIhraqes84wPmF1z7U/eQorqmB9Q+ig4mfTtR3zxVfcd6vVT5fseiDTVhbaLf144zLTSxWpgVscFSQitXsVnA3FHkHuXsy8OqYeGgtQHOPjwMocSN1udnp59Wth/jd6qxj9Gf9KjFYFi/fwjc+QcvHaTuGCycDo+4xny+evpE=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.41.0
Release Details
UpdatedAug. 19, 2026, 10:30 p.m.
Changelog

Added

  • The Help & Docs page now says how to support the project. A small section with the GitHub Sponsors and PayPal links — the same ones listed on the app store — for people who installed the app and never see either. The floating help panel carries the links too. Nothing nags: it sits in Help, and the app works fully without donating
  • A recurring transfer can now pay a credit card the way the card itself would, with the amount resolved fresh at every payment. Card payments have always been representable as recurring transfers, but only at a fixed amount — useless for a bill that is different every month, which left people faking it with duplicate bills or typing the figure in by hand each time. A transfer whose destination is a credit card (or line of credit) now offers an Amount type choice mirroring what card issuers offer: Fixed amount as before; Statement balance, which pays what was owed as of the due date — everything charged since the previous due date plus any remainder an underpayment carried forward, with later charges rolling to the next statement; Current balance, which clears everything owed at the moment of payment; or Minimum payment, which pays the minimum set on the card's account (never more than is actually owed). The figure is worked out from the card's own ledger when you mark the payment made (or auto-pay makes it), so it is never stale; the amount shown on the transfer between payments is the last one resolved, and the pre-booked next occurrence carries it as the forecast estimate. Reminders, the bills calendar and auto-pay all work unchanged, because the payment is an ordinary recurring transfer. The card's own account page joins in: a Statement due day field on credit-card and line-of-credit accounts records which day of the month the payment falls due — shown on the card's page as account information in its own right — and a Set up payment button appears on a card with no payment transfer, opening the form pre-filled with the card and that due day. Once a payment transfer exists, the page shows when the next payment is due (#347)

  • Subscribing to hosted receipt scanning, and managing that subscription, now happen from the settings page. With the Otherworld relay selected as the scanning provider, the admin settings show the plans with a Subscribe button that opens Stripe checkout in a new tab — the licence key is shown once after payment, emailed as a backup, and pasted into the field above. Once a key is saved the block flips to a Manage subscription button: your server asks the relay for a billing-portal link tied to that key, so changing plan, updating the card or cancelling needs no separate account and the key itself never reaches the browser. A hand-issued key (a trial, or one minted directly) is told plainly there is no subscription behind it rather than being bounced off a portal that would refuse it (#537)

  • A CSV export of every transaction you're looking at, not just the page on screen. The account Export button built its file out of the rows the browser had already loaded, so it silently stopped at 50 — a year-end export of 800 bookings produced a file of 50 that looked complete, which is worse than an error. The export is now built on the server from the same filters the view is using, so it covers the whole result set however many pages that is. The Transactions page gains its own Export button too, which with no filters set means every booking across every account in one file: previously the only export was per-account, so a club treasurer with three accounts had to stitch three files together. Filters still apply, so you can export one category, one date range or one tag set just as easily (#344)
  • The exported CSV now says which way the money went. Amounts carry a sign — expenses negative, income positive — so the Amount column totals correctly the moment you drop it into a spreadsheet, rather than adding your outgoings to your income. The Type column reads Income and Expense instead of the stored debit and credit. Transfers between your own accounts appear as they always have, one leg of each, which now means they cancel out in the total instead of inflating both sides. The file also gained Vendor, Account, Currency, Reference, Notes and Status columns — enough to do the books from without opening the app (#344)
  • A new Income & Expenses report, for the year-end job of showing what came in and what went out. Pick it under Reports and you get two tables — income by category and expenses by category — with each side's own total and the net between them, over whatever period you select. It exports to CSV and PDF like every other report, the CSV keeping the two tables as separate labelled sections so a treasurer's spreadsheet can take them straight. Like the other reports it respects accounts and categories you've marked as excluded from reports; unlike the transaction export, which is a plain ledger of what you filtered (#344)
  • The Belarusian ruble (BYN) is now one of the currencies you can pick. It appears wherever a currency is chosen — the default in Settings, an account's currency, a manual exchange rate — and amounts are written with the symbol after the number (1,234.56 Br), as they are in Belarus. Its daily rate is fetched alongside the other fiat currencies, though the historical series is not: the 90-day history comes from the ECB reference rates, which don't cover BYN, so a converted figure for a past date falls back the same way it does for any other currency the ECB doesn't publish (#343)
  • The API can split transactions, so capture apps can categorise receipt items too. POST /api/v1/transactions/{id}/splits sets the parts of a transaction, and POST /api/v1/transactions now takes an optional splits field so a phone can record the transaction, attach the photo and set the per-item categories in a single request. /api/v1/ocr/extract additionally reports the receipt's subtotal and tax, without which a client could not make the items reconcile to the total — splits must sum exactly, and most receipts print tax on its own line. GET /api/v1/capabilities gains splits_available so a client can gate its per-item screen on a boolean rather than parsing the version. All four are additions: no existing field was renamed or removed, so clients built against the previous shape are unaffected
  • Receipts with loyalty savings can be split too. A Clubcard, coupon or multibuy line means the items on a receipt legitimately add up to more than you paid — and that gap used to make the whole receipt look misread, so it was refused for splitting and flagged with a mismatch warning. The savings are now read from the receipt and become their own line in the split, at the printed amount but negative, exactly as tax gets its own line. Four shapes now reconcile: items alone, items plus tax, items minus savings, and both together. The mismatch warning still fires when the gap is genuinely unexplained, which is the case it exists for. Two robustness details, because the reader is a vision model that occasionally slips: when it under-reads the savings by a line, the server closes the gap from the printed total so the receipt still splits rather than being refused over a saving it half-missed; and an impossible negative tax or subtotal from the reader is dropped rather than trusted into the arithmetic
  • Turn a scanned receipt into per-item splits. After a scan, if the items on the receipt add up, the scan box offers to split the transaction into one line per item so each can carry its own category — useful when one shop trip covers groceries, household and a treat. Where the receipt prints tax separately, the tax becomes its own line at the printed amount rather than being smeared across the items, so every figure still matches the receipt in your hand. The offer only appears when the arithmetic actually reconciles (items alone, or items plus tax, equalling the total); a receipt with a discount line or an unreadable item is left as a single transaction instead of producing splits that would be rejected on save. Splits carry categories, not tags — tags remain per transaction
  • Receipts are filed by month and named after the transaction. They now land in Budget/Receipts/2026/08/ rather than one folder per year, and an uploaded photo is named 2026-08-05 The Corner Deli 23.77.jpg instead of keeping whatever the camera or capture app called it (often a UUID). That sorts chronologically in the folder and makes a receipt findable by shop or amount in Nextcloud's own search. Existing receipts are left exactly where they are. A file attached from your own Files keeps its name — it's your file, and renaming it isn't ours to do
  • Receipts can now be attached while you are still adding the transaction. The Receipts section used to appear only after saving — the attach endpoints need a transaction id — so adding a purchase with its receipt meant save, reopen, attach. Files you choose (or pick from your Files) are now held and listed with an "on save" tag, then attached the moment the transaction is created. If one fails to attach, the transaction is still saved and you are told which — re-submitting would only have duplicated it
  • Scan a receipt straight into the transaction form. When your administrator has set up receipt scanning, the Add Transaction dialog gains a drop zone: drop a photo on it (or click to pick one) and the date, amount, merchant and a suggested category are filled in for you to check. The photo is attached to the transaction when you save, so a receipt is one action rather than three. The box tells you exactly which fields it filled, how many items it read, and whether those items add up to the total — nothing is saved until you press Save, so a bad read costs a retype rather than a wrong record. Scanning also works when editing an existing transaction, where it only fills fields you have left empty: a scan is a suggestion, never an overwrite. The whole section stays hidden on servers with no OCR provider configured, rather than offering a button that cannot work
  • Receipt scanning can be configured from the command line: occ budget:ocr. Run it bare to see which provider is set, whether a key is stored, and — the useful part — whether the server can actually serve a scan right now. occ budget:ocr set --provider=custom --endpoint=… --model=… changes it, and --api-key-stdin reads a key from a pipe so it never reaches your shell history. It matters that this exists rather than reaching for occ config:app:set budget ocr_…: the raw config route looks equivalent but skips the provider and URL validation, and would store your API key in plaintext, since the encryption lives in the app rather than in Nextcloud's config layer. The command takes exactly the same path as the settings page, so a rejected value changes nothing and a key is always encrypted
  • A CSV column can now be mapped to a transaction's Notes. Bank exports often carry a line of extra information — a payment reference, a booking note, the counterparty's message — that belongs in neither the description nor the reference field, and until now it was simply dropped: the only way to keep it was to edit every imported transaction by hand. Notes now sits in the column mapping alongside Description, Vendor and Reference, and whatever you point it at is stored on the transaction. It also earns its own column in the import preview whenever something is mapped into it, so you can see you picked the right column before anything is written, and it can be saved in a template like every other mapping. Over-long values are truncated to what the field accepts rather than being imported into a transaction you could no longer edit (#340)
  • The API can now read a receipt photo into a draft transaction. POST /api/v1/ocr/extract takes a photographed receipt (JPEG, PNG or WebP) and returns a draft for the user to confirm: merchant, date, printed total, line items, and — on the vision-model providers — the currency when one is legible; nothing is recorded until the client saves it through the ordinary create call, so retrying costs nothing but another scan. The reading is done by whichever OCR provider the administrator configured (below); failures carry a stable machine code (ocr_not_configured, ocr_quota_exhausted, ocr_extraction_failed) so a client reacts to what happened rather than parsing prose, and ocr_available on the new GET /capabilities reports the real state so clients hide the flow instead of hitting the error. A category is suggested by running your own categorisation rules against the extracted merchant — computed on your server, so the provider sees the image and nothing else, ever. When the line items don't add up to the printed total the draft says so rather than silently trusting either side. Documented in the REST API guide and the OpenAPI description (#533)
  • Recording a transaction over the API is now retry-safe, and can carry the receipt with it. POST /api/v1/transactions accepts an optional idempotency_key: a client that times out on mobile data cannot know whether its POST committed, so a repeat of the same key within a week answers with the transaction the first attempt recorded instead of inserting a duplicate — the single most damaging failure a capture client can produce, closed server-side. The same call now takes an optional photo part, recording the transaction and attaching the receipt in one request, plus a merchant field and a type that defaults to money-out. A new GET /transactions/recent returns the newest activity flat and merchant-first for a capture app's glanceable list. Wire field names across v1 settled on snake_case (account_id, parent_id, line_items) before anything ships against it
  • Receipt scanning can now be set up, and it is off until you do. A new Receipt scanning block in Settings → Admin Settings chooses which OCR backend reads a photographed receipt: this Nextcloud's own configured AI provider, any OpenAI-compatible endpoint — a vision model on your own network is a first-class option, not a footnote — or Otherworld's hosted relay with a license key. The choice is server-wide and an administrator's to make, because it decides who else sees your receipts. Until one is chosen the app sends receipt images nowhere at all: there is no default backend and no fallback. Your server makes the request rather than your phone or browser, so an API key never leaves the server and a backend that isn't reachable from the internet works perfectly well. Keys are stored encrypted and are never shown again after saving — leave the field blank to keep the stored one. Only the image is ever sent; account names, balances and other transactions are not. The Receipt Scanning guide sets out exactly what goes where for each option. With the API endpoint above, scanning works for capture clients as soon as a provider is configured; the scan button in the web interface arrives in the next release
  • A documented REST API, so Budget can be reached from outside the web UI. A versioned, read-and-capture API now lives at /ocs/v2.php/apps/budget/api/v1 — list your accounts and categories, browse and filter transactions, record a new one, and attach a receipt photo to it. It authenticates with an ordinary Nextcloud app password (or a token from Nextcloud's Login flow v2), so there is no separate credential to manage and revoking the entry under Settings > Security cuts off whatever was using it. That makes a phone capture app, a shell script or an n8n workflow a matter of configuration rather than code — the REST API guide has worked examples, and a machine-readable OpenAPI description ships with the app. Version 1 deliberately stops at reading and appending: editing, deleting and everything else stays in the web UI, which keeps the contract small enough to hold still. Fields will be added to it, never removed or renamed. Every amount crosses the wire as an exact decimal string ("42.50") rather than a JSON number, so a client cannot lose a penny to floating point on the way in or out. Note this is quite separate from the internal endpoints the web UI calls, which follow the database and change without notice
  • The accounts page can now be tailored to what you actually want to see. A gear button next to the tile/list switcher opens display settings for the page. Tick which attributes appear on each account — account type, institution, (masked) account number, last reconciled date, converted balance, and, on tiles, the 7-day balance trend and the status dot. Drag those same attributes into the column order you want for the list view (Alt+/Alt+ does it from the keyboard); name and balance can be moved as well, they just can't be hidden. And choose how accounts are ordered: by name, balance, type, institution, last reconciled or date added, ascending or descending. Tiles follow the same attribute order as the list columns, hiding an attribute drops its column so the rest can spread out, and everything is remembered in your browser alongside the tile/list preference
  • Categories can now be left out of budgeting without being left out of everything else. A new Exclude from budgeting checkbox sits alongside Exclude from reports on a category. Where the reports flag removes a category from all spending figures, this one is budget-only: the category keeps counting in reports, the dashboard, insights and every total, and simply drops out of the Budget page, the summary cards, budget alerts, the budget vs. actual report and envelope rollover. Meant for spending you want to see but can't sensibly budget — gifts, medical bills, home repairs — so you stop being told you're over budget on a figure you never set. Excluding a parent excludes its subcategories too, and like the reports flag it stays with the owner on a shared category
  • Select every transaction matching the current filter, not just one page. Ticking the header checkbox on the Transactions list now offers "Select all N matching transactions" when more rows match than fit on the page, so a bulk delete or edit can cover thousands of rows in one go instead of 250 at a time. The selection is dropped if you change the filter, so a mass action can never silently include rows you're no longer looking at, and bulk deletes of many rows are much faster (the account balance is recomputed once per account instead of once per row) (#336)
  • A Help & Docs page, in the app. The sidebar's Help & Docs entry used to throw you straight out to GitHub. It now opens a real page listing every guide with a one-line summary, a shortcut to the keyboard cheat sheet, the Quick Add page URL, and the System Info panel for pasting into a bug report. The floating ? button still gives you the short version for whatever page you're on, and now links through to the full page

Changed

  • A saved OFX/QIF template now remembers your field mapping as well as your account routing. These templates stored the routing only, so a bank that puts the payee in the memo had to have Description and Notes re-pointed on every single import — the choice was silently reset to the format defaults each time. Picking a saved template now restores both. Templates you saved earlier carry no mapping and are unaffected: their routing applies exactly as before and the mapping keeps the defaults (#340)
  • A reference longer than 100 characters is now refused when you type it, instead of failing when it is saved. The field was validated against a 255-character limit while the database column holds 100, so anything in between passed every check and then broke on the way to disk — a clean "too long" message is a better outcome than a server error. Nothing already stored is affected (#340)
  • A rule condition saying an import source is not something will start behaving differently on OFX and QIF imports. Because those imports never recorded a source at all, a negated Import Source condition matched every row from them; now that they do record one, it is evaluated for real. If you have a rule along the lines of source is not "Bank Sync", check it still does what you meant on your next OFX or QIF import (#338)
  • An import rule that sets notes "only if empty" no longer fires on OFX rows that carry a memo. With the memo now kept in the transaction's notes (above), the field is genuinely no longer empty on those rows, so an if empty rule correctly leaves it alone; an append rule adds to the memo rather than replacing it. Rules set to always overwrite are unaffected (#338)
  • The bill, transfer, savings goal, debt scenario, pension, asset and contact dialogs now use the same layout. Each was a narrow single-column form that had to be scrolled; they are now laid out in columns sized to what they actually hold — three for a bill (Bill, Payment, Schedule) and a debt scenario (Scenario, Payments, Debts), two for a transfer, goal, pension and asset, and a compact single column for a contact. Everything in them is visible at once, with Save and Cancel pinned below the fields. A bill's split rows span the full width of the dialog rather than being squeezed into a column, and a pension shows the pot fields or the income fields depending on its type, without leaving a gap where the other one would be
  • The four tag dialogs now match the rest. Add Tag, Edit Tag, Add Tag Set and Edit Tag Set are two-field dialogs, so they stay compact rather than being stretched into columns — but they pick up the same chrome as the bigger dialogs: a rule under the title, and Save/Cancel on a divided bar at the bottom right instead of loose against the left edge
  • The category dialog gets the same treatment. Naming fields (name, type, parent, colour) sit under Details on the left, the two exclusion options under Options on the right, and Tag Sets spans the full width below them — no scrolling, and the two checkboxes now read as ordinary checkbox rows instead of a bold heading with a stray box floating above it
  • The transaction dialog gets the same three-column desktop layout as the account dialog. Adding or editing a transaction was a 500-pixel-wide strip roughly a screen and a half tall, with a line of help text under every field restating its label. It is now laid out as Transaction (date, account, type, amount), Details (description, vendor, category, split toggle, tags) and Extras (receipts, notes, exclude from forecast), all visible at once with nothing to scroll for. Switching on Split across categories opens the split table across the full width of the dialog instead of squeezing it into a narrow column
  • The account dialog now fits on one screen. Adding or editing an account meant scrolling through roughly two screens of form in a narrow 700-pixel strip — eighteen fields, most of them empty, each with a line of help text underneath repeating what its label already said, and the Save button stranded at the very bottom. The dialog is now laid out for a desktop screen: three columns — Details, Banking, and Rates & limits with Advanced beneath it — showing every field at once with nothing to scroll for and nothing hidden. A column block with nothing to offer your account type, such as rates and limits on a Cash account, doesn't appear at all; Save and Cancel are pinned below the fields; the help text that merely restated its label is gone; and the current balance is shown as the calculated figure it is rather than a text box you can't type into. The columns reflow to two and then to a single stack on narrow windows and phones
  • The documentation has a home of its own: budget.otherworld.dev/docs. Every link that used to send you to raw Markdown files on GitHub — the in-app help panel and Help & Docs page, the README, the install guide and the app store listing — now opens the rendered site, which is searchable and readable on a phone
  • The Settings page is tidier. The Save Changes / Reset All to Defaults buttons were stranded in the middle of the page, with the Quick Add Page and System Info sections stuck below them, and Danger Zone was not the last thing on the page. Sections now run in a sensible order, with Admin Settings and Danger Zone at the end and the buttons at the very bottom. Quick Add Page and System Info have moved to the new Help & Docs page, since neither was a setting
  • The action buttons on an account row in the list view no longer sit flush against the last column

Fixed

  • The backup now actually contains your data — all of it. The export/import zip under Settings → Migration carried only categories, accounts, transactions, bills, import rules and settings; everything else silently vanished when moving servers. Reported for tags (#351), but the full list of what a migration used to lose is sobering: tags and their assignments, tag sets, transaction splits, recurring income, savings goals, assets and their value history, pensions with contributions and snapshots, per-account interest-rate history, manual exchange rates, import templates and remembered account links, saved reports, net-worth and budget history, reconciliation history, debt payoff scenarios, muted categories, shared-expense contacts with their shares and settlements — and on transactions, the links joining transfer pairs (so every transfer fell apart into an income and an expense), bill references, the split flag, and reconciliation/pension links. All of it now exports, and imports with every cross-reference remapped to the new server's ids. Old backups still import exactly as before; new backups are format 1.2.0. Deliberately still excluded, and now stated in the archive's manifest: bank-sync connections (provider agreements are instance-specific and must be re-established), shares with other users (they reference people on the old server), receipt files (stored in Nextcloud Files, not in the app), and the fetched exchange-rate cache (your manually set rates are included)
  • Marking a recurring transfer paid no longer loses the deposit half of its pre-booked transactions. When a transfer had its next occurrence pre-booked as a scheduled pair, marking it paid cleared the withdrawal leg but deleted the deposit leg — the source account paid out and the destination account never received the money, quietly understating it by one payment each cycle. Both legs of the pair are now cleared together. Payments already recorded this way are missing their deposit; the Convert to transfer action on the surviving withdrawal recreates the other half
  • Transfers no longer count as income and spending in the analysis reports. The dashboard's income and expense totals have left transfers between your own accounts out since 2.28.0, but the Reports page never got the same treatment: a £500 transfer appeared as £500 of income in Income Analysis (grouped by month, source or category) and £500 of spending in Expense Analysis (by month, vendor, account or tag) — and in the new Income & Expenses report only the incoming half was counted, overstating the net by the full amount moved. Every report view now excludes linked transfers, matching the dashboard, so shuffling money between your accounts changes no report figure. Two things are unchanged by design: a report filtered to a single account still shows that account's own transfer legs, because the money genuinely entered or left it; and only transfers the app knows to be transfers are excluded — ones created with the Transfer type, recurring transfers, and rows joined with Match transfer. Two unlinked rows entered by hand still count as ordinary income and spending (#349)
  • "Use Default Categories" failed with "A category with this name already exists" whenever any default was still present. The button seeds the whole catalogue in one go and gave up on the first name it found already taken — creating nothing at all. Easy to hit without doing anything odd: the category list shows one side at a time, so emptying the Expense view put the button on screen while the Income tree still existed in full, and pressing it failed on Income before a single expense category was created. Seeding now fills in exactly what is missing — an existing category is kept as it is, its missing subcategories are added underneath it, and everything else is created around it — so the button always finishes what it can instead of refusing the lot. A double-click while the first request was still running could also race itself into duplicates; the button now ignores the second click (#348)
  • Amounts in Kazakhstani tenge were shown with the code rather than the symbol. KZT was selectable and priced correctly, but it was missing from the front-end's symbol table, so every figure came out as KZT1,234.56 where the rest of the app would have written ₸1,234.56
  • Envelope budgets ignored everything you spent in a category's subcategories, so the whole budget rolled over untouched. The carryover looked for spending filed against the budgeted category itself and nowhere else. Budget €300 on Groceries and file the receipts under Groceries › Supermarket — the ordinary way of using subcategories — and it found nothing to subtract: July carried the full €300, August carried €600, September €900, growing by the untouched budget every month. The same screen said so in two contradictory ways, because the Groceries row itself has always added its children up: "spent €250 of €300" sat directly beside "+€300 carried". An envelope now covers the whole branch — the category and everything filed underneath it — so the amount carried forward is the leftover you'd work out by hand. A subcategory with its own envelope still keeps its own chain and is left out of its parent's rather than counted twice. Subcategories stay out of a parent's envelope when you've excluded them from budgeting or from reports, when they budget on a different period (a quarterly amount can't be added to a monthly envelope), or when they're income categories — and so does anything filed underneath those. Budget alerts and the budget-vs-actual report read the same corrected figure. Nothing was stored wrong: the carryover is recalculated from your budgets and transactions every time it's shown, so the numbers correct themselves as soon as you update (#341)
  • Envelope budgets also ignored anything you spent in a shared account, with the same result. The two queries the carryover uses to total up spending were scoped to the accounts you own, while every other budget figure on the page is scoped to the accounts you can see. So a category you fund out of an account shared with you looked untouched to the envelope: the full budget rolled forward each month, next to a row that correctly showed the money as spent. Budget alerts had the same split — they now measure spending over the same accounts as the budget they compare it against, including their split transactions (#341)
  • A long CSV column could import a transaction you were then unable to edit. Text taken from a CSV was stored exactly as the file wrote it, with no regard for what the field can hold. A notes column over 2,000 characters — easy to hit with a bank that packs a whole payment reference into one cell — imported perfectly happily and then failed validation the moment you opened that transaction, so no change to it could be saved until you shortened the note by hand. Over-long Vendor and Reference values were worse on MySQL and PostgreSQL: the row was rejected outright and counted as an error rather than imported. Imported text is now truncated to the field's limit, exactly as OFX and QIF imports already were, and leading or trailing whitespace is stripped rather than stored (#340)
  • "Check the server log for details" pointed at a log with nothing in it. When rows failed to import the warning told you to look in the server log, but the import never wrote there — the only record was in the browser's developer console, which is not where anybody was being sent. Failed rows, unresolvable accounts and balance recalculation failures are now logged properly with the row number and the underlying error (#340)
  • The column mapping step never highlighted the columns you had mapped. Each mapped column was supposed to be marked in the preview table underneath; the highlight was looked up by column position while the mapping holds column names, so it silently matched nothing and no column was ever highlighted for any ordinary CSV (#340)
  • A transaction added "today" could be filed as a future payment and left out of the account balance. Whether a date counts as future was decided using the server's calendar, but the date comes from yours — the web form pre-fills your device's date, and a capture app sends the phone's. Whenever your local date ran ahead of the server's, everything you recorded was quietly marked scheduled, and scheduled transactions are deliberately excluded from the balance: you added a purchase and the balance did not move. On a UTC-hosted Nextcloud that is the hour after midnight for anyone in British Summer Time, and most of the working day for anyone in Australia or New Zealand. The date is now judged in your own timezone (the one Nextcloud already knows from your session), falling back to the instance's configured timezone, so today is today wherever you are — while genuinely future-dated payments are still scheduled and still stay out of the balance until their date arrives. Transactions already misfiled this way corrected themselves within a few hours through the existing scheduled-transaction job; nothing was lost
  • QIF import has never worked: it reported rows in the preview and then imported none of them. A QIF file's accounts are matched to yours by an identifier the QIF parser never actually produced, so every account in the file was skipped — the import finished reporting success, with zero transactions added and no error to explain it. Underneath that, the parser had no notion of where it was in the file: an !Account header block was read as though it were a transaction (importing a row dated with the account's description), and because a real Quicken export opens with its category list, that whole list was read as an extra account containing one bogus transaction per category. Accounts are now identified by their name in the file, !Account blocks set the account's name, type and description as they should, and the sections that never held transactions — the category list, classes, memorised payees, security prices — are skipped instead of being imported as data. A file that does not name its accounts shows them as Account 1, Account 2 in file order. Dates are also read properly now: Quicken pads them to a fixed width (12/ 4'98), which nothing recognised, and a date that cannot exist — a 13th month — was passed to the database as text rather than being rejected (#338)
  • Import rules could not match on "Import Source" for OFX, QIF or any non-CSV import. Only CSV imports recorded where a transaction came from, so a rule condition on Import Source was silently false for every OFX and QIF row — and, because an unknown field inverts under a NOT, a rule saying source is not … fired on all of them instead. OFX and QIF imports now record OFX Import and QIF Import, joining the existing CSV Import, Bank Sync and Toshl, and the values are listed in the rules guide. Note the source describes how a transaction arrived and is not stored on it, so this criterion still matches nothing when a rule is re-run over existing transactions — the guide now says so (#338)
  • The column mapping did nothing at all on OFX and QIF imports, and the memo was thrown away. Every field in the mapping step could be changed and none of them had any effect — the import silently ignored the mapping and always took the description from the OFX name field. Banks that put the real payee in the memo instead (a common Canadian pattern) had no way to import a usable description, and the memo itself was parsed, shown in the preview, and then discarded rather than saved anywhere. Worse, a statement whose entries carry only a memo and no name imported with a completely blank description. Now: Description, Notes, Vendor and Reference can each be pointed at any field the file actually contains, the memo is kept in the transaction's notes by default, and a missing name falls back to the memo instead of importing nothing. Date, amount and type come from the file's structure and are no longer offered as mappable, along with the income/expense, account and currency columns that these formats never had — those dropdowns are gone rather than left on screen doing nothing (#338)
  • The import preview showed every amount as a plain positive number, whichever way the row was going. The preview is sent each amount unsigned with the direction alongside it, and it drew the number while ignoring the direction — so a statement of nothing but expenses previewed as a column of figures indistinguishable from income, and the step whose whole purpose is to be checked before anything is written could not show the one thing most worth checking. Amounts in the preview are now signed and coloured: an expense reads -€91.29 in red, income €500.00 in green, and the column is right-aligned so the figures line up. What was imported was correct all along — only the preview was silent about it (#339)
  • A negative amount written any way other than a leading hyphen imported as income. Only -1234.56 was understood; every other notation had its sign thrown away with the currency symbols. That covers a trailing minus (1.234,56-, as written by a number of German and mainframe exports), brackets ((1,234.56), the accounting convention several US and UK banks follow), and a typographic minus or dash in place of an ASCII hyphen. A trailing minus was the worst of the three: left on the end of the number it also pushed the decimal separator out of place, so 91,29- imported as income of 9,129.00 — a hundred times the real figure, on the wrong side of the ledger. All three now import as expenses, and a lone - in an amount column still means "nothing here" rather than a negative. If you have already imported a file with trailing minuses, re-importing it will add the corrected rows rather than recognising them as duplicates, because the rows that went in were keyed on the wrong amount (#339)
  • Dialogs on the Assets, Pensions, Savings Goals, Debt Payoff, Tags and Import pages opened behind the sidebar. Fourteen dialogs — including Add Asset, Add Pension, New Scenario and Add Savings Goal — were written inside the page content area, which Nextcloud paints as its own layer. A dialog can never rise above the sidebar from in there, however high its own stacking order is set, so it appeared cut off behind the app navigation. They now sit alongside the dialogs that always worked, and cover the whole window like the rest
  • The remove button on a split row sat under the Description box instead of beside it. The row's Description input was written without its closing bracket, so the browser swallowed the tag that should have ended the field and folded the remove button into it — the row's fourth column stayed empty and the ✕ dropped onto its own line. It now sits at the end of the row where it belongs
  • A mapped Type column is no longer ignored, so unsigned exports stop importing as all income. Mapping a Type column (Expense/Income, Debit/Credit, DR/CR, Withdrawal/Deposit, …) had no effect: the direction was always taken from the sign of the amount. Files that write every amount as a positive number and state the direction in a separate column — Nextcloud Tables exports, and a number of banks and budgeting apps — therefore imported every single row as income, quietly moving the balance the wrong way by twice the amount. The mapped column now decides the direction; rows where it is blank or unrecognized still fall back to the sign (#333)
  • The import preview now warns before a batch goes in the wrong direction. Two new warnings appear above the preview summary: one when a mapped Type column is blank or unrecognized on some rows (naming how many), and one when nearly every row would be booked as income into an account whose history is nearly all expenses, or the reverse. Neither blocks the import (#333)
  • Every transaction showing "Unknown Account" after restoring a backup. Restoring a backup gives every account a new id, but a page that was already open kept the old ones, so nothing in the ledger could be matched to an account and the whole Account column read Unknown Account — with nothing in the browser console to explain it. The same happened in any second tab left open during a restore. The transaction list now notices that it is holding a stale account list and refreshes it by itself, and a restore finishes reloading its data before reporting success (#333)
  • A failed accounts request no longer blanks the Category column too. If the accounts request failed while the app was loading, the rest of the load was abandoned as well, so both the Account and Category columns fell back to Unknown Account and Uncategorized behind a generic "Failed to load data" message. The two lists now load independently, and the message names which one failed and says to reload the page when an expired session is the cause (#333)
  • Select all now counts during reconciliation. In a reconciliation session, the header select-all checkbox ticked the row checkboxes visually but the Ticked total and Difference didn't move, and the ticks never reached the server — so they were also silently lost when leaving and resuming the session. Select all now registers every row it ticks (or unticks) with the session exactly like a manual tick, and no longer wipes ticks made on other pages of the list (#337)
  • Deleting an account that still has transactions now offers to delete them too, instead of failing with an unhelpful message. The delete failed with "Failed to delete account: Failed to delete account" — the real reason (the account still has transactions) was being replaced by a generic message on its way to the browser. The prompt now says how many transactions the account has and offers to remove them along with it, which makes a bad import easy to undo; decline and nothing is deleted. Transfers pointing at the deleted transactions are unlinked, leaving the counterpart in the other account intact (#336)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureBbOGARv5bo0EfD87OHApDK4LSAVbklBnbu7Q0XNAXlA/b120kU9X1ByNzLNwChmoeOLSrKp+saviED0SZkaaD2VdC6KM+2NghhWl/8RsDzdjLnUS5mbhQ04KOXOClJ1iHzwKIRJvAkStGLPAP/McI7ol6QLHi3ABWXWDlBcT6bGKDC6v7cmbh9jOeoys4phwH0uJE9pOVlQg7SfHGd/VJKr6pcScapT9P5dOBj878vpqjYSc3KIFvQ5OfA9C836sCseYxi9jM8YPoaw+LzTfX5/t80Fv5I2woXsvXnwtjijARCotyD1uZ9QMAy7M5LLkEm6yUGjJYrEBMBpc3h8fiC7muLojTK+J9O7zk7oYNN8D6Q2YqdJ3e84cEagzf83gbKicTPX4kJ9C8bvUQzK5roVtgFwat/Ndu9c2uK/rwOUVmDKPHdzt3/SQQAl9712dX7lZTJVN9r3dm87AL1nfaJghemZOfQdcQwFkahMlHZOm+B0xKrSUqQWyfbw4xezPvVZEudqpPIhQ0lIlFro93ziB7KBUJvaJCx0UNMFr2Z4zCDY64wKLaq1sgSm8HQ4QxSdL1+bPWgTG+BVzchvbx6Cmh7DHmXTAr5XGPzEczdMWY0t16uZ4ZzftT5Ss+S/NKpV37SiFKPOKWzou4BFGU9qwl0DeYKy4E+/EDMX0W80=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.40.0
Release Details
UpdatedJuly 26, 2026, 9:40 p.m.
Changelog

Added

  • Keyboard shortcuts. Budget can now be driven from the keyboard. Press ? anywhere for a cheat sheet. Globally, / (or Ctrl/Cmd+K) focuses search and g then a letter jumps to any page in the sidebar (g d Dashboard, g t Transactions, and so on — every page has a letter). Any dialog now closes with Esc, traps Tab inside itself, focuses its first field on open, and saves with Enter. On the Transactions list, j/k move a row cursor, e (or Enter) edits the highlighted row, and x selects it. Shortcuts stay out of the way while you're typing in a field
  • Export and import your import rules as a file. New Export and Import buttons on the Rules page: Export downloads every rule you own as a single JSON file (a lightweight backup, or a way to move your rule set to another instance without a full data export); Import reads such a file back in and creates the rules. A rule referencing a category or account that doesn't exist on the target instance is rejected and reported rather than mis-filed. Rules shared with you are left out of the export, and rules remain part of the full data export too (#318)
  • Import rules can now be shared. Rules join the list of things you can share with another Nextcloud user (alongside accounts, categories, bills, income and goals) — pick which rules to share, read-only or read/write, from a share's Configure panel. Shared rules show a Shared badge on the Rules page, can be run and (with write) edited by the recipient, and run during their imports too; only the owner can delete one. A shared rule's set category/set account action only takes effect for the recipient when that category/account is also shared with them, so a transaction is never filed under something they can't see (#320)
  • Import rules can now match on the account. A new Account condition scopes a rule to a specific bank account (with NOT for "any account except this one"), and a companion Account Type condition matches by kind of account (checking, savings, credit card, …). Both work when importing into an account and when running rules over existing transactions (#322)
  • Tag sets now work on shared categories. Opening a category shared with you shows its tag sets; with write access you can add, edit and delete tag sets and tags on it just like your own categories, and read-only shares show them without edit controls. Previously any tag-set action on a shared category failed (#328)
  • Bulk edit can now clear a transaction's category. The Bulk Edit Transactions dialog's Category dropdown gained an Uncategorized option alongside Don't change, so you can un-categorize many transactions at once (#332)
  • Deleting a category that still has transactions now offers to reassign them. Instead of blocking with "reassign or delete them first", the delete prompt offers to move the category's transactions — and any in its subcategories — to Uncategorized and remove it in one step (#332)

Fixed

  • The browser Back button now moves between pages inside Budget. Switching pages (Dashboard, Transactions, Accounts, …) records a history entry and updates the address bar, so Back and Forward step through the pages you visited in the app instead of jumping straight out to whatever you were looking at before you opened Budget. The current page also survives a refresh, and links that deep-link into a page (e.g. from search) still work.
  • Bills with "Auto-pay when due" turned off could still auto-pay themselves. The auto-pay flag (and the other bill toggles) could be read as on when it arrived as text rather than a true/false value — the classic (bool)"false" trap — so a bill created or restored with auto-pay off could still be auto-paid. All bill toggles are now parsed strictly as booleans on create, edit and import (#335)
  • Cryptocurrency accounts and their transactions now keep full precision. Amounts were capped at 2 decimal places on entry and storage, so e.g. 0.00012345 BTC was rounded to 0.00. Account balances, transactions and splits now accept and store up to 8 decimals, following each currency's native precision (BTC 8dp, XRP 6dp, JOD 3dp, and so on); fiat currencies are unchanged and still 2dp. Amounts on bills, recurring income and savings goals denominated in crypto are not yet covered (#331)
  • Shared categories keep the owner's order, and editors can reorder them. Recipients saw shared categories in an arbitrary order and couldn't move them; they now appear in the owner's order, and a write-share recipient can drag to reorder (the new order applies for the owner and everyone it's shared with). Reordering no longer silently fails when sort positions collide — the whole sibling group is renumbered on each move (#328)
  • Shared categories now open for the recipient instead of doing nothing. A read-only shared category couldn't be selected in the list at all, and even when reached its detail/recent-transactions/spending endpoints returned 404 (they looked the category up under the viewer, so one owned by someone else was never found). Clicking a shared category now opens a read-only view showing the owner's transactions and analytics for it (#328)
  • Recording a bill's payment failed when the bill used a shared account. A bill can point at an account owned by another user — a partner's shared account — but marking it paid, and the one-click Record transaction repair, threw "Failed to record payment" (a DoesNotExistException in the log) because the transaction was booked against the person clicking rather than the account's owner. Bill payments are now recorded against the account owner, so a share recipient can mark shared bills paid; a bill whose account was since deleted now shows an actionable message instead of the generic failure (#334)
  • A one-time bill marked paid without a recorded transaction could not be reached to fix it. After a one-time bill is marked paid it deactivates and drops off the Bills list, yet it still appears in the Payments without a recorded transaction card telling you to assign an account first — with no way to open it. That prompt is now an Assign an account button that opens the bill for editing (#333)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureTlx5adQ84X1cU4v1VoYON+yY22etMZSb58OURK5dpJ/bpQdLjdhL6stjRFGshNhEHr1Ra/KTZs7/uCZLyvq+M0XBYGD+voy+pwmXwa6Wylyi99fJ2UhiXPHxKiExVq1EJY/PA7LcHAQy639r04gbQ4Q/BvDrOZYWAZuYCLrZrZFclfoIlzf/Ra5SFuCuWguuOd79cU/tXViv8xntJBIcIXoN58cadHF5iTo3Mt2XO7sNsUs7A8+1HDXsUldblvmLFFpH9ubJdYVDKqdzA104yRb0uPH08Zd6+y764r+uIsahSB/RwF3kJ20gcv5nurCaf9FvsI06PiyQnR73jMzlnoAaWxnSPZwGDa+gvQ/t56H+m+A9DlvVgnxexUa0C+Ga7cphcgVKWPWaRZFQzeofrcJ66wAH9uh338pw2R2Lq5F+s2NCOKuKo6uXocpf+VZ9GTsfRIrDEGL+4FwkFkxd0tHUBoohsOhROk/tXphvl/mIh5m4m3pRsjm7GviZASYoTXJe+kdclUUzpFMuXGrOFjSXCd1Plk2XsDMiHBzPEXAkaPlL9hdluXiuCCXrUYIF+S/U60qB1MuWRlwzTH80RovEgvyKGwZtzlDPtNLF0hM79iABKE5UgP1km9MRm7dyDWQDdogfWq+Oy97EJH8TDtYvuO2I79lQnppc9WrYB5E=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.39.1
Release Details
UpdatedJuly 11, 2026, 10:22 p.m.
Changelog

Fixed

  • Share recipients saw wrong dashboard totals. For a user whose accounts are all shared from someone else, the Income/Expenses This Month cards counted transactions in the owner's "Exclude from reports" categories — the exclusion list was built only from the viewer's own categories, so the owner's internal-transfer legs inflated the recipient's income and expenses while the owner's own dashboard was correct. Shared categories now keep their owner's exclusion for every viewer, and per-viewer "Hide from my reports" mutes are honored by these totals as well (#326)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignaturePTjw+Z1r+sKWQmZSlNfYPSTl5PFejqjMEgNyvQR1FXSKor9zNXxtxcAM0eYYthPn9YEprCKS9V6NC699ZbeWK6WbdRtprmP+rsvCifpjQyVtPDGLJ11LWzLVgw84pTHcolsdY756JO6KWW8hxp63bq3s4QE4rs3RTCEyHSpzpZ1pXSydTCTvheL1M/rtg3XyKpzBkoOqGh39Dnh9TH7JQt+cCB8VD84aeHcsvnxUkQJU3AmZwYGcP8wSNeLmDjt1S9yCv2h8NAReLQeTMbmdzNJtioLLiifkedz5bEgjVximgqI99mmV+8uhRBY0keT1hWXR6En4IrRkiJwlEyNZRHkukMa9jNmoNVvoRYCuQOVZ1wWGtkS8MCz5Ig63yPijEMh1bqnoi3+WA1g8s23dJVIziAHSKl0F+V7DKThsw2jBouMZeZ7bG0nMS9bFLcndAm1MbpWyuZATotUExNeYhEZEIwUOuF+esV5lnDoHTf0i/q6OJGa4hPPiNTE/rH4PS3Z4pdEZ4V9YhxYfsSs/9y+Y7xg/ZQWnLq2YVsTR7V8FgQwU4Bi8OGLsfbYZhSaUnHv60ObUB2U4WkD1mZZqDHKJXAIgVGulvHFAkXQVeGpRqbUCQNvgiVU8hfRaRmEr/y9Usub/3srDJn7qybeAxfOxA7rL+AlakEZBECHPJlY=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.39.0
Release Details
UpdatedJuly 11, 2026, 12:57 a.m.
Changelog

Added

  • The Bills page now flags payments without a recorded transaction. A warning card lists bills that were marked paid in the last 60 days without a transaction being created or linked — the situation where the app balance silently detaches from the bank. Each entry has a one-click Record transaction repair that books the missing payment (dated the day it was marked paid, both legs for transfers, splits applied). Deliberate skips via the Skip button are not flagged (#274)
  • QAR (Qatari Riyal) and JOD (Jordanian Dinar) are now available as account currencies. JOD amounts use the currency's native 3 decimal places. Automatic exchange rates cover both. Requested in #321

Fixed

  • Editing a monthly recurring income never saved the changes — the app showed "Income saved successfully" but the Expected Day (and every other field) kept its old value. Any update whose payload contained an empty field (a monthly income always sends its yearly-only "expected month" as empty) reloaded the entity mid-save and threw away the edits. Thanks to @redsteadz for the fix (#324, #325)
  • The "Exclude from forecast" checkbox on a transaction appeared unticked whenever the edit dialog was reopened, and saving the transaction again then really did reset the flag. The flag was stored correctly (including when set by an import rule) but the transaction list never sent it back to the browser, so the dialog always showed — and re-saved — it as off (#326)
  • Income/Expenses This Month (and the other report summary totals) deducted transactions in "Exclude from reports" categories without converting them to the base currency, so on multi-currency setups the deduction was applied at the wrong rate — and for a single selected account the deduction wrongly included every other account's excluded transactions too (#326)
  • Imports no longer bring in flagged duplicates by default. The preview's "Show duplicates" checkbox — on by default — secretly doubled as the skip-duplicates switch, so every import ran with duplicate-skipping off and rows flagged Duplicate were imported anyway. It is now purely a display filter; a new explicit "Import flagged duplicates too" option (off by default, resets each import) covers the deliberate re-import case. The preview's per-row checkboxes, which were never actually read by the import, are gone, and the New Transactions count no longer includes flagged duplicates (#327)
  • Marking a bill paid no longer suggests unrelated transactions as "existing" matches. The Existing Transaction Found dialog offered any unlinked same-day debit as a candidate — cigarettes could be presented as a "match" for a mortgage — steering people into marking bills paid without recording the payment, the classic source of app-vs-bank balance drift. Candidates now must match the bill by amount or name, a weak match is never pre-selected (the safe default is creating the transaction), and the "Don't create any transaction" option now states — and warns after — that the account balance will not reflect the payment (#274)
  • Overdue bills no longer double-book when marked paid. The scheduled placeholder pre-created for the next occurrence was written as an ordinary cleared transaction whenever the advanced due date was not in the future, so it counted toward the balance immediately — alongside the actual payment. Next-occurrence placeholders are now always scheduled, regardless of date
  • Restoring a backup preserves every bill setting. The data import dropped most bill fields: custom recurrence patterns (restored bills then advanced one day at a time instead of quarterly/etc.), transfer destination and description pattern, auto-pay, reminder days, tags, split templates, start/end dates, remaining payments, forecast exclusion and the future-transaction opt-out

Changed

  • The Match transfer dialog now also lists candidates from accounts in a different currency (any amount, within the date window), so cross-currency transfer pairs — e.g. imported from CSV — can finally be linked by hand. Automatic matching after imports is unchanged and still only links exact same-currency amounts (#326)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignaturegJm3RDjkvl1EBICN6Us5TsX5SdQbSGnRHvRIZmLsYaclkDVqW/mYCBjVgwjU50ifkv72zl3kxf5a8S3yxpo2WX6cnhkyyibLhs5Uzdrj9Egw47yYgMun8WH4647Y0uGP7QrX3Yf51SO7Ve+JWgdMRX+hWvG4K9hxUgAwWR3AmTYRsRXpmsNrOr97q2SPC3V0g9bAARDeSeWDGQ8SR05+OMIrQRj0Ct56fC1cTNWzHpPT+Qs17SJJcUUnK3tJWsM3wvGiwk62YMBy1cv1jx3JkOXnYvsa8bpSG3sL7aqr05QkAkvL9sSGxka6mDrC3CN1LHlwwQjPjWwoX9YDtOI04j0JPd0SzlhMYILaZNyouhoNTuY5YhDIG4aLjg737AAEBHgU3jvpWxaM8Oz2+9he9LkAJW6qA9DuzB/FmDNKxyJTmQ6S0LZ21d+Hkr0LD/2uKRSywlRBld+UNCWby8YrgIkyGomPH1rjDG28y1ApiqSozetcjSvDYwqULM2mLXU9OjD9a8UJk8B1R4Xd0TqgMmDCaAZrTdRLYYdTZEEaFbnDkbm8p4z2q+UGfn/UCNEOkg5pbu1WAsRubIKkPzNTz7gTSLI9u+qJfvoZg9c3Ae1OhXWDD9k/2Z+pCrbJhu8yDX+2JukXoAxNS+bnxaDxdoxRzIM+9jcbb0eyG3wJuLk=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.38.0
Release Details
UpdatedJuly 7, 2026, 1:07 a.m.
Changelog

Fixed

  • The account selector saved in the gear settings of insight tiles (Monthly Comparison, Large Transactions, Weekly Spending, Year-over-Year) was silently ignored — the tiles always showed all-accounts data. The saved account now actually scopes the tile's numbers
  • Importing transactions that trigger the Auto-Link as Transfer rule action no longer shows "Cannot use object of type Transaction as array" on the import screen. The import itself always completed — the error came from the transfer-linking step afterwards, which also means those transfers were never actually linked (#314)
  • The Recent Transactions dashboard tile now honors its "Rows to show" setting above 8 — the display respected the setting but the data fetch was hardcoded to 8 rows, so values of 9–20 silently showed only 8

Added

  • Edit auto-categorization rules as JSON. The rule editor gains a Builder / JSON toggle. The JSON view shows the raw rule structure — editable and paste-friendly — checked when you save, and switching back to Builder repopulates the visual widgets. A Copy JSON button makes it easy to move a rule between instances (category/account IDs are instance-specific, as noted in the view). Requested in #318

  • Hide shared categories from your own reports. Categories shared with you gain a per-viewer "Hide from my reports" toggle on the Categories page. Unlike the owner's "Exclude from reports" flag — which stays owner-only because it changes every viewer's reports at once — this only affects your own reports and dashboards; the owner and other viewers see no difference. Applied at the SQL layer through the same choke points as the owner flag, so every report and insight tile honors it consistently

  • "Exclude shared accounts" on the remaining dashboard tiles. The per-tile toggle added in v2.37 now also covers Budget Progress, Monthly Comparison, Large Transactions, Weekly Spending, Category Trends, Cash Flow Forecast and Year-over-Year (shown in the gear menu when you have shared accounts). Bills, income and pension tiles are deliberately not included — they show entity data, not account aggregates

  • Clickable spending charts. Clicking a slice (or bar) on the Spending by Category dashboard tile or the Reports page pie chart jumps to the transaction list filtered to that category, scoped to the chart's date range and account. Tiles set to "top-level only" include the subcategories in the filter so the listed transactions match the clicked amount (#317)

  • Per-bill opt-out of pre-created transactions. The "Create future transaction for this bill" checkbox is now a persistent bill setting instead of a one-shot option at creation. Bills with it unticked never get a scheduled placeholder — not at creation, not after marking paid, not after skipping — and toggling it on an existing bill adds or removes the pending placeholder immediately. Previously the checkbox only affected the moment a bill was created, while every payment re-enabled pre-booking unconditionally, so unticking it never actually opted a bill out (#311)

  • Convert a transaction into a transfer. The Match transfer dialog gains a "No match? Create the other side" section: pick one of your accounts and the app creates the opposite transaction there and links the pair as a transfer. Until now the dialog could only link two existing transactions, which left no way to correctly book payments to accounts that have nothing to import — e.g. a loan tracked as its own account (#313)

Changed

  • Scheduled (future-dated) transactions now show a Scheduled badge in the main transaction list, with a tooltip explaining they are not counted until they occur. Previously only the account detail view had the badge and the main list showed scheduled rows in italics alone, which made a bill's pre-created next occurrence easy to mistake for a duplicate booking (#311)
  • The transaction list Total no longer includes scheduled transactions — they are placeholders for money that has not moved yet (#311)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
Signatures/wP/jWqAxqTStZPLKWl/5nyJk/xpeAom+Kp7KakVOdJmzhNv/Z6KM/CUUOrGem4Qj5G1OEZ2tNrPkTneCVvfFU2S5aoayMDgcRaGquqwZisM/4a0KV9Husjq8mV0RVoqco16HBH8PUY+kYsbeWRcSp2q38Zq99L04zb1x5XY1rGe5YdP4/IydUoMpyzTtsGF00Tj6OUAMvlDTnJqCcetscuXX8yo33xm0dUfLxjZD2f9hsn8UTCwNN7v1+yBhwNN4jJsfyGTN+92XV2YDhRCfVWq/3bGqphHo+nYQvbyjndJRcaAwybOquX6MH7+wpDa5wpvNw9xzc2sYNm2FM08SYep3cX7uoXngifGZu2FBqyNHQ198dqEwqJbEVv2DrK5cAnQkbSS1glYYney/uXAlsqLEinHirrShNYRoq+ZEkxUhpdung3zSWwPe0Fd/mWh2chHiTV20A2tCrv7FRuRadpf75bq+y0xuIglVZQy5E1dT2nk3lPUUwB01w/ggmwrJ91hOchPoyoRoDhoBNxZJs903bQejWR/MdZ9pbXVmwxj1EOq8oWfWeQ5B+OEz/LbcplibODsNv6IUIYU++gxK8d2XCVzBgV2ayMqsRxFDxItgluqDcu4oTW8mh3A4z33PvbeCFFMsj2bKFbOslmuT2ZiVl58oTaQRTh61xeKEA=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.37.0
Release Details
UpdatedJune 27, 2026, 11:16 p.m.
Changelog

Added

  • Exclude shared accounts from reports. When other people have shared accounts with you, the Reports page gains an "Exclude shared accounts" toggle so you can see just your own accounts' figures. The same option is available per-tile (in the gear menu) on the account-based dashboard cards — Income vs Expenses, Spending by Category, Top Spending Categories and Recent Transactions. It's off by default (shared accounts are included, as before) and only appears when you actually have shared accounts. Note: a transfer between one of your accounts and a shared account can only be partly seen when shared accounts are excluded, so income/expense totals may be slightly overstated in that case.

Fixed

  • Saving share settings failed with "Some entities do not belong to you" (HTTP 400) when the "Auto-share new" toggle was enabled for a type, or after using Select All — the auto-share toggle (which shares the same data-type as the entity checkboxes) was being collected as a phantom entity and sent as a null id. Entity selection is now scoped precisely, so share settings save correctly with auto-share on (#306)

Changed

  • The Categories page now also lists categories that have been shared with you, shown read-only with a "Shared · <owner>" badge. Previously it showed only your own categories, so anyone using a budget made up entirely of shared categories saw an empty page even though the categories worked everywhere else (#306)
  • Categories shared with you at Edit permission are now editable — rename them and change their colour straight from the Categories page (they carry a "Shared (editable) · <owner>" badge). Read-only shares stay read-only, and a category's type, parent, budget, report visibility and deletion all remain owner-only (#306)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureFqJ17XG/szTfkAMsF+oCODYGClVjdeGArgFi3SrgeGhg4CFFzIVO98XEnYhxeCnwOcYGivzy0uhe60/Vv7kgml+lIVvRL1EZOxvjOES2KksQ50fqxGZSNz3EL54EA6R3Yvo6uLFBM9cbK0mmY5H+4i3UozKhKwzRa6PJLIZzpBsjtprJXHojWsQMR5KY7WDDbb9yD32uYzMnrXMxOiQ2PZGtG7aIhLS6DzC7Mtp/oLUgyRqBWoYMUWWLLi1qyeOr4/8Tdm9H5I36oxeoX2ZQlVuprpRjDPW5EITrljbyuIPy3CdAFn5tvvt8rkurEgCtPAaMv7gSXRZto6rJJqS4woUqX310+J0re9qa53Ls0J7Kezo5WpENoaFsvT6McjVG/4k6k4YN1/l74p97fFfR+1T2kC5VptpwVz4GZ2aSF9t226Sdkft7sv72aC3oQpa4PN3PIWj113aN2X5nnCGiD+NUW282/yAdacvMWVgB+t+Rbm0FIyWtGnbw0dKAlY3CAmQoBvqX9f2vqn1OFDxJhejg/i7+FAWQD83LIk6u2kNg/N4e2+hgLtO45wd5MU6TLXXTrb1mlikbbiP80Rla1p50fScosYTCqjJfz2lh5U6D2h/nquGHHvhf4R9q7eSkykmELHZUKiUyYlrLrOfiuxGRqaWSQWp9hm0CUog1HBE=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.36.0
Release Details
UpdatedJune 27, 2026, 1:15 p.m.
Changelog

Added

  • Auto-share new entities. Each person you share with now has an "Auto-share new" toggle per entity type (accounts, categories, bills, recurring income, savings goals) in their sharing settings. Turn it on and anything you create from then on is shared with them automatically, at the permission you choose — no more sharing each new bill or category by hand (#306)

Fixed

  • Code-integrity "Some files have not passed the integrity check" errors reporting FILE_MISSING for js/.htaccess and vendor/tecnickcom/tcpdf/tools/.htaccess. The app no longer ships any .htaccess files — the Nextcloud App Store strips them from the published archive, which left the signature expecting files that were no longer present. Neither file was needed (the JS one only set a redundant cache header) (#307)
  • Deprecation warning in the Nextcloud log — the notifier now throws UnknownNotificationException instead of InvalidArgumentException for unrecognised notifications, as required by Nextcloud 30+ (#308)
  • Reports and the dashboard summary were empty when a single account flagged "Exclude from reports" was the only account selected. Accounts flagged out of reports are now only dropped from the all-accounts views; explicitly selecting one shows its data as normal (#309)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureYxqf1NnAucAiXFVdwVmQJPaPUyuExQ8t/dwv4tDVpFb1kXDtGcIWoAdspiDz+HwdyPe+ul+/2GcDWiLPTF3TvIHwIaV+h+guDRYBEHMY95+Hy5W0BSuwBC7gto5dfsZEhL5xj5OsRIYrY/Fo8Tqj99kVzDK560o9NgI6Bp6ZkQpbwPRbTnbxUX27oF0oDjrg1ArS4IiE4ghZW1ct74Mlv4uoeg5zaVQlucrZK+rBJXixtpDnImHLPMkTvd+1bmkQTFtvArS1A37YkXkLKrKn4pzWvwv/q46ddih1NXBC7o6UoBwP1pWB1OxgNq3/98OdWyPs4GLumMmRdg+7PbY95Go97lBbNc/1mrBB9qQPXirFxYHMZWVDSRHSNRJ9cSMnZA/YzsVeOZOVkIwJWXhC5YGAEN8nq8HKIMBHzmi6UYdGM2VvGPmNZ+K3wlGMIkKlVfWfIJ7XIOCe6OLvQbwR/ATZ7pUyOE+AR21uu27zWGJ4iB4y/eCfCSE8vIxyPW7L0dwkzxU13iNNNxAUQgbNrs8EiQBLQlTCaBWCWp296Dds5nEGMEilQKX9vEXAhY9KRG5dzJjoZhZ14tWA3Hjp+5/Gs2AM4Bh3Rp1OGdhfQhFDmt/2GXcL16lfDcX28K1ub4FPYE8MEz6qDmLhqqwv9FeXQQbT/ZKdQn8NwuOlGFE=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.35.1
Release Details
UpdatedJune 25, 2026, 3:28 p.m.
Changelog

Fixed

  • Categories marked "Exclude from reports" are now consistently excluded everywhere, including the Income vs Expenses trend, Category Trends, Top Spending Categories and the monthly spending chart — not just the dashboard summary. Exclusion is now applied in the database query itself, so reports and dashboard insight tiles can no longer disagree about which categories count (#219)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignaturebX/9kwpiVjwDj0f2eU5xNE7zUpt8T/nkGCFg9HnDQoKynM7c1KaXhbh4isVQBbgy5kPGXSDP7DRfuSTYY5/M3PSv1JE8gOk/9lz2AGmTqlXrf4Kgq9oARAGcVHXB955dLvDkj6Vrk7zZ9cwrjq4aMBu02dW8ZgyAHStXybiWmkAbIxK768MHM4n5FXTRFw3P/ELVlDjCxgIpxVxD5EZaaA+n7RrjN9MRY2R8/GN7Og7yijcmnutMWtna4K19B9c3ShcfUkrwotvCUz3c+K10VQSfzUpN6RoindDB0j716jUZQ6IKzXBNNRiOjQ6N6s1MlmKwjyFyw0PY509hJY+dtjBEQBbFjK0pw7ZElfW4zDWteDzWRm7M1VjzUlRgPLsg7CJ980Rg8suZAMh3UH251vymCH0ykpMYqK1qiWDurz5GWdaDov6Z0YkQPQLnszzPa60kbO9VUHrYnG+6+KA6GoPW0EHFEqaUxXv+mRLr8Pm8BhjCiDghO7mlHZFN95hN5gkNyBdIPA9JmXAdnkrJBSQaDvZdejDwFJL+T+PgA2f9JomB8BQ/WkZ4uukyKUUFYToOhntQTe7dfE+I4VsD6BycbY7smaY/xGx6EvyXfntpYkgR7Fe2rYKaxBrcRcnhTmQBeLLz85M7fLKVjME72niQdRIZRaMZ+OmpCxKK2qU=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.35.0
Release Details
UpdatedJune 25, 2026, 12:36 a.m.
Changelog

Added

  • Pensions revamp. You can now record a contribution as a transfer from a bank account — the matching withdrawal is created automatically and kept out of your spending — and record withdrawals/drawdown back into an account (#304). Scheduled (recurring) contributions (monthly/quarterly/yearly) can post automatically or on demand (#251). DC pensions gained a configurable projection target with a progress indicator and a "today's money" (inflation-adjusted) view on the growth chart, plus an optional Pension Projection dashboard card. Bank legs that fund a pension show a Pension badge in the transaction list.

Fixed

  • Background-job "class does not exist" log spam that could appear after updating PHP/Nextcloud/the app: the app's autoloader is no longer "authoritative", so it falls back to PSR-4 and self-heals if PHP's cached class map is stale after an update (#305)
  • Newly-added dashboard widgets now load their data immediately instead of staying empty until the page is refreshed.
  • The pension detail panel's balance history and activity are no longer broken — those views called endpoints that didn't exist; they now show a proper balance chart and a merged timeline of contributions, withdrawals and balance updates, each removable (#251)
  • Editing a split transaction with three or more parts no longer zeroes or overwrites the other splits. The last split row is now a read-only "remaining" amount (transaction total minus the other parts), and the dialog blocks saving until the parts add up (#303)
  • Spending-anomaly notifications no longer crash with "The arguments array must contain 1 items, 0 given" — a stray % in the notification text made Nextcloud's translation layer fail, spamming the log every time notifications were rendered (#305)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureF/7pZ4sNzjJuqXXZoHmO+9OmUzkQz6ZDke3vkONfZ2uGfzBpwpDSIiGlfNv6gt40Ho8NTPNd0JuM+ESRohLlPAAftFoF+L4h+asH5s/lncoxgTZevEFl7NE14s+sPVdGdZqXGi0b3mohB+f1jOudpVbgB0bmCDvnZMEKiMSjB7XwH9iQqzu/8WyQNd28w+Bz2TbyAfu2PCtdD6jsmVCbvtCkmEdKOVJzRWuExH+vwvZ0ltX3mtorPl6HEzqKJWoDYG3tdbpSwml6w9F3qj8naVZ3tZYBrfvwABHoMD1LYpYwRss5C9UpJvu6UFfKQ4Xso1tBu5U+tYlAPKLbQ5J70o0C1aP66R+FvL8RlMHpY93duR32qZkT/6xV0NYQpd9xzXoLbB5YkZJuBLV8m3oP9k/pNEy8vwF5Kkb+/6zrJt4aSH/iiAqBoqvuT1itwScYsNpGHXWOrGHioCKiGkcMvamfr7her1fQ42wNiVIVWKaxNtjeYrVjmHCtWA2awjv3XRfcXdcL/4stuDpXxQ0Dnv2S/Ey9ZbGbqpc0DNyPZfKie5/QK5OnHPW9F8nHUsEhxDLbNezo11fKm1ykE0ja4nTZFKL3ml2D4aRDMYQe35MWJvW/fLcNW7dYOV969ZI52G8jTIUI/YphcNfCNK24fVkljrcBSybr8WavbELxVR0=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.34.0
Release Details
UpdatedJune 24, 2026, 12:34 p.m.
Changelog

Added

  • The transaction list filters now include a Reconciled filter (All / Reconciled / Not reconciled), so you can quickly see which transactions still need reconciling (#301)
  • A Budget alert threshold setting controls when a category appears on the Budget Alerts tile (default 80% of budget). Set it to 100% to be alerted only when a category actually goes over budget, rather than when it's merely approaching or fully used (#293)

Fixed

  • Creating a category (or account) no longer fails with "Unknown column 'excluded_from_reports'" on instances where an earlier upgrade was interrupted or restored from a mid-upgrade backup. A self-healing migration re-adds the affected columns automatically on update (#302)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
Signaturey+Qi2+U6CexZu8i+0DGrbLXwFbp+cHLVW62WRSfrovEAuJrnZy8paqAacEaE570GoHVd1b23Yihz4oDfOYStLASDVFk7xhVrarnlIqv4EH+Jyw0IR2iaLR+IvhJmSZc9N5nQ42i2z8UYetvQo0znzzNPmpT2FEJB1Sty9kCfHL7HiisG4hYwJp528McMVXgCYfn/XOZUQzOVY6rvis1hP8CiFbE4UMUQj/SgDpRjimcRCZy8fsRLgZHcfO2+BKYCSt5lqLDJSzsmewBFNMVWDdtZwPUxqyK8xaTwSnwWNBNXBRg5ZcDLJhhIJtk9cEezVTdJBZTw3wx7iCztR9RFQi9CZsRz9U9S4jLEdcV8m6OTa8XG22s2ZHt+I+hisGtlC1TOQ5fpPfSe9onWdA8jgC68RAFeOLJ+KmSkLQN1bbr9gUw47oB09Yd9sEtUDcFapfv+x9Zl3/s4ExwO6xDS/bwmRyZ/fq1z2jhVu/lMFd//+9ciOrCdty1p7440JVs/sx71Qcc0mRhZsMtIRYyBD2EFceUHx8cQCtOLL99+JtGkTakCMCwIxghuGoXnrq+9mRWjgROn1ysGEHDUyC8ZKCJ5f8TXOllqX2g+2fyOpFzHR66oP7lPwI5y3eW4VYJGT/lQzTavAtU148X2XaBUz+XA8Djuco3CCuGJuT9FhSU=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.33.1
Release Details
UpdatedJune 18, 2026, 3:03 p.m.
Changelog

Fixed

  • On some installs an earlier update was recorded as applied but didn't fully run (an interrupted upgrade, or a database restored from a backup taken mid-upgrade), leaving the excluded_from_forecast column missing — so every new transaction failed with "Unknown column 'excluded_from_forecast'". A migration now re-adds the column automatically on update. (Also surfaced by the new database-error detail field added in 2.32.0.) (#289)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignaturewGNDwrdOGHhLxiEiJQDsZrcL4BFQbGBTjeDU/3VJql8bIeDBHITKzJ3HH47kV1bFmsZ35q0o7xh/r4q6Kj9/SXM8gQCTxEtQ0q80MS85LGy5+9dUtJ0yBvrLfE6kwpNPDH+kqwBVcAGxmLr9vYau5uTFGdeB0WZ3gmesUvT5kuZfdREwJDQ19QWR40pJjHRcWqM5KnXCT1/wq7btWj9s/Vf9GVQvo85g9R7adODG1PVBr4gM6R9nTgsrn+60BJvNNO5f3W3wbuzvqaJhtVdknB9Z8fc7Vbq6mh6TgSPBmXgiK2VdCAWPaW2EmpVL8iwgOGazPGSajPkMZNNZDhzDNEpLcveJl61g/x5dVAxOevwFnN4CaX5c/YYppjcqtoWyYgoTNMv3enF3///tD0wS68iQzcU5UNmsOOKsAUVvRnf/oOX2b13NfsKPONAxcu4Q/UG8ybPqYwXT+T6Vs+IRmoLJLnOs/BUgbqmmRIG1Wfs2BusDFKNHHWoW1Z5t+GDLGx2cyNci7+rKPRh2seML8iPrt9lNv2M5NjzIJ9Wm0Xt0FKpIetR4gDpLSRvBtINaQ0jVuYVixt1yDKMUfE6GH4sNW9rNi2ZoKptz2MIxouBmLNXezA5Y0gvIlgA11Bi0YBrKPUAtmxNl8Jyxhle2Ll5bZbsupMy1otRB/+NGEOs=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.33.0
Release Details
UpdatedJune 18, 2026, 12:52 a.m.
Changelog

Added

  • Run reports on multiple accounts at once: the report Account filter is now a checklist — pick any set of accounts (e.g. all your credit cards, or all your checking accounts) or "All Accounts". Applies across the summary, spending, income, cash-flow, category-by-month and year-over-year reports and their CSV/PDF exports (#299)
  • Saved reports: save a report's settings (type, period, selected accounts, tags and options) under a name and re-run it later from the "Saved Reports" picker in the Reports view. The period is stored as the chosen preset (e.g. "Last 3 months") so a saved report always shows up-to-date data (#299)
  • Dashboard tiles that can be scoped to a specific account (Spending by Category, Income vs Expenses, Net Worth History, Recent Transactions, and the other account-aware widgets) now show a small label in their header naming the account they're analyzing — the account you picked in the tile's settings, or "All accounts" (#296)

Fixed

  • The Reports period selector didn't drive the report on reopen: the dropdown kept your last choice (e.g. "Last Year") but the report always reverted to "Last 3 Months", and clicking "Generate Report" used the reverted range instead of the shown period — you had to switch the dropdown away and back. The report now always matches the period shown in the selector (custom ranges are preserved) (#300)
  • The Quick Add Transaction dashboard widget couldn't be used on mobile — the lower fields and the "Add Transaction" button were clipped off the bottom of the tile, so a transaction could never be submitted. Its form is now condensed (each label sits beside its field with tighter spacing) so the whole form fits the tile, and it falls back to scrolling within the tile if it's resized very small (#298)
  • Editing a split transaction's amount (e.g. inline in the transaction list) left its splits at the old amounts, so they no longer summed to the transaction total. The splits are now rescaled proportionally to the new amount (the last split absorbs any rounding remainder)
  • In the edit-transaction dialog, changing one split amount now adjusts another split so the parts keep summing to the transaction total, instead of silently drifting out of balance
  • Split transactions weren't counted toward category budgets or spending. When a single transaction was split across categories (e.g. one $1,000 payment split into rent, parking and a deposit), each of those categories showed $0 spent. Split allocations now count toward category spending everywhere it's shown — the Budget view, the Spending by Category chart, and reports (#297)
  • Large amounts (e.g. values over 100,000) on the dashboard hero tiles (Net Worth, Income/Expenses This Month, Net Savings, Cash Flow) wrapped onto a second line, splitting the number mid-digits. The amount now stays on one line and its font scales down to fit narrow tiles instead of wrapping (#295)
  • The "Asset Value History" dashboard tile (and "Net Worth History") showed its empty-state message anchored near the bottom of the tile instead of vertically centered. When there's no data the message now fills and centers within the chart area (#294)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
Signaturejj+nUiPNSYYgtQ/7XYIkJNFo8vWIHaX28Q0XTtpN6RWmrW8qrJBIs2jTaaHwebC7SB5f7GP6vQxghh9+nCWfA+KlTKbm8YJg6yzah9xdTLo/JcUhTOinlH9yYoXxMiIY9EVwQLsPmef4sprTsS9oqBeSgZ7S8WRJYnxjAuljee9q0Sfai9AK+RQzBk6kgENhCAVt95ooZ3H5ukfFBSb/kyXa3IU+ngu6g5B9DgiJfBduecdkLEfc0dhYKelUyNaZa61qoG865podTGJFCFqzoSnlCXgRcJqJHjhdTERIeu/nHQAL/PhaPy0OSWK8l+kyrGveMEKDM6LvQ0Eo6B9Ul0ORobundabEat67f/hqaTmnDldOkkEm5a0WAYeQvYeeZCNLtiF26pWk66v6eQhXsrT6IwcJ/gxaC6oS8URm5yYub2iW9nVq6uZXRMJavJr8CmYl7MSqQRVvFKGlwHvD7X+YfEs+htKGYM017iWdICfQv/wbGi5JzIxqdm7QKrV9EGxgl4GFWvY/cyGZt4awfhoy4RljlFtsfJ02askgVFUloVGKOWeqZ5NbqXMDC+UonPONQ/RPM64u0L3NdVvmcXOwA8RBHCg1qgEiVkDBSsJyhK55+1J7Yn5fIC2emSU0BXOdzSFgg3BgUbYJQHgH30AwNf1iagO/WBOYDSu4jqs=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.32.0
Release Details
UpdatedJune 17, 2026, 3:02 p.m.
Changelog

Added

  • Category by Month report: a new report (Reports → Category by Month) showing income and expenses per category broken down by month, with a column per month and an overall total. Categories are listed alphabetically with sub-categories grouped under their parents, and parent rows include the totals of their sub-categories; a toggle switches to sorting by total instead. Defaults to year-to-date, follows the report date-range and account filters, and exports to CSV and PDF (#288)

Changed

  • API errors caused by the database now include the underlying driver message (e.g. a missing column) in a separate detail field of the error response, visible in the browser's network tab. The user-facing message is unchanged; this makes problems diagnosable on managed Nextcloud instances where admins can't read the server log. The executed SQL and any bound values are stripped from the detail (#289)

Fixed

  • The dashboard "Budget Alerts" tile showed a red "exceeded" alert (with "0% over") for a category whose spending exactly equalled its budget. Spending that fully uses the budget without going over is now treated as a "100% used" warning, not an over-budget alert; only spending that actually exceeds the budget shows as exceeded (#293)
  • PDF reports rendered non-Latin characters (Polish, Cyrillic, etc.) in account/category names as "?". The PDF exports used a built-in font limited to Western European characters; they now use an embedded Unicode font (DejaVu Sans), so names display correctly. Applies to the budget report, bills-calendar and year-over-year PDFs (#292)
  • Marking a recurring transfer as paid showed a success message but created no account entries. The Transfers screen was only updating the transfer's "last paid" date instead of calling the mark-paid action, so no transactions were recorded; it now creates the paired transfer transactions like the Bills screen does (#291)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureNKgPUY81JziKewMWFs4QeLNIwZ8JqGBZ6wvFlsItL4R47yoDLAn4+I1T/pwgEOi7KR2lCUFBckiAdI78FONIy+JyCFhY0w4WcGEltsQdsytRMQYAggOWw+OlYvlDMPI6zoMoRfVcIvC3d+4pUrP91cJIVwi+bu5OIYO0C7ErDFCyvMlHK+ifsGvBluQJ377z8wnBUQIWSfudOuXewIyBHCF1QXsRXsVe0CIGWPNnT3ibuwxjm92a4vzwqdTEYy2qQwzPgYWPhgZofSdEN6j08iuwUzM0i9yXWd0IVpRNLb8RIo9lTzhJsjolrNFGZd0iiQk5A/4NQ6VOLKItVhwXJKOZk7KzyYTZmEki+PaeHKSEjEzwYNqv2tL4VPrBjyq5Y3bRTnYS3uBBCOnkWwn6ozQ4PitvSgPpcqciCtrP1hYAa0oQ7FsP8+BVsepO8gn8+lIcVjx7mW+YvufESAyFRXgAy61QBNjcd34vtoEfLqhdP4f37gZ/jdmCicDQ3sLw/eUIL98BylXmNvOge43vnYuRgGl9gBO11ENaP3EhqhqsrVr5Gyu07MGlMhCRlBn21fRN5sMORHFNx6pL/DcpwC0xtpfWEtHTCcEcLvArqfSiQSMrJaDvqftcQNMWYt4hGZKMVR7SYZsAragHUiMfvWDu1mW7HLNsW8PwySZDrHA=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.31.0
Release Details
UpdatedJune 14, 2026, 7:05 p.m.
Changelog

Added

  • Exclude an account from totals: a per-account "Exclude from reports, dashboard & forecast" option (in the account's edit dialog) keeps the account fully tracked but leaves its transactions and balance out of every "all accounts" aggregation — reports, the dashboard, forecast, net worth, total balance and category budgets. The account still appears in your accounts list (with an "Excluded" badge) and on its own detail page, and selecting it explicitly in a report still works (#286)

Fixed

  • The account detail page's overview tiles only counted the transactions on the visible page (e.g. "50" for an account with 1,603). "Total Transactions", "This Month Income", "This Month Expenses" and "Avg. Transaction" are now aggregated server-side over the whole account, so they're correct regardless of paging (#285)
  • The dashboard spending chart's "Total Spending" figure (and each category's percentage) only summed the top 10 categories shown in the chart. It now reflects spending across all categories
  • The CSV import preview's "Auto-categorized" count was estimated from a 50-row sample and could be wrong for larger imports; it's now counted over the full file on the server
  • Editing an existing bill failed with "Failed to update bill" — saving the edit dialog (whether or not anything changed) returned a 400 error. The bill's start-date column, added with the limited-term bills feature, was missing from the list of updatable columns, so the always-sent start date was rejected before the save could run. Bills now save correctly, with a test guarding every persisted column (#284)
  • Opening an account's detail page returned a 500 error (the reconciliation-history request failed). The reconciliation controller was missing a trait it relied on, so it couldn't be constructed and every reconciliation endpoint failed; the account page surfaced it via the history sidebar. Now fixed and covered by tests (#283)
  • Starting an account reconciliation failed with a confusing "The string did not match the expected pattern" message (most visibly on Safari). The root cause was the reconciliation controller failing to construct (the #283 fix above resolves it); on top of that, the reconciliation screens now read error responses defensively, so any failure shows a clear message with the HTTP status instead of an opaque JSON-parsing error (#287)
  • The Budget Overview dashboard widget (and the digest, spending-anomaly and bill-reminder notifications) always showed amounts in US dollars regardless of your configured currency. The server-side amount formatter was reading the wrong settings key and falling back to USD; it now uses your default currency
  • The Budget Overview dashboard widget's "Total balance" now converts multi-currency accounts to your base currency instead of summing different currencies under one symbol (currencies without an exchange rate are excluded from the total and named)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureCseRrf2b0tfseaK8cBqqPjA8lhMT1C+aq6xVuP6vO3E6sRzawwkPNHdfK7CDaOro2TYW+agvm4g873WzOGVLIVa3FHEyFlnGRkFSwMz334bq1/Rcbw2WXdMbNUliZwdK76DNCauZ0JPz8FYIXr5cqkqbw80oHD/SWhWD5dTKRKJ2gpSvbNtXJfq32Sn04UVxrJq4StY11b5rJfCXR7P7RQxmFboIYJvhoVIfcebR+vighFLC9adkKVaF/xJ8tm1MVG6oJHJ4zKU87SV3+D8vB1xpxeWo2xRwseYSwg8Nk3ik6iXkcf4cHTACrCGyHhOXgCmltGkJ441alZ8kzOQCDe6Vw3Rx+zzgducfZGOQJPuIYcrpyZAAgN51xtDQJTWJNoT9jBrUmEv0r/ftZWj8QYnesnl8HgXUQPdLCsCaloLpISXkt7KzlHYlt4PgdMphbDBnuMROrXZtTeIwDCzwGAkatsK+l8HnM+FbMlpfszT7Ki1z2HYX/d+74aLRxkNUClx3fsQsxOtd0RxK9+/JPHW+W5Sv5kWbRSfiUrslL+pT7R15L9x4t3nFK8VUUEZSDcNynhSHxCVqrqOsV3mZ12eutyvQEPpN56qyLkaZmcoxOlOD2v4BKba8pBAL6YW05jx8hBWg9m0zAg4h3/qoA6zLDRrVfHi+LvUiiE1YDWs=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.30.2
Release Details
UpdatedJune 13, 2026, 6:03 p.m.
Changelog

Fixed

  • Dropdowns in the transaction list (the column-configuration gear menu and the in-cell category/tag/account editors) were cut off when the table had only a few rows, because the table area was shorter than the dropdowns. The transaction table now fills the available height, so every dropdown has room to open in full (#280)
  • The Tags column couldn't be shown/hidden — the Show/Hide Columns menu was missing a Tags entry, and the column wasn't wired into the visibility logic. Tags can now be toggled like the other columns (#281)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureRXpaKwi4ViRdeYM6mjC3JtrlDOFrm03LMBFc2gQMktdYfBEoyMrW3YBp+DPKezxnLOmETNnqjXAI+oswcQLQMkRbAcjuD1dpBBZi7x8kmvtc0lZUcrKRw2QKUzDD5luZaN7JE14o393XlPFxdqkaUbJvWTltA5xK/XO2H72GyvEO7/7de7HCcP2G4XTK5kGSeP3PHRNQ5MjiB49QlM7D95p7Od374Fbr0k52h0sWFHSA14LgJSyPXCgHxxJMqVy7O76LlS1Iedg8B4TFBbTJZVol/8emaHjBHvEwVVzSIIkr9wdtZ60aqrEhJfTqaRwdGS0ks53VE2ROoE829Jnc3Xkz4Xxc0WEqH5a4vxbUWnA8NbuaFNAsUcfXW+0TDTUeLT34IV8c6GZkwn0z4a1parjkif0yyEolfPhNomKX/JMl74aSG5i2BkKyDH3OXMg9oC0/czhOIxluUuFCwWJyd6cBOGd6r/R382SMMe+mCHDpuBxIY12gRo4bzcAfmYMQ3e6rrtgpFwxBllUaK8lC+yPy9x9502QHhZem922Tz7HokfuXuFxh1x9Z6doBSvoZOe2H2PIKRupmFf4I9epoRYdDQZjatpZpN3+oZnz6DmY7f9+g3gaZ7Dl9dkPydm96203Pox5SGz9vhOQaXeOIw+l+rLnXnbodzB3eyqz11Ig=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.28.3
Release Details
UpdatedJune 12, 2026, 1:14 a.m.
Changelog

Security

  • The recurring-income update endpoint no longer passes the raw request body through to the entity layer — a crafted payload could previously set internal fields such as the owning user (mass assignment, integrity only — no data disclosure). Update keys are now allowlisted like the other endpoints

Fixed

  • Auto-derived recurring budgets (#269) are now consistent across all surfaces: the dashboard "Budget Remaining" hero, Budget Progress/Breakdown widgets, Budget Health score, and budget alerts now apply the same recurring fallback as the Budget view — a category funded only by recurring bills can now trigger alerts and is counted in headline totals
  • Auto-derived budgets now respect bill start/end dates: a bill that hasn't started (or has ended) no longer counts toward today's budget, avoiding double-counting during a planned cost change (#268)
  • Recurring income summaries (Income view header, dashboard Income Tracking widget): semi-monthly income was counted at half its value, and a one-time income at full value every month until received
  • Transfers page monthly total: semi-monthly and semi-annual transfers were converted incorrectly
  • Live forecast cache: cache invalidation never matched the stored key (changes such as toggling "exclude from forecast" appeared to do nothing for up to 5 minutes), and the cache key ignored shared-account visibility, letting a share-restricted viewer briefly see the owner's totals
  • Editing a bill's amount without updating its split template is now rejected when the stored splits no longer match (the payment would have silently imported unsplit and uncategorized); setting a split template via the API now clears the bill-level category, matching creation
  • Multi-account import partial failures (e.g. a deleted destination account) are now reported in the UI instead of masquerading as a full success
  • Import preview now also flags repeated bank transaction IDs for accounts that will be created by the import
  • Long OFX FITID hashing threshold raised so every previously-imported FITID keeps its exact ID (re-import dedup continuity)
  • Auto-derived category budgets (#269) now handle every supported frequency correctly: semi-annual bills were over-counted 6×, semi-monthly halved, custom-schedule bills counted every month, and one-time bills inflated the budget monthly until marked paid (now excluded). Frequency math is delegated to the shared calculator, which also gained the missing semi-monthly conversion
  • Auto-derived budgets no longer apply to past months — they reflect today's recurring bills/income and were rewriting history (including overriding explicitly-zeroed snapshot budgets)
  • Multi-account import: an invalid destination account mid-import no longer aborts the batch, and deferred balance recomputes now always run for already-imported rows
  • Bank sync: the post-import balance recompute now keys on transaction creation, not the import counter, so a row persisted just before a non-fatal error still gets its balance update
  • The scheduled-transactions background job now recomputes balances from the ledger (it was the last remaining hand-computed balance delta, and could race concurrent imports)
  • Import preview now flags a repeated bank transaction ID (OFX FITID) within one file as the duplicate it is, matching what import actually does; per-account preview counts include rows that will import with skip-duplicates off
  • Marking a bill paid by linking an existing transaction now warns if the link silently failed (no money movement recorded)
  • Extremely long OFX FITIDs are hashed to stay within the import-ID column
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
Signaturefa7u8mWcwya82OCYZOh+XZFPRJH94oqiBM5WUtEtvU3Dh6Lq+pMs8A7e2aCOa0Y6AbwWH7TF6ZRtwanfSh2PjQMwAaDFlR5anBdAvr89L/fn3eK0uSrZetqNGmAT7Itlc0mT5KowbTvtWDRdK46oR4jjqgXKay6JeO7caGbAcKmyfhJARbfTXsb5etz/yhMX72X33ayUYtCo8nQrtxLTGO5AAPIcFbq1pa3W3d1SHuQ7Ibksv3WXrZe79ngT4pQpGp6xtz3ervqo86vrI8qH8DDg6g9IJE8D1iseOiVzRv/KI/N06LnY0OvUHNZwGrJph5Jh3BrYg2/5rSYzEP5VzaGyZm+AS0DO1bXf9BC5OqbRl3s/FsM+4UgowriYD0S2Zwc4/2j/W3mDRjOdGf0MJxd8SOxv7uW2P5JL0TImjA7mTgppSipw1ShGTl8BU7q11cCtFmuCmwGfvPlRLQtMqEdr93gNkY84rAja08K9Ro1/ySZtrEWVRh/lYzQqmpazsjlw1V4x+KYtn65LHr9Zxd46ToleV5kv1tEZJ1u7nFXeNnrfThyz78EqvLbVxzcqphrfrImGOD9/VhUwryM58KtVz7+tXmLjn3SsSmM8sz9DEljbEKK4zTV9mQgIxviGwzNuIGEFD+HaW6HRIsAzRNtXow5oT7Kgpqa3BnJ3HxM=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.28.2
Release Details
UpdatedJune 11, 2026, 6:33 p.m.
Changelog

Fixed

  • Dashboard could render half-empty (hero tiles only, widget grid invisible): a Chart.js resize on a hidden tile's detached canvas threw during initialization, and the widget grid was never revealed. Chart resizing now skips detached canvases and the grid is revealed before the resize pass. Likely also behind "nothing happens" reports after certain actions (#273)
  • Dashboard tiles with a saved account selection pointing at a deleted account (e.g. after factory reset + import re-numbered accounts) no longer error with 404s and stay empty — stale selections fall back to all accounts
  • Account balances are now derived from the ledger instead of running deltas — the root cause behind every historical balance-discrepancy report (#3, #89, #124, #163, #187, #194, #274). The stored balance was a running total that each transaction code path adjusted by hand; any missed or mis-signed delta corrupted it permanently. Every transaction create/update/delete (and retroactive rule run, repair action, import and bank sync) now recomputes balance = opening balance + net of non-scheduled transactions, making drift impossible and self-healing past inconsistencies on the next write. A one-time migration backfills the opening balance so displayed balances do not change on upgrade (#274)
  • Marking a bill as paid now warns loudly when no transaction was recorded (bill without an account, or transaction creation failed) — previously the bill was advanced silently and the account balance never reflected the payment, drifting from the real bank balance every cycle (#89, #274)
  • The app's own export→import now preserves transaction status (scheduled transactions no longer silently become balance-affecting after a migration) and restores the opening-balance invariant for imported accounts
  • "Skip Duplicate Transactions" off is now honored: previously rows whose import ID already existed were still rejected deeper in the stack (duplicate-ID guard + unique index), so parts of the batch silently failed to import. Intentional duplicates now get a uniquified import ID and the entire batch imports (#275)
  • Import duplicate detection no longer gives false positives for legitimately identical rows — e.g. two same-priced purchases on the same day with the same description. Identical rows within one file now import as distinct transactions (occurrence-aware import IDs), while re-importing the same statement still skips everything it already imported. Re-importing an older statement also recovers transactions the previous logic wrongly skipped (#276)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
Signaturekx2VkgWxozCE2LPp/nzgQQiqFxk/83sOdycv738Ly/uEwn/MhxF/kNtBlP4DMQbhmtkcHdt+kDIlQK1S5q1WHJWZQxjLc/ZCkj/ZEPkNBrDhHwdQCRh4TsRVJyfrIxXUTOCAKJLYk+0DXlnJB3kMhR81adns3wWNH9RkC4b62k3gXtzMR4n+jz/QJDGEAOXRpDUzxEm2TKqFot6sGRt3u0+rVo0bng6nogDJha0APeFI5Ujt+3mECw9MlxNt9nKbQlIGjAnraLVUFz0bXNLK7dbBS3PSzjLsUxhoNhAqMivfHEfLViOvIlCFNHzoWGxFnHK0flI2zJXUlOnaidOEyfhZWbqNpHZL4RZLIZWYQaztJgATNsK+L5aO0Md+Np1hgE8jkdY90gugiV06JqoPEWqCo/qSyaO9N3xYpeXrwfiL37JJqkigwg69RZN3OD1DfBT8ue7QlhT93dfg+39ERzbVY9QBu0gT+bwIs8tyE1MVXOaSjHKUkHab5dpGU3NQhvu/E1CO1BWA3dYvUUqvrvXKB96gm7IqNQEAkRi4JJHDPGtgzjERM+k8z/JA2xeJmPp7V3TZ/1WiKOoKMPz88soCJBMuj/LWnSpekLAGo4RJDy1JBlOm835e3ieJFVHwIwqG9YP7oRB/puFvYV6aaEXCnSkUcZV+z+2NXmHB8KM=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.28.1
Release Details
UpdatedJune 8, 2026, 12:13 p.m.
Changelog

Fixed

  • Install/upgrade aborted on Nextcloud 32 and earlier with "Primary index name on oc_budget_import_templates is too long". The budget_import_templates migration created its primary key without an explicit name, so Nextcloud derived a default name and hit the Oracle-compatibility identifier limit (the unprefixed table name is exactly 23 characters). The primary key now has an explicit short name. Thanks to @TheUnderdev for the report and fix (#272)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureXdUz/Pc10uA7L3R+vTa/cI52W9X8nDyH33zElCWeS/xWeYgonfr0GwLhn4ywE7rtUQF8e1Y8GhETbSd60otnPduP+4rXp7+5+b+iMTa3qfYi6gAd3Y1YJJrZqK0yx2Fdqld/nhQLfFpVkUSQl/JQ78RZanEh779Af5RejNl7lolRlJYg7ZNrLrFasWrpyrLNsg4+Tf74/vMpKWDXf0FEIqjnXZ0LKJm7Yjig4uazy+a5vDcDOrfq6fLU56d9ML/jBJK+9A2loT3I5HP7H2cngdLpwk6+MNLiYQDsdNzLGJJK9TK4hn0Cj+AV80mAQ45beagh4H0SmEoDTPvR/hC7LLlU5rtioE1Rg1tCvlZfHBuPcH9LZMq11Q3HVbZnvzkTdG3lKQlKeFhP86QOIjiAg1Frm0yuOt4nMSdG36N+k1C5szF7HrCoH+u1XgdY6fKI6WW71RkqXJ2IhwOorxcijLVQc2l3wyDLqoQrHtJA2yWGsI9NXlq+d5ZLJ03T7xvcLBPgSDTz91KqBABqJYRdCGhzAuQPe9M814mDu5XgdoCJNUKNrAl6YGvLvJXyj5j8I09qImqsQx09AmEBxi8YTZDbxuO8U/g3yKO14aBgGu3Z+v8+h6xyqJyNsPEbHHxpjfSbwAF/9FlvjA64nOTqPam3fPOjZAdqne5bgf05gFY=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.28.0
Release Details
UpdatedJune 7, 2026, 9:59 p.m.
Changelog

Added

  • Shared savings goals — share a savings goal with another Nextcloud user. Recipients see a "Shared" badge and can view progress; with write permission they can edit the goal and add money, while only the owner can delete it (#255)
  • Auto-derived budgets from recurring items — a (sub-)category with no manually-set budget now shows its committed recurring total (active recurring bills + recurring income, normalized to the budget period) as an automatic budget limit, marked "auto". Typing a value always overrides it (#269)
  • Exclude extraordinary/one-time items from the forecast — a per-transaction "exclude from forecast" flag (with a "No forecast" list badge), the same flag on recurring bills/income (propagated to generated transactions), and a matching import-rule action. Flagged amounts still affect your balance but are kept out of the projection averages (#270)
  • Reusable CSV import templates — save column mappings and import options and reapply them to future imports (#247)
  • OFX/QIF import account routing — route multi-account OFX/QIF files to the right Budget accounts, remembered across subsequent imports
  • Bank sync: pending transactions — option to import not-yet-posted (pending) transactions, automatically reconciled when they clear (#257)
  • Bill start dates — a bill only occurs on or after its start date, making it easy to change a recurring cost mid-year by ending one bill and starting another (#268)
  • "Shared with me" expenses view — recipients can now see expenses that have been shared with them (#248)
  • Dashboard period indicator — chart tiles now show a read-only indicator of the period they cover (#250)

Fixed

  • Dashboard now collapses to a single full-width column on phones, independent of your configured desktop column count (#249)
  • "Excluded from reports" categories no longer appear in the Budget view (#266, #267)
  • Category spending chart shows income as positive with the correct label (#265)
  • Tag-linked savings goals now sum net realized contributions (credits minus debits, excluding scheduled) (#264)
  • Recurring income description is now persisted on create (#263)
  • Transfers are now excluded from dashboard income/expense totals (#262)
  • Account Breakdown report now uses each account's own currency instead of a single assumed one (#256)
  • Fixed a PageController crash (TypeError) on unauthenticated requests (#259)
  • Quick Add date field normalization on iOS (#235)

Docs

  • Documented the standalone Quick Add page and the iOS home-screen workaround
  • Noted that GoCardless no longer accepts new bank-sync sign-ups; EU/UK self-hosters without an existing account are pointed to manual import (#271)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureiQMjVEdG/FWcc56MAPwvDd04E0ERl5pUWkrRWtdYdgbboBj0+7YAo+rDODFz5qC3EPqWBr7XRkjXOfvn9+m61v0w88Qy8SZQIZRHTAwRJuK5jDQbpfce5dropQgKW8btEIzI3BPE+DFBIDeV+qLNQEYT25ApMkUAz44PumVV0sJMibCGo0JBgIxHCPyem1NNjYaX3qQDt41eg8I5rH8wLCWGa7lNTtGyp8vaJ4ck0sh4J9sPuVzMdJoXQDHfGe5S8YY3GTwgvwyloNJQAFO+SQzm5WX6mC/IKAfpxwG82cQAEMm6B4geyHwaYGSFDEgrBuHOZj2fQmvQgzoarRN+U76bOhjQI0IqU76Pno3qM17eF+UKW8peDiqFBXpepGYfDoeyjQsF2GqxIK3C0bNUR5bp9RjNxkWckwvS2ihvP/2rg4lr05MuDDmIdBYG9Ny+PT9dEWBssQkXzIVX28Ox6P8xkorH0n5EoSRl3j+KMXbM34QteNMt1+jgsHAxcS8H57CwV3MC0uqZnhxUu/LbwIGHzvKbC6vN3F/3l6F+35rWM7UaQhdvr2W/1q5Swj5F2sp2Bq5jgrxbWIuUB9+pzftASgVUEmtd6blOUlJuuJj1wmaIrA9jx21+Bg8t/OmrQqB97ZHzint0WTdo7KTOviKZGnoZVXeoQthPmSyW7Wc=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath

Nextcloud 32

Budget 2.52.0
Release Details
UpdatedSept. 18, 2026, 11:44 a.m.
Changelog

Added

  • Import templates remember the character encoding. A statement in an encoding the importer cannot recognise on its own - an undeclared Cyrillic or Central European CSV reads as perfectly valid Western European text, just with the wrong letters - has to have its encoding picked by hand on the mapping screen, and that choice was lost on every import. A saved template now keeps it, and picking the template re-reads the file in that encoding straight away. Templates saved before this have no encoding stored and leave the picker as it is, so they cannot undo an encoding you have just chosen for the file in front of you. Contributed by @Saviq (#384)
  • Import rules can rewrite a transaction's description. A new Set Description action replaces the description a transaction arrived with - CARD PAYMENT TO TESCO STORES 2231 can become Groceries - either always or only when the description is empty. It runs on file imports, on bank sync and when rules are applied to existing transactions. Duplicate detection keeps using the description from the original file, so a statement imported again is still recognised after a rule has rewritten its descriptions. Contributed by @Saviq (#385)

  • The import review says which rows it cannot take, before you import. A file with an Account column can carry rows whose account cell is empty, and with Account for rows without one left on Skip rows without an account those rows are dropped. The review step never said so: a 75-row file whose last 29 rows had no account read as "Total 75, New 0, Duplicates 46", and the only mention of the missing 29 was a dialog after the import had already run. The reasons were there all along, the review step simply did not show them. A warning now sits above the statistics, in the same place as the direction warnings, saying how many of the file's rows will not be imported and why, with the row numbers behind each reason. Where the reason is an empty account cell it points at the fallback account select below it, which is what fixes it, and choosing an account there clears the warning and brings those rows back into the count. The row numbers also match between the review step and the dialog after the import now, the review step counted from 0 whilst the import counted from 1. Reported by @TerjeTM (#388)

  • The Budget Alerts tile can be told which categories it may alert about. Since 2.28.3 a category with no budget of its own falls back to the amount its bills and recurring income commit it to, so categories that were never budgeted against started appearing on the tile, and spending 190.00 against a 56.03 figure worked out from a bill reads as "239% over". The tile's settings, on the gear when the dashboard is unlocked, now offer Only categories with a budget I set, which leaves the derived budgets out and gives back what the tile showed before that fallback existed, and a list of every category with a budget in play that can be unticked one at a time. Rows whose budget came from a bill are marked, so it is clear which ones the checkbox covers. The filter is stored with your settings rather than with the tile, so budget alert notifications and the digest honour it as well, and the budget figures on the Budget page, the Nextcloud dashboard panel and the digest are untouched by it. With a filter on, a tile with nothing left to show stays up and says how many categories are muted rather than disappearing, which would take the gear with it. Reported by @TerjeTM (#389)

Changed

  • The mapping screen redraws as soon as you change the delimiter, the header toggle or the encoding. Changing the delimiter used to leave the columns and preview split the old way, with a note that the file would be re-parsed in the next step, and toggling Skip first row (headers) did not touch the preview at all - so neither could be checked before moving on. All three now re-read the uploaded file on the spot and redraw the column choices and the preview, keeping every column you had already picked that still exists. Picking a saved template does the same with the template's own delimiter and header setting, so its mapping lands on columns split the way it expects. Contributed by @Saviq (#383)
  • Translations. Ukrainian is now included, the Polish and Russian translations asked for in #382 are in, and German and French have been updated from Weblate.

Fixed

  • Expenses another user splits with you count towards your balance with them. When another Nextcloud user split an expense with you it showed under Shared with me as outstanding, however your contact for that person still read "Settled", opening it listed no expenses, and the totals at the top of Shared Expenses left it out. Each split is stored against the person who made it, and a contact card only ever read the splits you had made yourself. A contact linked to a Nextcloud user now also counts what that user has split with you, from your side, so their "owes you £40" is your "you owe £40", and where you have both split expenses with each other the card shows what is left once one is taken off the other. Their splits are listed in the contact's details marked split by with their name, and the payments they record show in the settlement history as payments from you. Only the person who split an expense can settle it, so Settle All and Record Payment still only reach your own splits, and are greyed out when none of yours are open. The contact has to be linked to their Nextcloud account, the same as for Shared with me. Reported by @Bow-Wow75 (#390)
  • A paid one-time bill keeps its due date. Marking a one-time bill paid cleared its next due date, and a bill created before 2.49.0 - when one-time bills gained a real Due Date - had nothing else to show, so a paid invoice read "No due date" in the list and opened with an empty Due Date beside the old Due Day and Due Month fields. The date a one-time bill was due is now kept when it is paid and the list shows it; bills paid before this release get their date back from the day and month they still hold, in the year nearest to the payment. The form no longer offers Due Day and Due Month for a one-time bill: the Due Date is its whole schedule, and it has to be filled in (#333)
  • The Bills Calendar no longer shows a bill as due for months it has moved past, or for months before it existed. Since 2.49.0 a month was struck through only when a payment was recorded against it, so a bill marked paid with Don't create any transaction - a yearly premium in February - stayed green in September as if still outstanding. Every bill was also projected back to January whatever day it was created, so a bill added on 8 September read as owed for the eight months before it, and those months inflated the monthly totals. A month the bill has moved past without a recorded payment is now struck through with a dashed line and its tooltip says no payment was recorded, and nothing is drawn before the bill's creation date unless a start date says the schedule began earlier - a bill with nothing left in the year drops out of the table rather than sitting there as a row of blanks. A payment linked from before then still shows as a paid month (#333)
  • Tab-separated CSV files can be imported. The Tab delimiter option sent the two characters \t instead of a tab, which the CSV reader refuses, so choosing it made the import fail - and a tab-separated file that was detected correctly showed a blank delimiter and was then read with commas. The option now sends a real tab, and a template saved from the old option is read as a tab too (#383)
  • The import review shows how many transactions the file holds. Total Transactions on the review step always read 0, whatever the file contained. The account page has a transaction counter with the same element id, and it sits earlier in the page, so every update meant for the import summary went to that hidden counter instead
  • Clicking quickly through months on the Budget page no longer shows another month's figures. Every month change starts its own loads of the spending and the budget amounts, and an earlier load that finished last replaced the newer figures, so June could show May's spending or May's budgets. Only the most recent load is shown now, and a budget load that fails leaves the base budgets rather than another month's. Contributed by @almeidandres (#387)
  • The dashboard follows your budget start day. With a Budget start day set, the income, expenses, savings and budget-remaining figures at the top of the dashboard still covered the calendar month, and Budget Progress set to the current budget period used the budgets of the month the period started in - a period from 28 August to 27 September was measured against August's budgets. The top figures now cover the current budget period and show its dates under their labels, and both use the budgets of the month the Budget page lists that period under, the month its 15th falls in. Envelope carryover, which the dashboard only added for whole calendar months, now counts for the budget period too. The six-month charts stay on calendar months. Contributed by @almeidandres (#386)
  • Every budget surface agrees on which month is running when you have a budget start day. A period is listed under the month its 15th falls in, so with a start day of the 10th, 5 September is still in August's period, and with the 28th, 29 September is already in October's. Budget alerts, and the Budget Health tile built on them, still used the budgets of the calendar month, the Budget page opened on the calendar month, and turning on envelope budgeting started the envelope in the calendar month too. All of them now use the period running today. The recurring-bill fallback and the "(projected)" carryover mark also treat that period as the current one, so a period that has already ended no longer borrows today's recurring figures. A category's details follow suit: This month, the trend and the monthly chart count spending per budget period instead of per calendar month, and the chart ends with the period running today. The same goes for the dashboard's Monthly Comparison tile, which now compares the running period with the one before, and for This Month Income and This Month Expenses on an account's page, and both show the dates they cover.
  • The Monthly Comparison and Weekly Spending tiles show the real figures. Both tiles looked for income and expenses at the top of the summary they load, however the summary keeps them under its totals, so they showed zeros whatever was in the accounts. They read the totals now.
  • An overdrawn envelope shows as over budget. When the overspend carried into a month is larger than that month's budget, nothing is left to spend, but the Budget page showed the row as "No budget set" with no remaining figure, and the dashboard's Budget Progress tile left it out. Both now show it as over budget, with what it owes as the remaining amount, as the alerts and reports already did.
  • The budget adjustment notice names the right month everywhere. "Budgets adjusted from ..." and its confirmation dialog read the month as midnight UTC, so anywhere west of UTC they named the month before the one being adjusted
  • The Budget page shows the right period for a start day of the 15th everywhere. The month picker's date was read as midnight UTC, which is still the 14th anywhere west of UTC, so in the Americas a budget start day of the 15th showed each month the period before the one it should
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureYjtb6oj/6u2vw+lMxUwTdqaoecbNZKr8zgforTdMu2KAUE/D7PJQiWgI+mlRDXOoDp++CZJkbkDwEIknVcN6Zl5rCfUtSvMwdVk4IvOKwG7AW2qqDhnHDplkWBwPMEFNNJdQxPnjsDTNYxTEtGnOXwl2gxc9NMIFSD3c/DeCbxzLZd61DaVpjQohgLF7EKuVeLohtjay574dEpwpXH9z50nYJ0bO65jUTxrnZmLoafqKyQRu7tqurEWjlkhUcZRBALUnDzc1KwA+7kP1K1SwVoJkiuJwqcZNju3hsz8US7leYtvEnQL0Qsp+TnCHKiGibv/G5kVVwgvGZ0ThI20UeIHQOMKDZXj+d+CKuskMLpBJTUZPJaQyTeyIfFQ858nZlHHKC1mSRno6XPO1pYQCvHBzf+TIZBtF9U7N9svhxDJ2eXRAXJbp+BrtfuVrBEFkXE/4kilamlMPdGi1nG0EkcnKB9tVaqryzKWgWb97hfuBftBulfa+kaGjJAH9ZMwf9GioTzOCSdLf32lC+XFlDFxf93nTrzfNPB3dU+v/F1ZiItBx3WvAcXbYdg2lYa8y/A8liLqYXj19o9GqDbhNFVhCVQNvfFn0nfq/otpkY6sMH+brtN4O1HQfNqOOn6Lp09HRh299sfO8kuCaQDIGfeyNb4qNNJALi6bewhAaORk=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.51.0
Release Details
UpdatedSept. 11, 2026, 1:17 p.m.
Changelog

Added

  • Accounts can be deleted in bulk. Tick the accounts you want gone and delete them in one go, from either the tile or the list view. This existed for transactions and categories but never for accounts, and the gap only really bites in the one situation that produces dozens of them at once - an import with the wrong column mapped to Account, which creates one account per distinct value in that column. Deleting those one at a time also ran into the delete endpoint's rate limit of ten calls a minute, and an account that still holds transactions costs two of them, so the clean-up stalled about five accounts in. The whole selection now goes in a single request. The destructive half is kept a separate decision: the first confirmation removes only the accounts that are already empty, and anything still holding transactions is kept back and asked about in a second dialog that names those accounts and totals their transactions, so nothing with history in it is deleted by a click meant for an empty account. Closed accounts can be selected too (#381)
  • The import preview warns when a column mapping is about to create a pile of accounts. Mapping the wrong column to Account creates one account per distinct value in it, and mapping the date column gives you one account per day. The preview did list what it was about to create, but as a comma-separated line among the statistics, which reads as a note rather than as a reason to go back. Above five new accounts it is now a proper warning, sitting above the stats where the direction warnings already sit, because it answers the same question - whether to import at all. When most of the new account names parse as dates it says so outright and points at the account column mapping, rather than leaving you to work out afterwards why you have forty accounts (#381)
  • Bulk edit can add and remove tags. Tagging a run of transactions meant opening each one in turn: the bulk editor only ever touched fields stored on the transaction row itself, and a tag is not one of them. Tags... in the bulk bar now adds and removes tags across the whole selection at once, a cross-page select all matching selection included. The two lists are deliberately separate rather than one set of checkboxes - a tag you leave unchecked is not touched either way, so adding one tag to a hundred transactions cannot quietly strip the tags those transactions already carry. Adding a tag a transaction already has does nothing, and neither does removing one it does not have, so the same change can be re-run over an overlapping selection without anything happening twice. Category tags are offered too, grouped under the category they belong to. A tag set belongs to one category, so across a selection spanning several it can only reach part of what you picked - rather than leave you to find that out afterwards, each group says how far it reaches (applies to 12 of 50), only the categories actually in your selection are offered at all, and the confirmation names any tag that fell short instead of claiming it did more. Anything the tags cannot cover is counted underneath, including split transactions, which have no category of their own once split. Removing is not restricted the same way: a transaction re-categorised after it was tagged keeps the old tag, and gating removal would leave that tag impossible to clear in bulk. Requested by @joeftiger (#379)

Fixed

  • Names with an ampersand or a quote come out right in confirmations and messages. A category called "Food & Dining" was named in its own delete confirmation as "Food &amp; Dining", and the same went for anything carrying a quote or an angle bracket - an account, a contact, a saved report. Translated text has its inserted values escaped for HTML by default, which is right for the many places that text is used as markup and wrong for the two that show it literally: the confirmations and the little messages that slide in at the top right. Both now undo that escaping, so a name reads the way it was typed. This was true of the old browser confirmations too; it is simply visible now that the dialogs are the app's own (#381)
  • Editing a reconciled transaction in the list no longer asks twice. Changing the amount, date or account of a reconciled transaction directly in the table warns you first, and that warning could appear a second time straight after you had answered it - once because opening it moved the cursor out of the cell you were editing, and once more when the table redrew behind it. Answering once is now enough (#381)
  • Confirmations stop working after a few of them in a row. Every confirmation in the app was a browser dialog, and browsers offer to switch those off: after a handful in quick succession, Chrome and Firefox add a Prevent this page from creating additional dialogs checkbox to the box, and once it is ticked every later confirmation is answered no instantly without anything being drawn. From that moment the app looked broken rather than cautious - Delete did nothing whatsoever, no dialog, no error, no message, and nothing short of reloading the page brought it back. Clearing up a handful of accounts left behind by a mis-mapped import was more than enough to trigger it, which is how this came to light: two accounts deleted fine, and every delete button after that appeared dead. Confirmations, prompts and alerts are now drawn by the app itself, so there is nothing left for a browser to suppress. They take the keyboard - Enter confirms, Escape cancels, Tab stays inside the dialog - and a confirmation for something that deletes data now says so with a red button rather than a neutral OK. Reported by @missunderstoodninja (#381)
  • Tag pickers can be reached with the keyboard. Every tag checkbox in the app was hidden outright rather than just visually, which takes it out of the tab order and out of what a screen reader can announce - the coloured badge was the only way to set a tag, and only with a mouse. The checkboxes are now hidden visually but still focusable, and a badge shows a focus ring when you tab onto it. Nothing looks different with a mouse (#379)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureomDWujOwOWa9L4Xhc5Xr+YxrNL/X4KJz7URuQ3oocoKImK3zBZp5nUdl464tQpzylxC8sTBVsN9SqEm6KKKsPGkY92c4QnEzKWsuAM1fVZDgAqU/8oCyq6pSlRTrxxmHFN+PmioiScBnhErLMyrvPWkjVSpve7kIb5v1QRqf4nqJFuxeSOJAX1JgOM1tVME5Loxrm6SFZOsXaEXpKgqGF9SSuWXPAd1qGAO+MkugHo6zEjelkCYAWzkq2/tCZHOtIExuhBUk/BuSCMd9AaYhLb2iRJVT4FYcf14uRWCdfHmbRkNuGZNV63hbwNXwvIdP0KB9ZJ3QLV82V7LFyWY+s0VfssxJnKzjm8afeKo6zxq5SeRZmTVZDAxX7+aogVVWIqB18uwCI0dYWbMZQgR6PRqig0lf8E1j6KOiMRimZeHw0mkKFDV6ytcZEHgS8PuCih1ol9XaF+tNz4QJkKu/49A23APwrCUanew/Fs0BOhH7ydCNAl7sM5xpXKx4/4hoLJrA9tzTRwQUn1dmjbRk0QjThANrvqu+m0Gz97XWEwyyj3zHQyWYNy0Ozg1W1P01U/iFGH96Nd2emV2OO63z/AAmHrGWyBVBK73VlNx1guwaf8//c6XYbrbSJdF/smvbQcMa1MikuJq4DMpItW8vmvC+YOvUycpSHDkl7Hf+TC4=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.50.1
Release Details
UpdatedSept. 10, 2026, 1:21 a.m.
Changelog

Fixed

  • Save stops working on the transaction form after the split editor has been used. Turning Split across categories on and back off - or switching the type to Transfer with it on - hid the split rows but left them sitting inside the form. A hidden field is still checked by the browser, and an empty one it cannot put on screen is one it will not report either: the form simply refused to submit, with no message, no request and no error in the console, for every transaction from then on until the page was reloaded. Firefox and Chrome at least log something; Safari says nothing at all. Putting the split editor away now empties it, and a split amount is no longer a field the browser polices - an incomplete split was already caught on save, and says what is wrong in a way you can actually see. Reported by @SGiersch (#380)
  • Adding a transaction from an account preselects that account. The Add Transaction button on an account's page was reading the account being viewed from the wrong object, so it always came through empty and the picker opened blank - on the one screen where there is no question which account you meant (#380)
  • Transfer matching finds the other half in a shared account. A transfer between an account you own and one your partner has shared with you could not be matched: the search for the opposite leg only ever looked at rows you own, and a transaction in a shared account belongs to that account's owner, so the match dialog reported nothing to match and the bulk scan skipped the pair entirely. Linking the two was already allowed - it was only finding them that was not. The match dialog, the bulk scan and bulk linking now search every account you can write to, shared ones included. Accounts shared with you read-only are left out, because linking writes to both legs and a candidate you cannot write to could never have been linked anyway. Reported by @lexiconzero (#378)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignaturebuZC6LMTRyNL1vila15DJJFe8dDZf/j3oCjxjP7KvrqebYszACpNqevFzP0b+HFTrgRwXMF7+ZnHeZDVV4l4KuZgfeI78fVJnNhQQeYNYqcIRiZZTKoqfm3zpU0OzCqWchvR7Mgslc6IIuBGjmM5EAx53O05t69k00ylo5G2YLfeMtyeg9hlqRERfuE5aMa7w5YhvBcskq9gIbtuGRU5ZfK++QikEJxZS9Quy9H7iDuuRBrPgumyJyURxaENIodcPhTuHjC/95LQWciAI6bj562mWuNglVdBEC+9+oNRN12vyMHerogSRRNpfqKwMb93Yzhlw3gkjkD9DsZvVuzuek98QAxEhTDZeEcZ5o4aAB2m+mRAmx77mj0OrfvLcyL7ekKUCr6G0/xJkU3XtEG3WDF20OupAcXsNbYBduRIoCvozx/pEGOkIipe4oQOlh6POT7MkXWfxBGJaG3N8SzmUqihyNgx8KuoxodhHsw09O8ncNlmkiBEGNn0+Hx/UXiijxE4ucigWPVSmUP6SU6F8dpjU2EU/jqbIdxPiyz3r/tt/vbVXDw41c7wd5nnkHyubljlBW6KL1uREbhrl7fdRCgjzJkPKA+fa4tdpa83af3llfzKcnyO6TXQ/nPL+xI0eLwRlXUIp4eW9xIeY0sZ3bOwjMdOemiR1Q9lGSloAZc=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.50.0
Release Details
UpdatedSept. 5, 2026, 11:16 p.m.
Changelog

Added

  • Budget alerts and forecast warnings actually notify you now. The two switches at the top of Settings → Notifications have been there since the first release and never did anything - nothing read them, and the app had no such notification to send, so the only place a budget alert ever appeared was a dashboard card you had to go and look at. Budget Alerts now sends a notification the first time a category reaches your alert threshold (80% by default) in a budget period, and a second one if that category goes on to exceed its budget. That is the most it will send per category per period, so the nightly check cannot turn into nightly noise; a category that drops back under its threshold is forgotten, so it can alert again if it climbs back. Forecast Warnings sends at most one notification a month when the six-month forecast projects your combined balance below zero, naming the month it happens and the figure it falls to. Both default to on and are switched off from those same two checkboxes

Fixed

  • The Bills Calendar never shows an occurrence as paid while the bill still says it is due. 2.49.0 placed each payment on the nearest due date, and a bill paid twice at the end of a month - or paid a few days before the next cycle - had the extra payment land on the following occurrence, so the calendar struck through September while the Bills page showed the same occurrence as upcoming. The bill already knows which occurrences are done: marking one paid moves its next due date on a cycle, so everything before that date is closed and everything from it on is still owed. Payments are now only ever placed on closed occurrences; a second payment in a month shows as that month's larger amount rather than as a month that was never paid. Reported within the hour by @TerjeTM (#375)
  • One-time bills with the same name share one calendar row. Now that paid one-time bills stay in the year's calendar, a garage that sent three invoices appeared three times, one cell each. They are folded into one row with a cell per invoice, each keeping its own amount, the way recurring bills already read (#375)
  • Exported reports come out in your language. The PDF and CSV a report exports to were written with English labels whatever language Nextcloud was set to - the exporter never asked the translator, so a German user got Total Income and Account Breakdown in an otherwise German app. Every label in the report, Year over Year and Bills Calendar exports now goes through the same translations the screen uses, month names included, and the monthly scheduled report is produced in its recipient's language rather than the server's. Labels that already exist on screen are translated straight away; the few headings that only ever appeared in the exports are new to translators and fill in as the translations arrive (#377)
  • A monthly digest can report unusual spending. Unusual-spending detection judges a month that is still in progress, so it stays quiet before the 10th - pro-rating the rent on the 2nd would flag it every time. The monthly digest is sent on the 1st, so its unusual-spending section was empty every single time it went out, and the weekly digest only filled it in on the weeks that happened to start after the 10th. The digest now asks about the period it is actually reporting on: a finished week or month, compared against the same six-month typical figure scaled to that period's length, with no early-month rule to apply because a finished period is not a partial one. That also settles a mismatch in what the digest was telling you - it reported this month's spending so far inside a summary of last week or month, and now reports the period it covers
  • The digest notification says how many categories are spending unusually. The count was being attached to the notification and then never shown, so a digest that had found something looked exactly like one that had not
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignaturekDEMKCHGsB6XHpH0lnwbdVN2PlHEz5a/0JU2HlikRqJOIHvusKOCEPzyqSYRH/8U5+wPMQcWAi6Zlb8pcjgNh3CwemL7dVDMnrV7w65ZbG5xhBtzlziNuhs1FCJzqYQshdgCJzd2xQFJYJOqTqFXqdFQK6US+0Tgm47K6ROYrFUL/9JEhdaoH3kUz8PAP2WOq+IYdRfeUBlXUslF6pbtDWQ9g6gVSTUDF1Kj0V6UU+/M+GqrHY4flUN5Q9k6lGRLri8eBRO2woA5jdLWxJ5tyonb6F9e65yjlOIYbC3QV+TaHwH5MLbj9lmkrbAjFUMaaSWQ0VuEaj8vupo46ebxm2V4dGN4oisWd0VKRmlpGpGdDLIDYT1aZwIrVIRWPIicpqiFkLdOOo+YOCIl3XHNu6lPLxdR/jNcEDORoRJq6yPVtWZTroXgXM3TznOcNLXKotj7v/o1MPxId8uMms/wiu8PRksNIlFeLnmV8czhjhI+ZLElYqwCyMJjCUZUUB3ebdvRtbDqvuJBwuYp36Oi5UKfBTXqYzbAAO8qr4nAH/gdQsA8X+YquAMuux31ilINMpOvFX71Yf7/E15pqYZfvEQS0hq1hV4xIcgVAreEOHbIIFGcVB5WdrvYNeNP366rB5WsKXUBDGFrTEIL5vtj8OHgLqVYoEgBZNg/RL9j/Fc=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.49.0
Release Details
UpdatedSept. 3, 2026, 11:53 p.m.
Changelog

Added

  • A one-time bill can be dated in the past. A bill only ever stored a day and a month, and every date it worked out from them was rolled forward past today - right for a schedule, useless for an invoice from last month, which became due next year the moment you saved it, and jumped again if you tried to edit it back. For one-time bills the schedule fields now give way to a single Due Date, taken literally: an August invoice entered in September is due in August, shows as overdue until you mark it paid, and lands in August on the Bills Calendar. The placeholder transaction a new bill pre-creates is always a scheduled one, whatever its date: with a past date it was being written as a cleared payment, booking the money as spent for a bill nobody had paid (#375)

Fixed

  • The import's fallback account is reachable when the file has its own account column. A blank account cell now falls back to the account you choose - but the select that chooses it was hidden the moment an Account column was mapped, so the fallback could never be set from the wizard and those rows still failed with "no account was chosen". On the preview step the select now stays, relabelled Account for rows without one, and is optional: leave it empty and such rows are skipped with that reason listed (#333)
  • On SQLite, a failed save now gets the unfinished-update hint too. The hint recognised MySQL's and PostgreSQL's error codes and SQLite's "no such column", but SQLite words a failed INSERT as table X has no column named Y - which is exactly the failed save the hint exists for - and that slipped through, leaving the bare SQL. Found by running the check in a browser against a dropped column (#333)
  • The Bills Calendar shows what was actually paid. Paid months were guessed in the browser from the bill's last payment date - every month up to it counted as paid - so a bill you started paying in September showed January to August paid too, and a one-time bill fell out of the calendar the moment paying it deactivated it. The cells now come from the payments recorded against each bill: a month with a payment is paid and shows the amount that actually went out, months still to come show the expected amount, and the monthly totals follow suit. A payment made a few days late counts for the month it was due, a payment with no scheduled month near it appears as an extra paid month rather than vanishing, and a bill that is inactive now but was paid this year stays in the year's picture (#375)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureUTnFglOyY//mXGi7y/LDtH4919NkTXqAr1p4PsIxsYx5fusaiKeFTWxlcugWVBcXNirEhMLHMF/hTpCv05X/jQ0yMlB2LW8Q4bUwppTjyg44BEEACZuQWr1FTs7KhmlbU/nCDKTIuC+Uk458xB8kdIiggZoDRqb4JoINSJ2tXL5KeNQgeyyq8hqOm5pwUBxlJRgx61f8EPP4+JWoAY3DWZUGJvpmk8i0VrNtxOvHT2BTdfMxLauNboowdmko+GQv3ZLEoAwP0D1UI4pjcwxcOQdAkQuM4wXwN6tywUjdmzPTmYSTxEMO1XAnc1v22KUA7bQxkHYcg5viQMbtAA459AsY2ImPJdxGyt0PbszsxOgomnZ6BHQdohkI3zbgX2XRtRc0RycVyzkDtnuk1Nr4k8nEyhimtNea3nOZ5S3yQhrC7CPqpeoXqc/gzl5b2QrO1bC07TxUIMs9knOBR/SMWsXcSq2pzYY9FCW9+XsUVQ2XKi8CQmYiAi+rO8/RNLCkyz8OHkQuMtpdmv1YI7INkGwTr0wU0TVw1bC9ozc2GWsDeJGSYJBDn43uQQ+dyCr8xMhzkURYqjcvMYsgPUjTMY2AB0mFYow2XlRK67AE9hXrLSK25TIVHBH1JMkDx65jmH5jGQwmG8vbHjIoEygsJBRvy0hmb8uK7Pq1u5OyqnI=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.48.0
Release Details
UpdatedSept. 3, 2026, 9:09 p.m.
Changelog

Added

  • Tags can be hidden once they have served their purpose. A tag for a trip you have taken or a project that has finished keeps its history, but has no business in the picker for every new transaction — and deleting it would strip it from everything it is on. Editing a tag, on the Tags page for a global tag or in the category view for a tag-set tag, now offers a Hidden checkbox. A hidden tag is no longer offered when tagging a new transaction, bill, transfer or rule action, or when linking a savings goal, and it shows dimmed with a Hidden label where tags are managed so it can be found and unhidden. Everything that already carries the tag keeps it: the transactions stay tagged, the transaction filter and reports still list it, and a hidden tag already on the item being edited stays in its form, checked, so editing something else does not strip it (#373)
  • An account can be closed. An old bank account you no longer hold can be marked closed from the Advanced section of its edit dialog. It keeps every transaction and still counts in reports, the dashboard and net worth, but it no longer appears in any picker for new activity — the transaction and quick-add forms, transfers, bills, recurring income, imports, import rules, bank-sync mappings, savings goals and pension contributions. Pickers that filter history keep listing it, so its past stays reachable, and opening an old transaction that sits in a closed account keeps that account selected, labelled (closed). The accounts page lists closed accounts in a collapsed section of their own, and the account's page shows a Closed badge and drops the reconcile and card-payment actions. Closing is refused, with the reason shown in the form, while the balance is not zero, while any transaction is dated after today, or while an active bill, transfer, recurring income, pension contribution, bank-sync mapping or import rule still pays into or out of the account — the message names each one so it can be reassigned first. The standalone quick-add page and the import's account auto-matching skip closed accounts too, the interest accrual job leaves them alone, and the public API's GET /accounts gains an additive closed field so a capture client can filter on it (#372)

Fixed

  • Restoring a backup keeps the "exclude from reports" flag. The restore rebuilt each account field by field and never copied the flag, so every restore since the option was added put excluded accounts straight back into every total, silently. The new closed flag is restored the same way (#372)
  • The account form shows the real reason when an edit is refused. A refused account update always came back as "Failed to update account", hiding the specific message — including the reload notice a stale page gets when saving a debt. Refusals that carry a reason now reach the form verbatim (#372)
  • The unfinished-update warning now checks the database itself, and names the exact fix. It used to compare the migration files on disk with the list Nextcloud had recorded as run, and that misses both ways an install can actually be broken: a migration recorded as applied whose column is nevertheless not there, and a migration file that never reached the server. The instance that prompted this had run the recommended occ app:disable && occ app:enable to the letter and still could not save a bill, because that only re-runs what is unrecorded. The check now reads the live schema and compares it with every column the app writes, lists what is missing by table and column, and - for a change that is recorded but absent - names the precise occ migrations:execute budget <version> to re-run it, with the debug toggle those commands need. A column no migration on the server adds is called out as an incomplete install instead. The warning appears on the app's pages, in the admin overview, and in the error a failed save shows, where it now bypasses the "already verified" shortcut because a save just failed. Not being able to read the schema warns about nothing, as before (#333)
  • Repair Data no longer deletes both halves of a duplicate pair, and no longer orphans what hangs off a transaction. Its duplicate cleanup removed rows straight from the database, so any splits, tags, attachments and shared-expense records on a deleted transaction were left behind with nothing to join back to - invisible, and beyond the reach of every cleanup the app has, factory reset included. It also had three detectors flagging the same rows, each free to pick a different keeper: two placeholders written by the same payment share a creation time, so which one counted as "the real payment" came down to sort order, and a pair flagged both ways had both halves deleted - the payment removed along with its duplicate. Deletions now go through the same cascade every other part of the app uses, and a row another finding is keeping is never deleted; anything left ambiguous is simply left for a second run
  • Reconciling an account no longer means ticking your way through the whole ledger. A first reconciliation has nothing earlier to anchor on, so it starts from the account's opening balance - which means every transaction since has to be ticked before the difference reaches zero. On a real account that was 860 rows at 25 to a page, against an unfiltered list that still included scheduled rows dated years ahead. Starting a session now narrows the list to the account, to transactions dated on or before the statement date, and to rows not already reconciled - those are inside the starting balance already, so ticking one would have counted it twice - and the bar offers Tick all N transactions up to \<date> to do the whole statement in one click, leaving you to untick what your bank has not taken yet. Nothing is written to the transactions until Finish, so it is a starting point to correct from. The Create adjustment button no longer appears until something has been ticked, since before that the "difference" is simply the account's entire history, and the starting balance now explains in its tooltip where its number came from. Leaving a session hands the list back unfiltered (#374)
  • Marking a bill paid without recording a transaction no longer leaves it looking due. Choosing Don't create any transaction or linking one that already existed left the pre-created row for the occurrence you had just paid sitting in the ledger, still scheduled - so the bill went on showing as upcoming - and at the same time suppressed the row for the next occurrence, so the forecast lost it. One flag was answering two different questions. Recording the payment is now about this payment alone, and whether the next occurrence is pre-created is the bill's own Create future transaction setting, which is how skipping an occurrence and editing a bill have always read it. Existing leftovers clear themselves the next time that bill is marked paid. The dialog also now says that the bill moves on to its next due date whichever option you pick (#376)
  • Rows with an empty account column are imported instead of thrown away. A file that carries its own account column had every row with that cell left blank dropped, even though the import screen had already been told which account the file belongs to - one reporter lost 14 of 27 rows that way, in silence, and only noticed because the balance was wrong. A blank cell now falls back to the account chosen for the import. A cell that names an account which cannot be resolved is still reported rather than guessed at, since that one would misfile the row (#333)
  • The importer no longer invents an account out of a file's header row. With "first row is a header" switched off, the header line is read as data - and because it holds the column titles, its account cell held the word "Account:", which the importer duly created as a real account in dollars. Only a row that would import as a transaction can name an account now, so a header line is ignored the same way the import itself ignores it. New accounts the importer creates also take your default currency rather than always US dollars (#333)
  • The import tells you why rows failed instead of pointing at the server log. A partly failed import said "%n rows could not be imported - check the server log for details" and put the actual reasons in the browser console, where nobody looks - and on an instance whose logging is misconfigured, or where the admin cannot read the log at all, there was nowhere left to find out. The reasons now open in a window as soon as the import finishes, one line per reason with the rows it applies to, so fourteen rows failing the same way read as one problem rather than fourteen (#333)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignaturewDpgdodKiAH0BJNKoHpu1H3xardvLeUHU4/1s4cGzs/N9ZfELYEXGP9FnFBY0fSJWBscyElRGGL3vR58ISgUep5I5P9aX+JA/uHMtjeyafCVQGj/YNbhZtz/hKtNb2zM+erfMrzq6pLkleaPsCFoe5tEt3ufMZKASjvCpU1R3j4Ec6bDjiom1fk90CImC26ZItTfc5Vu/dxGtACVerJ0IvZzQPvR1J2FY1xDlqCeeuapHMmB/z3V5Px9JQU0BC+nM5qF335DutR30cz0BP7ghkp7juBWtj5fBMe2bRYmqu+AOVdcbniqHtHvktQmMjv77gQzTupn8tfNtOSf4qLK5YbiqOfMXnIIai5qmrgJE1tsO17hPQmpxol9owkPC2gRa7TwHsS09K3cMrEjpKNORD5hkFlc2m9eQR2xRAu68dWQwXkhbnmu42PcpwqQsKdLhDbwBWRJHyFqsMSds4mjYhUN5+wvQbWSsQTXoO8Z9InCntaQsDxR1rTX6CWxAy0gHx+ZD0hGv0ttqWbJzEiOPrlYwLbDvserRhlotDAahPDxsdV3PEwj28+Jtv04Ie0vE/k9n56NsAFY3e8PGjJE156W6+qurFoiXi2OcJynyAmsOsoj8DTLKnMsVMVtlw16lNZZ6uAANdDUrG1QOE8F065BkQxwg69PR3qHL3jfsgY=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.47.0
Release Details
UpdatedAug. 29, 2026, 9:47 p.m.
Changelog

Added

  • The import screen can be told which character encoding a statement uses. Some files simply cannot be identified from their contents: every single-byte encoding accepts every possible byte, so an undeclared Cyrillic export is indistinguishable from a Western European one and any automatic answer is a guess. The mapping step now carries a Character Encoding picker, listing Western European, Central European, Cyrillic, Greek, Turkish, Hebrew, Japanese, Chinese and Korean options alongside Unicode, with the detected encoding named in the hint beneath it. It sits directly above the preview, so a wrong guess is visible as mojibake and correcting it redraws the columns and preview immediately. Uploads are now kept exactly as they arrived rather than converted on the way in, which is what makes the choice reversible — previously the original bytes were discarded at upload and a bad guess could not be undone (#371)

Fixed

  • A statement that isn't UTF-8 is no longer read as Latin-1 regardless. Files that aren't UTF-8 were run through a list of fallback encodings, but the first entry accepts every possible byte, so it always matched and the rest were never reached — every such upload was decoded as Latin-1 whatever it actually was, turning a Cyrillic statement into Ïÿò¸ðî÷êà and a Japanese one into ûÀ;út;àz, with no error to say anything had gone wrong. A file that declares its own encoding is now believed: OFX states it in its header and camt XML in its declaration. Anything undeclared falls back to Windows-1252 rather than ISO-8859-1 — the two agree except over the range holding the curly quotes, dashes and euro signs statements are full of. Converted XML also has its declaration corrected to match its new contents, which previously made the parser decode the file a second time and produce exactly the corruption the conversion was there to prevent. Note that an undeclared file in a non-Western encoding still can't be identified from its bytes alone — single-byte encodings are indistinguishable, and testing for the multi-byte ones proved worse than not trying, since ordinary German, Spanish and French text validates cleanly as GB18030. That case needs an encoding picker on the import screen (#371)
  • Statements written in your own language import again. A CSV, OFX or QIF holding a decent amount of non-ASCII text was refused outright as "File appears to be binary" — which took in Cyrillic, Greek, Hebrew, Arabic and CJK statements wholesale, and caught plain accented Latin too, so a French or Spanish export could trip it as easily as a Russian one. The binary check allowed the first byte of a multi-byte UTF-8 character but not the bytes that follow it, and every non-ASCII character has at least one, so roughly half the bytes of a Cyrillic file were counted as unprintable against a 10% limit. High bytes are simply what non-English text looks like, in UTF-8 and in the older 8-bit encodings banks still export, so they no longer count against a file at all; genuine binaries are caught by their null bytes and control characters, which text does not contain. Reported with a diagnosis and a fix by @ba1amut (#369)
  • "Auto-pay when due" can be switched on while editing a bill. The checkbox needs a pay-from account, and the only thing that worked that out hung off the account dropdown's own change event — but opening a bill fills that dropdown from code, which fires no such event. So every existing bill opened with auto-pay greyed out, however long it had had an account, and the only way to reach the checkbox was to re-pick the account by hand. Creating a bill was unaffected, which is why it went unnoticed. The state is now recomputed whenever the form opens (#370)
  • Editing a bill shared with you no longer strips its category and pay-from account. Sharing is granted per type, so a bill can be shared while the account it pays from is not — and both dropdowns can only list what you are allowed to see. The form silently fell back to "No specific account", and saving submitted that as no account, wiping the setting off the owner's bill; the same went for an unshared category. The real values now stay selected, shown as Unavailable (not shared with you) so it is clear why they cannot be changed, and they survive the save untouched. Auto-pay is also refused server-side when a bill would be left switched on with nothing to pay from — a pairing the create path has always rejected (#370)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignaturexHUL+LrtKQmEHZ8YQwsy+xFaIqzNZrPxOFdHD44Th6v2oSFX5rCCI2kmScHUejaVOt1t0nLiJ2qf5ZSRVvOmPPeeinPhoqGhwYlP0Nkgt8Rb0x1zPZTJj63Na8ESocx7CpajZTDxKc8pAFrQJ+H03K4UDks+/1F0qFF2NYa1soV6+c+fIuMPDaYC+DjO3aeWaJabhTUgUymMmqHLxqlhAyw+a8LJ2ABwYyT8P/rmIQ267T72D8ng0f8/ubS4mvfICaoAbtMA8H5Rnn7/gcPMDv1nJyTv97ShefnigmiykqBSWJsJQE8Ax/RYNfXWJ3Gl9uRxzXigxKYwpGtWMFnE9G2JN/eOh5oG042V5wn1QI0QcfWG2QFilp5uOD6ZVTfyPG+um2Y0FQLFe4PJnxyYpnrXmWglFFMyEVCVa0a7+AJmb7DVfjz/9vhBewTYCJ/j9XDlw8Efu28ZYWtsgZ5vZIlH4a90WalHLWHprUsNLDrUSyl+WRLTWDYDfEviRHJBCrrcz34Zyo8An0+sM9ccQalvH78w4X9PDIL5pMS90MHgyYrXVGyMPqSG65FliBn0qku7pP8wCqUabT9Ac3ofyztTlj0dy+tHyuu0OLPb+FxaLUoCgw5PaOSNSOXgDw8amDnleLNrZjvHIEsoYCS2jXtxU0rrTbmFXi4djM4jyTQ=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.46.0
Release Details
UpdatedAug. 29, 2026, 2:08 a.m.
Changelog

Added

  • A Money Flow diagram shows where the money went. Reports gains a Money Flow type that draws the period's cash as a flow diagram: income categories stream into a central Cash Flow node, which fans out into your expense categories and their subcategories, with what's left shown as a Surplus band — or a Deficit feeding in when spending exceeded income. Amounts label every node, category colors carry through, and the usual period and shared-account filters apply (#366)

Fixed

  • Bills and income shared with you can be opened again. Opening a bill your partner created failed with "Failed to load bill", and so did every action on it: editing, deleting, marking it paid or unpaid, skipping a payment, and the Record transaction repair. Sharing grants visibility, not identity, but each of those looked the bill up as the person clicking rather than as its owner, so the app approved the action and then could not find the bill to carry it out (a DoesNotExistException in the log). Bill actions now run against the bill's owner, so a shared bill behaves like one of your own, and Mark Unpaid is offered on shared bills for the first time. Shared recurring income had the identical fault and is fixed with it, and its Mark received action — which had no permission check at all, only the scoping that made it fail — now refuses a read-only share properly (#368)
  • A transfer between accounts shared with you now completes. Creating a transfer in an account owned by someone else booked both sides and then failed to join them, leaving two unconnected transactions behind every attempt and putting the raw database query on screen as the error message. Both rows belong to the account's owner, while the linking step went looking for them as the person clicking. Linking, unlinking and Create and link now work across shared accounts, and a transaction you cannot reach reports itself as not found — which also means it reaches the log, where this failure left no trace at all (#368)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
Signaturex0J8AUUfQbAJljP4bb8goctxFgu6woboHqgqhSLiZLzSNh4/bgeYYYsy4ubudGRmEAdnJZqL9XcqPKKaaVIxVXVRFVCS24iGpCdqXhCW0MMvoROv7VMao+dHMrfPhungZxdm+nKurDuI2drTpZLmbckIj6+PnjLP0Z6M+a/P7wRw/3gtdHcf1KoNmRGNIlqUUolPhYJJFQbhgsf8yg/nzDMjm0OKXYvOKWSI+GR1HFQoNSLVx9TPk2zrBOT/ARpvDEStnWWBZxhn2shkEVFNE1ntupx4AmkerIySit3CB5j4H7imaHsIYwPHDhL+MEj9afFllpMnogByvQ+nHCvJ3v7PeuNYGgQTxMvoVKpvtPDyo2610eVQDQlK8UEzmOdimk7shlkllXiE/ZEIaeFINp17VuQbYlTwuuZlNfTendUZirhPFK4xR3AL6cpTxJHq/Xc/npPYAYk8wPyYseNnFL5A3/d2UXiT/m57GQiIMkTMrayR6kYmYjGYT2EAVSRjhA0wESnCJb6jVMc6YTcBVQ3uFXnA5gR1hdulx1Qj2lRhJpBSCcXBCl/4QHDv4OIhk4Is5DWUxcw91iuaBhMCpoJLwU+kkuaibIrsiV2L3np7EeZzPtxOsRG4GyCZRyvTvCVO7HVHu///wPi1sfMH4R05Ri0AUfbqdpqPrE70mG0=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.45.0
Release Details
UpdatedAug. 29, 2026, 12:59 a.m.
Changelog

Added

  • Bi-weekly schedules can be anchored to a date. Bi-weekly income, bills and transfers used to lock onto whichever week you happened to create them in — pick "every other Friday" and the app silently decided which Friday from the creation date, with no way to say "no, the other week" (#363). Transfers were worse off still: the form only offered a day-of-month field, which means nothing to a bi-weekly schedule (#364). Income now takes a First payment date for weekly and bi-weekly frequencies, and the transfer form gains the same start-date field bills have had — the date pins both the weekday and the week, and every occurrence lands a clean 14 (or 7) days from it, whether the date you give is in the past or the future. While a start date is set the weekday field follows it and locks, so the form cannot claim a different day than the schedule runs on. Note for existing bills and transfers: a start date you set before this release only delayed the first occurrence; from now on it anchors the schedule, so a weekly or bi-weekly bill with a start date will settle onto that date's weekday and week
  • Bills can be marked unpaid. Marking a bill paid by mistake was final: the Undo button lived in a ten-second toast, and once it was gone nothing could revert the paid state — deleting the payment transaction left the bill still claiming to be paid (#365). Every payment now stores what it changed, so a Mark Unpaid action on the bill reverts the most recent one properly: the due date rolls back, a one-time bill comes back to life instead of staying vanished, a statement-amount bill gets its exact amount back (which cannot be recomputed after the fact), and the payment transactions are cleaned up — including when you already deleted one of them yourself. Auto-paid and import-matched bills get the same revert, which the toast never offered them — a payment that was linked to an imported transaction unlinks it rather than deleting money that genuinely left your bank. Recurring transfers can be reverted too, from the Transfers view. The stored revert applies to the most recent payment only, and editing the bill's amount or schedule discards it — reverting would otherwise restore values from before your edit

  • CSV files without a header row can be imported. The importer always treated the first row as a header and silently ate it — a headerless export lost its first transaction with no way to say otherwise. A First row is a header toggle (on by default, matching the old behaviour) now controls it, columns are matched by position, and blank or duplicate header cells get translated "Column N" placeholders in the mapping dropdowns instead of untranslated internal names. Saved templates keep working: they store your file's real header names where they exist, so they survive language changes and column reordering. Templates saved from files with duplicate blank headers ("Column N (2)") need their columns re-picked once. Contributed by @Saviq (#367)

  • The database-updates warning reaches the admin overview. The check that detects the app's own migrations never having run (the "Unknown column" trap, #333) now registers as a proper Nextcloud setup check, so it appears under Settings > Administration > Overview and in occ setupchecks — visible to the admin who can actually run the fix, not just to whoever next opens the app

Fixed

  • A category drill-down into subcategories now says so. Opening a parent category's transactions (from Category Details or a chart slice) applies the parent plus its subcategories, but the filter panel could only display the parent — and picking the parent to narrow down to just it did nothing. The category dropdown now shows a combined entry like "Groceries + 2 subcategories" for the applied scope, and choosing the plain parent genuinely narrows to it (#361)
  • The bills list stops fetching every dead bill. Keeping paid one-time bills reachable for Mark Unpaid meant fetching the whole bill history and discarding most of it in the browser. The server now returns active bills plus the revertible ones directly, so the payload stays small however old the install (#365)
  • A category's count badge and its panel agree on damaged rows. A row carrying both its own category and split parts (the old bulk-edit damage) was excluded from the tree's count badge but still listed in the Category Details panel — off by one on the same screen. The panel now applies the same rule; Repair Data remains the way to fix the rows themselves (#360)
  • The split flag's grey states are resolved once and for all. Two damaged states have haunted long-lived databases: rows from before the flag existed (held NULL), and rows whose restore claimed they were split while the parts never made it into the old backups (#351). A one-time update resolves every such row from the parts table — the single source of truth — and restores now do the same, so the states cannot return. This fixes three real casualties: rule runs categorize legacy transactions again (they had started skipping every pre-2026 row while reporting success), assigning a category to a damaged row now sticks instead of silently vanishing while the row stayed listed as uncategorized forever, and the Uncategorized filter no longer offers up split parents whose categorisation is exactly how such rows were created (#360)
  • Find Duplicates no longer loses a next-day duplicate at a group boundary. Groups anchor on their first transaction so distinct purchases cannot chain together — but a pair one day apart could straddle two groups and the second copy went unreported entirely. Rows near the boundary are now carried into the next group, so every pair within the window is reported together and the no-chaining rule still holds (#333)
  • A savings goal that has gone backwards shows an empty bar, not a full one. The Savings view's goal list was the last progress bar without the negative clamp the others got in v2.44.2 — withdrawals exceeding deposits painted the bar completely full
  • The Category Trends tile sticks to expense categories. It relied on a side effect of the old one-direction totals to keep income categories out; with netted figures an income category could slip into the spending list. It now filters by category type explicitly
  • The database-updates warning can no longer be silenced by a mid-deploy race. If the check ran at the exact moment app files were being replaced, a failed directory read followed by a successful one within the same page load could record the version as verified while updates were genuinely pending — permanently hiding the banner on exactly the instance it exists for. The verified marker and the pending list now come from the same scan
  • Editing a bi-weekly bill no longer silently shifts which week it falls in. The consistency check that runs on every edit recomputed the due date "from today", so changing an amount or a note in the off week flipped the schedule's parity — the bill quietly moved a week. With a start date set, the schedule now recomputes from its anchor, and an unrelated edit can never move it (#363, #364)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureV/r+TeR/H5y0TiUgo9apV0nHrv4yLWR3o2yHxeSCrwBr87AyJBO6EphcfUm/aNNDYHbJfh2Nk4ghsMvljrNWPCgMFZdwynngNS3IbrSFauamMsnuvkxDcO5h+R5aAIyBfyog9idiDesDMJF2B1dDbe3COOlxDq5i8xiiP+BGqLpoeOYZKT2dpqoaYB9j16sGk5BSE07vSFnF8kz2PGcpgExtfEqMMVCDRGQUvU02KgLqNb6oFx0abf5NhRGTpNZPMyOMwWH0CVTATrZj7r9LBp8+HQqHUjCRqPTwsYbAVBZZKYwyrtU3Wd/4VaSpKW2bMS7OWA/663hc74b0Rt/QTy0brPK2oiQyM6PisiwlZHAz6nuQWRDUiyezWVS9yLBiVDavZxby7XJAIrb49a8dSESUj7/7eRaO9xAb21oULrp39o0d0GKWBxFf2fuV/uBJ/tQh1pgj7n5PHQ01kZ3Dy1znPGH//sIfsw5nBLeKQQGZvcp4ell+s19FJr2SoKe+HgY8Wo/eCobVpai8GbpeA1HsNc7ixuKIPdxpAsY7X/mNg92GEndFExIDBkUgQfbPYd+LkmjlJdtXqluxB24WdVIVdKDJakxk860CHTUo+k7UgVroJUffjXXwXvFKQCWZG8f/5Tt4eh3QpRfaqQGWpAjQ0lw/AURkUdA0FlN4ELo=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.44.2
Release Details
UpdatedAug. 28, 2026, 3:19 p.m.
Changelog

Fixed

  • The Budget page's Spent really does net refunds now. v2.44.0 said a refund comes off what you have spent, and it did — on the budget report, the dashboard tiles, the alerts and the digest. The Budget page itself reads a different query, which kept the old one-direction sum, so the very page the issue was reported against still showed $216.90 where Category Details showed $58.29. That query now nets the same way as everywhere else. A month whose refunds exceed its spending shows the true negative figure instead of being flipped into looking like money spent, and its progress bar sits empty rather than painting full — on the dashboard's Budget Progress tile and the savings-goal tiles too, where a negative used to render as a completely full bar. Changing a category's budget period also refreshes its row with the right direction and the selected month, instead of flipping an income category's Spent to a large negative until the next reload (#361)
  • "View All Transactions" on a category lists the transactions its figures are built from. The button quietly filtered to money-out only (money-in for income categories), so an expense category's refunds were missing from the very list the netted figures above it summarise — the panel said $58.29 and the list it opened could only add up to $216.90. It also ignored the panel's period and account selection, listing everything ever recorded. It now applies no direction filter and opens scoped to the same date window and account the panel is showing (#361)
  • The transaction filters panel shows the filters that are actually applied. Arriving at the Transactions view through a category's "View All Transactions" or a chart drill-down replaced the applied filters but left the panel's controls showing whatever they held before, so the list and the dropdowns above it disagreed — and because any change to one control re-reads all of them, a stale control could silently re-apply an old filter. The panel now rewrites every control whenever the filters are set for you, clearing the ones that no longer apply (#361)
  • The last places that ignored split transactions now count them. A split carries its categories on its individual parts, and five surfaces were still reading the transaction's own category, which a split never has. Year over Year compared a year of split receipts against a year that predated splitting and called the difference a collapse. The Forecast's category trends dropped every split into Uncategorized and showed nothing against the categories the money actually went to. The count beside each category on the Categories page read 0 for a category funded entirely by splits, next to a panel listing its transactions. Find Duplicates showed a dash where the category belonged. And a CSV export with no category filter left the Category cell empty on exactly the transactions someone had taken the trouble to itemise -- it now names them, and a category is named once however many parts of the receipt went to it (#360)
  • Find Duplicates no longer chains separate purchases into one giant "duplicate" group. Each candidate was compared against the previous row added to the group rather than the first, so five identical-amount purchases a few days apart -- a regular coffee order, a repeated fare -- linked end to end into a single group spanning far more than the 3-day window, and the tool told you to delete transactions that were nothing of the sort. A row now joins a group only when it is within the window of the group's first transaction (#333)
  • Deleting a category no longer leaves split parts pointing at it. The delete guard is deliberately blind to splits (a category used only by split parts must stay deletable), but nothing cleaned those parts up afterwards, so they kept referencing a category id that no longer existed. Deleting a category -- with or without reassigning its transactions -- now degrades its split parts to uncategorized, which is what the reassignment already did for ordinary transactions. Find Duplicates also names a split Split now instead of showing a dash (#360)
  • Splits from before the split feature existed are counted once, everywhere. A transaction whose split flag was never written -- imports predating the column, and backups restored from those versions -- was in a grey state: some queries treated it as a split, others as an ordinary transaction, so depending on the screen its money was counted twice, or not at all, or it was offered up for categorisation, which is how a transaction ends up claiming a category and carrying its own breakdown. Every query pair now agrees on one rule -- a transaction with split parts counts through its parts, full stop -- covering the budget carryovers, the monthly report, Year over Year, the forecast, per-account totals, uncategorized listings and rule runs. Restoring a backup now re-marks the transactions that actually received split parts, whatever the archive claimed, and the very large id lists a restore or a year-long report can produce are processed in batches instead of one oversized query (#360)
  • The app now notices when its own database updates never ran, and says so before anything fails. If Nextcloud replaces the app's files without finishing the upgrade, the database changes that came with the new version are skipped. Nothing looks wrong -- reading data does not touch the new columns -- and then the first thing you save fails with a database error nobody can act on. Every page now checks whether any of its database updates are missing and, if so, shows a banner naming how many and the command an administrator can run to finish them. Checking costs nothing once a version has been confirmed complete, and the banner clears itself as soon as the updates are applied (#333)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureDm8DKf6I3AofLr0FMZsDKeE4q19LhQ2NgVNbRwtRNtCcfcpkF7RWros6LUOJacOmyNa9EuRDVUGQJtTGSasNt4dXxhwDjw7hDsmm2NUaTTrnoLoY32V9zyBLZqtSLb30uZTr6O8q03UGO0MsNQr5IsOcNbi7KflfjmUbYY99cIycOm/FBoLBm+LWQlDH+eQZigjqEk5GMvsLgyY2LuYQE6226WS1W96gI3neUzwICij5OWn/hdkl4axB6Y2Ei7bWofiMRSwY4oeiLF1mmgk1C4OfyoZomZEhsytxXok5wt38K4SMQBL4A+zpVoQBp0cBdFrGUynC/eNtmQjS9nsJSs0woZ3H6+QrlMCmJ+PRqSbn5kEO7PBzXMXUYNg9mqd0mUeYjH0mW1SKpF51FsBKjMHNmi1ReNqQhiRAJq+9JzyiaUuCv/gigDXOaLCR5NvRld0RbMYfnWN9XZ18k8/b+oKwzBG/oY6mqmgR0mUl24lXHK7djSHbhfmCIAG6hpOxgrL6cFguUdqNuoCGhBvUaUBJn742J4Hh4Lx4jq+zQJE1rJf4xpNhcT6VKLJNS7DrSd62oPm80FBXSu9colzmlv3C67SDYwL5TxqdM8OCsPTJvH0IWnr9R+qrrPh5MMqy3XMDyYvzDMjiK0OWmzob4ZxMCg2gi1asdtcjd5PqNgU=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.44.1
Release Details
UpdatedAug. 28, 2026, 12:44 a.m.
Changelog

Fixed

  • When the app's update has not finished, the app now says so and how to finish it. If Nextcloud updates the files but never runs the app upgrade, the migrations that add new columns never run -- the app carries on reading fine, because reads do not notice a missing column, and then the first thing you save fails. Until now that surfaced as the database's own words, "Unknown column 'amount_type'", which is accurate and no use to anyone. Any missing column or table now comes with the command that fixes it: occ app:disable budget && occ app:enable budget. Reproduced against MariaDB, where neither occ upgrade (which upgrades the server) nor occ app:update (which looks for a newer release in the app store) does anything about it (#333)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureJfhfoodWHfhncS8NhWVo/wOO4gi2kDEn4S8M8TzZg5Qfbjwxmkmh4Pn294Og1wL1uIp5gbCGyS2aIzcDN0HoEf7DhN98hxRaZ5P5/5CBFLgTGTNwJmDX9A4Xtwk81o4/3jbeLAPUJspX2OkQKGzyNtFqrCi5aDG/JF5D0Yf49WBnYG3BZp5rSaEOmrD2Scm8D3EmE5wDsIIKg+Zl1iCVHsUX/Z7TG6lVzPxeW4JVIU4NX8hhUziOOGMXthSBM5GxZX4okbtfGm9uVeUOe49rT/kXcm7mTG2Xb/4Phywh7vFqMckiOTSwP2fLttq7LFUv0XtUoaOhxjfhFJBdQIDi9qhtJRMcRvXE8kPbswzpyN9W/nC6lv44Q0Bxse967DXVQ8ZoxIWCByl6/5Z4Ooi978d0lWc/HsZYqMX5SXTb3KoALYNCG2+8WfkXwF+kZ0kPc//K6Uh/r+lgO7Gx55xaR2XkmDhClY7u/PMhLOsc0segdjc4obFyHns/iTeKJjV+aEaOvlbNq5aDKioozMZr2vQhL9XfEv4rKLq5VTxaD0s/WOv4dMJxhA/7LRpC53OlPrFN1IKPgmXUS2v2gTtP7fF9eDvZ6u66ra9zTe/j+R7y2y8mMo0zcUMnPPUxJ5fgX5saIPC2svL65fawwwghOMQTiydg6jEmbipPDU38RJQ=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.44.0
Release Details
UpdatedAug. 26, 2026, 12:34 a.m.
Changelog

Added

  • Dashboard tiles can follow your budget period. Spending by Category, Top Spending Categories and Budget Progress gain a Current budget period date range in their gear settings, which tracks the Budget start day you set in Settings. If your money arrives on the 25th, the tile now covers the 25th to the 24th like the rest of the budget surfaces do, instead of cutting your cycle in half at the month boundary. Spending by Category's header chip names the days it is actually showing — "25 Aug – 24 Sept" — rather than repeating the setting back at you. The other tiles are unchanged: a balance-history chart and the income-vs-expenses series cover a span rather than one cycle, so the option is not offered there (#333)
  • Cash Flow Forecast and Year-over-Year now actually draw. Both tiles have been in the Add Tiles menu with a card, a chart area and a working server request behind them — and no code to draw the result, so they sat blank however long you waited. Both are off by default, which is why this went unnoticed. Cash Flow Forecast now plots your projected balance month by month, starting from today's balance so each step reads as a change, with that month's income and expenses in the tooltip; choose Next 3 / 6 / 12 months in its gear settings. Year-over-Year plots income against expenses for each of the last 2, 3 or 5 years, matching the chart on the Reports page so the two cannot disagree (#333)
  • The bills tiles let you choose how far ahead to look. Upcoming Bills and Bills Due Soon now take a Look ahead setting of the next 30, 60 or 90 days. Upcoming Bills previously showed whatever came first with no horizon at all, and Bills Due Soon was fixed at 14 days. Both still include bills up to a week overdue, so an unpaid bill does not vanish from the tile that exists to chase it — Upcoming Bills previously had no such cutoff and would show a bill overdue by months right alongside this week's, and now drops anything more than seven days overdue the same way Bills Due Soon already did (#333)

Fixed

  • "Last 30 days" on a dashboard tile now means the last 30 days. It meant the month so far: on the 24th you saw 24 days, and on the 1st of a month the tile charted a single day. "Last year" behaved the same way — the year so far, so on 3 January it showed three days. This is why a tile could flatly disagree with the budget alerts sitting above it on the same screen, and it hit anyone whose spending does not line up with the calendar month hardest, because the biggest bills of the cycle fell outside the window entirely. Affects Spending by Category, Top Spending Categories and Budget Progress. "Last 90 days" and "Last 6 months" were near enough but drifted by a day around month ends — six months back from 31 March landed on 1 October — and are now exact (#333)
  • Every Date Range dropdown on the dashboard now does something. Ten tiles offered one and ignored it: you could pick a range, it saved, and the tile carried on showing its own hardcoded window. Large Transactions had no date filter whatsoever — it ranked your biggest transactions over all time — and now honours the range. Weekly Spending was pinned to the last 7 days, and its daily average divided by 7 regardless; both now follow the range you pick, and its label — which always read "This week" — now names the range it is actually showing. That default week is now an explicit Last 7 days setting rather than a hardcoded one, so it is both the tile's starting point and a choice you can change like any other range. Category Trends compared this calendar month against last, and now compares the range you chose against the equal-length stretch immediately before it, so the two figures are like for like at any range. Where a range could never apply, the dropdown is gone rather than lying: Monthly Comparison is this month against last by definition, Debt Chart is a payoff projection with no window, and Income Tracking's headline is a monthly rate that cannot vary with one (#333)
  • The Cash Flow Forecast tile was asking the server for the wrong thing. It sent a days value the forecast endpoint does not accept, so the parameter was discarded and the default horizon used every time (#333)
  • When something fails to save, the app now tells you why. Errors across the app showed a fixed message -- "Failed to create bill", "Failed to save transaction" -- whatever had actually gone wrong, so a validation problem and a database problem looked identical and neither was actionable. Where a failure comes from the database the server already attaches a short, sanitised description of it, a missing column for instance, specifically so the cause is visible to people who cannot read their server's log. Nothing in the interface was reading it. That description now appears alongside the message everywhere a save, delete or update can fail -- transactions, accounts, categories, bills, rules, pensions, assets, transfers, income and bank sync (#362)
  • Bills with a statement or minimum-payment amount explain themselves when rejected. Those amount types only work on a transfer pointing at a credit card, and the two rules enforcing that were being replaced by the generic "Failed to create bill" instead of being shown. Genuinely unexpected failures still stay generic (#362)
  • Repair Data can clear the stray categories off your split transactions. The rows the old bulk edit and the rule runs left behind are still there, each claiming a category it should never have had. Settings > Repair Data gains Split Transactions Carrying a Category, listing every one it finds with the category currently stuck to it. Repairing removes only that stray category: the split stays a split, and every part of it is left exactly as it was. Genuine splits, ordinary transactions, and a transaction explicitly marked unsplit are all left alone, and the scan drains to empty once run rather than reporting the same rows forever (#360)
  • Rules no longer break a split transaction by categorising it. A split's categories live on its parts, and its own category is deliberately left empty -- so writing one onto it produces a row that claims a category and carries its own breakdown, which every per-category total then counts twice. Bulk edit was stopped from doing this a while back, but Run rule now and Run group rules write straight to the database and went around that guard, so rules were still quietly creating the damage. A rule now leaves a split's category alone while still applying everything else it does -- vendor, notes, tags and the rest -- so splits stay covered by your rules. The preview and the results list name such a row Split instead of showing it as Uncategorized, which read as a change that was never going to happen (#360)
  • A transaction damaged by the old bulk-edit bug is no longer counted twice. Before it was fixed, "filter by Uncategorized, select all, set a category" wrote a category onto split transactions without removing the parts underneath, leaving rows that claim to be in a category and carry their own breakdown. Nothing has ever cleaned those up, so they are still sitting in databases -- and the queries behind Spending by Category, the Reports charts and the Category Details panel added up both, reporting a split receipt at its full amount plus each of its parts, and counting it as two transactions. A category could therefore show more spending than the transactions underneath it actually came to. Each transaction is now counted once, through its parts where it has them (#360)
  • Budgets count the money you spent through a split. A split transaction holds no category of its own -- its categories sit on the individual parts -- and the query behind every budget figure only ever looked at the transaction's own category. So a receipt split between Groceries and Household added nothing to either budget: the progress bars read low, remaining read high, and the budget report agreed with them. Budget alerts have counted split money since they were added and the spending charts since v2.33.0, so a category could raise an over-budget alert while the bar right next to it showed room to spare. Affects Budget Progress, Budget Breakdown and Budget Remaining on the dashboard, the Budget view, Reports > Budget and its CSV and PDF, the scheduled monthly report email, and the Unusual spending section of the digest along with its notifications. Splits restored from a backup made before v2.41.0, which lost the flag marking a transaction as split, are counted too, and a transaction damaged by the old bulk-edit bug -- which stamped a category onto a split parent without removing its parts -- now counts through its parts rather than dumping the whole receipt into the one category it was stamped with (#360)
  • A refund now comes off what you have spent. Spent on the Budget page counted only money going out, so a bill that was refunded, a returned purchase or a reimbursed expense left the category looking fully spent -- a $216.90 phone bill with $158.61 credited back read as $216.90 spent, and the bar sat at 100% over a $120 budget. It now reads $58.29, which is the figure Category Details has always shown for the same category: the two screens disagreed, and the budget was the one that was wrong. The same net figure now feeds Reports > Budget and its exports, the Budget Progress, Budget Breakdown and Budget Remaining tiles, the budget alerts -- which is what stops a category raising an over-budget alert while the bar beside it shows room to spare -- and the Unusual spending digest, where a purchase you sent back no longer reads as a spike. Income categories are measured by what came in, with anything paid back out subtracted; Reports > Budget was previously asking for money-out on those too, so an income category with a budget reported nothing against it (#361)
  • A split transaction on the dashboard names the categories you sorted it into. Recent Transactions read each row's own category, and splitting a transaction moves the categories onto its individual parts -- so however carefully a receipt had been divided up, the tile called it Uncategorized. It now names the categories the parts went to, with a coloured dot for each and the part-by-part breakdown on hover, the way the transactions list and the account register have since v2.43.1. Where the tile is too narrow for all of them the names run to an ellipsis rather than pushing the amount off the row, and a split that arrives without its parts is called a Split, which is at least true (#360)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureQHxBHmyBaONUhmqkujdb3Z0HaVDO5kl4378wYHWJgtW/QHl6D1QNcKQzzhB2nVoXZz322zCDeUae1eIk3C+EX4X5q2MolNnL9UAL0TvS0oSfQcAtWTFCAO1Z79C1uYbCxM6CUNNrGmZdoZ41ivw9OJQOICFu5nd0RHQ+w25DUCKK0SOEQXWia7LN5o0RnpTwKYxSxQHIb4dajJvbWsW+oibyBkP/yZsbfJRls3Z2zWYvEEnQhWiKTaJC4Ijfz6DgP6U/M9Z5DjhIZgyxPy5OGTOLd9aZl64K3JzcQqKDKJJ8wTDz9iUXb+bCitxDyq0chgLG4tbSyFyK7+aAcWchHZXufXDmPmAsTikDVgc6srYeKyqv2VFpa/IBA1m0GeAzN2KqIRzDbiyttRGgQQ5i2VPH4owiA8un5ak46XVpD+q5Xy/SwEZVmjCY8AZsZePmPvM9gESC+hBy6P5YuNksSar/dD++REsQCeFkCIiqf4y61wyD0WY3qHYF4yDpWzH8vVhbKSMy0x9W1JR3ZUmv0MbidSvgiOwxpPPtWVuPPRDbLKg3ENzv4bq8IK8PzR0t5jHNSFKWu7C1jrJ3gE7yoxJ5zMnsw6v3HJhedy2Jfx2C2EZsZv1XCzaXYxKBr0uaHVcOSn9/4Rn9OXf95th7bgRN6aCrU34M1ELL3RmocKs=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.43.0
Release Details
UpdatedAug. 24, 2026, 1:27 a.m.
Changelog

Added

  • Liability accounts now ask what a positive balance means instead of guessing. Editing a credit card, loan, mortgage or line of credit shows an Amount owed field that takes a plain positive number — the app adds the minus sign — with a separate This account is in credit tick for the case where you have overpaid and the lender owes you. Switching an account between a debt type and a savings type converts the figure for you and shows the resulting current balance before you save. Creating a liability works the same way. The choice is recorded with the account, so an export and restore keeps it (#353)
  • Several CSV columns can feed one text field. Banks often split what belongs together — a merchant column and a details column, say, or a reference spread over two. On the import mapping step, Description, Notes, Vendor and Reference are now checklists: tick every column that belongs in the field and the values are joined with a comma, in the order the columns appear in the file, with blank cells skipped. The same works for those four fields on OFX, QIF and camt files, and a saved import template keeps the whole selection. A single ticked column imports exactly as it always has, so re-importing an overlapping statement still recognises its transactions. Thanks to @Saviq for the feature (#355)
  • Category trees can be exported and imported. The Categories page has Export and Import buttons next to Add Category. Export downloads your whole tree as a readable JSON file; Import takes that file back, or a CSV of Parent > Child paths, shows exactly what would be created before anything is written, and leaves categories that already exist untouched while adding whatever is missing underneath them. Handy for backing up a carefully built structure, sharing it, or having a spreadsheet or an AI assistant draft one and loading it in a single step (#354)

Fixed

  • Editing a loan or credit card no longer turns your debt into an asset. Typing your statement balance as a positive number into the Opening Balance field stored it as a positive number, which the app reads as "the lender owes you this" — so a £5,000 loan quietly added £5,000 to your net worth instead of subtracting it, a £10,000 swing, and every later recalculation re-derived the wrong balance from it. Nothing on screen said so. Positive balances on a debt stay supported, because a genuine overpayment is a real thing, but the app now asks which you mean rather than reading it off the sign. If this already happened to you, Settings › Repair Data will find it: run Scan for Issues and the new Debts Recorded as Being in Credit section lists every affected account with what it reads now and what it will read afterwards — untick any you really have overpaid, and those are recorded as genuine credits and left out of future scans. Two related consequences are fixed alongside it: an account you have overpaid no longer appears in the debt payoff planner as something to pay off, and it no longer counts towards Total Liabilities on the Accounts page, where it was pulling net worth down by twice the credit (#353)
  • An account edit that does not touch the opening balance no longer rewrites the balance. Renaming an account, changing its institution or ticking a checkbox resubmitted the opening balance every time, so an unrelated edit depended on that value round-tripping through the form perfectly. It is now sent only when you actually change it (#353)
  • Reopening a split transaction no longer scrambles its parts, and saving it no longer throws them away. A split of 10 into 1, 3 and 6 came back as 1, 9.00 and 0.00 — the second part had swallowed the rest and the third was empty. The parts were always safe in the database; the editor was overwriting them as it drew them. It fills the last row automatically with whatever is left over, and it was doing that after adding each row, so every stored amount was recalculated away the moment the next row appeared. It now draws all the rows first and works out the remainder once, which is what it should have been doing. If you saved a transaction from that scrambled view, the parts you saw are what got stored — the third one was dropped for being 0.00, quietly, because the total still added up. Worth re-checking any split of three or more parts you edited recently; their categories will have been wrong in reports for the months involved. Splits of four or more parts had a second symptom — Save appeared to do nothing at all, with no message — which is fixed by the same change (#358)
  • Filtering transactions by Uncategorized no longer lists your split transactions. A split transaction has no category of its own by design — its categories live on the individual parts — and the filter was reading that as "not categorised yet", so every split you had ever made turned up in a list meant for things needing attention. Split transactions are now left out of it, and out of the dashboard's uncategorised list and the "only uncategorised transactions" option when running import rules, which read the same way. The bulk-edit consequence is the one worth knowing about: filtering by Uncategorized, selecting all and setting a category used to write that category onto the split transactions caught up in the list, after which they were counted twice in reports — once for the whole transaction and again for each of its parts. Setting a category on a split transaction is now ignored rather than obeyed; unsplitting one still assigns a category as it always has (#356)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignaturelQsdNi/Ed5bU8/Ch8iyHVXKdX+l8qhRm8fCwRYfB/ObxW6pncVobhw57Bzvu/2yio4Wb+MyJ+DZ8T75pZ9+ugVmWX+q/VSLx4PEAmnr9upL0m7AvJN33BXARoFWBzKVFHnfEy/RuYgtxnNfOmoiblZXbAeBs5zyxxeQKrYSMSHfdwdG/t9HZNFNvFEyp7k7XEU1xQ5HaAo6kResw+25vTU/lkvJNXYmNnmWr3ZxUo7qphCOw/ZJU4aMi+g8RjrWIp86biPeM8mIr57Oacrm3fIQnGTgfk7lqX5FGTjhjLTnDKin+AyFQCpkuki47leJ+W4VwS/LvObLDHn/WcYhjmkdmGXTGFZGhVYAHz3VcPklRmERDkafXZ7lPk0tWZjma/W4SCf6u8Pu3Ni5fVeZ9Zp7qiCjNomRBmMl2nlW2EC/GYJAW7c78TM1Gq9qw6EAAweO5/7JMtOMaA4Klm1XKmE6CpDmu6Ox4E0+RiaDZJ6lHnC7JcfNweMtbgZb4tK/1nAXqum2v4vIQcIDpfk2ROqxkvthclKe05z2p1oe2qg/mEWqwx51ZHR0PvMhmNYGh9VVi3F7KiT0v1K6D06CAAOJu6TeJTMKX5asGJ8K2PkVKk0E7uVWGKp7+WRBU4ILvUftG5d8Pz7ChCY35XVwknHbY/Rx7DNno+1h3YzkblIU=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.42.0
Release Details
UpdatedAug. 21, 2026, 9:23 p.m.
Changelog

Added

  • Receipts can be filed wherever you keep your app data. Uploaded receipts have always landed in Budget/Receipts/<year>/<month>/ in your Files; a new Receipts folder setting lets you point that anywhere inside your own Files instead — Applications/Budget, say, to sit alongside other apps' folders. The year and month subfolders are still created underneath, and receipts attached before the change stay exactly where they are: the app never moves or deletes your files. Applies to uploads from the web form, the API and receipt scanning alike (#352)
  • Bank statements in camt.053 XML can now be imported. Many European banks — Swiss ones in particular — export statements as ISO 20022 camt.053 (and intraday camt.052) XML rather than CSV or OFX. Drop one on the Import page and it behaves like an OFX file: every account in the statement is listed with its IBAN, auto-matched to the account of yours carrying that IBAN, and routed there. The parser reads what the payer wrote (the remittance text), who the other side was (the counterparty, which becomes the vendor), the bank's own entry text, and the transaction type code, and a batch entry such as a collective payment is split into its individual transactions with their own counterparties. Duplicate detection uses the bank's own entry reference — more reliable than the CSV content hash — except where a bank stamps the same reference on every entry, in which case the hash is used rather than collapsing the statement into one transaction. Every camt.053 schema version parses, including files with the namespace stripped (#350)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureRhkTM0z3ZXIpnFc2BJ0widME7KmhTp6jnd/kaHn42N1eiC9JQhiDUCGmqbCweHhswB3HBwwBoG37XE5L/9s97L13vmrIT+19EVx+f3o2xHXeVe0J19F0BKOxyW5mKYt7xQqo/dwCQ+qDk06kH89XPta+ppz28+qcfaEnBiEtnnzlyeOqyXgs6qWuM/sZW/WUau5dPKZxfkK57IgPaBIfx/R8cttcyokpplD5kV+rmGz8+AvAbvqcT06aGCzjQQtK4/ADbBe7PiGxy7Yy64B9LhgphkHuXqk1hzJiuC0exn+8z02QXGq5g2nDbATK6ZF6n6v6wIrSnEZtvRBvd2rloAQe5K5aiP6Ae6TPyILrunKGTL7Je1d/sqWO+103WdwcfLSI2rYHM00CUOdmxRttecjkJvc+sarc7m1M+fFIePC4SC5RlKJin/v9tUf/m+ie0+/UvqrcReF6hjCfN7jp8LBNjJQGsbpOBm+WO6v2i5GSKV/vNWLw4qln0rQXobu0jdSIhraqes84wPmF1z7U/eQorqmB9Q+ig4mfTtR3zxVfcd6vVT5fseiDTVhbaLf144zLTSxWpgVscFSQitXsVnA3FHkHuXsy8OqYeGgtQHOPjwMocSN1udnp59Wth/jd6qxj9Gf9KjFYFi/fwjc+QcvHaTuGCycDo+4xny+evpE=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.41.0
Release Details
UpdatedAug. 19, 2026, 10:30 p.m.
Changelog

Added

  • The Help & Docs page now says how to support the project. A small section with the GitHub Sponsors and PayPal links — the same ones listed on the app store — for people who installed the app and never see either. The floating help panel carries the links too. Nothing nags: it sits in Help, and the app works fully without donating
  • A recurring transfer can now pay a credit card the way the card itself would, with the amount resolved fresh at every payment. Card payments have always been representable as recurring transfers, but only at a fixed amount — useless for a bill that is different every month, which left people faking it with duplicate bills or typing the figure in by hand each time. A transfer whose destination is a credit card (or line of credit) now offers an Amount type choice mirroring what card issuers offer: Fixed amount as before; Statement balance, which pays what was owed as of the due date — everything charged since the previous due date plus any remainder an underpayment carried forward, with later charges rolling to the next statement; Current balance, which clears everything owed at the moment of payment; or Minimum payment, which pays the minimum set on the card's account (never more than is actually owed). The figure is worked out from the card's own ledger when you mark the payment made (or auto-pay makes it), so it is never stale; the amount shown on the transfer between payments is the last one resolved, and the pre-booked next occurrence carries it as the forecast estimate. Reminders, the bills calendar and auto-pay all work unchanged, because the payment is an ordinary recurring transfer. The card's own account page joins in: a Statement due day field on credit-card and line-of-credit accounts records which day of the month the payment falls due — shown on the card's page as account information in its own right — and a Set up payment button appears on a card with no payment transfer, opening the form pre-filled with the card and that due day. Once a payment transfer exists, the page shows when the next payment is due (#347)

  • Subscribing to hosted receipt scanning, and managing that subscription, now happen from the settings page. With the Otherworld relay selected as the scanning provider, the admin settings show the plans with a Subscribe button that opens Stripe checkout in a new tab — the licence key is shown once after payment, emailed as a backup, and pasted into the field above. Once a key is saved the block flips to a Manage subscription button: your server asks the relay for a billing-portal link tied to that key, so changing plan, updating the card or cancelling needs no separate account and the key itself never reaches the browser. A hand-issued key (a trial, or one minted directly) is told plainly there is no subscription behind it rather than being bounced off a portal that would refuse it (#537)

  • A CSV export of every transaction you're looking at, not just the page on screen. The account Export button built its file out of the rows the browser had already loaded, so it silently stopped at 50 — a year-end export of 800 bookings produced a file of 50 that looked complete, which is worse than an error. The export is now built on the server from the same filters the view is using, so it covers the whole result set however many pages that is. The Transactions page gains its own Export button too, which with no filters set means every booking across every account in one file: previously the only export was per-account, so a club treasurer with three accounts had to stitch three files together. Filters still apply, so you can export one category, one date range or one tag set just as easily (#344)
  • The exported CSV now says which way the money went. Amounts carry a sign — expenses negative, income positive — so the Amount column totals correctly the moment you drop it into a spreadsheet, rather than adding your outgoings to your income. The Type column reads Income and Expense instead of the stored debit and credit. Transfers between your own accounts appear as they always have, one leg of each, which now means they cancel out in the total instead of inflating both sides. The file also gained Vendor, Account, Currency, Reference, Notes and Status columns — enough to do the books from without opening the app (#344)
  • A new Income & Expenses report, for the year-end job of showing what came in and what went out. Pick it under Reports and you get two tables — income by category and expenses by category — with each side's own total and the net between them, over whatever period you select. It exports to CSV and PDF like every other report, the CSV keeping the two tables as separate labelled sections so a treasurer's spreadsheet can take them straight. Like the other reports it respects accounts and categories you've marked as excluded from reports; unlike the transaction export, which is a plain ledger of what you filtered (#344)
  • The Belarusian ruble (BYN) is now one of the currencies you can pick. It appears wherever a currency is chosen — the default in Settings, an account's currency, a manual exchange rate — and amounts are written with the symbol after the number (1,234.56 Br), as they are in Belarus. Its daily rate is fetched alongside the other fiat currencies, though the historical series is not: the 90-day history comes from the ECB reference rates, which don't cover BYN, so a converted figure for a past date falls back the same way it does for any other currency the ECB doesn't publish (#343)
  • The API can split transactions, so capture apps can categorise receipt items too. POST /api/v1/transactions/{id}/splits sets the parts of a transaction, and POST /api/v1/transactions now takes an optional splits field so a phone can record the transaction, attach the photo and set the per-item categories in a single request. /api/v1/ocr/extract additionally reports the receipt's subtotal and tax, without which a client could not make the items reconcile to the total — splits must sum exactly, and most receipts print tax on its own line. GET /api/v1/capabilities gains splits_available so a client can gate its per-item screen on a boolean rather than parsing the version. All four are additions: no existing field was renamed or removed, so clients built against the previous shape are unaffected
  • Receipts with loyalty savings can be split too. A Clubcard, coupon or multibuy line means the items on a receipt legitimately add up to more than you paid — and that gap used to make the whole receipt look misread, so it was refused for splitting and flagged with a mismatch warning. The savings are now read from the receipt and become their own line in the split, at the printed amount but negative, exactly as tax gets its own line. Four shapes now reconcile: items alone, items plus tax, items minus savings, and both together. The mismatch warning still fires when the gap is genuinely unexplained, which is the case it exists for. Two robustness details, because the reader is a vision model that occasionally slips: when it under-reads the savings by a line, the server closes the gap from the printed total so the receipt still splits rather than being refused over a saving it half-missed; and an impossible negative tax or subtotal from the reader is dropped rather than trusted into the arithmetic
  • Turn a scanned receipt into per-item splits. After a scan, if the items on the receipt add up, the scan box offers to split the transaction into one line per item so each can carry its own category — useful when one shop trip covers groceries, household and a treat. Where the receipt prints tax separately, the tax becomes its own line at the printed amount rather than being smeared across the items, so every figure still matches the receipt in your hand. The offer only appears when the arithmetic actually reconciles (items alone, or items plus tax, equalling the total); a receipt with a discount line or an unreadable item is left as a single transaction instead of producing splits that would be rejected on save. Splits carry categories, not tags — tags remain per transaction
  • Receipts are filed by month and named after the transaction. They now land in Budget/Receipts/2026/08/ rather than one folder per year, and an uploaded photo is named 2026-08-05 The Corner Deli 23.77.jpg instead of keeping whatever the camera or capture app called it (often a UUID). That sorts chronologically in the folder and makes a receipt findable by shop or amount in Nextcloud's own search. Existing receipts are left exactly where they are. A file attached from your own Files keeps its name — it's your file, and renaming it isn't ours to do
  • Receipts can now be attached while you are still adding the transaction. The Receipts section used to appear only after saving — the attach endpoints need a transaction id — so adding a purchase with its receipt meant save, reopen, attach. Files you choose (or pick from your Files) are now held and listed with an "on save" tag, then attached the moment the transaction is created. If one fails to attach, the transaction is still saved and you are told which — re-submitting would only have duplicated it
  • Scan a receipt straight into the transaction form. When your administrator has set up receipt scanning, the Add Transaction dialog gains a drop zone: drop a photo on it (or click to pick one) and the date, amount, merchant and a suggested category are filled in for you to check. The photo is attached to the transaction when you save, so a receipt is one action rather than three. The box tells you exactly which fields it filled, how many items it read, and whether those items add up to the total — nothing is saved until you press Save, so a bad read costs a retype rather than a wrong record. Scanning also works when editing an existing transaction, where it only fills fields you have left empty: a scan is a suggestion, never an overwrite. The whole section stays hidden on servers with no OCR provider configured, rather than offering a button that cannot work
  • Receipt scanning can be configured from the command line: occ budget:ocr. Run it bare to see which provider is set, whether a key is stored, and — the useful part — whether the server can actually serve a scan right now. occ budget:ocr set --provider=custom --endpoint=… --model=… changes it, and --api-key-stdin reads a key from a pipe so it never reaches your shell history. It matters that this exists rather than reaching for occ config:app:set budget ocr_…: the raw config route looks equivalent but skips the provider and URL validation, and would store your API key in plaintext, since the encryption lives in the app rather than in Nextcloud's config layer. The command takes exactly the same path as the settings page, so a rejected value changes nothing and a key is always encrypted
  • A CSV column can now be mapped to a transaction's Notes. Bank exports often carry a line of extra information — a payment reference, a booking note, the counterparty's message — that belongs in neither the description nor the reference field, and until now it was simply dropped: the only way to keep it was to edit every imported transaction by hand. Notes now sits in the column mapping alongside Description, Vendor and Reference, and whatever you point it at is stored on the transaction. It also earns its own column in the import preview whenever something is mapped into it, so you can see you picked the right column before anything is written, and it can be saved in a template like every other mapping. Over-long values are truncated to what the field accepts rather than being imported into a transaction you could no longer edit (#340)
  • The API can now read a receipt photo into a draft transaction. POST /api/v1/ocr/extract takes a photographed receipt (JPEG, PNG or WebP) and returns a draft for the user to confirm: merchant, date, printed total, line items, and — on the vision-model providers — the currency when one is legible; nothing is recorded until the client saves it through the ordinary create call, so retrying costs nothing but another scan. The reading is done by whichever OCR provider the administrator configured (below); failures carry a stable machine code (ocr_not_configured, ocr_quota_exhausted, ocr_extraction_failed) so a client reacts to what happened rather than parsing prose, and ocr_available on the new GET /capabilities reports the real state so clients hide the flow instead of hitting the error. A category is suggested by running your own categorisation rules against the extracted merchant — computed on your server, so the provider sees the image and nothing else, ever. When the line items don't add up to the printed total the draft says so rather than silently trusting either side. Documented in the REST API guide and the OpenAPI description (#533)
  • Recording a transaction over the API is now retry-safe, and can carry the receipt with it. POST /api/v1/transactions accepts an optional idempotency_key: a client that times out on mobile data cannot know whether its POST committed, so a repeat of the same key within a week answers with the transaction the first attempt recorded instead of inserting a duplicate — the single most damaging failure a capture client can produce, closed server-side. The same call now takes an optional photo part, recording the transaction and attaching the receipt in one request, plus a merchant field and a type that defaults to money-out. A new GET /transactions/recent returns the newest activity flat and merchant-first for a capture app's glanceable list. Wire field names across v1 settled on snake_case (account_id, parent_id, line_items) before anything ships against it
  • Receipt scanning can now be set up, and it is off until you do. A new Receipt scanning block in Settings → Admin Settings chooses which OCR backend reads a photographed receipt: this Nextcloud's own configured AI provider, any OpenAI-compatible endpoint — a vision model on your own network is a first-class option, not a footnote — or Otherworld's hosted relay with a license key. The choice is server-wide and an administrator's to make, because it decides who else sees your receipts. Until one is chosen the app sends receipt images nowhere at all: there is no default backend and no fallback. Your server makes the request rather than your phone or browser, so an API key never leaves the server and a backend that isn't reachable from the internet works perfectly well. Keys are stored encrypted and are never shown again after saving — leave the field blank to keep the stored one. Only the image is ever sent; account names, balances and other transactions are not. The Receipt Scanning guide sets out exactly what goes where for each option. With the API endpoint above, scanning works for capture clients as soon as a provider is configured; the scan button in the web interface arrives in the next release
  • A documented REST API, so Budget can be reached from outside the web UI. A versioned, read-and-capture API now lives at /ocs/v2.php/apps/budget/api/v1 — list your accounts and categories, browse and filter transactions, record a new one, and attach a receipt photo to it. It authenticates with an ordinary Nextcloud app password (or a token from Nextcloud's Login flow v2), so there is no separate credential to manage and revoking the entry under Settings > Security cuts off whatever was using it. That makes a phone capture app, a shell script or an n8n workflow a matter of configuration rather than code — the REST API guide has worked examples, and a machine-readable OpenAPI description ships with the app. Version 1 deliberately stops at reading and appending: editing, deleting and everything else stays in the web UI, which keeps the contract small enough to hold still. Fields will be added to it, never removed or renamed. Every amount crosses the wire as an exact decimal string ("42.50") rather than a JSON number, so a client cannot lose a penny to floating point on the way in or out. Note this is quite separate from the internal endpoints the web UI calls, which follow the database and change without notice
  • The accounts page can now be tailored to what you actually want to see. A gear button next to the tile/list switcher opens display settings for the page. Tick which attributes appear on each account — account type, institution, (masked) account number, last reconciled date, converted balance, and, on tiles, the 7-day balance trend and the status dot. Drag those same attributes into the column order you want for the list view (Alt+/Alt+ does it from the keyboard); name and balance can be moved as well, they just can't be hidden. And choose how accounts are ordered: by name, balance, type, institution, last reconciled or date added, ascending or descending. Tiles follow the same attribute order as the list columns, hiding an attribute drops its column so the rest can spread out, and everything is remembered in your browser alongside the tile/list preference
  • Categories can now be left out of budgeting without being left out of everything else. A new Exclude from budgeting checkbox sits alongside Exclude from reports on a category. Where the reports flag removes a category from all spending figures, this one is budget-only: the category keeps counting in reports, the dashboard, insights and every total, and simply drops out of the Budget page, the summary cards, budget alerts, the budget vs. actual report and envelope rollover. Meant for spending you want to see but can't sensibly budget — gifts, medical bills, home repairs — so you stop being told you're over budget on a figure you never set. Excluding a parent excludes its subcategories too, and like the reports flag it stays with the owner on a shared category
  • Select every transaction matching the current filter, not just one page. Ticking the header checkbox on the Transactions list now offers "Select all N matching transactions" when more rows match than fit on the page, so a bulk delete or edit can cover thousands of rows in one go instead of 250 at a time. The selection is dropped if you change the filter, so a mass action can never silently include rows you're no longer looking at, and bulk deletes of many rows are much faster (the account balance is recomputed once per account instead of once per row) (#336)
  • A Help & Docs page, in the app. The sidebar's Help & Docs entry used to throw you straight out to GitHub. It now opens a real page listing every guide with a one-line summary, a shortcut to the keyboard cheat sheet, the Quick Add page URL, and the System Info panel for pasting into a bug report. The floating ? button still gives you the short version for whatever page you're on, and now links through to the full page

Changed

  • A saved OFX/QIF template now remembers your field mapping as well as your account routing. These templates stored the routing only, so a bank that puts the payee in the memo had to have Description and Notes re-pointed on every single import — the choice was silently reset to the format defaults each time. Picking a saved template now restores both. Templates you saved earlier carry no mapping and are unaffected: their routing applies exactly as before and the mapping keeps the defaults (#340)
  • A reference longer than 100 characters is now refused when you type it, instead of failing when it is saved. The field was validated against a 255-character limit while the database column holds 100, so anything in between passed every check and then broke on the way to disk — a clean "too long" message is a better outcome than a server error. Nothing already stored is affected (#340)
  • A rule condition saying an import source is not something will start behaving differently on OFX and QIF imports. Because those imports never recorded a source at all, a negated Import Source condition matched every row from them; now that they do record one, it is evaluated for real. If you have a rule along the lines of source is not "Bank Sync", check it still does what you meant on your next OFX or QIF import (#338)
  • An import rule that sets notes "only if empty" no longer fires on OFX rows that carry a memo. With the memo now kept in the transaction's notes (above), the field is genuinely no longer empty on those rows, so an if empty rule correctly leaves it alone; an append rule adds to the memo rather than replacing it. Rules set to always overwrite are unaffected (#338)
  • The bill, transfer, savings goal, debt scenario, pension, asset and contact dialogs now use the same layout. Each was a narrow single-column form that had to be scrolled; they are now laid out in columns sized to what they actually hold — three for a bill (Bill, Payment, Schedule) and a debt scenario (Scenario, Payments, Debts), two for a transfer, goal, pension and asset, and a compact single column for a contact. Everything in them is visible at once, with Save and Cancel pinned below the fields. A bill's split rows span the full width of the dialog rather than being squeezed into a column, and a pension shows the pot fields or the income fields depending on its type, without leaving a gap where the other one would be
  • The four tag dialogs now match the rest. Add Tag, Edit Tag, Add Tag Set and Edit Tag Set are two-field dialogs, so they stay compact rather than being stretched into columns — but they pick up the same chrome as the bigger dialogs: a rule under the title, and Save/Cancel on a divided bar at the bottom right instead of loose against the left edge
  • The category dialog gets the same treatment. Naming fields (name, type, parent, colour) sit under Details on the left, the two exclusion options under Options on the right, and Tag Sets spans the full width below them — no scrolling, and the two checkboxes now read as ordinary checkbox rows instead of a bold heading with a stray box floating above it
  • The transaction dialog gets the same three-column desktop layout as the account dialog. Adding or editing a transaction was a 500-pixel-wide strip roughly a screen and a half tall, with a line of help text under every field restating its label. It is now laid out as Transaction (date, account, type, amount), Details (description, vendor, category, split toggle, tags) and Extras (receipts, notes, exclude from forecast), all visible at once with nothing to scroll for. Switching on Split across categories opens the split table across the full width of the dialog instead of squeezing it into a narrow column
  • The account dialog now fits on one screen. Adding or editing an account meant scrolling through roughly two screens of form in a narrow 700-pixel strip — eighteen fields, most of them empty, each with a line of help text underneath repeating what its label already said, and the Save button stranded at the very bottom. The dialog is now laid out for a desktop screen: three columns — Details, Banking, and Rates & limits with Advanced beneath it — showing every field at once with nothing to scroll for and nothing hidden. A column block with nothing to offer your account type, such as rates and limits on a Cash account, doesn't appear at all; Save and Cancel are pinned below the fields; the help text that merely restated its label is gone; and the current balance is shown as the calculated figure it is rather than a text box you can't type into. The columns reflow to two and then to a single stack on narrow windows and phones
  • The documentation has a home of its own: budget.otherworld.dev/docs. Every link that used to send you to raw Markdown files on GitHub — the in-app help panel and Help & Docs page, the README, the install guide and the app store listing — now opens the rendered site, which is searchable and readable on a phone
  • The Settings page is tidier. The Save Changes / Reset All to Defaults buttons were stranded in the middle of the page, with the Quick Add Page and System Info sections stuck below them, and Danger Zone was not the last thing on the page. Sections now run in a sensible order, with Admin Settings and Danger Zone at the end and the buttons at the very bottom. Quick Add Page and System Info have moved to the new Help & Docs page, since neither was a setting
  • The action buttons on an account row in the list view no longer sit flush against the last column

Fixed

  • The backup now actually contains your data — all of it. The export/import zip under Settings → Migration carried only categories, accounts, transactions, bills, import rules and settings; everything else silently vanished when moving servers. Reported for tags (#351), but the full list of what a migration used to lose is sobering: tags and their assignments, tag sets, transaction splits, recurring income, savings goals, assets and their value history, pensions with contributions and snapshots, per-account interest-rate history, manual exchange rates, import templates and remembered account links, saved reports, net-worth and budget history, reconciliation history, debt payoff scenarios, muted categories, shared-expense contacts with their shares and settlements — and on transactions, the links joining transfer pairs (so every transfer fell apart into an income and an expense), bill references, the split flag, and reconciliation/pension links. All of it now exports, and imports with every cross-reference remapped to the new server's ids. Old backups still import exactly as before; new backups are format 1.2.0. Deliberately still excluded, and now stated in the archive's manifest: bank-sync connections (provider agreements are instance-specific and must be re-established), shares with other users (they reference people on the old server), receipt files (stored in Nextcloud Files, not in the app), and the fetched exchange-rate cache (your manually set rates are included)
  • Marking a recurring transfer paid no longer loses the deposit half of its pre-booked transactions. When a transfer had its next occurrence pre-booked as a scheduled pair, marking it paid cleared the withdrawal leg but deleted the deposit leg — the source account paid out and the destination account never received the money, quietly understating it by one payment each cycle. Both legs of the pair are now cleared together. Payments already recorded this way are missing their deposit; the Convert to transfer action on the surviving withdrawal recreates the other half
  • Transfers no longer count as income and spending in the analysis reports. The dashboard's income and expense totals have left transfers between your own accounts out since 2.28.0, but the Reports page never got the same treatment: a £500 transfer appeared as £500 of income in Income Analysis (grouped by month, source or category) and £500 of spending in Expense Analysis (by month, vendor, account or tag) — and in the new Income & Expenses report only the incoming half was counted, overstating the net by the full amount moved. Every report view now excludes linked transfers, matching the dashboard, so shuffling money between your accounts changes no report figure. Two things are unchanged by design: a report filtered to a single account still shows that account's own transfer legs, because the money genuinely entered or left it; and only transfers the app knows to be transfers are excluded — ones created with the Transfer type, recurring transfers, and rows joined with Match transfer. Two unlinked rows entered by hand still count as ordinary income and spending (#349)
  • "Use Default Categories" failed with "A category with this name already exists" whenever any default was still present. The button seeds the whole catalogue in one go and gave up on the first name it found already taken — creating nothing at all. Easy to hit without doing anything odd: the category list shows one side at a time, so emptying the Expense view put the button on screen while the Income tree still existed in full, and pressing it failed on Income before a single expense category was created. Seeding now fills in exactly what is missing — an existing category is kept as it is, its missing subcategories are added underneath it, and everything else is created around it — so the button always finishes what it can instead of refusing the lot. A double-click while the first request was still running could also race itself into duplicates; the button now ignores the second click (#348)
  • Amounts in Kazakhstani tenge were shown with the code rather than the symbol. KZT was selectable and priced correctly, but it was missing from the front-end's symbol table, so every figure came out as KZT1,234.56 where the rest of the app would have written ₸1,234.56
  • Envelope budgets ignored everything you spent in a category's subcategories, so the whole budget rolled over untouched. The carryover looked for spending filed against the budgeted category itself and nowhere else. Budget €300 on Groceries and file the receipts under Groceries › Supermarket — the ordinary way of using subcategories — and it found nothing to subtract: July carried the full €300, August carried €600, September €900, growing by the untouched budget every month. The same screen said so in two contradictory ways, because the Groceries row itself has always added its children up: "spent €250 of €300" sat directly beside "+€300 carried". An envelope now covers the whole branch — the category and everything filed underneath it — so the amount carried forward is the leftover you'd work out by hand. A subcategory with its own envelope still keeps its own chain and is left out of its parent's rather than counted twice. Subcategories stay out of a parent's envelope when you've excluded them from budgeting or from reports, when they budget on a different period (a quarterly amount can't be added to a monthly envelope), or when they're income categories — and so does anything filed underneath those. Budget alerts and the budget-vs-actual report read the same corrected figure. Nothing was stored wrong: the carryover is recalculated from your budgets and transactions every time it's shown, so the numbers correct themselves as soon as you update (#341)
  • Envelope budgets also ignored anything you spent in a shared account, with the same result. The two queries the carryover uses to total up spending were scoped to the accounts you own, while every other budget figure on the page is scoped to the accounts you can see. So a category you fund out of an account shared with you looked untouched to the envelope: the full budget rolled forward each month, next to a row that correctly showed the money as spent. Budget alerts had the same split — they now measure spending over the same accounts as the budget they compare it against, including their split transactions (#341)
  • A long CSV column could import a transaction you were then unable to edit. Text taken from a CSV was stored exactly as the file wrote it, with no regard for what the field can hold. A notes column over 2,000 characters — easy to hit with a bank that packs a whole payment reference into one cell — imported perfectly happily and then failed validation the moment you opened that transaction, so no change to it could be saved until you shortened the note by hand. Over-long Vendor and Reference values were worse on MySQL and PostgreSQL: the row was rejected outright and counted as an error rather than imported. Imported text is now truncated to the field's limit, exactly as OFX and QIF imports already were, and leading or trailing whitespace is stripped rather than stored (#340)
  • "Check the server log for details" pointed at a log with nothing in it. When rows failed to import the warning told you to look in the server log, but the import never wrote there — the only record was in the browser's developer console, which is not where anybody was being sent. Failed rows, unresolvable accounts and balance recalculation failures are now logged properly with the row number and the underlying error (#340)
  • The column mapping step never highlighted the columns you had mapped. Each mapped column was supposed to be marked in the preview table underneath; the highlight was looked up by column position while the mapping holds column names, so it silently matched nothing and no column was ever highlighted for any ordinary CSV (#340)
  • A transaction added "today" could be filed as a future payment and left out of the account balance. Whether a date counts as future was decided using the server's calendar, but the date comes from yours — the web form pre-fills your device's date, and a capture app sends the phone's. Whenever your local date ran ahead of the server's, everything you recorded was quietly marked scheduled, and scheduled transactions are deliberately excluded from the balance: you added a purchase and the balance did not move. On a UTC-hosted Nextcloud that is the hour after midnight for anyone in British Summer Time, and most of the working day for anyone in Australia or New Zealand. The date is now judged in your own timezone (the one Nextcloud already knows from your session), falling back to the instance's configured timezone, so today is today wherever you are — while genuinely future-dated payments are still scheduled and still stay out of the balance until their date arrives. Transactions already misfiled this way corrected themselves within a few hours through the existing scheduled-transaction job; nothing was lost
  • QIF import has never worked: it reported rows in the preview and then imported none of them. A QIF file's accounts are matched to yours by an identifier the QIF parser never actually produced, so every account in the file was skipped — the import finished reporting success, with zero transactions added and no error to explain it. Underneath that, the parser had no notion of where it was in the file: an !Account header block was read as though it were a transaction (importing a row dated with the account's description), and because a real Quicken export opens with its category list, that whole list was read as an extra account containing one bogus transaction per category. Accounts are now identified by their name in the file, !Account blocks set the account's name, type and description as they should, and the sections that never held transactions — the category list, classes, memorised payees, security prices — are skipped instead of being imported as data. A file that does not name its accounts shows them as Account 1, Account 2 in file order. Dates are also read properly now: Quicken pads them to a fixed width (12/ 4'98), which nothing recognised, and a date that cannot exist — a 13th month — was passed to the database as text rather than being rejected (#338)
  • Import rules could not match on "Import Source" for OFX, QIF or any non-CSV import. Only CSV imports recorded where a transaction came from, so a rule condition on Import Source was silently false for every OFX and QIF row — and, because an unknown field inverts under a NOT, a rule saying source is not … fired on all of them instead. OFX and QIF imports now record OFX Import and QIF Import, joining the existing CSV Import, Bank Sync and Toshl, and the values are listed in the rules guide. Note the source describes how a transaction arrived and is not stored on it, so this criterion still matches nothing when a rule is re-run over existing transactions — the guide now says so (#338)
  • The column mapping did nothing at all on OFX and QIF imports, and the memo was thrown away. Every field in the mapping step could be changed and none of them had any effect — the import silently ignored the mapping and always took the description from the OFX name field. Banks that put the real payee in the memo instead (a common Canadian pattern) had no way to import a usable description, and the memo itself was parsed, shown in the preview, and then discarded rather than saved anywhere. Worse, a statement whose entries carry only a memo and no name imported with a completely blank description. Now: Description, Notes, Vendor and Reference can each be pointed at any field the file actually contains, the memo is kept in the transaction's notes by default, and a missing name falls back to the memo instead of importing nothing. Date, amount and type come from the file's structure and are no longer offered as mappable, along with the income/expense, account and currency columns that these formats never had — those dropdowns are gone rather than left on screen doing nothing (#338)
  • The import preview showed every amount as a plain positive number, whichever way the row was going. The preview is sent each amount unsigned with the direction alongside it, and it drew the number while ignoring the direction — so a statement of nothing but expenses previewed as a column of figures indistinguishable from income, and the step whose whole purpose is to be checked before anything is written could not show the one thing most worth checking. Amounts in the preview are now signed and coloured: an expense reads -€91.29 in red, income €500.00 in green, and the column is right-aligned so the figures line up. What was imported was correct all along — only the preview was silent about it (#339)
  • A negative amount written any way other than a leading hyphen imported as income. Only -1234.56 was understood; every other notation had its sign thrown away with the currency symbols. That covers a trailing minus (1.234,56-, as written by a number of German and mainframe exports), brackets ((1,234.56), the accounting convention several US and UK banks follow), and a typographic minus or dash in place of an ASCII hyphen. A trailing minus was the worst of the three: left on the end of the number it also pushed the decimal separator out of place, so 91,29- imported as income of 9,129.00 — a hundred times the real figure, on the wrong side of the ledger. All three now import as expenses, and a lone - in an amount column still means "nothing here" rather than a negative. If you have already imported a file with trailing minuses, re-importing it will add the corrected rows rather than recognising them as duplicates, because the rows that went in were keyed on the wrong amount (#339)
  • Dialogs on the Assets, Pensions, Savings Goals, Debt Payoff, Tags and Import pages opened behind the sidebar. Fourteen dialogs — including Add Asset, Add Pension, New Scenario and Add Savings Goal — were written inside the page content area, which Nextcloud paints as its own layer. A dialog can never rise above the sidebar from in there, however high its own stacking order is set, so it appeared cut off behind the app navigation. They now sit alongside the dialogs that always worked, and cover the whole window like the rest
  • The remove button on a split row sat under the Description box instead of beside it. The row's Description input was written without its closing bracket, so the browser swallowed the tag that should have ended the field and folded the remove button into it — the row's fourth column stayed empty and the ✕ dropped onto its own line. It now sits at the end of the row where it belongs
  • A mapped Type column is no longer ignored, so unsigned exports stop importing as all income. Mapping a Type column (Expense/Income, Debit/Credit, DR/CR, Withdrawal/Deposit, …) had no effect: the direction was always taken from the sign of the amount. Files that write every amount as a positive number and state the direction in a separate column — Nextcloud Tables exports, and a number of banks and budgeting apps — therefore imported every single row as income, quietly moving the balance the wrong way by twice the amount. The mapped column now decides the direction; rows where it is blank or unrecognized still fall back to the sign (#333)
  • The import preview now warns before a batch goes in the wrong direction. Two new warnings appear above the preview summary: one when a mapped Type column is blank or unrecognized on some rows (naming how many), and one when nearly every row would be booked as income into an account whose history is nearly all expenses, or the reverse. Neither blocks the import (#333)
  • Every transaction showing "Unknown Account" after restoring a backup. Restoring a backup gives every account a new id, but a page that was already open kept the old ones, so nothing in the ledger could be matched to an account and the whole Account column read Unknown Account — with nothing in the browser console to explain it. The same happened in any second tab left open during a restore. The transaction list now notices that it is holding a stale account list and refreshes it by itself, and a restore finishes reloading its data before reporting success (#333)
  • A failed accounts request no longer blanks the Category column too. If the accounts request failed while the app was loading, the rest of the load was abandoned as well, so both the Account and Category columns fell back to Unknown Account and Uncategorized behind a generic "Failed to load data" message. The two lists now load independently, and the message names which one failed and says to reload the page when an expired session is the cause (#333)
  • Select all now counts during reconciliation. In a reconciliation session, the header select-all checkbox ticked the row checkboxes visually but the Ticked total and Difference didn't move, and the ticks never reached the server — so they were also silently lost when leaving and resuming the session. Select all now registers every row it ticks (or unticks) with the session exactly like a manual tick, and no longer wipes ticks made on other pages of the list (#337)
  • Deleting an account that still has transactions now offers to delete them too, instead of failing with an unhelpful message. The delete failed with "Failed to delete account: Failed to delete account" — the real reason (the account still has transactions) was being replaced by a generic message on its way to the browser. The prompt now says how many transactions the account has and offers to remove them along with it, which makes a bad import easy to undo; decline and nothing is deleted. Transfers pointing at the deleted transactions are unlinked, leaving the counterpart in the other account intact (#336)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureBbOGARv5bo0EfD87OHApDK4LSAVbklBnbu7Q0XNAXlA/b120kU9X1ByNzLNwChmoeOLSrKp+saviED0SZkaaD2VdC6KM+2NghhWl/8RsDzdjLnUS5mbhQ04KOXOClJ1iHzwKIRJvAkStGLPAP/McI7ol6QLHi3ABWXWDlBcT6bGKDC6v7cmbh9jOeoys4phwH0uJE9pOVlQg7SfHGd/VJKr6pcScapT9P5dOBj878vpqjYSc3KIFvQ5OfA9C836sCseYxi9jM8YPoaw+LzTfX5/t80Fv5I2woXsvXnwtjijARCotyD1uZ9QMAy7M5LLkEm6yUGjJYrEBMBpc3h8fiC7muLojTK+J9O7zk7oYNN8D6Q2YqdJ3e84cEagzf83gbKicTPX4kJ9C8bvUQzK5roVtgFwat/Ndu9c2uK/rwOUVmDKPHdzt3/SQQAl9712dX7lZTJVN9r3dm87AL1nfaJghemZOfQdcQwFkahMlHZOm+B0xKrSUqQWyfbw4xezPvVZEudqpPIhQ0lIlFro93ziB7KBUJvaJCx0UNMFr2Z4zCDY64wKLaq1sgSm8HQ4QxSdL1+bPWgTG+BVzchvbx6Cmh7DHmXTAr5XGPzEczdMWY0t16uZ4ZzftT5Ss+S/NKpV37SiFKPOKWzou4BFGU9qwl0DeYKy4E+/EDMX0W80=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.40.0
Release Details
UpdatedJuly 26, 2026, 9:40 p.m.
Changelog

Added

  • Keyboard shortcuts. Budget can now be driven from the keyboard. Press ? anywhere for a cheat sheet. Globally, / (or Ctrl/Cmd+K) focuses search and g then a letter jumps to any page in the sidebar (g d Dashboard, g t Transactions, and so on — every page has a letter). Any dialog now closes with Esc, traps Tab inside itself, focuses its first field on open, and saves with Enter. On the Transactions list, j/k move a row cursor, e (or Enter) edits the highlighted row, and x selects it. Shortcuts stay out of the way while you're typing in a field
  • Export and import your import rules as a file. New Export and Import buttons on the Rules page: Export downloads every rule you own as a single JSON file (a lightweight backup, or a way to move your rule set to another instance without a full data export); Import reads such a file back in and creates the rules. A rule referencing a category or account that doesn't exist on the target instance is rejected and reported rather than mis-filed. Rules shared with you are left out of the export, and rules remain part of the full data export too (#318)
  • Import rules can now be shared. Rules join the list of things you can share with another Nextcloud user (alongside accounts, categories, bills, income and goals) — pick which rules to share, read-only or read/write, from a share's Configure panel. Shared rules show a Shared badge on the Rules page, can be run and (with write) edited by the recipient, and run during their imports too; only the owner can delete one. A shared rule's set category/set account action only takes effect for the recipient when that category/account is also shared with them, so a transaction is never filed under something they can't see (#320)
  • Import rules can now match on the account. A new Account condition scopes a rule to a specific bank account (with NOT for "any account except this one"), and a companion Account Type condition matches by kind of account (checking, savings, credit card, …). Both work when importing into an account and when running rules over existing transactions (#322)
  • Tag sets now work on shared categories. Opening a category shared with you shows its tag sets; with write access you can add, edit and delete tag sets and tags on it just like your own categories, and read-only shares show them without edit controls. Previously any tag-set action on a shared category failed (#328)
  • Bulk edit can now clear a transaction's category. The Bulk Edit Transactions dialog's Category dropdown gained an Uncategorized option alongside Don't change, so you can un-categorize many transactions at once (#332)
  • Deleting a category that still has transactions now offers to reassign them. Instead of blocking with "reassign or delete them first", the delete prompt offers to move the category's transactions — and any in its subcategories — to Uncategorized and remove it in one step (#332)

Fixed

  • The browser Back button now moves between pages inside Budget. Switching pages (Dashboard, Transactions, Accounts, …) records a history entry and updates the address bar, so Back and Forward step through the pages you visited in the app instead of jumping straight out to whatever you were looking at before you opened Budget. The current page also survives a refresh, and links that deep-link into a page (e.g. from search) still work.
  • Bills with "Auto-pay when due" turned off could still auto-pay themselves. The auto-pay flag (and the other bill toggles) could be read as on when it arrived as text rather than a true/false value — the classic (bool)"false" trap — so a bill created or restored with auto-pay off could still be auto-paid. All bill toggles are now parsed strictly as booleans on create, edit and import (#335)
  • Cryptocurrency accounts and their transactions now keep full precision. Amounts were capped at 2 decimal places on entry and storage, so e.g. 0.00012345 BTC was rounded to 0.00. Account balances, transactions and splits now accept and store up to 8 decimals, following each currency's native precision (BTC 8dp, XRP 6dp, JOD 3dp, and so on); fiat currencies are unchanged and still 2dp. Amounts on bills, recurring income and savings goals denominated in crypto are not yet covered (#331)
  • Shared categories keep the owner's order, and editors can reorder them. Recipients saw shared categories in an arbitrary order and couldn't move them; they now appear in the owner's order, and a write-share recipient can drag to reorder (the new order applies for the owner and everyone it's shared with). Reordering no longer silently fails when sort positions collide — the whole sibling group is renumbered on each move (#328)
  • Shared categories now open for the recipient instead of doing nothing. A read-only shared category couldn't be selected in the list at all, and even when reached its detail/recent-transactions/spending endpoints returned 404 (they looked the category up under the viewer, so one owned by someone else was never found). Clicking a shared category now opens a read-only view showing the owner's transactions and analytics for it (#328)
  • Recording a bill's payment failed when the bill used a shared account. A bill can point at an account owned by another user — a partner's shared account — but marking it paid, and the one-click Record transaction repair, threw "Failed to record payment" (a DoesNotExistException in the log) because the transaction was booked against the person clicking rather than the account's owner. Bill payments are now recorded against the account owner, so a share recipient can mark shared bills paid; a bill whose account was since deleted now shows an actionable message instead of the generic failure (#334)
  • A one-time bill marked paid without a recorded transaction could not be reached to fix it. After a one-time bill is marked paid it deactivates and drops off the Bills list, yet it still appears in the Payments without a recorded transaction card telling you to assign an account first — with no way to open it. That prompt is now an Assign an account button that opens the bill for editing (#333)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureTlx5adQ84X1cU4v1VoYON+yY22etMZSb58OURK5dpJ/bpQdLjdhL6stjRFGshNhEHr1Ra/KTZs7/uCZLyvq+M0XBYGD+voy+pwmXwa6Wylyi99fJ2UhiXPHxKiExVq1EJY/PA7LcHAQy639r04gbQ4Q/BvDrOZYWAZuYCLrZrZFclfoIlzf/Ra5SFuCuWguuOd79cU/tXViv8xntJBIcIXoN58cadHF5iTo3Mt2XO7sNsUs7A8+1HDXsUldblvmLFFpH9ubJdYVDKqdzA104yRb0uPH08Zd6+y764r+uIsahSB/RwF3kJ20gcv5nurCaf9FvsI06PiyQnR73jMzlnoAaWxnSPZwGDa+gvQ/t56H+m+A9DlvVgnxexUa0C+Ga7cphcgVKWPWaRZFQzeofrcJ66wAH9uh338pw2R2Lq5F+s2NCOKuKo6uXocpf+VZ9GTsfRIrDEGL+4FwkFkxd0tHUBoohsOhROk/tXphvl/mIh5m4m3pRsjm7GviZASYoTXJe+kdclUUzpFMuXGrOFjSXCd1Plk2XsDMiHBzPEXAkaPlL9hdluXiuCCXrUYIF+S/U60qB1MuWRlwzTH80RovEgvyKGwZtzlDPtNLF0hM79iABKE5UgP1km9MRm7dyDWQDdogfWq+Oy97EJH8TDtYvuO2I79lQnppc9WrYB5E=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.39.1
Release Details
UpdatedJuly 11, 2026, 10:22 p.m.
Changelog

Fixed

  • Share recipients saw wrong dashboard totals. For a user whose accounts are all shared from someone else, the Income/Expenses This Month cards counted transactions in the owner's "Exclude from reports" categories — the exclusion list was built only from the viewer's own categories, so the owner's internal-transfer legs inflated the recipient's income and expenses while the owner's own dashboard was correct. Shared categories now keep their owner's exclusion for every viewer, and per-viewer "Hide from my reports" mutes are honored by these totals as well (#326)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignaturePTjw+Z1r+sKWQmZSlNfYPSTl5PFejqjMEgNyvQR1FXSKor9zNXxtxcAM0eYYthPn9YEprCKS9V6NC699ZbeWK6WbdRtprmP+rsvCifpjQyVtPDGLJ11LWzLVgw84pTHcolsdY756JO6KWW8hxp63bq3s4QE4rs3RTCEyHSpzpZ1pXSydTCTvheL1M/rtg3XyKpzBkoOqGh39Dnh9TH7JQt+cCB8VD84aeHcsvnxUkQJU3AmZwYGcP8wSNeLmDjt1S9yCv2h8NAReLQeTMbmdzNJtioLLiifkedz5bEgjVximgqI99mmV+8uhRBY0keT1hWXR6En4IrRkiJwlEyNZRHkukMa9jNmoNVvoRYCuQOVZ1wWGtkS8MCz5Ig63yPijEMh1bqnoi3+WA1g8s23dJVIziAHSKl0F+V7DKThsw2jBouMZeZ7bG0nMS9bFLcndAm1MbpWyuZATotUExNeYhEZEIwUOuF+esV5lnDoHTf0i/q6OJGa4hPPiNTE/rH4PS3Z4pdEZ4V9YhxYfsSs/9y+Y7xg/ZQWnLq2YVsTR7V8FgQwU4Bi8OGLsfbYZhSaUnHv60ObUB2U4WkD1mZZqDHKJXAIgVGulvHFAkXQVeGpRqbUCQNvgiVU8hfRaRmEr/y9Usub/3srDJn7qybeAxfOxA7rL+AlakEZBECHPJlY=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.39.0
Release Details
UpdatedJuly 11, 2026, 12:57 a.m.
Changelog

Added

  • The Bills page now flags payments without a recorded transaction. A warning card lists bills that were marked paid in the last 60 days without a transaction being created or linked — the situation where the app balance silently detaches from the bank. Each entry has a one-click Record transaction repair that books the missing payment (dated the day it was marked paid, both legs for transfers, splits applied). Deliberate skips via the Skip button are not flagged (#274)
  • QAR (Qatari Riyal) and JOD (Jordanian Dinar) are now available as account currencies. JOD amounts use the currency's native 3 decimal places. Automatic exchange rates cover both. Requested in #321

Fixed

  • Editing a monthly recurring income never saved the changes — the app showed "Income saved successfully" but the Expected Day (and every other field) kept its old value. Any update whose payload contained an empty field (a monthly income always sends its yearly-only "expected month" as empty) reloaded the entity mid-save and threw away the edits. Thanks to @redsteadz for the fix (#324, #325)
  • The "Exclude from forecast" checkbox on a transaction appeared unticked whenever the edit dialog was reopened, and saving the transaction again then really did reset the flag. The flag was stored correctly (including when set by an import rule) but the transaction list never sent it back to the browser, so the dialog always showed — and re-saved — it as off (#326)
  • Income/Expenses This Month (and the other report summary totals) deducted transactions in "Exclude from reports" categories without converting them to the base currency, so on multi-currency setups the deduction was applied at the wrong rate — and for a single selected account the deduction wrongly included every other account's excluded transactions too (#326)
  • Imports no longer bring in flagged duplicates by default. The preview's "Show duplicates" checkbox — on by default — secretly doubled as the skip-duplicates switch, so every import ran with duplicate-skipping off and rows flagged Duplicate were imported anyway. It is now purely a display filter; a new explicit "Import flagged duplicates too" option (off by default, resets each import) covers the deliberate re-import case. The preview's per-row checkboxes, which were never actually read by the import, are gone, and the New Transactions count no longer includes flagged duplicates (#327)
  • Marking a bill paid no longer suggests unrelated transactions as "existing" matches. The Existing Transaction Found dialog offered any unlinked same-day debit as a candidate — cigarettes could be presented as a "match" for a mortgage — steering people into marking bills paid without recording the payment, the classic source of app-vs-bank balance drift. Candidates now must match the bill by amount or name, a weak match is never pre-selected (the safe default is creating the transaction), and the "Don't create any transaction" option now states — and warns after — that the account balance will not reflect the payment (#274)
  • Overdue bills no longer double-book when marked paid. The scheduled placeholder pre-created for the next occurrence was written as an ordinary cleared transaction whenever the advanced due date was not in the future, so it counted toward the balance immediately — alongside the actual payment. Next-occurrence placeholders are now always scheduled, regardless of date
  • Restoring a backup preserves every bill setting. The data import dropped most bill fields: custom recurrence patterns (restored bills then advanced one day at a time instead of quarterly/etc.), transfer destination and description pattern, auto-pay, reminder days, tags, split templates, start/end dates, remaining payments, forecast exclusion and the future-transaction opt-out

Changed

  • The Match transfer dialog now also lists candidates from accounts in a different currency (any amount, within the date window), so cross-currency transfer pairs — e.g. imported from CSV — can finally be linked by hand. Automatic matching after imports is unchanged and still only links exact same-currency amounts (#326)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignaturegJm3RDjkvl1EBICN6Us5TsX5SdQbSGnRHvRIZmLsYaclkDVqW/mYCBjVgwjU50ifkv72zl3kxf5a8S3yxpo2WX6cnhkyyibLhs5Uzdrj9Egw47yYgMun8WH4647Y0uGP7QrX3Yf51SO7Ve+JWgdMRX+hWvG4K9hxUgAwWR3AmTYRsRXpmsNrOr97q2SPC3V0g9bAARDeSeWDGQ8SR05+OMIrQRj0Ct56fC1cTNWzHpPT+Qs17SJJcUUnK3tJWsM3wvGiwk62YMBy1cv1jx3JkOXnYvsa8bpSG3sL7aqr05QkAkvL9sSGxka6mDrC3CN1LHlwwQjPjWwoX9YDtOI04j0JPd0SzlhMYILaZNyouhoNTuY5YhDIG4aLjg737AAEBHgU3jvpWxaM8Oz2+9he9LkAJW6qA9DuzB/FmDNKxyJTmQ6S0LZ21d+Hkr0LD/2uKRSywlRBld+UNCWby8YrgIkyGomPH1rjDG28y1ApiqSozetcjSvDYwqULM2mLXU9OjD9a8UJk8B1R4Xd0TqgMmDCaAZrTdRLYYdTZEEaFbnDkbm8p4z2q+UGfn/UCNEOkg5pbu1WAsRubIKkPzNTz7gTSLI9u+qJfvoZg9c3Ae1OhXWDD9k/2Z+pCrbJhu8yDX+2JukXoAxNS+bnxaDxdoxRzIM+9jcbb0eyG3wJuLk=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.38.0
Release Details
UpdatedJuly 7, 2026, 1:07 a.m.
Changelog

Fixed

  • The account selector saved in the gear settings of insight tiles (Monthly Comparison, Large Transactions, Weekly Spending, Year-over-Year) was silently ignored — the tiles always showed all-accounts data. The saved account now actually scopes the tile's numbers
  • Importing transactions that trigger the Auto-Link as Transfer rule action no longer shows "Cannot use object of type Transaction as array" on the import screen. The import itself always completed — the error came from the transfer-linking step afterwards, which also means those transfers were never actually linked (#314)
  • The Recent Transactions dashboard tile now honors its "Rows to show" setting above 8 — the display respected the setting but the data fetch was hardcoded to 8 rows, so values of 9–20 silently showed only 8

Added

  • Edit auto-categorization rules as JSON. The rule editor gains a Builder / JSON toggle. The JSON view shows the raw rule structure — editable and paste-friendly — checked when you save, and switching back to Builder repopulates the visual widgets. A Copy JSON button makes it easy to move a rule between instances (category/account IDs are instance-specific, as noted in the view). Requested in #318

  • Hide shared categories from your own reports. Categories shared with you gain a per-viewer "Hide from my reports" toggle on the Categories page. Unlike the owner's "Exclude from reports" flag — which stays owner-only because it changes every viewer's reports at once — this only affects your own reports and dashboards; the owner and other viewers see no difference. Applied at the SQL layer through the same choke points as the owner flag, so every report and insight tile honors it consistently

  • "Exclude shared accounts" on the remaining dashboard tiles. The per-tile toggle added in v2.37 now also covers Budget Progress, Monthly Comparison, Large Transactions, Weekly Spending, Category Trends, Cash Flow Forecast and Year-over-Year (shown in the gear menu when you have shared accounts). Bills, income and pension tiles are deliberately not included — they show entity data, not account aggregates

  • Clickable spending charts. Clicking a slice (or bar) on the Spending by Category dashboard tile or the Reports page pie chart jumps to the transaction list filtered to that category, scoped to the chart's date range and account. Tiles set to "top-level only" include the subcategories in the filter so the listed transactions match the clicked amount (#317)

  • Per-bill opt-out of pre-created transactions. The "Create future transaction for this bill" checkbox is now a persistent bill setting instead of a one-shot option at creation. Bills with it unticked never get a scheduled placeholder — not at creation, not after marking paid, not after skipping — and toggling it on an existing bill adds or removes the pending placeholder immediately. Previously the checkbox only affected the moment a bill was created, while every payment re-enabled pre-booking unconditionally, so unticking it never actually opted a bill out (#311)

  • Convert a transaction into a transfer. The Match transfer dialog gains a "No match? Create the other side" section: pick one of your accounts and the app creates the opposite transaction there and links the pair as a transfer. Until now the dialog could only link two existing transactions, which left no way to correctly book payments to accounts that have nothing to import — e.g. a loan tracked as its own account (#313)

Changed

  • Scheduled (future-dated) transactions now show a Scheduled badge in the main transaction list, with a tooltip explaining they are not counted until they occur. Previously only the account detail view had the badge and the main list showed scheduled rows in italics alone, which made a bill's pre-created next occurrence easy to mistake for a duplicate booking (#311)
  • The transaction list Total no longer includes scheduled transactions — they are placeholders for money that has not moved yet (#311)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
Signatures/wP/jWqAxqTStZPLKWl/5nyJk/xpeAom+Kp7KakVOdJmzhNv/Z6KM/CUUOrGem4Qj5G1OEZ2tNrPkTneCVvfFU2S5aoayMDgcRaGquqwZisM/4a0KV9Husjq8mV0RVoqco16HBH8PUY+kYsbeWRcSp2q38Zq99L04zb1x5XY1rGe5YdP4/IydUoMpyzTtsGF00Tj6OUAMvlDTnJqCcetscuXX8yo33xm0dUfLxjZD2f9hsn8UTCwNN7v1+yBhwNN4jJsfyGTN+92XV2YDhRCfVWq/3bGqphHo+nYQvbyjndJRcaAwybOquX6MH7+wpDa5wpvNw9xzc2sYNm2FM08SYep3cX7uoXngifGZu2FBqyNHQ198dqEwqJbEVv2DrK5cAnQkbSS1glYYney/uXAlsqLEinHirrShNYRoq+ZEkxUhpdung3zSWwPe0Fd/mWh2chHiTV20A2tCrv7FRuRadpf75bq+y0xuIglVZQy5E1dT2nk3lPUUwB01w/ggmwrJ91hOchPoyoRoDhoBNxZJs903bQejWR/MdZ9pbXVmwxj1EOq8oWfWeQ5B+OEz/LbcplibODsNv6IUIYU++gxK8d2XCVzBgV2ayMqsRxFDxItgluqDcu4oTW8mh3A4z33PvbeCFFMsj2bKFbOslmuT2ZiVl58oTaQRTh61xeKEA=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.37.0
Release Details
UpdatedJune 27, 2026, 11:16 p.m.
Changelog

Added

  • Exclude shared accounts from reports. When other people have shared accounts with you, the Reports page gains an "Exclude shared accounts" toggle so you can see just your own accounts' figures. The same option is available per-tile (in the gear menu) on the account-based dashboard cards — Income vs Expenses, Spending by Category, Top Spending Categories and Recent Transactions. It's off by default (shared accounts are included, as before) and only appears when you actually have shared accounts. Note: a transfer between one of your accounts and a shared account can only be partly seen when shared accounts are excluded, so income/expense totals may be slightly overstated in that case.

Fixed

  • Saving share settings failed with "Some entities do not belong to you" (HTTP 400) when the "Auto-share new" toggle was enabled for a type, or after using Select All — the auto-share toggle (which shares the same data-type as the entity checkboxes) was being collected as a phantom entity and sent as a null id. Entity selection is now scoped precisely, so share settings save correctly with auto-share on (#306)

Changed

  • The Categories page now also lists categories that have been shared with you, shown read-only with a "Shared · <owner>" badge. Previously it showed only your own categories, so anyone using a budget made up entirely of shared categories saw an empty page even though the categories worked everywhere else (#306)
  • Categories shared with you at Edit permission are now editable — rename them and change their colour straight from the Categories page (they carry a "Shared (editable) · <owner>" badge). Read-only shares stay read-only, and a category's type, parent, budget, report visibility and deletion all remain owner-only (#306)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureFqJ17XG/szTfkAMsF+oCODYGClVjdeGArgFi3SrgeGhg4CFFzIVO98XEnYhxeCnwOcYGivzy0uhe60/Vv7kgml+lIVvRL1EZOxvjOES2KksQ50fqxGZSNz3EL54EA6R3Yvo6uLFBM9cbK0mmY5H+4i3UozKhKwzRa6PJLIZzpBsjtprJXHojWsQMR5KY7WDDbb9yD32uYzMnrXMxOiQ2PZGtG7aIhLS6DzC7Mtp/oLUgyRqBWoYMUWWLLi1qyeOr4/8Tdm9H5I36oxeoX2ZQlVuprpRjDPW5EITrljbyuIPy3CdAFn5tvvt8rkurEgCtPAaMv7gSXRZto6rJJqS4woUqX310+J0re9qa53Ls0J7Kezo5WpENoaFsvT6McjVG/4k6k4YN1/l74p97fFfR+1T2kC5VptpwVz4GZ2aSF9t226Sdkft7sv72aC3oQpa4PN3PIWj113aN2X5nnCGiD+NUW282/yAdacvMWVgB+t+Rbm0FIyWtGnbw0dKAlY3CAmQoBvqX9f2vqn1OFDxJhejg/i7+FAWQD83LIk6u2kNg/N4e2+hgLtO45wd5MU6TLXXTrb1mlikbbiP80Rla1p50fScosYTCqjJfz2lh5U6D2h/nquGHHvhf4R9q7eSkykmELHZUKiUyYlrLrOfiuxGRqaWSQWp9hm0CUog1HBE=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.36.0
Release Details
UpdatedJune 27, 2026, 1:15 p.m.
Changelog

Added

  • Auto-share new entities. Each person you share with now has an "Auto-share new" toggle per entity type (accounts, categories, bills, recurring income, savings goals) in their sharing settings. Turn it on and anything you create from then on is shared with them automatically, at the permission you choose — no more sharing each new bill or category by hand (#306)

Fixed

  • Code-integrity "Some files have not passed the integrity check" errors reporting FILE_MISSING for js/.htaccess and vendor/tecnickcom/tcpdf/tools/.htaccess. The app no longer ships any .htaccess files — the Nextcloud App Store strips them from the published archive, which left the signature expecting files that were no longer present. Neither file was needed (the JS one only set a redundant cache header) (#307)
  • Deprecation warning in the Nextcloud log — the notifier now throws UnknownNotificationException instead of InvalidArgumentException for unrecognised notifications, as required by Nextcloud 30+ (#308)
  • Reports and the dashboard summary were empty when a single account flagged "Exclude from reports" was the only account selected. Accounts flagged out of reports are now only dropped from the all-accounts views; explicitly selecting one shows its data as normal (#309)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureYxqf1NnAucAiXFVdwVmQJPaPUyuExQ8t/dwv4tDVpFb1kXDtGcIWoAdspiDz+HwdyPe+ul+/2GcDWiLPTF3TvIHwIaV+h+guDRYBEHMY95+Hy5W0BSuwBC7gto5dfsZEhL5xj5OsRIYrY/Fo8Tqj99kVzDK560o9NgI6Bp6ZkQpbwPRbTnbxUX27oF0oDjrg1ArS4IiE4ghZW1ct74Mlv4uoeg5zaVQlucrZK+rBJXixtpDnImHLPMkTvd+1bmkQTFtvArS1A37YkXkLKrKn4pzWvwv/q46ddih1NXBC7o6UoBwP1pWB1OxgNq3/98OdWyPs4GLumMmRdg+7PbY95Go97lBbNc/1mrBB9qQPXirFxYHMZWVDSRHSNRJ9cSMnZA/YzsVeOZOVkIwJWXhC5YGAEN8nq8HKIMBHzmi6UYdGM2VvGPmNZ+K3wlGMIkKlVfWfIJ7XIOCe6OLvQbwR/ATZ7pUyOE+AR21uu27zWGJ4iB4y/eCfCSE8vIxyPW7L0dwkzxU13iNNNxAUQgbNrs8EiQBLQlTCaBWCWp296Dds5nEGMEilQKX9vEXAhY9KRG5dzJjoZhZ14tWA3Hjp+5/Gs2AM4Bh3Rp1OGdhfQhFDmt/2GXcL16lfDcX28K1ub4FPYE8MEz6qDmLhqqwv9FeXQQbT/ZKdQn8NwuOlGFE=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.35.1
Release Details
UpdatedJune 25, 2026, 3:28 p.m.
Changelog

Fixed

  • Categories marked "Exclude from reports" are now consistently excluded everywhere, including the Income vs Expenses trend, Category Trends, Top Spending Categories and the monthly spending chart — not just the dashboard summary. Exclusion is now applied in the database query itself, so reports and dashboard insight tiles can no longer disagree about which categories count (#219)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignaturebX/9kwpiVjwDj0f2eU5xNE7zUpt8T/nkGCFg9HnDQoKynM7c1KaXhbh4isVQBbgy5kPGXSDP7DRfuSTYY5/M3PSv1JE8gOk/9lz2AGmTqlXrf4Kgq9oARAGcVHXB955dLvDkj6Vrk7zZ9cwrjq4aMBu02dW8ZgyAHStXybiWmkAbIxK768MHM4n5FXTRFw3P/ELVlDjCxgIpxVxD5EZaaA+n7RrjN9MRY2R8/GN7Og7yijcmnutMWtna4K19B9c3ShcfUkrwotvCUz3c+K10VQSfzUpN6RoindDB0j716jUZQ6IKzXBNNRiOjQ6N6s1MlmKwjyFyw0PY509hJY+dtjBEQBbFjK0pw7ZElfW4zDWteDzWRm7M1VjzUlRgPLsg7CJ980Rg8suZAMh3UH251vymCH0ykpMYqK1qiWDurz5GWdaDov6Z0YkQPQLnszzPa60kbO9VUHrYnG+6+KA6GoPW0EHFEqaUxXv+mRLr8Pm8BhjCiDghO7mlHZFN95hN5gkNyBdIPA9JmXAdnkrJBSQaDvZdejDwFJL+T+PgA2f9JomB8BQ/WkZ4uukyKUUFYToOhntQTe7dfE+I4VsD6BycbY7smaY/xGx6EvyXfntpYkgR7Fe2rYKaxBrcRcnhTmQBeLLz85M7fLKVjME72niQdRIZRaMZ+OmpCxKK2qU=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.35.0
Release Details
UpdatedJune 25, 2026, 12:36 a.m.
Changelog

Added

  • Pensions revamp. You can now record a contribution as a transfer from a bank account — the matching withdrawal is created automatically and kept out of your spending — and record withdrawals/drawdown back into an account (#304). Scheduled (recurring) contributions (monthly/quarterly/yearly) can post automatically or on demand (#251). DC pensions gained a configurable projection target with a progress indicator and a "today's money" (inflation-adjusted) view on the growth chart, plus an optional Pension Projection dashboard card. Bank legs that fund a pension show a Pension badge in the transaction list.

Fixed

  • Background-job "class does not exist" log spam that could appear after updating PHP/Nextcloud/the app: the app's autoloader is no longer "authoritative", so it falls back to PSR-4 and self-heals if PHP's cached class map is stale after an update (#305)
  • Newly-added dashboard widgets now load their data immediately instead of staying empty until the page is refreshed.
  • The pension detail panel's balance history and activity are no longer broken — those views called endpoints that didn't exist; they now show a proper balance chart and a merged timeline of contributions, withdrawals and balance updates, each removable (#251)
  • Editing a split transaction with three or more parts no longer zeroes or overwrites the other splits. The last split row is now a read-only "remaining" amount (transaction total minus the other parts), and the dialog blocks saving until the parts add up (#303)
  • Spending-anomaly notifications no longer crash with "The arguments array must contain 1 items, 0 given" — a stray % in the notification text made Nextcloud's translation layer fail, spamming the log every time notifications were rendered (#305)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureF/7pZ4sNzjJuqXXZoHmO+9OmUzkQz6ZDke3vkONfZ2uGfzBpwpDSIiGlfNv6gt40Ho8NTPNd0JuM+ESRohLlPAAftFoF+L4h+asH5s/lncoxgTZevEFl7NE14s+sPVdGdZqXGi0b3mohB+f1jOudpVbgB0bmCDvnZMEKiMSjB7XwH9iQqzu/8WyQNd28w+Bz2TbyAfu2PCtdD6jsmVCbvtCkmEdKOVJzRWuExH+vwvZ0ltX3mtorPl6HEzqKJWoDYG3tdbpSwml6w9F3qj8naVZ3tZYBrfvwABHoMD1LYpYwRss5C9UpJvu6UFfKQ4Xso1tBu5U+tYlAPKLbQ5J70o0C1aP66R+FvL8RlMHpY93duR32qZkT/6xV0NYQpd9xzXoLbB5YkZJuBLV8m3oP9k/pNEy8vwF5Kkb+/6zrJt4aSH/iiAqBoqvuT1itwScYsNpGHXWOrGHioCKiGkcMvamfr7her1fQ42wNiVIVWKaxNtjeYrVjmHCtWA2awjv3XRfcXdcL/4stuDpXxQ0Dnv2S/Ey9ZbGbqpc0DNyPZfKie5/QK5OnHPW9F8nHUsEhxDLbNezo11fKm1ykE0ja4nTZFKL3ml2D4aRDMYQe35MWJvW/fLcNW7dYOV969ZI52G8jTIUI/YphcNfCNK24fVkljrcBSybr8WavbELxVR0=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.34.0
Release Details
UpdatedJune 24, 2026, 12:34 p.m.
Changelog

Added

  • The transaction list filters now include a Reconciled filter (All / Reconciled / Not reconciled), so you can quickly see which transactions still need reconciling (#301)
  • A Budget alert threshold setting controls when a category appears on the Budget Alerts tile (default 80% of budget). Set it to 100% to be alerted only when a category actually goes over budget, rather than when it's merely approaching or fully used (#293)

Fixed

  • Creating a category (or account) no longer fails with "Unknown column 'excluded_from_reports'" on instances where an earlier upgrade was interrupted or restored from a mid-upgrade backup. A self-healing migration re-adds the affected columns automatically on update (#302)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
Signaturey+Qi2+U6CexZu8i+0DGrbLXwFbp+cHLVW62WRSfrovEAuJrnZy8paqAacEaE570GoHVd1b23Yihz4oDfOYStLASDVFk7xhVrarnlIqv4EH+Jyw0IR2iaLR+IvhJmSZc9N5nQ42i2z8UYetvQo0znzzNPmpT2FEJB1Sty9kCfHL7HiisG4hYwJp528McMVXgCYfn/XOZUQzOVY6rvis1hP8CiFbE4UMUQj/SgDpRjimcRCZy8fsRLgZHcfO2+BKYCSt5lqLDJSzsmewBFNMVWDdtZwPUxqyK8xaTwSnwWNBNXBRg5ZcDLJhhIJtk9cEezVTdJBZTw3wx7iCztR9RFQi9CZsRz9U9S4jLEdcV8m6OTa8XG22s2ZHt+I+hisGtlC1TOQ5fpPfSe9onWdA8jgC68RAFeOLJ+KmSkLQN1bbr9gUw47oB09Yd9sEtUDcFapfv+x9Zl3/s4ExwO6xDS/bwmRyZ/fq1z2jhVu/lMFd//+9ciOrCdty1p7440JVs/sx71Qcc0mRhZsMtIRYyBD2EFceUHx8cQCtOLL99+JtGkTakCMCwIxghuGoXnrq+9mRWjgROn1ysGEHDUyC8ZKCJ5f8TXOllqX2g+2fyOpFzHR66oP7lPwI5y3eW4VYJGT/lQzTavAtU148X2XaBUz+XA8Djuco3CCuGJuT9FhSU=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.33.1
Release Details
UpdatedJune 18, 2026, 3:03 p.m.
Changelog

Fixed

  • On some installs an earlier update was recorded as applied but didn't fully run (an interrupted upgrade, or a database restored from a backup taken mid-upgrade), leaving the excluded_from_forecast column missing — so every new transaction failed with "Unknown column 'excluded_from_forecast'". A migration now re-adds the column automatically on update. (Also surfaced by the new database-error detail field added in 2.32.0.) (#289)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignaturewGNDwrdOGHhLxiEiJQDsZrcL4BFQbGBTjeDU/3VJql8bIeDBHITKzJ3HH47kV1bFmsZ35q0o7xh/r4q6Kj9/SXM8gQCTxEtQ0q80MS85LGy5+9dUtJ0yBvrLfE6kwpNPDH+kqwBVcAGxmLr9vYau5uTFGdeB0WZ3gmesUvT5kuZfdREwJDQ19QWR40pJjHRcWqM5KnXCT1/wq7btWj9s/Vf9GVQvo85g9R7adODG1PVBr4gM6R9nTgsrn+60BJvNNO5f3W3wbuzvqaJhtVdknB9Z8fc7Vbq6mh6TgSPBmXgiK2VdCAWPaW2EmpVL8iwgOGazPGSajPkMZNNZDhzDNEpLcveJl61g/x5dVAxOevwFnN4CaX5c/YYppjcqtoWyYgoTNMv3enF3///tD0wS68iQzcU5UNmsOOKsAUVvRnf/oOX2b13NfsKPONAxcu4Q/UG8ybPqYwXT+T6Vs+IRmoLJLnOs/BUgbqmmRIG1Wfs2BusDFKNHHWoW1Z5t+GDLGx2cyNci7+rKPRh2seML8iPrt9lNv2M5NjzIJ9Wm0Xt0FKpIetR4gDpLSRvBtINaQ0jVuYVixt1yDKMUfE6GH4sNW9rNi2ZoKptz2MIxouBmLNXezA5Y0gvIlgA11Bi0YBrKPUAtmxNl8Jyxhle2Ll5bZbsupMy1otRB/+NGEOs=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.33.0
Release Details
UpdatedJune 18, 2026, 12:52 a.m.
Changelog

Added

  • Run reports on multiple accounts at once: the report Account filter is now a checklist — pick any set of accounts (e.g. all your credit cards, or all your checking accounts) or "All Accounts". Applies across the summary, spending, income, cash-flow, category-by-month and year-over-year reports and their CSV/PDF exports (#299)
  • Saved reports: save a report's settings (type, period, selected accounts, tags and options) under a name and re-run it later from the "Saved Reports" picker in the Reports view. The period is stored as the chosen preset (e.g. "Last 3 months") so a saved report always shows up-to-date data (#299)
  • Dashboard tiles that can be scoped to a specific account (Spending by Category, Income vs Expenses, Net Worth History, Recent Transactions, and the other account-aware widgets) now show a small label in their header naming the account they're analyzing — the account you picked in the tile's settings, or "All accounts" (#296)

Fixed

  • The Reports period selector didn't drive the report on reopen: the dropdown kept your last choice (e.g. "Last Year") but the report always reverted to "Last 3 Months", and clicking "Generate Report" used the reverted range instead of the shown period — you had to switch the dropdown away and back. The report now always matches the period shown in the selector (custom ranges are preserved) (#300)
  • The Quick Add Transaction dashboard widget couldn't be used on mobile — the lower fields and the "Add Transaction" button were clipped off the bottom of the tile, so a transaction could never be submitted. Its form is now condensed (each label sits beside its field with tighter spacing) so the whole form fits the tile, and it falls back to scrolling within the tile if it's resized very small (#298)
  • Editing a split transaction's amount (e.g. inline in the transaction list) left its splits at the old amounts, so they no longer summed to the transaction total. The splits are now rescaled proportionally to the new amount (the last split absorbs any rounding remainder)
  • In the edit-transaction dialog, changing one split amount now adjusts another split so the parts keep summing to the transaction total, instead of silently drifting out of balance
  • Split transactions weren't counted toward category budgets or spending. When a single transaction was split across categories (e.g. one $1,000 payment split into rent, parking and a deposit), each of those categories showed $0 spent. Split allocations now count toward category spending everywhere it's shown — the Budget view, the Spending by Category chart, and reports (#297)
  • Large amounts (e.g. values over 100,000) on the dashboard hero tiles (Net Worth, Income/Expenses This Month, Net Savings, Cash Flow) wrapped onto a second line, splitting the number mid-digits. The amount now stays on one line and its font scales down to fit narrow tiles instead of wrapping (#295)
  • The "Asset Value History" dashboard tile (and "Net Worth History") showed its empty-state message anchored near the bottom of the tile instead of vertically centered. When there's no data the message now fills and centers within the chart area (#294)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
Signaturejj+nUiPNSYYgtQ/7XYIkJNFo8vWIHaX28Q0XTtpN6RWmrW8qrJBIs2jTaaHwebC7SB5f7GP6vQxghh9+nCWfA+KlTKbm8YJg6yzah9xdTLo/JcUhTOinlH9yYoXxMiIY9EVwQLsPmef4sprTsS9oqBeSgZ7S8WRJYnxjAuljee9q0Sfai9AK+RQzBk6kgENhCAVt95ooZ3H5ukfFBSb/kyXa3IU+ngu6g5B9DgiJfBduecdkLEfc0dhYKelUyNaZa61qoG865podTGJFCFqzoSnlCXgRcJqJHjhdTERIeu/nHQAL/PhaPy0OSWK8l+kyrGveMEKDM6LvQ0Eo6B9Ul0ORobundabEat67f/hqaTmnDldOkkEm5a0WAYeQvYeeZCNLtiF26pWk66v6eQhXsrT6IwcJ/gxaC6oS8URm5yYub2iW9nVq6uZXRMJavJr8CmYl7MSqQRVvFKGlwHvD7X+YfEs+htKGYM017iWdICfQv/wbGi5JzIxqdm7QKrV9EGxgl4GFWvY/cyGZt4awfhoy4RljlFtsfJ02askgVFUloVGKOWeqZ5NbqXMDC+UonPONQ/RPM64u0L3NdVvmcXOwA8RBHCg1qgEiVkDBSsJyhK55+1J7Yn5fIC2emSU0BXOdzSFgg3BgUbYJQHgH30AwNf1iagO/WBOYDSu4jqs=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.32.0
Release Details
UpdatedJune 17, 2026, 3:02 p.m.
Changelog

Added

  • Category by Month report: a new report (Reports → Category by Month) showing income and expenses per category broken down by month, with a column per month and an overall total. Categories are listed alphabetically with sub-categories grouped under their parents, and parent rows include the totals of their sub-categories; a toggle switches to sorting by total instead. Defaults to year-to-date, follows the report date-range and account filters, and exports to CSV and PDF (#288)

Changed

  • API errors caused by the database now include the underlying driver message (e.g. a missing column) in a separate detail field of the error response, visible in the browser's network tab. The user-facing message is unchanged; this makes problems diagnosable on managed Nextcloud instances where admins can't read the server log. The executed SQL and any bound values are stripped from the detail (#289)

Fixed

  • The dashboard "Budget Alerts" tile showed a red "exceeded" alert (with "0% over") for a category whose spending exactly equalled its budget. Spending that fully uses the budget without going over is now treated as a "100% used" warning, not an over-budget alert; only spending that actually exceeds the budget shows as exceeded (#293)
  • PDF reports rendered non-Latin characters (Polish, Cyrillic, etc.) in account/category names as "?". The PDF exports used a built-in font limited to Western European characters; they now use an embedded Unicode font (DejaVu Sans), so names display correctly. Applies to the budget report, bills-calendar and year-over-year PDFs (#292)
  • Marking a recurring transfer as paid showed a success message but created no account entries. The Transfers screen was only updating the transfer's "last paid" date instead of calling the mark-paid action, so no transactions were recorded; it now creates the paired transfer transactions like the Bills screen does (#291)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureNKgPUY81JziKewMWFs4QeLNIwZ8JqGBZ6wvFlsItL4R47yoDLAn4+I1T/pwgEOi7KR2lCUFBckiAdI78FONIy+JyCFhY0w4WcGEltsQdsytRMQYAggOWw+OlYvlDMPI6zoMoRfVcIvC3d+4pUrP91cJIVwi+bu5OIYO0C7ErDFCyvMlHK+ifsGvBluQJ377z8wnBUQIWSfudOuXewIyBHCF1QXsRXsVe0CIGWPNnT3ibuwxjm92a4vzwqdTEYy2qQwzPgYWPhgZofSdEN6j08iuwUzM0i9yXWd0IVpRNLb8RIo9lTzhJsjolrNFGZd0iiQk5A/4NQ6VOLKItVhwXJKOZk7KzyYTZmEki+PaeHKSEjEzwYNqv2tL4VPrBjyq5Y3bRTnYS3uBBCOnkWwn6ozQ4PitvSgPpcqciCtrP1hYAa0oQ7FsP8+BVsepO8gn8+lIcVjx7mW+YvufESAyFRXgAy61QBNjcd34vtoEfLqhdP4f37gZ/jdmCicDQ3sLw/eUIL98BylXmNvOge43vnYuRgGl9gBO11ENaP3EhqhqsrVr5Gyu07MGlMhCRlBn21fRN5sMORHFNx6pL/DcpwC0xtpfWEtHTCcEcLvArqfSiQSMrJaDvqftcQNMWYt4hGZKMVR7SYZsAragHUiMfvWDu1mW7HLNsW8PwySZDrHA=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.31.0
Release Details
UpdatedJune 14, 2026, 7:05 p.m.
Changelog

Added

  • Exclude an account from totals: a per-account "Exclude from reports, dashboard & forecast" option (in the account's edit dialog) keeps the account fully tracked but leaves its transactions and balance out of every "all accounts" aggregation — reports, the dashboard, forecast, net worth, total balance and category budgets. The account still appears in your accounts list (with an "Excluded" badge) and on its own detail page, and selecting it explicitly in a report still works (#286)

Fixed

  • The account detail page's overview tiles only counted the transactions on the visible page (e.g. "50" for an account with 1,603). "Total Transactions", "This Month Income", "This Month Expenses" and "Avg. Transaction" are now aggregated server-side over the whole account, so they're correct regardless of paging (#285)
  • The dashboard spending chart's "Total Spending" figure (and each category's percentage) only summed the top 10 categories shown in the chart. It now reflects spending across all categories
  • The CSV import preview's "Auto-categorized" count was estimated from a 50-row sample and could be wrong for larger imports; it's now counted over the full file on the server
  • Editing an existing bill failed with "Failed to update bill" — saving the edit dialog (whether or not anything changed) returned a 400 error. The bill's start-date column, added with the limited-term bills feature, was missing from the list of updatable columns, so the always-sent start date was rejected before the save could run. Bills now save correctly, with a test guarding every persisted column (#284)
  • Opening an account's detail page returned a 500 error (the reconciliation-history request failed). The reconciliation controller was missing a trait it relied on, so it couldn't be constructed and every reconciliation endpoint failed; the account page surfaced it via the history sidebar. Now fixed and covered by tests (#283)
  • Starting an account reconciliation failed with a confusing "The string did not match the expected pattern" message (most visibly on Safari). The root cause was the reconciliation controller failing to construct (the #283 fix above resolves it); on top of that, the reconciliation screens now read error responses defensively, so any failure shows a clear message with the HTTP status instead of an opaque JSON-parsing error (#287)
  • The Budget Overview dashboard widget (and the digest, spending-anomaly and bill-reminder notifications) always showed amounts in US dollars regardless of your configured currency. The server-side amount formatter was reading the wrong settings key and falling back to USD; it now uses your default currency
  • The Budget Overview dashboard widget's "Total balance" now converts multi-currency accounts to your base currency instead of summing different currencies under one symbol (currencies without an exchange rate are excluded from the total and named)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureCseRrf2b0tfseaK8cBqqPjA8lhMT1C+aq6xVuP6vO3E6sRzawwkPNHdfK7CDaOro2TYW+agvm4g873WzOGVLIVa3FHEyFlnGRkFSwMz334bq1/Rcbw2WXdMbNUliZwdK76DNCauZ0JPz8FYIXr5cqkqbw80oHD/SWhWD5dTKRKJ2gpSvbNtXJfq32Sn04UVxrJq4StY11b5rJfCXR7P7RQxmFboIYJvhoVIfcebR+vighFLC9adkKVaF/xJ8tm1MVG6oJHJ4zKU87SV3+D8vB1xpxeWo2xRwseYSwg8Nk3ik6iXkcf4cHTACrCGyHhOXgCmltGkJ441alZ8kzOQCDe6Vw3Rx+zzgducfZGOQJPuIYcrpyZAAgN51xtDQJTWJNoT9jBrUmEv0r/ftZWj8QYnesnl8HgXUQPdLCsCaloLpISXkt7KzlHYlt4PgdMphbDBnuMROrXZtTeIwDCzwGAkatsK+l8HnM+FbMlpfszT7Ki1z2HYX/d+74aLRxkNUClx3fsQsxOtd0RxK9+/JPHW+W5Sv5kWbRSfiUrslL+pT7R15L9x4t3nFK8VUUEZSDcNynhSHxCVqrqOsV3mZ12eutyvQEPpN56qyLkaZmcoxOlOD2v4BKba8pBAL6YW05jx8hBWg9m0zAg4h3/qoA6zLDRrVfHi+LvUiiE1YDWs=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.30.2
Release Details
UpdatedJune 13, 2026, 6:03 p.m.
Changelog

Fixed

  • Dropdowns in the transaction list (the column-configuration gear menu and the in-cell category/tag/account editors) were cut off when the table had only a few rows, because the table area was shorter than the dropdowns. The transaction table now fills the available height, so every dropdown has room to open in full (#280)
  • The Tags column couldn't be shown/hidden — the Show/Hide Columns menu was missing a Tags entry, and the column wasn't wired into the visibility logic. Tags can now be toggled like the other columns (#281)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureRXpaKwi4ViRdeYM6mjC3JtrlDOFrm03LMBFc2gQMktdYfBEoyMrW3YBp+DPKezxnLOmETNnqjXAI+oswcQLQMkRbAcjuD1dpBBZi7x8kmvtc0lZUcrKRw2QKUzDD5luZaN7JE14o393XlPFxdqkaUbJvWTltA5xK/XO2H72GyvEO7/7de7HCcP2G4XTK5kGSeP3PHRNQ5MjiB49QlM7D95p7Od374Fbr0k52h0sWFHSA14LgJSyPXCgHxxJMqVy7O76LlS1Iedg8B4TFBbTJZVol/8emaHjBHvEwVVzSIIkr9wdtZ60aqrEhJfTqaRwdGS0ks53VE2ROoE829Jnc3Xkz4Xxc0WEqH5a4vxbUWnA8NbuaFNAsUcfXW+0TDTUeLT34IV8c6GZkwn0z4a1parjkif0yyEolfPhNomKX/JMl74aSG5i2BkKyDH3OXMg9oC0/czhOIxluUuFCwWJyd6cBOGd6r/R382SMMe+mCHDpuBxIY12gRo4bzcAfmYMQ3e6rrtgpFwxBllUaK8lC+yPy9x9502QHhZem922Tz7HokfuXuFxh1x9Z6doBSvoZOe2H2PIKRupmFf4I9epoRYdDQZjatpZpN3+oZnz6DmY7f9+g3gaZ7Dl9dkPydm96203Pox5SGz9vhOQaXeOIw+l+rLnXnbodzB3eyqz11Ig=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.28.3
Release Details
UpdatedJune 12, 2026, 1:14 a.m.
Changelog

Security

  • The recurring-income update endpoint no longer passes the raw request body through to the entity layer — a crafted payload could previously set internal fields such as the owning user (mass assignment, integrity only — no data disclosure). Update keys are now allowlisted like the other endpoints

Fixed

  • Auto-derived recurring budgets (#269) are now consistent across all surfaces: the dashboard "Budget Remaining" hero, Budget Progress/Breakdown widgets, Budget Health score, and budget alerts now apply the same recurring fallback as the Budget view — a category funded only by recurring bills can now trigger alerts and is counted in headline totals
  • Auto-derived budgets now respect bill start/end dates: a bill that hasn't started (or has ended) no longer counts toward today's budget, avoiding double-counting during a planned cost change (#268)
  • Recurring income summaries (Income view header, dashboard Income Tracking widget): semi-monthly income was counted at half its value, and a one-time income at full value every month until received
  • Transfers page monthly total: semi-monthly and semi-annual transfers were converted incorrectly
  • Live forecast cache: cache invalidation never matched the stored key (changes such as toggling "exclude from forecast" appeared to do nothing for up to 5 minutes), and the cache key ignored shared-account visibility, letting a share-restricted viewer briefly see the owner's totals
  • Editing a bill's amount without updating its split template is now rejected when the stored splits no longer match (the payment would have silently imported unsplit and uncategorized); setting a split template via the API now clears the bill-level category, matching creation
  • Multi-account import partial failures (e.g. a deleted destination account) are now reported in the UI instead of masquerading as a full success
  • Import preview now also flags repeated bank transaction IDs for accounts that will be created by the import
  • Long OFX FITID hashing threshold raised so every previously-imported FITID keeps its exact ID (re-import dedup continuity)
  • Auto-derived category budgets (#269) now handle every supported frequency correctly: semi-annual bills were over-counted 6×, semi-monthly halved, custom-schedule bills counted every month, and one-time bills inflated the budget monthly until marked paid (now excluded). Frequency math is delegated to the shared calculator, which also gained the missing semi-monthly conversion
  • Auto-derived budgets no longer apply to past months — they reflect today's recurring bills/income and were rewriting history (including overriding explicitly-zeroed snapshot budgets)
  • Multi-account import: an invalid destination account mid-import no longer aborts the batch, and deferred balance recomputes now always run for already-imported rows
  • Bank sync: the post-import balance recompute now keys on transaction creation, not the import counter, so a row persisted just before a non-fatal error still gets its balance update
  • The scheduled-transactions background job now recomputes balances from the ledger (it was the last remaining hand-computed balance delta, and could race concurrent imports)
  • Import preview now flags a repeated bank transaction ID (OFX FITID) within one file as the duplicate it is, matching what import actually does; per-account preview counts include rows that will import with skip-duplicates off
  • Marking a bill paid by linking an existing transaction now warns if the link silently failed (no money movement recorded)
  • Extremely long OFX FITIDs are hashed to stay within the import-ID column
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
Signaturefa7u8mWcwya82OCYZOh+XZFPRJH94oqiBM5WUtEtvU3Dh6Lq+pMs8A7e2aCOa0Y6AbwWH7TF6ZRtwanfSh2PjQMwAaDFlR5anBdAvr89L/fn3eK0uSrZetqNGmAT7Itlc0mT5KowbTvtWDRdK46oR4jjqgXKay6JeO7caGbAcKmyfhJARbfTXsb5etz/yhMX72X33ayUYtCo8nQrtxLTGO5AAPIcFbq1pa3W3d1SHuQ7Ibksv3WXrZe79ngT4pQpGp6xtz3ervqo86vrI8qH8DDg6g9IJE8D1iseOiVzRv/KI/N06LnY0OvUHNZwGrJph5Jh3BrYg2/5rSYzEP5VzaGyZm+AS0DO1bXf9BC5OqbRl3s/FsM+4UgowriYD0S2Zwc4/2j/W3mDRjOdGf0MJxd8SOxv7uW2P5JL0TImjA7mTgppSipw1ShGTl8BU7q11cCtFmuCmwGfvPlRLQtMqEdr93gNkY84rAja08K9Ro1/ySZtrEWVRh/lYzQqmpazsjlw1V4x+KYtn65LHr9Zxd46ToleV5kv1tEZJ1u7nFXeNnrfThyz78EqvLbVxzcqphrfrImGOD9/VhUwryM58KtVz7+tXmLjn3SsSmM8sz9DEljbEKK4zTV9mQgIxviGwzNuIGEFD+HaW6HRIsAzRNtXow5oT7Kgpqa3BnJ3HxM=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.28.2
Release Details
UpdatedJune 11, 2026, 6:33 p.m.
Changelog

Fixed

  • Dashboard could render half-empty (hero tiles only, widget grid invisible): a Chart.js resize on a hidden tile's detached canvas threw during initialization, and the widget grid was never revealed. Chart resizing now skips detached canvases and the grid is revealed before the resize pass. Likely also behind "nothing happens" reports after certain actions (#273)
  • Dashboard tiles with a saved account selection pointing at a deleted account (e.g. after factory reset + import re-numbered accounts) no longer error with 404s and stay empty — stale selections fall back to all accounts
  • Account balances are now derived from the ledger instead of running deltas — the root cause behind every historical balance-discrepancy report (#3, #89, #124, #163, #187, #194, #274). The stored balance was a running total that each transaction code path adjusted by hand; any missed or mis-signed delta corrupted it permanently. Every transaction create/update/delete (and retroactive rule run, repair action, import and bank sync) now recomputes balance = opening balance + net of non-scheduled transactions, making drift impossible and self-healing past inconsistencies on the next write. A one-time migration backfills the opening balance so displayed balances do not change on upgrade (#274)
  • Marking a bill as paid now warns loudly when no transaction was recorded (bill without an account, or transaction creation failed) — previously the bill was advanced silently and the account balance never reflected the payment, drifting from the real bank balance every cycle (#89, #274)
  • The app's own export→import now preserves transaction status (scheduled transactions no longer silently become balance-affecting after a migration) and restores the opening-balance invariant for imported accounts
  • "Skip Duplicate Transactions" off is now honored: previously rows whose import ID already existed were still rejected deeper in the stack (duplicate-ID guard + unique index), so parts of the batch silently failed to import. Intentional duplicates now get a uniquified import ID and the entire batch imports (#275)
  • Import duplicate detection no longer gives false positives for legitimately identical rows — e.g. two same-priced purchases on the same day with the same description. Identical rows within one file now import as distinct transactions (occurrence-aware import IDs), while re-importing the same statement still skips everything it already imported. Re-importing an older statement also recovers transactions the previous logic wrongly skipped (#276)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
Signaturekx2VkgWxozCE2LPp/nzgQQiqFxk/83sOdycv738Ly/uEwn/MhxF/kNtBlP4DMQbhmtkcHdt+kDIlQK1S5q1WHJWZQxjLc/ZCkj/ZEPkNBrDhHwdQCRh4TsRVJyfrIxXUTOCAKJLYk+0DXlnJB3kMhR81adns3wWNH9RkC4b62k3gXtzMR4n+jz/QJDGEAOXRpDUzxEm2TKqFot6sGRt3u0+rVo0bng6nogDJha0APeFI5Ujt+3mECw9MlxNt9nKbQlIGjAnraLVUFz0bXNLK7dbBS3PSzjLsUxhoNhAqMivfHEfLViOvIlCFNHzoWGxFnHK0flI2zJXUlOnaidOEyfhZWbqNpHZL4RZLIZWYQaztJgATNsK+L5aO0Md+Np1hgE8jkdY90gugiV06JqoPEWqCo/qSyaO9N3xYpeXrwfiL37JJqkigwg69RZN3OD1DfBT8ue7QlhT93dfg+39ERzbVY9QBu0gT+bwIs8tyE1MVXOaSjHKUkHab5dpGU3NQhvu/E1CO1BWA3dYvUUqvrvXKB96gm7IqNQEAkRi4JJHDPGtgzjERM+k8z/JA2xeJmPp7V3TZ/1WiKOoKMPz88soCJBMuj/LWnSpekLAGo4RJDy1JBlOm835e3ieJFVHwIwqG9YP7oRB/puFvYV6aaEXCnSkUcZV+z+2NXmHB8KM=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.28.1
Release Details
UpdatedJune 8, 2026, 12:13 p.m.
Changelog

Fixed

  • Install/upgrade aborted on Nextcloud 32 and earlier with "Primary index name on oc_budget_import_templates is too long". The budget_import_templates migration created its primary key without an explicit name, so Nextcloud derived a default name and hit the Oracle-compatibility identifier limit (the unprefixed table name is exactly 23 characters). The primary key now has an explicit short name. Thanks to @TheUnderdev for the report and fix (#272)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureXdUz/Pc10uA7L3R+vTa/cI52W9X8nDyH33zElCWeS/xWeYgonfr0GwLhn4ywE7rtUQF8e1Y8GhETbSd60otnPduP+4rXp7+5+b+iMTa3qfYi6gAd3Y1YJJrZqK0yx2Fdqld/nhQLfFpVkUSQl/JQ78RZanEh779Af5RejNl7lolRlJYg7ZNrLrFasWrpyrLNsg4+Tf74/vMpKWDXf0FEIqjnXZ0LKJm7Yjig4uazy+a5vDcDOrfq6fLU56d9ML/jBJK+9A2loT3I5HP7H2cngdLpwk6+MNLiYQDsdNzLGJJK9TK4hn0Cj+AV80mAQ45beagh4H0SmEoDTPvR/hC7LLlU5rtioE1Rg1tCvlZfHBuPcH9LZMq11Q3HVbZnvzkTdG3lKQlKeFhP86QOIjiAg1Frm0yuOt4nMSdG36N+k1C5szF7HrCoH+u1XgdY6fKI6WW71RkqXJ2IhwOorxcijLVQc2l3wyDLqoQrHtJA2yWGsI9NXlq+d5ZLJ03T7xvcLBPgSDTz91KqBABqJYRdCGhzAuQPe9M814mDu5XgdoCJNUKNrAl6YGvLvJXyj5j8I09qImqsQx09AmEBxi8YTZDbxuO8U/g3yKO14aBgGu3Z+v8+h6xyqJyNsPEbHHxpjfSbwAF/9FlvjA64nOTqPam3fPOjZAdqne5bgf05gFY=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.28.0
Release Details
UpdatedJune 7, 2026, 9:59 p.m.
Changelog

Added

  • Shared savings goals — share a savings goal with another Nextcloud user. Recipients see a "Shared" badge and can view progress; with write permission they can edit the goal and add money, while only the owner can delete it (#255)
  • Auto-derived budgets from recurring items — a (sub-)category with no manually-set budget now shows its committed recurring total (active recurring bills + recurring income, normalized to the budget period) as an automatic budget limit, marked "auto". Typing a value always overrides it (#269)
  • Exclude extraordinary/one-time items from the forecast — a per-transaction "exclude from forecast" flag (with a "No forecast" list badge), the same flag on recurring bills/income (propagated to generated transactions), and a matching import-rule action. Flagged amounts still affect your balance but are kept out of the projection averages (#270)
  • Reusable CSV import templates — save column mappings and import options and reapply them to future imports (#247)
  • OFX/QIF import account routing — route multi-account OFX/QIF files to the right Budget accounts, remembered across subsequent imports
  • Bank sync: pending transactions — option to import not-yet-posted (pending) transactions, automatically reconciled when they clear (#257)
  • Bill start dates — a bill only occurs on or after its start date, making it easy to change a recurring cost mid-year by ending one bill and starting another (#268)
  • "Shared with me" expenses view — recipients can now see expenses that have been shared with them (#248)
  • Dashboard period indicator — chart tiles now show a read-only indicator of the period they cover (#250)

Fixed

  • Dashboard now collapses to a single full-width column on phones, independent of your configured desktop column count (#249)
  • "Excluded from reports" categories no longer appear in the Budget view (#266, #267)
  • Category spending chart shows income as positive with the correct label (#265)
  • Tag-linked savings goals now sum net realized contributions (credits minus debits, excluding scheduled) (#264)
  • Recurring income description is now persisted on create (#263)
  • Transfers are now excluded from dashboard income/expense totals (#262)
  • Account Breakdown report now uses each account's own currency instead of a single assumed one (#256)
  • Fixed a PageController crash (TypeError) on unauthenticated requests (#259)
  • Quick Add date field normalization on iOS (#235)

Docs

  • Documented the standalone Quick Add page and the iOS home-screen workaround
  • Noted that GoCardless no longer accepts new bank-sync sign-ups; EU/UK self-hosters without an existing account are pointed to manual import (#271)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureiQMjVEdG/FWcc56MAPwvDd04E0ERl5pUWkrRWtdYdgbboBj0+7YAo+rDODFz5qC3EPqWBr7XRkjXOfvn9+m61v0w88Qy8SZQIZRHTAwRJuK5jDQbpfce5dropQgKW8btEIzI3BPE+DFBIDeV+qLNQEYT25ApMkUAz44PumVV0sJMibCGo0JBgIxHCPyem1NNjYaX3qQDt41eg8I5rH8wLCWGa7lNTtGyp8vaJ4ck0sh4J9sPuVzMdJoXQDHfGe5S8YY3GTwgvwyloNJQAFO+SQzm5WX6mC/IKAfpxwG82cQAEMm6B4geyHwaYGSFDEgrBuHOZj2fQmvQgzoarRN+U76bOhjQI0IqU76Pno3qM17eF+UKW8peDiqFBXpepGYfDoeyjQsF2GqxIK3C0bNUR5bp9RjNxkWckwvS2ihvP/2rg4lr05MuDDmIdBYG9Ny+PT9dEWBssQkXzIVX28Ox6P8xkorH0n5EoSRl3j+KMXbM34QteNMt1+jgsHAxcS8H57CwV3MC0uqZnhxUu/LbwIGHzvKbC6vN3F/3l6F+35rWM7UaQhdvr2W/1q5Swj5F2sp2Bq5jgrxbWIuUB9+pzftASgVUEmtd6blOUlJuuJj1wmaIrA9jx21+Bg8t/OmrQqB97ZHzint0WTdo7KTOviKZGnoZVXeoQthPmSyW7Wc=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath

Nextcloud 31

Budget 2.52.0
Release Details
UpdatedSept. 18, 2026, 11:44 a.m.
Changelog

Added

  • Import templates remember the character encoding. A statement in an encoding the importer cannot recognise on its own - an undeclared Cyrillic or Central European CSV reads as perfectly valid Western European text, just with the wrong letters - has to have its encoding picked by hand on the mapping screen, and that choice was lost on every import. A saved template now keeps it, and picking the template re-reads the file in that encoding straight away. Templates saved before this have no encoding stored and leave the picker as it is, so they cannot undo an encoding you have just chosen for the file in front of you. Contributed by @Saviq (#384)
  • Import rules can rewrite a transaction's description. A new Set Description action replaces the description a transaction arrived with - CARD PAYMENT TO TESCO STORES 2231 can become Groceries - either always or only when the description is empty. It runs on file imports, on bank sync and when rules are applied to existing transactions. Duplicate detection keeps using the description from the original file, so a statement imported again is still recognised after a rule has rewritten its descriptions. Contributed by @Saviq (#385)

  • The import review says which rows it cannot take, before you import. A file with an Account column can carry rows whose account cell is empty, and with Account for rows without one left on Skip rows without an account those rows are dropped. The review step never said so: a 75-row file whose last 29 rows had no account read as "Total 75, New 0, Duplicates 46", and the only mention of the missing 29 was a dialog after the import had already run. The reasons were there all along, the review step simply did not show them. A warning now sits above the statistics, in the same place as the direction warnings, saying how many of the file's rows will not be imported and why, with the row numbers behind each reason. Where the reason is an empty account cell it points at the fallback account select below it, which is what fixes it, and choosing an account there clears the warning and brings those rows back into the count. The row numbers also match between the review step and the dialog after the import now, the review step counted from 0 whilst the import counted from 1. Reported by @TerjeTM (#388)

  • The Budget Alerts tile can be told which categories it may alert about. Since 2.28.3 a category with no budget of its own falls back to the amount its bills and recurring income commit it to, so categories that were never budgeted against started appearing on the tile, and spending 190.00 against a 56.03 figure worked out from a bill reads as "239% over". The tile's settings, on the gear when the dashboard is unlocked, now offer Only categories with a budget I set, which leaves the derived budgets out and gives back what the tile showed before that fallback existed, and a list of every category with a budget in play that can be unticked one at a time. Rows whose budget came from a bill are marked, so it is clear which ones the checkbox covers. The filter is stored with your settings rather than with the tile, so budget alert notifications and the digest honour it as well, and the budget figures on the Budget page, the Nextcloud dashboard panel and the digest are untouched by it. With a filter on, a tile with nothing left to show stays up and says how many categories are muted rather than disappearing, which would take the gear with it. Reported by @TerjeTM (#389)

Changed

  • The mapping screen redraws as soon as you change the delimiter, the header toggle or the encoding. Changing the delimiter used to leave the columns and preview split the old way, with a note that the file would be re-parsed in the next step, and toggling Skip first row (headers) did not touch the preview at all - so neither could be checked before moving on. All three now re-read the uploaded file on the spot and redraw the column choices and the preview, keeping every column you had already picked that still exists. Picking a saved template does the same with the template's own delimiter and header setting, so its mapping lands on columns split the way it expects. Contributed by @Saviq (#383)
  • Translations. Ukrainian is now included, the Polish and Russian translations asked for in #382 are in, and German and French have been updated from Weblate.

Fixed

  • Expenses another user splits with you count towards your balance with them. When another Nextcloud user split an expense with you it showed under Shared with me as outstanding, however your contact for that person still read "Settled", opening it listed no expenses, and the totals at the top of Shared Expenses left it out. Each split is stored against the person who made it, and a contact card only ever read the splits you had made yourself. A contact linked to a Nextcloud user now also counts what that user has split with you, from your side, so their "owes you £40" is your "you owe £40", and where you have both split expenses with each other the card shows what is left once one is taken off the other. Their splits are listed in the contact's details marked split by with their name, and the payments they record show in the settlement history as payments from you. Only the person who split an expense can settle it, so Settle All and Record Payment still only reach your own splits, and are greyed out when none of yours are open. The contact has to be linked to their Nextcloud account, the same as for Shared with me. Reported by @Bow-Wow75 (#390)
  • A paid one-time bill keeps its due date. Marking a one-time bill paid cleared its next due date, and a bill created before 2.49.0 - when one-time bills gained a real Due Date - had nothing else to show, so a paid invoice read "No due date" in the list and opened with an empty Due Date beside the old Due Day and Due Month fields. The date a one-time bill was due is now kept when it is paid and the list shows it; bills paid before this release get their date back from the day and month they still hold, in the year nearest to the payment. The form no longer offers Due Day and Due Month for a one-time bill: the Due Date is its whole schedule, and it has to be filled in (#333)
  • The Bills Calendar no longer shows a bill as due for months it has moved past, or for months before it existed. Since 2.49.0 a month was struck through only when a payment was recorded against it, so a bill marked paid with Don't create any transaction - a yearly premium in February - stayed green in September as if still outstanding. Every bill was also projected back to January whatever day it was created, so a bill added on 8 September read as owed for the eight months before it, and those months inflated the monthly totals. A month the bill has moved past without a recorded payment is now struck through with a dashed line and its tooltip says no payment was recorded, and nothing is drawn before the bill's creation date unless a start date says the schedule began earlier - a bill with nothing left in the year drops out of the table rather than sitting there as a row of blanks. A payment linked from before then still shows as a paid month (#333)
  • Tab-separated CSV files can be imported. The Tab delimiter option sent the two characters \t instead of a tab, which the CSV reader refuses, so choosing it made the import fail - and a tab-separated file that was detected correctly showed a blank delimiter and was then read with commas. The option now sends a real tab, and a template saved from the old option is read as a tab too (#383)
  • The import review shows how many transactions the file holds. Total Transactions on the review step always read 0, whatever the file contained. The account page has a transaction counter with the same element id, and it sits earlier in the page, so every update meant for the import summary went to that hidden counter instead
  • Clicking quickly through months on the Budget page no longer shows another month's figures. Every month change starts its own loads of the spending and the budget amounts, and an earlier load that finished last replaced the newer figures, so June could show May's spending or May's budgets. Only the most recent load is shown now, and a budget load that fails leaves the base budgets rather than another month's. Contributed by @almeidandres (#387)
  • The dashboard follows your budget start day. With a Budget start day set, the income, expenses, savings and budget-remaining figures at the top of the dashboard still covered the calendar month, and Budget Progress set to the current budget period used the budgets of the month the period started in - a period from 28 August to 27 September was measured against August's budgets. The top figures now cover the current budget period and show its dates under their labels, and both use the budgets of the month the Budget page lists that period under, the month its 15th falls in. Envelope carryover, which the dashboard only added for whole calendar months, now counts for the budget period too. The six-month charts stay on calendar months. Contributed by @almeidandres (#386)
  • Every budget surface agrees on which month is running when you have a budget start day. A period is listed under the month its 15th falls in, so with a start day of the 10th, 5 September is still in August's period, and with the 28th, 29 September is already in October's. Budget alerts, and the Budget Health tile built on them, still used the budgets of the calendar month, the Budget page opened on the calendar month, and turning on envelope budgeting started the envelope in the calendar month too. All of them now use the period running today. The recurring-bill fallback and the "(projected)" carryover mark also treat that period as the current one, so a period that has already ended no longer borrows today's recurring figures. A category's details follow suit: This month, the trend and the monthly chart count spending per budget period instead of per calendar month, and the chart ends with the period running today. The same goes for the dashboard's Monthly Comparison tile, which now compares the running period with the one before, and for This Month Income and This Month Expenses on an account's page, and both show the dates they cover.
  • The Monthly Comparison and Weekly Spending tiles show the real figures. Both tiles looked for income and expenses at the top of the summary they load, however the summary keeps them under its totals, so they showed zeros whatever was in the accounts. They read the totals now.
  • An overdrawn envelope shows as over budget. When the overspend carried into a month is larger than that month's budget, nothing is left to spend, but the Budget page showed the row as "No budget set" with no remaining figure, and the dashboard's Budget Progress tile left it out. Both now show it as over budget, with what it owes as the remaining amount, as the alerts and reports already did.
  • The budget adjustment notice names the right month everywhere. "Budgets adjusted from ..." and its confirmation dialog read the month as midnight UTC, so anywhere west of UTC they named the month before the one being adjusted
  • The Budget page shows the right period for a start day of the 15th everywhere. The month picker's date was read as midnight UTC, which is still the 14th anywhere west of UTC, so in the Americas a budget start day of the 15th showed each month the period before the one it should
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureYjtb6oj/6u2vw+lMxUwTdqaoecbNZKr8zgforTdMu2KAUE/D7PJQiWgI+mlRDXOoDp++CZJkbkDwEIknVcN6Zl5rCfUtSvMwdVk4IvOKwG7AW2qqDhnHDplkWBwPMEFNNJdQxPnjsDTNYxTEtGnOXwl2gxc9NMIFSD3c/DeCbxzLZd61DaVpjQohgLF7EKuVeLohtjay574dEpwpXH9z50nYJ0bO65jUTxrnZmLoafqKyQRu7tqurEWjlkhUcZRBALUnDzc1KwA+7kP1K1SwVoJkiuJwqcZNju3hsz8US7leYtvEnQL0Qsp+TnCHKiGibv/G5kVVwgvGZ0ThI20UeIHQOMKDZXj+d+CKuskMLpBJTUZPJaQyTeyIfFQ858nZlHHKC1mSRno6XPO1pYQCvHBzf+TIZBtF9U7N9svhxDJ2eXRAXJbp+BrtfuVrBEFkXE/4kilamlMPdGi1nG0EkcnKB9tVaqryzKWgWb97hfuBftBulfa+kaGjJAH9ZMwf9GioTzOCSdLf32lC+XFlDFxf93nTrzfNPB3dU+v/F1ZiItBx3WvAcXbYdg2lYa8y/A8liLqYXj19o9GqDbhNFVhCVQNvfFn0nfq/otpkY6sMH+brtN4O1HQfNqOOn6Lp09HRh299sfO8kuCaQDIGfeyNb4qNNJALi6bewhAaORk=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.51.0
Release Details
UpdatedSept. 11, 2026, 1:17 p.m.
Changelog

Added

  • Accounts can be deleted in bulk. Tick the accounts you want gone and delete them in one go, from either the tile or the list view. This existed for transactions and categories but never for accounts, and the gap only really bites in the one situation that produces dozens of them at once - an import with the wrong column mapped to Account, which creates one account per distinct value in that column. Deleting those one at a time also ran into the delete endpoint's rate limit of ten calls a minute, and an account that still holds transactions costs two of them, so the clean-up stalled about five accounts in. The whole selection now goes in a single request. The destructive half is kept a separate decision: the first confirmation removes only the accounts that are already empty, and anything still holding transactions is kept back and asked about in a second dialog that names those accounts and totals their transactions, so nothing with history in it is deleted by a click meant for an empty account. Closed accounts can be selected too (#381)
  • The import preview warns when a column mapping is about to create a pile of accounts. Mapping the wrong column to Account creates one account per distinct value in it, and mapping the date column gives you one account per day. The preview did list what it was about to create, but as a comma-separated line among the statistics, which reads as a note rather than as a reason to go back. Above five new accounts it is now a proper warning, sitting above the stats where the direction warnings already sit, because it answers the same question - whether to import at all. When most of the new account names parse as dates it says so outright and points at the account column mapping, rather than leaving you to work out afterwards why you have forty accounts (#381)
  • Bulk edit can add and remove tags. Tagging a run of transactions meant opening each one in turn: the bulk editor only ever touched fields stored on the transaction row itself, and a tag is not one of them. Tags... in the bulk bar now adds and removes tags across the whole selection at once, a cross-page select all matching selection included. The two lists are deliberately separate rather than one set of checkboxes - a tag you leave unchecked is not touched either way, so adding one tag to a hundred transactions cannot quietly strip the tags those transactions already carry. Adding a tag a transaction already has does nothing, and neither does removing one it does not have, so the same change can be re-run over an overlapping selection without anything happening twice. Category tags are offered too, grouped under the category they belong to. A tag set belongs to one category, so across a selection spanning several it can only reach part of what you picked - rather than leave you to find that out afterwards, each group says how far it reaches (applies to 12 of 50), only the categories actually in your selection are offered at all, and the confirmation names any tag that fell short instead of claiming it did more. Anything the tags cannot cover is counted underneath, including split transactions, which have no category of their own once split. Removing is not restricted the same way: a transaction re-categorised after it was tagged keeps the old tag, and gating removal would leave that tag impossible to clear in bulk. Requested by @joeftiger (#379)

Fixed

  • Names with an ampersand or a quote come out right in confirmations and messages. A category called "Food & Dining" was named in its own delete confirmation as "Food &amp; Dining", and the same went for anything carrying a quote or an angle bracket - an account, a contact, a saved report. Translated text has its inserted values escaped for HTML by default, which is right for the many places that text is used as markup and wrong for the two that show it literally: the confirmations and the little messages that slide in at the top right. Both now undo that escaping, so a name reads the way it was typed. This was true of the old browser confirmations too; it is simply visible now that the dialogs are the app's own (#381)
  • Editing a reconciled transaction in the list no longer asks twice. Changing the amount, date or account of a reconciled transaction directly in the table warns you first, and that warning could appear a second time straight after you had answered it - once because opening it moved the cursor out of the cell you were editing, and once more when the table redrew behind it. Answering once is now enough (#381)
  • Confirmations stop working after a few of them in a row. Every confirmation in the app was a browser dialog, and browsers offer to switch those off: after a handful in quick succession, Chrome and Firefox add a Prevent this page from creating additional dialogs checkbox to the box, and once it is ticked every later confirmation is answered no instantly without anything being drawn. From that moment the app looked broken rather than cautious - Delete did nothing whatsoever, no dialog, no error, no message, and nothing short of reloading the page brought it back. Clearing up a handful of accounts left behind by a mis-mapped import was more than enough to trigger it, which is how this came to light: two accounts deleted fine, and every delete button after that appeared dead. Confirmations, prompts and alerts are now drawn by the app itself, so there is nothing left for a browser to suppress. They take the keyboard - Enter confirms, Escape cancels, Tab stays inside the dialog - and a confirmation for something that deletes data now says so with a red button rather than a neutral OK. Reported by @missunderstoodninja (#381)
  • Tag pickers can be reached with the keyboard. Every tag checkbox in the app was hidden outright rather than just visually, which takes it out of the tab order and out of what a screen reader can announce - the coloured badge was the only way to set a tag, and only with a mouse. The checkboxes are now hidden visually but still focusable, and a badge shows a focus ring when you tab onto it. Nothing looks different with a mouse (#379)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureomDWujOwOWa9L4Xhc5Xr+YxrNL/X4KJz7URuQ3oocoKImK3zBZp5nUdl464tQpzylxC8sTBVsN9SqEm6KKKsPGkY92c4QnEzKWsuAM1fVZDgAqU/8oCyq6pSlRTrxxmHFN+PmioiScBnhErLMyrvPWkjVSpve7kIb5v1QRqf4nqJFuxeSOJAX1JgOM1tVME5Loxrm6SFZOsXaEXpKgqGF9SSuWXPAd1qGAO+MkugHo6zEjelkCYAWzkq2/tCZHOtIExuhBUk/BuSCMd9AaYhLb2iRJVT4FYcf14uRWCdfHmbRkNuGZNV63hbwNXwvIdP0KB9ZJ3QLV82V7LFyWY+s0VfssxJnKzjm8afeKo6zxq5SeRZmTVZDAxX7+aogVVWIqB18uwCI0dYWbMZQgR6PRqig0lf8E1j6KOiMRimZeHw0mkKFDV6ytcZEHgS8PuCih1ol9XaF+tNz4QJkKu/49A23APwrCUanew/Fs0BOhH7ydCNAl7sM5xpXKx4/4hoLJrA9tzTRwQUn1dmjbRk0QjThANrvqu+m0Gz97XWEwyyj3zHQyWYNy0Ozg1W1P01U/iFGH96Nd2emV2OO63z/AAmHrGWyBVBK73VlNx1guwaf8//c6XYbrbSJdF/smvbQcMa1MikuJq4DMpItW8vmvC+YOvUycpSHDkl7Hf+TC4=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.50.1
Release Details
UpdatedSept. 10, 2026, 1:21 a.m.
Changelog

Fixed

  • Save stops working on the transaction form after the split editor has been used. Turning Split across categories on and back off - or switching the type to Transfer with it on - hid the split rows but left them sitting inside the form. A hidden field is still checked by the browser, and an empty one it cannot put on screen is one it will not report either: the form simply refused to submit, with no message, no request and no error in the console, for every transaction from then on until the page was reloaded. Firefox and Chrome at least log something; Safari says nothing at all. Putting the split editor away now empties it, and a split amount is no longer a field the browser polices - an incomplete split was already caught on save, and says what is wrong in a way you can actually see. Reported by @SGiersch (#380)
  • Adding a transaction from an account preselects that account. The Add Transaction button on an account's page was reading the account being viewed from the wrong object, so it always came through empty and the picker opened blank - on the one screen where there is no question which account you meant (#380)
  • Transfer matching finds the other half in a shared account. A transfer between an account you own and one your partner has shared with you could not be matched: the search for the opposite leg only ever looked at rows you own, and a transaction in a shared account belongs to that account's owner, so the match dialog reported nothing to match and the bulk scan skipped the pair entirely. Linking the two was already allowed - it was only finding them that was not. The match dialog, the bulk scan and bulk linking now search every account you can write to, shared ones included. Accounts shared with you read-only are left out, because linking writes to both legs and a candidate you cannot write to could never have been linked anyway. Reported by @lexiconzero (#378)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignaturebuZC6LMTRyNL1vila15DJJFe8dDZf/j3oCjxjP7KvrqebYszACpNqevFzP0b+HFTrgRwXMF7+ZnHeZDVV4l4KuZgfeI78fVJnNhQQeYNYqcIRiZZTKoqfm3zpU0OzCqWchvR7Mgslc6IIuBGjmM5EAx53O05t69k00ylo5G2YLfeMtyeg9hlqRERfuE5aMa7w5YhvBcskq9gIbtuGRU5ZfK++QikEJxZS9Quy9H7iDuuRBrPgumyJyURxaENIodcPhTuHjC/95LQWciAI6bj562mWuNglVdBEC+9+oNRN12vyMHerogSRRNpfqKwMb93Yzhlw3gkjkD9DsZvVuzuek98QAxEhTDZeEcZ5o4aAB2m+mRAmx77mj0OrfvLcyL7ekKUCr6G0/xJkU3XtEG3WDF20OupAcXsNbYBduRIoCvozx/pEGOkIipe4oQOlh6POT7MkXWfxBGJaG3N8SzmUqihyNgx8KuoxodhHsw09O8ncNlmkiBEGNn0+Hx/UXiijxE4ucigWPVSmUP6SU6F8dpjU2EU/jqbIdxPiyz3r/tt/vbVXDw41c7wd5nnkHyubljlBW6KL1uREbhrl7fdRCgjzJkPKA+fa4tdpa83af3llfzKcnyO6TXQ/nPL+xI0eLwRlXUIp4eW9xIeY0sZ3bOwjMdOemiR1Q9lGSloAZc=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.50.0
Release Details
UpdatedSept. 5, 2026, 11:16 p.m.
Changelog

Added

  • Budget alerts and forecast warnings actually notify you now. The two switches at the top of Settings → Notifications have been there since the first release and never did anything - nothing read them, and the app had no such notification to send, so the only place a budget alert ever appeared was a dashboard card you had to go and look at. Budget Alerts now sends a notification the first time a category reaches your alert threshold (80% by default) in a budget period, and a second one if that category goes on to exceed its budget. That is the most it will send per category per period, so the nightly check cannot turn into nightly noise; a category that drops back under its threshold is forgotten, so it can alert again if it climbs back. Forecast Warnings sends at most one notification a month when the six-month forecast projects your combined balance below zero, naming the month it happens and the figure it falls to. Both default to on and are switched off from those same two checkboxes

Fixed

  • The Bills Calendar never shows an occurrence as paid while the bill still says it is due. 2.49.0 placed each payment on the nearest due date, and a bill paid twice at the end of a month - or paid a few days before the next cycle - had the extra payment land on the following occurrence, so the calendar struck through September while the Bills page showed the same occurrence as upcoming. The bill already knows which occurrences are done: marking one paid moves its next due date on a cycle, so everything before that date is closed and everything from it on is still owed. Payments are now only ever placed on closed occurrences; a second payment in a month shows as that month's larger amount rather than as a month that was never paid. Reported within the hour by @TerjeTM (#375)
  • One-time bills with the same name share one calendar row. Now that paid one-time bills stay in the year's calendar, a garage that sent three invoices appeared three times, one cell each. They are folded into one row with a cell per invoice, each keeping its own amount, the way recurring bills already read (#375)
  • Exported reports come out in your language. The PDF and CSV a report exports to were written with English labels whatever language Nextcloud was set to - the exporter never asked the translator, so a German user got Total Income and Account Breakdown in an otherwise German app. Every label in the report, Year over Year and Bills Calendar exports now goes through the same translations the screen uses, month names included, and the monthly scheduled report is produced in its recipient's language rather than the server's. Labels that already exist on screen are translated straight away; the few headings that only ever appeared in the exports are new to translators and fill in as the translations arrive (#377)
  • A monthly digest can report unusual spending. Unusual-spending detection judges a month that is still in progress, so it stays quiet before the 10th - pro-rating the rent on the 2nd would flag it every time. The monthly digest is sent on the 1st, so its unusual-spending section was empty every single time it went out, and the weekly digest only filled it in on the weeks that happened to start after the 10th. The digest now asks about the period it is actually reporting on: a finished week or month, compared against the same six-month typical figure scaled to that period's length, with no early-month rule to apply because a finished period is not a partial one. That also settles a mismatch in what the digest was telling you - it reported this month's spending so far inside a summary of last week or month, and now reports the period it covers
  • The digest notification says how many categories are spending unusually. The count was being attached to the notification and then never shown, so a digest that had found something looked exactly like one that had not
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignaturekDEMKCHGsB6XHpH0lnwbdVN2PlHEz5a/0JU2HlikRqJOIHvusKOCEPzyqSYRH/8U5+wPMQcWAi6Zlb8pcjgNh3CwemL7dVDMnrV7w65ZbG5xhBtzlziNuhs1FCJzqYQshdgCJzd2xQFJYJOqTqFXqdFQK6US+0Tgm47K6ROYrFUL/9JEhdaoH3kUz8PAP2WOq+IYdRfeUBlXUslF6pbtDWQ9g6gVSTUDF1Kj0V6UU+/M+GqrHY4flUN5Q9k6lGRLri8eBRO2woA5jdLWxJ5tyonb6F9e65yjlOIYbC3QV+TaHwH5MLbj9lmkrbAjFUMaaSWQ0VuEaj8vupo46ebxm2V4dGN4oisWd0VKRmlpGpGdDLIDYT1aZwIrVIRWPIicpqiFkLdOOo+YOCIl3XHNu6lPLxdR/jNcEDORoRJq6yPVtWZTroXgXM3TznOcNLXKotj7v/o1MPxId8uMms/wiu8PRksNIlFeLnmV8czhjhI+ZLElYqwCyMJjCUZUUB3ebdvRtbDqvuJBwuYp36Oi5UKfBTXqYzbAAO8qr4nAH/gdQsA8X+YquAMuux31ilINMpOvFX71Yf7/E15pqYZfvEQS0hq1hV4xIcgVAreEOHbIIFGcVB5WdrvYNeNP366rB5WsKXUBDGFrTEIL5vtj8OHgLqVYoEgBZNg/RL9j/Fc=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.49.0
Release Details
UpdatedSept. 3, 2026, 11:53 p.m.
Changelog

Added

  • A one-time bill can be dated in the past. A bill only ever stored a day and a month, and every date it worked out from them was rolled forward past today - right for a schedule, useless for an invoice from last month, which became due next year the moment you saved it, and jumped again if you tried to edit it back. For one-time bills the schedule fields now give way to a single Due Date, taken literally: an August invoice entered in September is due in August, shows as overdue until you mark it paid, and lands in August on the Bills Calendar. The placeholder transaction a new bill pre-creates is always a scheduled one, whatever its date: with a past date it was being written as a cleared payment, booking the money as spent for a bill nobody had paid (#375)

Fixed

  • The import's fallback account is reachable when the file has its own account column. A blank account cell now falls back to the account you choose - but the select that chooses it was hidden the moment an Account column was mapped, so the fallback could never be set from the wizard and those rows still failed with "no account was chosen". On the preview step the select now stays, relabelled Account for rows without one, and is optional: leave it empty and such rows are skipped with that reason listed (#333)
  • On SQLite, a failed save now gets the unfinished-update hint too. The hint recognised MySQL's and PostgreSQL's error codes and SQLite's "no such column", but SQLite words a failed INSERT as table X has no column named Y - which is exactly the failed save the hint exists for - and that slipped through, leaving the bare SQL. Found by running the check in a browser against a dropped column (#333)
  • The Bills Calendar shows what was actually paid. Paid months were guessed in the browser from the bill's last payment date - every month up to it counted as paid - so a bill you started paying in September showed January to August paid too, and a one-time bill fell out of the calendar the moment paying it deactivated it. The cells now come from the payments recorded against each bill: a month with a payment is paid and shows the amount that actually went out, months still to come show the expected amount, and the monthly totals follow suit. A payment made a few days late counts for the month it was due, a payment with no scheduled month near it appears as an extra paid month rather than vanishing, and a bill that is inactive now but was paid this year stays in the year's picture (#375)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureUTnFglOyY//mXGi7y/LDtH4919NkTXqAr1p4PsIxsYx5fusaiKeFTWxlcugWVBcXNirEhMLHMF/hTpCv05X/jQ0yMlB2LW8Q4bUwppTjyg44BEEACZuQWr1FTs7KhmlbU/nCDKTIuC+Uk458xB8kdIiggZoDRqb4JoINSJ2tXL5KeNQgeyyq8hqOm5pwUBxlJRgx61f8EPP4+JWoAY3DWZUGJvpmk8i0VrNtxOvHT2BTdfMxLauNboowdmko+GQv3ZLEoAwP0D1UI4pjcwxcOQdAkQuM4wXwN6tywUjdmzPTmYSTxEMO1XAnc1v22KUA7bQxkHYcg5viQMbtAA459AsY2ImPJdxGyt0PbszsxOgomnZ6BHQdohkI3zbgX2XRtRc0RycVyzkDtnuk1Nr4k8nEyhimtNea3nOZ5S3yQhrC7CPqpeoXqc/gzl5b2QrO1bC07TxUIMs9knOBR/SMWsXcSq2pzYY9FCW9+XsUVQ2XKi8CQmYiAi+rO8/RNLCkyz8OHkQuMtpdmv1YI7INkGwTr0wU0TVw1bC9ozc2GWsDeJGSYJBDn43uQQ+dyCr8xMhzkURYqjcvMYsgPUjTMY2AB0mFYow2XlRK67AE9hXrLSK25TIVHBH1JMkDx65jmH5jGQwmG8vbHjIoEygsJBRvy0hmb8uK7Pq1u5OyqnI=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.48.0
Release Details
UpdatedSept. 3, 2026, 9:09 p.m.
Changelog

Added

  • Tags can be hidden once they have served their purpose. A tag for a trip you have taken or a project that has finished keeps its history, but has no business in the picker for every new transaction — and deleting it would strip it from everything it is on. Editing a tag, on the Tags page for a global tag or in the category view for a tag-set tag, now offers a Hidden checkbox. A hidden tag is no longer offered when tagging a new transaction, bill, transfer or rule action, or when linking a savings goal, and it shows dimmed with a Hidden label where tags are managed so it can be found and unhidden. Everything that already carries the tag keeps it: the transactions stay tagged, the transaction filter and reports still list it, and a hidden tag already on the item being edited stays in its form, checked, so editing something else does not strip it (#373)
  • An account can be closed. An old bank account you no longer hold can be marked closed from the Advanced section of its edit dialog. It keeps every transaction and still counts in reports, the dashboard and net worth, but it no longer appears in any picker for new activity — the transaction and quick-add forms, transfers, bills, recurring income, imports, import rules, bank-sync mappings, savings goals and pension contributions. Pickers that filter history keep listing it, so its past stays reachable, and opening an old transaction that sits in a closed account keeps that account selected, labelled (closed). The accounts page lists closed accounts in a collapsed section of their own, and the account's page shows a Closed badge and drops the reconcile and card-payment actions. Closing is refused, with the reason shown in the form, while the balance is not zero, while any transaction is dated after today, or while an active bill, transfer, recurring income, pension contribution, bank-sync mapping or import rule still pays into or out of the account — the message names each one so it can be reassigned first. The standalone quick-add page and the import's account auto-matching skip closed accounts too, the interest accrual job leaves them alone, and the public API's GET /accounts gains an additive closed field so a capture client can filter on it (#372)

Fixed

  • Restoring a backup keeps the "exclude from reports" flag. The restore rebuilt each account field by field and never copied the flag, so every restore since the option was added put excluded accounts straight back into every total, silently. The new closed flag is restored the same way (#372)
  • The account form shows the real reason when an edit is refused. A refused account update always came back as "Failed to update account", hiding the specific message — including the reload notice a stale page gets when saving a debt. Refusals that carry a reason now reach the form verbatim (#372)
  • The unfinished-update warning now checks the database itself, and names the exact fix. It used to compare the migration files on disk with the list Nextcloud had recorded as run, and that misses both ways an install can actually be broken: a migration recorded as applied whose column is nevertheless not there, and a migration file that never reached the server. The instance that prompted this had run the recommended occ app:disable && occ app:enable to the letter and still could not save a bill, because that only re-runs what is unrecorded. The check now reads the live schema and compares it with every column the app writes, lists what is missing by table and column, and - for a change that is recorded but absent - names the precise occ migrations:execute budget <version> to re-run it, with the debug toggle those commands need. A column no migration on the server adds is called out as an incomplete install instead. The warning appears on the app's pages, in the admin overview, and in the error a failed save shows, where it now bypasses the "already verified" shortcut because a save just failed. Not being able to read the schema warns about nothing, as before (#333)
  • Repair Data no longer deletes both halves of a duplicate pair, and no longer orphans what hangs off a transaction. Its duplicate cleanup removed rows straight from the database, so any splits, tags, attachments and shared-expense records on a deleted transaction were left behind with nothing to join back to - invisible, and beyond the reach of every cleanup the app has, factory reset included. It also had three detectors flagging the same rows, each free to pick a different keeper: two placeholders written by the same payment share a creation time, so which one counted as "the real payment" came down to sort order, and a pair flagged both ways had both halves deleted - the payment removed along with its duplicate. Deletions now go through the same cascade every other part of the app uses, and a row another finding is keeping is never deleted; anything left ambiguous is simply left for a second run
  • Reconciling an account no longer means ticking your way through the whole ledger. A first reconciliation has nothing earlier to anchor on, so it starts from the account's opening balance - which means every transaction since has to be ticked before the difference reaches zero. On a real account that was 860 rows at 25 to a page, against an unfiltered list that still included scheduled rows dated years ahead. Starting a session now narrows the list to the account, to transactions dated on or before the statement date, and to rows not already reconciled - those are inside the starting balance already, so ticking one would have counted it twice - and the bar offers Tick all N transactions up to \<date> to do the whole statement in one click, leaving you to untick what your bank has not taken yet. Nothing is written to the transactions until Finish, so it is a starting point to correct from. The Create adjustment button no longer appears until something has been ticked, since before that the "difference" is simply the account's entire history, and the starting balance now explains in its tooltip where its number came from. Leaving a session hands the list back unfiltered (#374)
  • Marking a bill paid without recording a transaction no longer leaves it looking due. Choosing Don't create any transaction or linking one that already existed left the pre-created row for the occurrence you had just paid sitting in the ledger, still scheduled - so the bill went on showing as upcoming - and at the same time suppressed the row for the next occurrence, so the forecast lost it. One flag was answering two different questions. Recording the payment is now about this payment alone, and whether the next occurrence is pre-created is the bill's own Create future transaction setting, which is how skipping an occurrence and editing a bill have always read it. Existing leftovers clear themselves the next time that bill is marked paid. The dialog also now says that the bill moves on to its next due date whichever option you pick (#376)
  • Rows with an empty account column are imported instead of thrown away. A file that carries its own account column had every row with that cell left blank dropped, even though the import screen had already been told which account the file belongs to - one reporter lost 14 of 27 rows that way, in silence, and only noticed because the balance was wrong. A blank cell now falls back to the account chosen for the import. A cell that names an account which cannot be resolved is still reported rather than guessed at, since that one would misfile the row (#333)
  • The importer no longer invents an account out of a file's header row. With "first row is a header" switched off, the header line is read as data - and because it holds the column titles, its account cell held the word "Account:", which the importer duly created as a real account in dollars. Only a row that would import as a transaction can name an account now, so a header line is ignored the same way the import itself ignores it. New accounts the importer creates also take your default currency rather than always US dollars (#333)
  • The import tells you why rows failed instead of pointing at the server log. A partly failed import said "%n rows could not be imported - check the server log for details" and put the actual reasons in the browser console, where nobody looks - and on an instance whose logging is misconfigured, or where the admin cannot read the log at all, there was nowhere left to find out. The reasons now open in a window as soon as the import finishes, one line per reason with the rows it applies to, so fourteen rows failing the same way read as one problem rather than fourteen (#333)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignaturewDpgdodKiAH0BJNKoHpu1H3xardvLeUHU4/1s4cGzs/N9ZfELYEXGP9FnFBY0fSJWBscyElRGGL3vR58ISgUep5I5P9aX+JA/uHMtjeyafCVQGj/YNbhZtz/hKtNb2zM+erfMrzq6pLkleaPsCFoe5tEt3ufMZKASjvCpU1R3j4Ec6bDjiom1fk90CImC26ZItTfc5Vu/dxGtACVerJ0IvZzQPvR1J2FY1xDlqCeeuapHMmB/z3V5Px9JQU0BC+nM5qF335DutR30cz0BP7ghkp7juBWtj5fBMe2bRYmqu+AOVdcbniqHtHvktQmMjv77gQzTupn8tfNtOSf4qLK5YbiqOfMXnIIai5qmrgJE1tsO17hPQmpxol9owkPC2gRa7TwHsS09K3cMrEjpKNORD5hkFlc2m9eQR2xRAu68dWQwXkhbnmu42PcpwqQsKdLhDbwBWRJHyFqsMSds4mjYhUN5+wvQbWSsQTXoO8Z9InCntaQsDxR1rTX6CWxAy0gHx+ZD0hGv0ttqWbJzEiOPrlYwLbDvserRhlotDAahPDxsdV3PEwj28+Jtv04Ie0vE/k9n56NsAFY3e8PGjJE156W6+qurFoiXi2OcJynyAmsOsoj8DTLKnMsVMVtlw16lNZZ6uAANdDUrG1QOE8F065BkQxwg69PR3qHL3jfsgY=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.47.0
Release Details
UpdatedAug. 29, 2026, 9:47 p.m.
Changelog

Added

  • The import screen can be told which character encoding a statement uses. Some files simply cannot be identified from their contents: every single-byte encoding accepts every possible byte, so an undeclared Cyrillic export is indistinguishable from a Western European one and any automatic answer is a guess. The mapping step now carries a Character Encoding picker, listing Western European, Central European, Cyrillic, Greek, Turkish, Hebrew, Japanese, Chinese and Korean options alongside Unicode, with the detected encoding named in the hint beneath it. It sits directly above the preview, so a wrong guess is visible as mojibake and correcting it redraws the columns and preview immediately. Uploads are now kept exactly as they arrived rather than converted on the way in, which is what makes the choice reversible — previously the original bytes were discarded at upload and a bad guess could not be undone (#371)

Fixed

  • A statement that isn't UTF-8 is no longer read as Latin-1 regardless. Files that aren't UTF-8 were run through a list of fallback encodings, but the first entry accepts every possible byte, so it always matched and the rest were never reached — every such upload was decoded as Latin-1 whatever it actually was, turning a Cyrillic statement into Ïÿò¸ðî÷êà and a Japanese one into ûÀ;út;àz, with no error to say anything had gone wrong. A file that declares its own encoding is now believed: OFX states it in its header and camt XML in its declaration. Anything undeclared falls back to Windows-1252 rather than ISO-8859-1 — the two agree except over the range holding the curly quotes, dashes and euro signs statements are full of. Converted XML also has its declaration corrected to match its new contents, which previously made the parser decode the file a second time and produce exactly the corruption the conversion was there to prevent. Note that an undeclared file in a non-Western encoding still can't be identified from its bytes alone — single-byte encodings are indistinguishable, and testing for the multi-byte ones proved worse than not trying, since ordinary German, Spanish and French text validates cleanly as GB18030. That case needs an encoding picker on the import screen (#371)
  • Statements written in your own language import again. A CSV, OFX or QIF holding a decent amount of non-ASCII text was refused outright as "File appears to be binary" — which took in Cyrillic, Greek, Hebrew, Arabic and CJK statements wholesale, and caught plain accented Latin too, so a French or Spanish export could trip it as easily as a Russian one. The binary check allowed the first byte of a multi-byte UTF-8 character but not the bytes that follow it, and every non-ASCII character has at least one, so roughly half the bytes of a Cyrillic file were counted as unprintable against a 10% limit. High bytes are simply what non-English text looks like, in UTF-8 and in the older 8-bit encodings banks still export, so they no longer count against a file at all; genuine binaries are caught by their null bytes and control characters, which text does not contain. Reported with a diagnosis and a fix by @ba1amut (#369)
  • "Auto-pay when due" can be switched on while editing a bill. The checkbox needs a pay-from account, and the only thing that worked that out hung off the account dropdown's own change event — but opening a bill fills that dropdown from code, which fires no such event. So every existing bill opened with auto-pay greyed out, however long it had had an account, and the only way to reach the checkbox was to re-pick the account by hand. Creating a bill was unaffected, which is why it went unnoticed. The state is now recomputed whenever the form opens (#370)
  • Editing a bill shared with you no longer strips its category and pay-from account. Sharing is granted per type, so a bill can be shared while the account it pays from is not — and both dropdowns can only list what you are allowed to see. The form silently fell back to "No specific account", and saving submitted that as no account, wiping the setting off the owner's bill; the same went for an unshared category. The real values now stay selected, shown as Unavailable (not shared with you) so it is clear why they cannot be changed, and they survive the save untouched. Auto-pay is also refused server-side when a bill would be left switched on with nothing to pay from — a pairing the create path has always rejected (#370)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignaturexHUL+LrtKQmEHZ8YQwsy+xFaIqzNZrPxOFdHD44Th6v2oSFX5rCCI2kmScHUejaVOt1t0nLiJ2qf5ZSRVvOmPPeeinPhoqGhwYlP0Nkgt8Rb0x1zPZTJj63Na8ESocx7CpajZTDxKc8pAFrQJ+H03K4UDks+/1F0qFF2NYa1soV6+c+fIuMPDaYC+DjO3aeWaJabhTUgUymMmqHLxqlhAyw+a8LJ2ABwYyT8P/rmIQ267T72D8ng0f8/ubS4mvfICaoAbtMA8H5Rnn7/gcPMDv1nJyTv97ShefnigmiykqBSWJsJQE8Ax/RYNfXWJ3Gl9uRxzXigxKYwpGtWMFnE9G2JN/eOh5oG042V5wn1QI0QcfWG2QFilp5uOD6ZVTfyPG+um2Y0FQLFe4PJnxyYpnrXmWglFFMyEVCVa0a7+AJmb7DVfjz/9vhBewTYCJ/j9XDlw8Efu28ZYWtsgZ5vZIlH4a90WalHLWHprUsNLDrUSyl+WRLTWDYDfEviRHJBCrrcz34Zyo8An0+sM9ccQalvH78w4X9PDIL5pMS90MHgyYrXVGyMPqSG65FliBn0qku7pP8wCqUabT9Ac3ofyztTlj0dy+tHyuu0OLPb+FxaLUoCgw5PaOSNSOXgDw8amDnleLNrZjvHIEsoYCS2jXtxU0rrTbmFXi4djM4jyTQ=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.46.0
Release Details
UpdatedAug. 29, 2026, 2:08 a.m.
Changelog

Added

  • A Money Flow diagram shows where the money went. Reports gains a Money Flow type that draws the period's cash as a flow diagram: income categories stream into a central Cash Flow node, which fans out into your expense categories and their subcategories, with what's left shown as a Surplus band — or a Deficit feeding in when spending exceeded income. Amounts label every node, category colors carry through, and the usual period and shared-account filters apply (#366)

Fixed

  • Bills and income shared with you can be opened again. Opening a bill your partner created failed with "Failed to load bill", and so did every action on it: editing, deleting, marking it paid or unpaid, skipping a payment, and the Record transaction repair. Sharing grants visibility, not identity, but each of those looked the bill up as the person clicking rather than as its owner, so the app approved the action and then could not find the bill to carry it out (a DoesNotExistException in the log). Bill actions now run against the bill's owner, so a shared bill behaves like one of your own, and Mark Unpaid is offered on shared bills for the first time. Shared recurring income had the identical fault and is fixed with it, and its Mark received action — which had no permission check at all, only the scoping that made it fail — now refuses a read-only share properly (#368)
  • A transfer between accounts shared with you now completes. Creating a transfer in an account owned by someone else booked both sides and then failed to join them, leaving two unconnected transactions behind every attempt and putting the raw database query on screen as the error message. Both rows belong to the account's owner, while the linking step went looking for them as the person clicking. Linking, unlinking and Create and link now work across shared accounts, and a transaction you cannot reach reports itself as not found — which also means it reaches the log, where this failure left no trace at all (#368)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
Signaturex0J8AUUfQbAJljP4bb8goctxFgu6woboHqgqhSLiZLzSNh4/bgeYYYsy4ubudGRmEAdnJZqL9XcqPKKaaVIxVXVRFVCS24iGpCdqXhCW0MMvoROv7VMao+dHMrfPhungZxdm+nKurDuI2drTpZLmbckIj6+PnjLP0Z6M+a/P7wRw/3gtdHcf1KoNmRGNIlqUUolPhYJJFQbhgsf8yg/nzDMjm0OKXYvOKWSI+GR1HFQoNSLVx9TPk2zrBOT/ARpvDEStnWWBZxhn2shkEVFNE1ntupx4AmkerIySit3CB5j4H7imaHsIYwPHDhL+MEj9afFllpMnogByvQ+nHCvJ3v7PeuNYGgQTxMvoVKpvtPDyo2610eVQDQlK8UEzmOdimk7shlkllXiE/ZEIaeFINp17VuQbYlTwuuZlNfTendUZirhPFK4xR3AL6cpTxJHq/Xc/npPYAYk8wPyYseNnFL5A3/d2UXiT/m57GQiIMkTMrayR6kYmYjGYT2EAVSRjhA0wESnCJb6jVMc6YTcBVQ3uFXnA5gR1hdulx1Qj2lRhJpBSCcXBCl/4QHDv4OIhk4Is5DWUxcw91iuaBhMCpoJLwU+kkuaibIrsiV2L3np7EeZzPtxOsRG4GyCZRyvTvCVO7HVHu///wPi1sfMH4R05Ri0AUfbqdpqPrE70mG0=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.45.0
Release Details
UpdatedAug. 29, 2026, 12:59 a.m.
Changelog

Added

  • Bi-weekly schedules can be anchored to a date. Bi-weekly income, bills and transfers used to lock onto whichever week you happened to create them in — pick "every other Friday" and the app silently decided which Friday from the creation date, with no way to say "no, the other week" (#363). Transfers were worse off still: the form only offered a day-of-month field, which means nothing to a bi-weekly schedule (#364). Income now takes a First payment date for weekly and bi-weekly frequencies, and the transfer form gains the same start-date field bills have had — the date pins both the weekday and the week, and every occurrence lands a clean 14 (or 7) days from it, whether the date you give is in the past or the future. While a start date is set the weekday field follows it and locks, so the form cannot claim a different day than the schedule runs on. Note for existing bills and transfers: a start date you set before this release only delayed the first occurrence; from now on it anchors the schedule, so a weekly or bi-weekly bill with a start date will settle onto that date's weekday and week
  • Bills can be marked unpaid. Marking a bill paid by mistake was final: the Undo button lived in a ten-second toast, and once it was gone nothing could revert the paid state — deleting the payment transaction left the bill still claiming to be paid (#365). Every payment now stores what it changed, so a Mark Unpaid action on the bill reverts the most recent one properly: the due date rolls back, a one-time bill comes back to life instead of staying vanished, a statement-amount bill gets its exact amount back (which cannot be recomputed after the fact), and the payment transactions are cleaned up — including when you already deleted one of them yourself. Auto-paid and import-matched bills get the same revert, which the toast never offered them — a payment that was linked to an imported transaction unlinks it rather than deleting money that genuinely left your bank. Recurring transfers can be reverted too, from the Transfers view. The stored revert applies to the most recent payment only, and editing the bill's amount or schedule discards it — reverting would otherwise restore values from before your edit

  • CSV files without a header row can be imported. The importer always treated the first row as a header and silently ate it — a headerless export lost its first transaction with no way to say otherwise. A First row is a header toggle (on by default, matching the old behaviour) now controls it, columns are matched by position, and blank or duplicate header cells get translated "Column N" placeholders in the mapping dropdowns instead of untranslated internal names. Saved templates keep working: they store your file's real header names where they exist, so they survive language changes and column reordering. Templates saved from files with duplicate blank headers ("Column N (2)") need their columns re-picked once. Contributed by @Saviq (#367)

  • The database-updates warning reaches the admin overview. The check that detects the app's own migrations never having run (the "Unknown column" trap, #333) now registers as a proper Nextcloud setup check, so it appears under Settings > Administration > Overview and in occ setupchecks — visible to the admin who can actually run the fix, not just to whoever next opens the app

Fixed

  • A category drill-down into subcategories now says so. Opening a parent category's transactions (from Category Details or a chart slice) applies the parent plus its subcategories, but the filter panel could only display the parent — and picking the parent to narrow down to just it did nothing. The category dropdown now shows a combined entry like "Groceries + 2 subcategories" for the applied scope, and choosing the plain parent genuinely narrows to it (#361)
  • The bills list stops fetching every dead bill. Keeping paid one-time bills reachable for Mark Unpaid meant fetching the whole bill history and discarding most of it in the browser. The server now returns active bills plus the revertible ones directly, so the payload stays small however old the install (#365)
  • A category's count badge and its panel agree on damaged rows. A row carrying both its own category and split parts (the old bulk-edit damage) was excluded from the tree's count badge but still listed in the Category Details panel — off by one on the same screen. The panel now applies the same rule; Repair Data remains the way to fix the rows themselves (#360)
  • The split flag's grey states are resolved once and for all. Two damaged states have haunted long-lived databases: rows from before the flag existed (held NULL), and rows whose restore claimed they were split while the parts never made it into the old backups (#351). A one-time update resolves every such row from the parts table — the single source of truth — and restores now do the same, so the states cannot return. This fixes three real casualties: rule runs categorize legacy transactions again (they had started skipping every pre-2026 row while reporting success), assigning a category to a damaged row now sticks instead of silently vanishing while the row stayed listed as uncategorized forever, and the Uncategorized filter no longer offers up split parents whose categorisation is exactly how such rows were created (#360)
  • Find Duplicates no longer loses a next-day duplicate at a group boundary. Groups anchor on their first transaction so distinct purchases cannot chain together — but a pair one day apart could straddle two groups and the second copy went unreported entirely. Rows near the boundary are now carried into the next group, so every pair within the window is reported together and the no-chaining rule still holds (#333)
  • A savings goal that has gone backwards shows an empty bar, not a full one. The Savings view's goal list was the last progress bar without the negative clamp the others got in v2.44.2 — withdrawals exceeding deposits painted the bar completely full
  • The Category Trends tile sticks to expense categories. It relied on a side effect of the old one-direction totals to keep income categories out; with netted figures an income category could slip into the spending list. It now filters by category type explicitly
  • The database-updates warning can no longer be silenced by a mid-deploy race. If the check ran at the exact moment app files were being replaced, a failed directory read followed by a successful one within the same page load could record the version as verified while updates were genuinely pending — permanently hiding the banner on exactly the instance it exists for. The verified marker and the pending list now come from the same scan
  • Editing a bi-weekly bill no longer silently shifts which week it falls in. The consistency check that runs on every edit recomputed the due date "from today", so changing an amount or a note in the off week flipped the schedule's parity — the bill quietly moved a week. With a start date set, the schedule now recomputes from its anchor, and an unrelated edit can never move it (#363, #364)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureV/r+TeR/H5y0TiUgo9apV0nHrv4yLWR3o2yHxeSCrwBr87AyJBO6EphcfUm/aNNDYHbJfh2Nk4ghsMvljrNWPCgMFZdwynngNS3IbrSFauamMsnuvkxDcO5h+R5aAIyBfyog9idiDesDMJF2B1dDbe3COOlxDq5i8xiiP+BGqLpoeOYZKT2dpqoaYB9j16sGk5BSE07vSFnF8kz2PGcpgExtfEqMMVCDRGQUvU02KgLqNb6oFx0abf5NhRGTpNZPMyOMwWH0CVTATrZj7r9LBp8+HQqHUjCRqPTwsYbAVBZZKYwyrtU3Wd/4VaSpKW2bMS7OWA/663hc74b0Rt/QTy0brPK2oiQyM6PisiwlZHAz6nuQWRDUiyezWVS9yLBiVDavZxby7XJAIrb49a8dSESUj7/7eRaO9xAb21oULrp39o0d0GKWBxFf2fuV/uBJ/tQh1pgj7n5PHQ01kZ3Dy1znPGH//sIfsw5nBLeKQQGZvcp4ell+s19FJr2SoKe+HgY8Wo/eCobVpai8GbpeA1HsNc7ixuKIPdxpAsY7X/mNg92GEndFExIDBkUgQfbPYd+LkmjlJdtXqluxB24WdVIVdKDJakxk860CHTUo+k7UgVroJUffjXXwXvFKQCWZG8f/5Tt4eh3QpRfaqQGWpAjQ0lw/AURkUdA0FlN4ELo=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.44.2
Release Details
UpdatedAug. 28, 2026, 3:19 p.m.
Changelog

Fixed

  • The Budget page's Spent really does net refunds now. v2.44.0 said a refund comes off what you have spent, and it did — on the budget report, the dashboard tiles, the alerts and the digest. The Budget page itself reads a different query, which kept the old one-direction sum, so the very page the issue was reported against still showed $216.90 where Category Details showed $58.29. That query now nets the same way as everywhere else. A month whose refunds exceed its spending shows the true negative figure instead of being flipped into looking like money spent, and its progress bar sits empty rather than painting full — on the dashboard's Budget Progress tile and the savings-goal tiles too, where a negative used to render as a completely full bar. Changing a category's budget period also refreshes its row with the right direction and the selected month, instead of flipping an income category's Spent to a large negative until the next reload (#361)
  • "View All Transactions" on a category lists the transactions its figures are built from. The button quietly filtered to money-out only (money-in for income categories), so an expense category's refunds were missing from the very list the netted figures above it summarise — the panel said $58.29 and the list it opened could only add up to $216.90. It also ignored the panel's period and account selection, listing everything ever recorded. It now applies no direction filter and opens scoped to the same date window and account the panel is showing (#361)
  • The transaction filters panel shows the filters that are actually applied. Arriving at the Transactions view through a category's "View All Transactions" or a chart drill-down replaced the applied filters but left the panel's controls showing whatever they held before, so the list and the dropdowns above it disagreed — and because any change to one control re-reads all of them, a stale control could silently re-apply an old filter. The panel now rewrites every control whenever the filters are set for you, clearing the ones that no longer apply (#361)
  • The last places that ignored split transactions now count them. A split carries its categories on its individual parts, and five surfaces were still reading the transaction's own category, which a split never has. Year over Year compared a year of split receipts against a year that predated splitting and called the difference a collapse. The Forecast's category trends dropped every split into Uncategorized and showed nothing against the categories the money actually went to. The count beside each category on the Categories page read 0 for a category funded entirely by splits, next to a panel listing its transactions. Find Duplicates showed a dash where the category belonged. And a CSV export with no category filter left the Category cell empty on exactly the transactions someone had taken the trouble to itemise -- it now names them, and a category is named once however many parts of the receipt went to it (#360)
  • Find Duplicates no longer chains separate purchases into one giant "duplicate" group. Each candidate was compared against the previous row added to the group rather than the first, so five identical-amount purchases a few days apart -- a regular coffee order, a repeated fare -- linked end to end into a single group spanning far more than the 3-day window, and the tool told you to delete transactions that were nothing of the sort. A row now joins a group only when it is within the window of the group's first transaction (#333)
  • Deleting a category no longer leaves split parts pointing at it. The delete guard is deliberately blind to splits (a category used only by split parts must stay deletable), but nothing cleaned those parts up afterwards, so they kept referencing a category id that no longer existed. Deleting a category -- with or without reassigning its transactions -- now degrades its split parts to uncategorized, which is what the reassignment already did for ordinary transactions. Find Duplicates also names a split Split now instead of showing a dash (#360)
  • Splits from before the split feature existed are counted once, everywhere. A transaction whose split flag was never written -- imports predating the column, and backups restored from those versions -- was in a grey state: some queries treated it as a split, others as an ordinary transaction, so depending on the screen its money was counted twice, or not at all, or it was offered up for categorisation, which is how a transaction ends up claiming a category and carrying its own breakdown. Every query pair now agrees on one rule -- a transaction with split parts counts through its parts, full stop -- covering the budget carryovers, the monthly report, Year over Year, the forecast, per-account totals, uncategorized listings and rule runs. Restoring a backup now re-marks the transactions that actually received split parts, whatever the archive claimed, and the very large id lists a restore or a year-long report can produce are processed in batches instead of one oversized query (#360)
  • The app now notices when its own database updates never ran, and says so before anything fails. If Nextcloud replaces the app's files without finishing the upgrade, the database changes that came with the new version are skipped. Nothing looks wrong -- reading data does not touch the new columns -- and then the first thing you save fails with a database error nobody can act on. Every page now checks whether any of its database updates are missing and, if so, shows a banner naming how many and the command an administrator can run to finish them. Checking costs nothing once a version has been confirmed complete, and the banner clears itself as soon as the updates are applied (#333)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureDm8DKf6I3AofLr0FMZsDKeE4q19LhQ2NgVNbRwtRNtCcfcpkF7RWros6LUOJacOmyNa9EuRDVUGQJtTGSasNt4dXxhwDjw7hDsmm2NUaTTrnoLoY32V9zyBLZqtSLb30uZTr6O8q03UGO0MsNQr5IsOcNbi7KflfjmUbYY99cIycOm/FBoLBm+LWQlDH+eQZigjqEk5GMvsLgyY2LuYQE6226WS1W96gI3neUzwICij5OWn/hdkl4axB6Y2Ei7bWofiMRSwY4oeiLF1mmgk1C4OfyoZomZEhsytxXok5wt38K4SMQBL4A+zpVoQBp0cBdFrGUynC/eNtmQjS9nsJSs0woZ3H6+QrlMCmJ+PRqSbn5kEO7PBzXMXUYNg9mqd0mUeYjH0mW1SKpF51FsBKjMHNmi1ReNqQhiRAJq+9JzyiaUuCv/gigDXOaLCR5NvRld0RbMYfnWN9XZ18k8/b+oKwzBG/oY6mqmgR0mUl24lXHK7djSHbhfmCIAG6hpOxgrL6cFguUdqNuoCGhBvUaUBJn742J4Hh4Lx4jq+zQJE1rJf4xpNhcT6VKLJNS7DrSd62oPm80FBXSu9colzmlv3C67SDYwL5TxqdM8OCsPTJvH0IWnr9R+qrrPh5MMqy3XMDyYvzDMjiK0OWmzob4ZxMCg2gi1asdtcjd5PqNgU=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.44.1
Release Details
UpdatedAug. 28, 2026, 12:44 a.m.
Changelog

Fixed

  • When the app's update has not finished, the app now says so and how to finish it. If Nextcloud updates the files but never runs the app upgrade, the migrations that add new columns never run -- the app carries on reading fine, because reads do not notice a missing column, and then the first thing you save fails. Until now that surfaced as the database's own words, "Unknown column 'amount_type'", which is accurate and no use to anyone. Any missing column or table now comes with the command that fixes it: occ app:disable budget && occ app:enable budget. Reproduced against MariaDB, where neither occ upgrade (which upgrades the server) nor occ app:update (which looks for a newer release in the app store) does anything about it (#333)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureJfhfoodWHfhncS8NhWVo/wOO4gi2kDEn4S8M8TzZg5Qfbjwxmkmh4Pn294Og1wL1uIp5gbCGyS2aIzcDN0HoEf7DhN98hxRaZ5P5/5CBFLgTGTNwJmDX9A4Xtwk81o4/3jbeLAPUJspX2OkQKGzyNtFqrCi5aDG/JF5D0Yf49WBnYG3BZp5rSaEOmrD2Scm8D3EmE5wDsIIKg+Zl1iCVHsUX/Z7TG6lVzPxeW4JVIU4NX8hhUziOOGMXthSBM5GxZX4okbtfGm9uVeUOe49rT/kXcm7mTG2Xb/4Phywh7vFqMckiOTSwP2fLttq7LFUv0XtUoaOhxjfhFJBdQIDi9qhtJRMcRvXE8kPbswzpyN9W/nC6lv44Q0Bxse967DXVQ8ZoxIWCByl6/5Z4Ooi978d0lWc/HsZYqMX5SXTb3KoALYNCG2+8WfkXwF+kZ0kPc//K6Uh/r+lgO7Gx55xaR2XkmDhClY7u/PMhLOsc0segdjc4obFyHns/iTeKJjV+aEaOvlbNq5aDKioozMZr2vQhL9XfEv4rKLq5VTxaD0s/WOv4dMJxhA/7LRpC53OlPrFN1IKPgmXUS2v2gTtP7fF9eDvZ6u66ra9zTe/j+R7y2y8mMo0zcUMnPPUxJ5fgX5saIPC2svL65fawwwghOMQTiydg6jEmbipPDU38RJQ=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.44.0
Release Details
UpdatedAug. 26, 2026, 12:34 a.m.
Changelog

Added

  • Dashboard tiles can follow your budget period. Spending by Category, Top Spending Categories and Budget Progress gain a Current budget period date range in their gear settings, which tracks the Budget start day you set in Settings. If your money arrives on the 25th, the tile now covers the 25th to the 24th like the rest of the budget surfaces do, instead of cutting your cycle in half at the month boundary. Spending by Category's header chip names the days it is actually showing — "25 Aug – 24 Sept" — rather than repeating the setting back at you. The other tiles are unchanged: a balance-history chart and the income-vs-expenses series cover a span rather than one cycle, so the option is not offered there (#333)
  • Cash Flow Forecast and Year-over-Year now actually draw. Both tiles have been in the Add Tiles menu with a card, a chart area and a working server request behind them — and no code to draw the result, so they sat blank however long you waited. Both are off by default, which is why this went unnoticed. Cash Flow Forecast now plots your projected balance month by month, starting from today's balance so each step reads as a change, with that month's income and expenses in the tooltip; choose Next 3 / 6 / 12 months in its gear settings. Year-over-Year plots income against expenses for each of the last 2, 3 or 5 years, matching the chart on the Reports page so the two cannot disagree (#333)
  • The bills tiles let you choose how far ahead to look. Upcoming Bills and Bills Due Soon now take a Look ahead setting of the next 30, 60 or 90 days. Upcoming Bills previously showed whatever came first with no horizon at all, and Bills Due Soon was fixed at 14 days. Both still include bills up to a week overdue, so an unpaid bill does not vanish from the tile that exists to chase it — Upcoming Bills previously had no such cutoff and would show a bill overdue by months right alongside this week's, and now drops anything more than seven days overdue the same way Bills Due Soon already did (#333)

Fixed

  • "Last 30 days" on a dashboard tile now means the last 30 days. It meant the month so far: on the 24th you saw 24 days, and on the 1st of a month the tile charted a single day. "Last year" behaved the same way — the year so far, so on 3 January it showed three days. This is why a tile could flatly disagree with the budget alerts sitting above it on the same screen, and it hit anyone whose spending does not line up with the calendar month hardest, because the biggest bills of the cycle fell outside the window entirely. Affects Spending by Category, Top Spending Categories and Budget Progress. "Last 90 days" and "Last 6 months" were near enough but drifted by a day around month ends — six months back from 31 March landed on 1 October — and are now exact (#333)
  • Every Date Range dropdown on the dashboard now does something. Ten tiles offered one and ignored it: you could pick a range, it saved, and the tile carried on showing its own hardcoded window. Large Transactions had no date filter whatsoever — it ranked your biggest transactions over all time — and now honours the range. Weekly Spending was pinned to the last 7 days, and its daily average divided by 7 regardless; both now follow the range you pick, and its label — which always read "This week" — now names the range it is actually showing. That default week is now an explicit Last 7 days setting rather than a hardcoded one, so it is both the tile's starting point and a choice you can change like any other range. Category Trends compared this calendar month against last, and now compares the range you chose against the equal-length stretch immediately before it, so the two figures are like for like at any range. Where a range could never apply, the dropdown is gone rather than lying: Monthly Comparison is this month against last by definition, Debt Chart is a payoff projection with no window, and Income Tracking's headline is a monthly rate that cannot vary with one (#333)
  • The Cash Flow Forecast tile was asking the server for the wrong thing. It sent a days value the forecast endpoint does not accept, so the parameter was discarded and the default horizon used every time (#333)
  • When something fails to save, the app now tells you why. Errors across the app showed a fixed message -- "Failed to create bill", "Failed to save transaction" -- whatever had actually gone wrong, so a validation problem and a database problem looked identical and neither was actionable. Where a failure comes from the database the server already attaches a short, sanitised description of it, a missing column for instance, specifically so the cause is visible to people who cannot read their server's log. Nothing in the interface was reading it. That description now appears alongside the message everywhere a save, delete or update can fail -- transactions, accounts, categories, bills, rules, pensions, assets, transfers, income and bank sync (#362)
  • Bills with a statement or minimum-payment amount explain themselves when rejected. Those amount types only work on a transfer pointing at a credit card, and the two rules enforcing that were being replaced by the generic "Failed to create bill" instead of being shown. Genuinely unexpected failures still stay generic (#362)
  • Repair Data can clear the stray categories off your split transactions. The rows the old bulk edit and the rule runs left behind are still there, each claiming a category it should never have had. Settings > Repair Data gains Split Transactions Carrying a Category, listing every one it finds with the category currently stuck to it. Repairing removes only that stray category: the split stays a split, and every part of it is left exactly as it was. Genuine splits, ordinary transactions, and a transaction explicitly marked unsplit are all left alone, and the scan drains to empty once run rather than reporting the same rows forever (#360)
  • Rules no longer break a split transaction by categorising it. A split's categories live on its parts, and its own category is deliberately left empty -- so writing one onto it produces a row that claims a category and carries its own breakdown, which every per-category total then counts twice. Bulk edit was stopped from doing this a while back, but Run rule now and Run group rules write straight to the database and went around that guard, so rules were still quietly creating the damage. A rule now leaves a split's category alone while still applying everything else it does -- vendor, notes, tags and the rest -- so splits stay covered by your rules. The preview and the results list name such a row Split instead of showing it as Uncategorized, which read as a change that was never going to happen (#360)
  • A transaction damaged by the old bulk-edit bug is no longer counted twice. Before it was fixed, "filter by Uncategorized, select all, set a category" wrote a category onto split transactions without removing the parts underneath, leaving rows that claim to be in a category and carry their own breakdown. Nothing has ever cleaned those up, so they are still sitting in databases -- and the queries behind Spending by Category, the Reports charts and the Category Details panel added up both, reporting a split receipt at its full amount plus each of its parts, and counting it as two transactions. A category could therefore show more spending than the transactions underneath it actually came to. Each transaction is now counted once, through its parts where it has them (#360)
  • Budgets count the money you spent through a split. A split transaction holds no category of its own -- its categories sit on the individual parts -- and the query behind every budget figure only ever looked at the transaction's own category. So a receipt split between Groceries and Household added nothing to either budget: the progress bars read low, remaining read high, and the budget report agreed with them. Budget alerts have counted split money since they were added and the spending charts since v2.33.0, so a category could raise an over-budget alert while the bar right next to it showed room to spare. Affects Budget Progress, Budget Breakdown and Budget Remaining on the dashboard, the Budget view, Reports > Budget and its CSV and PDF, the scheduled monthly report email, and the Unusual spending section of the digest along with its notifications. Splits restored from a backup made before v2.41.0, which lost the flag marking a transaction as split, are counted too, and a transaction damaged by the old bulk-edit bug -- which stamped a category onto a split parent without removing its parts -- now counts through its parts rather than dumping the whole receipt into the one category it was stamped with (#360)
  • A refund now comes off what you have spent. Spent on the Budget page counted only money going out, so a bill that was refunded, a returned purchase or a reimbursed expense left the category looking fully spent -- a $216.90 phone bill with $158.61 credited back read as $216.90 spent, and the bar sat at 100% over a $120 budget. It now reads $58.29, which is the figure Category Details has always shown for the same category: the two screens disagreed, and the budget was the one that was wrong. The same net figure now feeds Reports > Budget and its exports, the Budget Progress, Budget Breakdown and Budget Remaining tiles, the budget alerts -- which is what stops a category raising an over-budget alert while the bar beside it shows room to spare -- and the Unusual spending digest, where a purchase you sent back no longer reads as a spike. Income categories are measured by what came in, with anything paid back out subtracted; Reports > Budget was previously asking for money-out on those too, so an income category with a budget reported nothing against it (#361)
  • A split transaction on the dashboard names the categories you sorted it into. Recent Transactions read each row's own category, and splitting a transaction moves the categories onto its individual parts -- so however carefully a receipt had been divided up, the tile called it Uncategorized. It now names the categories the parts went to, with a coloured dot for each and the part-by-part breakdown on hover, the way the transactions list and the account register have since v2.43.1. Where the tile is too narrow for all of them the names run to an ellipsis rather than pushing the amount off the row, and a split that arrives without its parts is called a Split, which is at least true (#360)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureQHxBHmyBaONUhmqkujdb3Z0HaVDO5kl4378wYHWJgtW/QHl6D1QNcKQzzhB2nVoXZz322zCDeUae1eIk3C+EX4X5q2MolNnL9UAL0TvS0oSfQcAtWTFCAO1Z79C1uYbCxM6CUNNrGmZdoZ41ivw9OJQOICFu5nd0RHQ+w25DUCKK0SOEQXWia7LN5o0RnpTwKYxSxQHIb4dajJvbWsW+oibyBkP/yZsbfJRls3Z2zWYvEEnQhWiKTaJC4Ijfz6DgP6U/M9Z5DjhIZgyxPy5OGTOLd9aZl64K3JzcQqKDKJJ8wTDz9iUXb+bCitxDyq0chgLG4tbSyFyK7+aAcWchHZXufXDmPmAsTikDVgc6srYeKyqv2VFpa/IBA1m0GeAzN2KqIRzDbiyttRGgQQ5i2VPH4owiA8un5ak46XVpD+q5Xy/SwEZVmjCY8AZsZePmPvM9gESC+hBy6P5YuNksSar/dD++REsQCeFkCIiqf4y61wyD0WY3qHYF4yDpWzH8vVhbKSMy0x9W1JR3ZUmv0MbidSvgiOwxpPPtWVuPPRDbLKg3ENzv4bq8IK8PzR0t5jHNSFKWu7C1jrJ3gE7yoxJ5zMnsw6v3HJhedy2Jfx2C2EZsZv1XCzaXYxKBr0uaHVcOSn9/4Rn9OXf95th7bgRN6aCrU34M1ELL3RmocKs=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.43.0
Release Details
UpdatedAug. 24, 2026, 1:27 a.m.
Changelog

Added

  • Liability accounts now ask what a positive balance means instead of guessing. Editing a credit card, loan, mortgage or line of credit shows an Amount owed field that takes a plain positive number — the app adds the minus sign — with a separate This account is in credit tick for the case where you have overpaid and the lender owes you. Switching an account between a debt type and a savings type converts the figure for you and shows the resulting current balance before you save. Creating a liability works the same way. The choice is recorded with the account, so an export and restore keeps it (#353)
  • Several CSV columns can feed one text field. Banks often split what belongs together — a merchant column and a details column, say, or a reference spread over two. On the import mapping step, Description, Notes, Vendor and Reference are now checklists: tick every column that belongs in the field and the values are joined with a comma, in the order the columns appear in the file, with blank cells skipped. The same works for those four fields on OFX, QIF and camt files, and a saved import template keeps the whole selection. A single ticked column imports exactly as it always has, so re-importing an overlapping statement still recognises its transactions. Thanks to @Saviq for the feature (#355)
  • Category trees can be exported and imported. The Categories page has Export and Import buttons next to Add Category. Export downloads your whole tree as a readable JSON file; Import takes that file back, or a CSV of Parent > Child paths, shows exactly what would be created before anything is written, and leaves categories that already exist untouched while adding whatever is missing underneath them. Handy for backing up a carefully built structure, sharing it, or having a spreadsheet or an AI assistant draft one and loading it in a single step (#354)

Fixed

  • Editing a loan or credit card no longer turns your debt into an asset. Typing your statement balance as a positive number into the Opening Balance field stored it as a positive number, which the app reads as "the lender owes you this" — so a £5,000 loan quietly added £5,000 to your net worth instead of subtracting it, a £10,000 swing, and every later recalculation re-derived the wrong balance from it. Nothing on screen said so. Positive balances on a debt stay supported, because a genuine overpayment is a real thing, but the app now asks which you mean rather than reading it off the sign. If this already happened to you, Settings › Repair Data will find it: run Scan for Issues and the new Debts Recorded as Being in Credit section lists every affected account with what it reads now and what it will read afterwards — untick any you really have overpaid, and those are recorded as genuine credits and left out of future scans. Two related consequences are fixed alongside it: an account you have overpaid no longer appears in the debt payoff planner as something to pay off, and it no longer counts towards Total Liabilities on the Accounts page, where it was pulling net worth down by twice the credit (#353)
  • An account edit that does not touch the opening balance no longer rewrites the balance. Renaming an account, changing its institution or ticking a checkbox resubmitted the opening balance every time, so an unrelated edit depended on that value round-tripping through the form perfectly. It is now sent only when you actually change it (#353)
  • Reopening a split transaction no longer scrambles its parts, and saving it no longer throws them away. A split of 10 into 1, 3 and 6 came back as 1, 9.00 and 0.00 — the second part had swallowed the rest and the third was empty. The parts were always safe in the database; the editor was overwriting them as it drew them. It fills the last row automatically with whatever is left over, and it was doing that after adding each row, so every stored amount was recalculated away the moment the next row appeared. It now draws all the rows first and works out the remainder once, which is what it should have been doing. If you saved a transaction from that scrambled view, the parts you saw are what got stored — the third one was dropped for being 0.00, quietly, because the total still added up. Worth re-checking any split of three or more parts you edited recently; their categories will have been wrong in reports for the months involved. Splits of four or more parts had a second symptom — Save appeared to do nothing at all, with no message — which is fixed by the same change (#358)
  • Filtering transactions by Uncategorized no longer lists your split transactions. A split transaction has no category of its own by design — its categories live on the individual parts — and the filter was reading that as "not categorised yet", so every split you had ever made turned up in a list meant for things needing attention. Split transactions are now left out of it, and out of the dashboard's uncategorised list and the "only uncategorised transactions" option when running import rules, which read the same way. The bulk-edit consequence is the one worth knowing about: filtering by Uncategorized, selecting all and setting a category used to write that category onto the split transactions caught up in the list, after which they were counted twice in reports — once for the whole transaction and again for each of its parts. Setting a category on a split transaction is now ignored rather than obeyed; unsplitting one still assigns a category as it always has (#356)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignaturelQsdNi/Ed5bU8/Ch8iyHVXKdX+l8qhRm8fCwRYfB/ObxW6pncVobhw57Bzvu/2yio4Wb+MyJ+DZ8T75pZ9+ugVmWX+q/VSLx4PEAmnr9upL0m7AvJN33BXARoFWBzKVFHnfEy/RuYgtxnNfOmoiblZXbAeBs5zyxxeQKrYSMSHfdwdG/t9HZNFNvFEyp7k7XEU1xQ5HaAo6kResw+25vTU/lkvJNXYmNnmWr3ZxUo7qphCOw/ZJU4aMi+g8RjrWIp86biPeM8mIr57Oacrm3fIQnGTgfk7lqX5FGTjhjLTnDKin+AyFQCpkuki47leJ+W4VwS/LvObLDHn/WcYhjmkdmGXTGFZGhVYAHz3VcPklRmERDkafXZ7lPk0tWZjma/W4SCf6u8Pu3Ni5fVeZ9Zp7qiCjNomRBmMl2nlW2EC/GYJAW7c78TM1Gq9qw6EAAweO5/7JMtOMaA4Klm1XKmE6CpDmu6Ox4E0+RiaDZJ6lHnC7JcfNweMtbgZb4tK/1nAXqum2v4vIQcIDpfk2ROqxkvthclKe05z2p1oe2qg/mEWqwx51ZHR0PvMhmNYGh9VVi3F7KiT0v1K6D06CAAOJu6TeJTMKX5asGJ8K2PkVKk0E7uVWGKp7+WRBU4ILvUftG5d8Pz7ChCY35XVwknHbY/Rx7DNno+1h3YzkblIU=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.42.0
Release Details
UpdatedAug. 21, 2026, 9:23 p.m.
Changelog

Added

  • Receipts can be filed wherever you keep your app data. Uploaded receipts have always landed in Budget/Receipts/<year>/<month>/ in your Files; a new Receipts folder setting lets you point that anywhere inside your own Files instead — Applications/Budget, say, to sit alongside other apps' folders. The year and month subfolders are still created underneath, and receipts attached before the change stay exactly where they are: the app never moves or deletes your files. Applies to uploads from the web form, the API and receipt scanning alike (#352)
  • Bank statements in camt.053 XML can now be imported. Many European banks — Swiss ones in particular — export statements as ISO 20022 camt.053 (and intraday camt.052) XML rather than CSV or OFX. Drop one on the Import page and it behaves like an OFX file: every account in the statement is listed with its IBAN, auto-matched to the account of yours carrying that IBAN, and routed there. The parser reads what the payer wrote (the remittance text), who the other side was (the counterparty, which becomes the vendor), the bank's own entry text, and the transaction type code, and a batch entry such as a collective payment is split into its individual transactions with their own counterparties. Duplicate detection uses the bank's own entry reference — more reliable than the CSV content hash — except where a bank stamps the same reference on every entry, in which case the hash is used rather than collapsing the statement into one transaction. Every camt.053 schema version parses, including files with the namespace stripped (#350)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureRhkTM0z3ZXIpnFc2BJ0widME7KmhTp6jnd/kaHn42N1eiC9JQhiDUCGmqbCweHhswB3HBwwBoG37XE5L/9s97L13vmrIT+19EVx+f3o2xHXeVe0J19F0BKOxyW5mKYt7xQqo/dwCQ+qDk06kH89XPta+ppz28+qcfaEnBiEtnnzlyeOqyXgs6qWuM/sZW/WUau5dPKZxfkK57IgPaBIfx/R8cttcyokpplD5kV+rmGz8+AvAbvqcT06aGCzjQQtK4/ADbBe7PiGxy7Yy64B9LhgphkHuXqk1hzJiuC0exn+8z02QXGq5g2nDbATK6ZF6n6v6wIrSnEZtvRBvd2rloAQe5K5aiP6Ae6TPyILrunKGTL7Je1d/sqWO+103WdwcfLSI2rYHM00CUOdmxRttecjkJvc+sarc7m1M+fFIePC4SC5RlKJin/v9tUf/m+ie0+/UvqrcReF6hjCfN7jp8LBNjJQGsbpOBm+WO6v2i5GSKV/vNWLw4qln0rQXobu0jdSIhraqes84wPmF1z7U/eQorqmB9Q+ig4mfTtR3zxVfcd6vVT5fseiDTVhbaLf144zLTSxWpgVscFSQitXsVnA3FHkHuXsy8OqYeGgtQHOPjwMocSN1udnp59Wth/jd6qxj9Gf9KjFYFi/fwjc+QcvHaTuGCycDo+4xny+evpE=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.41.0
Release Details
UpdatedAug. 19, 2026, 10:30 p.m.
Changelog

Added

  • The Help & Docs page now says how to support the project. A small section with the GitHub Sponsors and PayPal links — the same ones listed on the app store — for people who installed the app and never see either. The floating help panel carries the links too. Nothing nags: it sits in Help, and the app works fully without donating
  • A recurring transfer can now pay a credit card the way the card itself would, with the amount resolved fresh at every payment. Card payments have always been representable as recurring transfers, but only at a fixed amount — useless for a bill that is different every month, which left people faking it with duplicate bills or typing the figure in by hand each time. A transfer whose destination is a credit card (or line of credit) now offers an Amount type choice mirroring what card issuers offer: Fixed amount as before; Statement balance, which pays what was owed as of the due date — everything charged since the previous due date plus any remainder an underpayment carried forward, with later charges rolling to the next statement; Current balance, which clears everything owed at the moment of payment; or Minimum payment, which pays the minimum set on the card's account (never more than is actually owed). The figure is worked out from the card's own ledger when you mark the payment made (or auto-pay makes it), so it is never stale; the amount shown on the transfer between payments is the last one resolved, and the pre-booked next occurrence carries it as the forecast estimate. Reminders, the bills calendar and auto-pay all work unchanged, because the payment is an ordinary recurring transfer. The card's own account page joins in: a Statement due day field on credit-card and line-of-credit accounts records which day of the month the payment falls due — shown on the card's page as account information in its own right — and a Set up payment button appears on a card with no payment transfer, opening the form pre-filled with the card and that due day. Once a payment transfer exists, the page shows when the next payment is due (#347)

  • Subscribing to hosted receipt scanning, and managing that subscription, now happen from the settings page. With the Otherworld relay selected as the scanning provider, the admin settings show the plans with a Subscribe button that opens Stripe checkout in a new tab — the licence key is shown once after payment, emailed as a backup, and pasted into the field above. Once a key is saved the block flips to a Manage subscription button: your server asks the relay for a billing-portal link tied to that key, so changing plan, updating the card or cancelling needs no separate account and the key itself never reaches the browser. A hand-issued key (a trial, or one minted directly) is told plainly there is no subscription behind it rather than being bounced off a portal that would refuse it (#537)

  • A CSV export of every transaction you're looking at, not just the page on screen. The account Export button built its file out of the rows the browser had already loaded, so it silently stopped at 50 — a year-end export of 800 bookings produced a file of 50 that looked complete, which is worse than an error. The export is now built on the server from the same filters the view is using, so it covers the whole result set however many pages that is. The Transactions page gains its own Export button too, which with no filters set means every booking across every account in one file: previously the only export was per-account, so a club treasurer with three accounts had to stitch three files together. Filters still apply, so you can export one category, one date range or one tag set just as easily (#344)
  • The exported CSV now says which way the money went. Amounts carry a sign — expenses negative, income positive — so the Amount column totals correctly the moment you drop it into a spreadsheet, rather than adding your outgoings to your income. The Type column reads Income and Expense instead of the stored debit and credit. Transfers between your own accounts appear as they always have, one leg of each, which now means they cancel out in the total instead of inflating both sides. The file also gained Vendor, Account, Currency, Reference, Notes and Status columns — enough to do the books from without opening the app (#344)
  • A new Income & Expenses report, for the year-end job of showing what came in and what went out. Pick it under Reports and you get two tables — income by category and expenses by category — with each side's own total and the net between them, over whatever period you select. It exports to CSV and PDF like every other report, the CSV keeping the two tables as separate labelled sections so a treasurer's spreadsheet can take them straight. Like the other reports it respects accounts and categories you've marked as excluded from reports; unlike the transaction export, which is a plain ledger of what you filtered (#344)
  • The Belarusian ruble (BYN) is now one of the currencies you can pick. It appears wherever a currency is chosen — the default in Settings, an account's currency, a manual exchange rate — and amounts are written with the symbol after the number (1,234.56 Br), as they are in Belarus. Its daily rate is fetched alongside the other fiat currencies, though the historical series is not: the 90-day history comes from the ECB reference rates, which don't cover BYN, so a converted figure for a past date falls back the same way it does for any other currency the ECB doesn't publish (#343)
  • The API can split transactions, so capture apps can categorise receipt items too. POST /api/v1/transactions/{id}/splits sets the parts of a transaction, and POST /api/v1/transactions now takes an optional splits field so a phone can record the transaction, attach the photo and set the per-item categories in a single request. /api/v1/ocr/extract additionally reports the receipt's subtotal and tax, without which a client could not make the items reconcile to the total — splits must sum exactly, and most receipts print tax on its own line. GET /api/v1/capabilities gains splits_available so a client can gate its per-item screen on a boolean rather than parsing the version. All four are additions: no existing field was renamed or removed, so clients built against the previous shape are unaffected
  • Receipts with loyalty savings can be split too. A Clubcard, coupon or multibuy line means the items on a receipt legitimately add up to more than you paid — and that gap used to make the whole receipt look misread, so it was refused for splitting and flagged with a mismatch warning. The savings are now read from the receipt and become their own line in the split, at the printed amount but negative, exactly as tax gets its own line. Four shapes now reconcile: items alone, items plus tax, items minus savings, and both together. The mismatch warning still fires when the gap is genuinely unexplained, which is the case it exists for. Two robustness details, because the reader is a vision model that occasionally slips: when it under-reads the savings by a line, the server closes the gap from the printed total so the receipt still splits rather than being refused over a saving it half-missed; and an impossible negative tax or subtotal from the reader is dropped rather than trusted into the arithmetic
  • Turn a scanned receipt into per-item splits. After a scan, if the items on the receipt add up, the scan box offers to split the transaction into one line per item so each can carry its own category — useful when one shop trip covers groceries, household and a treat. Where the receipt prints tax separately, the tax becomes its own line at the printed amount rather than being smeared across the items, so every figure still matches the receipt in your hand. The offer only appears when the arithmetic actually reconciles (items alone, or items plus tax, equalling the total); a receipt with a discount line or an unreadable item is left as a single transaction instead of producing splits that would be rejected on save. Splits carry categories, not tags — tags remain per transaction
  • Receipts are filed by month and named after the transaction. They now land in Budget/Receipts/2026/08/ rather than one folder per year, and an uploaded photo is named 2026-08-05 The Corner Deli 23.77.jpg instead of keeping whatever the camera or capture app called it (often a UUID). That sorts chronologically in the folder and makes a receipt findable by shop or amount in Nextcloud's own search. Existing receipts are left exactly where they are. A file attached from your own Files keeps its name — it's your file, and renaming it isn't ours to do
  • Receipts can now be attached while you are still adding the transaction. The Receipts section used to appear only after saving — the attach endpoints need a transaction id — so adding a purchase with its receipt meant save, reopen, attach. Files you choose (or pick from your Files) are now held and listed with an "on save" tag, then attached the moment the transaction is created. If one fails to attach, the transaction is still saved and you are told which — re-submitting would only have duplicated it
  • Scan a receipt straight into the transaction form. When your administrator has set up receipt scanning, the Add Transaction dialog gains a drop zone: drop a photo on it (or click to pick one) and the date, amount, merchant and a suggested category are filled in for you to check. The photo is attached to the transaction when you save, so a receipt is one action rather than three. The box tells you exactly which fields it filled, how many items it read, and whether those items add up to the total — nothing is saved until you press Save, so a bad read costs a retype rather than a wrong record. Scanning also works when editing an existing transaction, where it only fills fields you have left empty: a scan is a suggestion, never an overwrite. The whole section stays hidden on servers with no OCR provider configured, rather than offering a button that cannot work
  • Receipt scanning can be configured from the command line: occ budget:ocr. Run it bare to see which provider is set, whether a key is stored, and — the useful part — whether the server can actually serve a scan right now. occ budget:ocr set --provider=custom --endpoint=… --model=… changes it, and --api-key-stdin reads a key from a pipe so it never reaches your shell history. It matters that this exists rather than reaching for occ config:app:set budget ocr_…: the raw config route looks equivalent but skips the provider and URL validation, and would store your API key in plaintext, since the encryption lives in the app rather than in Nextcloud's config layer. The command takes exactly the same path as the settings page, so a rejected value changes nothing and a key is always encrypted
  • A CSV column can now be mapped to a transaction's Notes. Bank exports often carry a line of extra information — a payment reference, a booking note, the counterparty's message — that belongs in neither the description nor the reference field, and until now it was simply dropped: the only way to keep it was to edit every imported transaction by hand. Notes now sits in the column mapping alongside Description, Vendor and Reference, and whatever you point it at is stored on the transaction. It also earns its own column in the import preview whenever something is mapped into it, so you can see you picked the right column before anything is written, and it can be saved in a template like every other mapping. Over-long values are truncated to what the field accepts rather than being imported into a transaction you could no longer edit (#340)
  • The API can now read a receipt photo into a draft transaction. POST /api/v1/ocr/extract takes a photographed receipt (JPEG, PNG or WebP) and returns a draft for the user to confirm: merchant, date, printed total, line items, and — on the vision-model providers — the currency when one is legible; nothing is recorded until the client saves it through the ordinary create call, so retrying costs nothing but another scan. The reading is done by whichever OCR provider the administrator configured (below); failures carry a stable machine code (ocr_not_configured, ocr_quota_exhausted, ocr_extraction_failed) so a client reacts to what happened rather than parsing prose, and ocr_available on the new GET /capabilities reports the real state so clients hide the flow instead of hitting the error. A category is suggested by running your own categorisation rules against the extracted merchant — computed on your server, so the provider sees the image and nothing else, ever. When the line items don't add up to the printed total the draft says so rather than silently trusting either side. Documented in the REST API guide and the OpenAPI description (#533)
  • Recording a transaction over the API is now retry-safe, and can carry the receipt with it. POST /api/v1/transactions accepts an optional idempotency_key: a client that times out on mobile data cannot know whether its POST committed, so a repeat of the same key within a week answers with the transaction the first attempt recorded instead of inserting a duplicate — the single most damaging failure a capture client can produce, closed server-side. The same call now takes an optional photo part, recording the transaction and attaching the receipt in one request, plus a merchant field and a type that defaults to money-out. A new GET /transactions/recent returns the newest activity flat and merchant-first for a capture app's glanceable list. Wire field names across v1 settled on snake_case (account_id, parent_id, line_items) before anything ships against it
  • Receipt scanning can now be set up, and it is off until you do. A new Receipt scanning block in Settings → Admin Settings chooses which OCR backend reads a photographed receipt: this Nextcloud's own configured AI provider, any OpenAI-compatible endpoint — a vision model on your own network is a first-class option, not a footnote — or Otherworld's hosted relay with a license key. The choice is server-wide and an administrator's to make, because it decides who else sees your receipts. Until one is chosen the app sends receipt images nowhere at all: there is no default backend and no fallback. Your server makes the request rather than your phone or browser, so an API key never leaves the server and a backend that isn't reachable from the internet works perfectly well. Keys are stored encrypted and are never shown again after saving — leave the field blank to keep the stored one. Only the image is ever sent; account names, balances and other transactions are not. The Receipt Scanning guide sets out exactly what goes where for each option. With the API endpoint above, scanning works for capture clients as soon as a provider is configured; the scan button in the web interface arrives in the next release
  • A documented REST API, so Budget can be reached from outside the web UI. A versioned, read-and-capture API now lives at /ocs/v2.php/apps/budget/api/v1 — list your accounts and categories, browse and filter transactions, record a new one, and attach a receipt photo to it. It authenticates with an ordinary Nextcloud app password (or a token from Nextcloud's Login flow v2), so there is no separate credential to manage and revoking the entry under Settings > Security cuts off whatever was using it. That makes a phone capture app, a shell script or an n8n workflow a matter of configuration rather than code — the REST API guide has worked examples, and a machine-readable OpenAPI description ships with the app. Version 1 deliberately stops at reading and appending: editing, deleting and everything else stays in the web UI, which keeps the contract small enough to hold still. Fields will be added to it, never removed or renamed. Every amount crosses the wire as an exact decimal string ("42.50") rather than a JSON number, so a client cannot lose a penny to floating point on the way in or out. Note this is quite separate from the internal endpoints the web UI calls, which follow the database and change without notice
  • The accounts page can now be tailored to what you actually want to see. A gear button next to the tile/list switcher opens display settings for the page. Tick which attributes appear on each account — account type, institution, (masked) account number, last reconciled date, converted balance, and, on tiles, the 7-day balance trend and the status dot. Drag those same attributes into the column order you want for the list view (Alt+/Alt+ does it from the keyboard); name and balance can be moved as well, they just can't be hidden. And choose how accounts are ordered: by name, balance, type, institution, last reconciled or date added, ascending or descending. Tiles follow the same attribute order as the list columns, hiding an attribute drops its column so the rest can spread out, and everything is remembered in your browser alongside the tile/list preference
  • Categories can now be left out of budgeting without being left out of everything else. A new Exclude from budgeting checkbox sits alongside Exclude from reports on a category. Where the reports flag removes a category from all spending figures, this one is budget-only: the category keeps counting in reports, the dashboard, insights and every total, and simply drops out of the Budget page, the summary cards, budget alerts, the budget vs. actual report and envelope rollover. Meant for spending you want to see but can't sensibly budget — gifts, medical bills, home repairs — so you stop being told you're over budget on a figure you never set. Excluding a parent excludes its subcategories too, and like the reports flag it stays with the owner on a shared category
  • Select every transaction matching the current filter, not just one page. Ticking the header checkbox on the Transactions list now offers "Select all N matching transactions" when more rows match than fit on the page, so a bulk delete or edit can cover thousands of rows in one go instead of 250 at a time. The selection is dropped if you change the filter, so a mass action can never silently include rows you're no longer looking at, and bulk deletes of many rows are much faster (the account balance is recomputed once per account instead of once per row) (#336)
  • A Help & Docs page, in the app. The sidebar's Help & Docs entry used to throw you straight out to GitHub. It now opens a real page listing every guide with a one-line summary, a shortcut to the keyboard cheat sheet, the Quick Add page URL, and the System Info panel for pasting into a bug report. The floating ? button still gives you the short version for whatever page you're on, and now links through to the full page

Changed

  • A saved OFX/QIF template now remembers your field mapping as well as your account routing. These templates stored the routing only, so a bank that puts the payee in the memo had to have Description and Notes re-pointed on every single import — the choice was silently reset to the format defaults each time. Picking a saved template now restores both. Templates you saved earlier carry no mapping and are unaffected: their routing applies exactly as before and the mapping keeps the defaults (#340)
  • A reference longer than 100 characters is now refused when you type it, instead of failing when it is saved. The field was validated against a 255-character limit while the database column holds 100, so anything in between passed every check and then broke on the way to disk — a clean "too long" message is a better outcome than a server error. Nothing already stored is affected (#340)
  • A rule condition saying an import source is not something will start behaving differently on OFX and QIF imports. Because those imports never recorded a source at all, a negated Import Source condition matched every row from them; now that they do record one, it is evaluated for real. If you have a rule along the lines of source is not "Bank Sync", check it still does what you meant on your next OFX or QIF import (#338)
  • An import rule that sets notes "only if empty" no longer fires on OFX rows that carry a memo. With the memo now kept in the transaction's notes (above), the field is genuinely no longer empty on those rows, so an if empty rule correctly leaves it alone; an append rule adds to the memo rather than replacing it. Rules set to always overwrite are unaffected (#338)
  • The bill, transfer, savings goal, debt scenario, pension, asset and contact dialogs now use the same layout. Each was a narrow single-column form that had to be scrolled; they are now laid out in columns sized to what they actually hold — three for a bill (Bill, Payment, Schedule) and a debt scenario (Scenario, Payments, Debts), two for a transfer, goal, pension and asset, and a compact single column for a contact. Everything in them is visible at once, with Save and Cancel pinned below the fields. A bill's split rows span the full width of the dialog rather than being squeezed into a column, and a pension shows the pot fields or the income fields depending on its type, without leaving a gap where the other one would be
  • The four tag dialogs now match the rest. Add Tag, Edit Tag, Add Tag Set and Edit Tag Set are two-field dialogs, so they stay compact rather than being stretched into columns — but they pick up the same chrome as the bigger dialogs: a rule under the title, and Save/Cancel on a divided bar at the bottom right instead of loose against the left edge
  • The category dialog gets the same treatment. Naming fields (name, type, parent, colour) sit under Details on the left, the two exclusion options under Options on the right, and Tag Sets spans the full width below them — no scrolling, and the two checkboxes now read as ordinary checkbox rows instead of a bold heading with a stray box floating above it
  • The transaction dialog gets the same three-column desktop layout as the account dialog. Adding or editing a transaction was a 500-pixel-wide strip roughly a screen and a half tall, with a line of help text under every field restating its label. It is now laid out as Transaction (date, account, type, amount), Details (description, vendor, category, split toggle, tags) and Extras (receipts, notes, exclude from forecast), all visible at once with nothing to scroll for. Switching on Split across categories opens the split table across the full width of the dialog instead of squeezing it into a narrow column
  • The account dialog now fits on one screen. Adding or editing an account meant scrolling through roughly two screens of form in a narrow 700-pixel strip — eighteen fields, most of them empty, each with a line of help text underneath repeating what its label already said, and the Save button stranded at the very bottom. The dialog is now laid out for a desktop screen: three columns — Details, Banking, and Rates & limits with Advanced beneath it — showing every field at once with nothing to scroll for and nothing hidden. A column block with nothing to offer your account type, such as rates and limits on a Cash account, doesn't appear at all; Save and Cancel are pinned below the fields; the help text that merely restated its label is gone; and the current balance is shown as the calculated figure it is rather than a text box you can't type into. The columns reflow to two and then to a single stack on narrow windows and phones
  • The documentation has a home of its own: budget.otherworld.dev/docs. Every link that used to send you to raw Markdown files on GitHub — the in-app help panel and Help & Docs page, the README, the install guide and the app store listing — now opens the rendered site, which is searchable and readable on a phone
  • The Settings page is tidier. The Save Changes / Reset All to Defaults buttons were stranded in the middle of the page, with the Quick Add Page and System Info sections stuck below them, and Danger Zone was not the last thing on the page. Sections now run in a sensible order, with Admin Settings and Danger Zone at the end and the buttons at the very bottom. Quick Add Page and System Info have moved to the new Help & Docs page, since neither was a setting
  • The action buttons on an account row in the list view no longer sit flush against the last column

Fixed

  • The backup now actually contains your data — all of it. The export/import zip under Settings → Migration carried only categories, accounts, transactions, bills, import rules and settings; everything else silently vanished when moving servers. Reported for tags (#351), but the full list of what a migration used to lose is sobering: tags and their assignments, tag sets, transaction splits, recurring income, savings goals, assets and their value history, pensions with contributions and snapshots, per-account interest-rate history, manual exchange rates, import templates and remembered account links, saved reports, net-worth and budget history, reconciliation history, debt payoff scenarios, muted categories, shared-expense contacts with their shares and settlements — and on transactions, the links joining transfer pairs (so every transfer fell apart into an income and an expense), bill references, the split flag, and reconciliation/pension links. All of it now exports, and imports with every cross-reference remapped to the new server's ids. Old backups still import exactly as before; new backups are format 1.2.0. Deliberately still excluded, and now stated in the archive's manifest: bank-sync connections (provider agreements are instance-specific and must be re-established), shares with other users (they reference people on the old server), receipt files (stored in Nextcloud Files, not in the app), and the fetched exchange-rate cache (your manually set rates are included)
  • Marking a recurring transfer paid no longer loses the deposit half of its pre-booked transactions. When a transfer had its next occurrence pre-booked as a scheduled pair, marking it paid cleared the withdrawal leg but deleted the deposit leg — the source account paid out and the destination account never received the money, quietly understating it by one payment each cycle. Both legs of the pair are now cleared together. Payments already recorded this way are missing their deposit; the Convert to transfer action on the surviving withdrawal recreates the other half
  • Transfers no longer count as income and spending in the analysis reports. The dashboard's income and expense totals have left transfers between your own accounts out since 2.28.0, but the Reports page never got the same treatment: a £500 transfer appeared as £500 of income in Income Analysis (grouped by month, source or category) and £500 of spending in Expense Analysis (by month, vendor, account or tag) — and in the new Income & Expenses report only the incoming half was counted, overstating the net by the full amount moved. Every report view now excludes linked transfers, matching the dashboard, so shuffling money between your accounts changes no report figure. Two things are unchanged by design: a report filtered to a single account still shows that account's own transfer legs, because the money genuinely entered or left it; and only transfers the app knows to be transfers are excluded — ones created with the Transfer type, recurring transfers, and rows joined with Match transfer. Two unlinked rows entered by hand still count as ordinary income and spending (#349)
  • "Use Default Categories" failed with "A category with this name already exists" whenever any default was still present. The button seeds the whole catalogue in one go and gave up on the first name it found already taken — creating nothing at all. Easy to hit without doing anything odd: the category list shows one side at a time, so emptying the Expense view put the button on screen while the Income tree still existed in full, and pressing it failed on Income before a single expense category was created. Seeding now fills in exactly what is missing — an existing category is kept as it is, its missing subcategories are added underneath it, and everything else is created around it — so the button always finishes what it can instead of refusing the lot. A double-click while the first request was still running could also race itself into duplicates; the button now ignores the second click (#348)
  • Amounts in Kazakhstani tenge were shown with the code rather than the symbol. KZT was selectable and priced correctly, but it was missing from the front-end's symbol table, so every figure came out as KZT1,234.56 where the rest of the app would have written ₸1,234.56
  • Envelope budgets ignored everything you spent in a category's subcategories, so the whole budget rolled over untouched. The carryover looked for spending filed against the budgeted category itself and nowhere else. Budget €300 on Groceries and file the receipts under Groceries › Supermarket — the ordinary way of using subcategories — and it found nothing to subtract: July carried the full €300, August carried €600, September €900, growing by the untouched budget every month. The same screen said so in two contradictory ways, because the Groceries row itself has always added its children up: "spent €250 of €300" sat directly beside "+€300 carried". An envelope now covers the whole branch — the category and everything filed underneath it — so the amount carried forward is the leftover you'd work out by hand. A subcategory with its own envelope still keeps its own chain and is left out of its parent's rather than counted twice. Subcategories stay out of a parent's envelope when you've excluded them from budgeting or from reports, when they budget on a different period (a quarterly amount can't be added to a monthly envelope), or when they're income categories — and so does anything filed underneath those. Budget alerts and the budget-vs-actual report read the same corrected figure. Nothing was stored wrong: the carryover is recalculated from your budgets and transactions every time it's shown, so the numbers correct themselves as soon as you update (#341)
  • Envelope budgets also ignored anything you spent in a shared account, with the same result. The two queries the carryover uses to total up spending were scoped to the accounts you own, while every other budget figure on the page is scoped to the accounts you can see. So a category you fund out of an account shared with you looked untouched to the envelope: the full budget rolled forward each month, next to a row that correctly showed the money as spent. Budget alerts had the same split — they now measure spending over the same accounts as the budget they compare it against, including their split transactions (#341)
  • A long CSV column could import a transaction you were then unable to edit. Text taken from a CSV was stored exactly as the file wrote it, with no regard for what the field can hold. A notes column over 2,000 characters — easy to hit with a bank that packs a whole payment reference into one cell — imported perfectly happily and then failed validation the moment you opened that transaction, so no change to it could be saved until you shortened the note by hand. Over-long Vendor and Reference values were worse on MySQL and PostgreSQL: the row was rejected outright and counted as an error rather than imported. Imported text is now truncated to the field's limit, exactly as OFX and QIF imports already were, and leading or trailing whitespace is stripped rather than stored (#340)
  • "Check the server log for details" pointed at a log with nothing in it. When rows failed to import the warning told you to look in the server log, but the import never wrote there — the only record was in the browser's developer console, which is not where anybody was being sent. Failed rows, unresolvable accounts and balance recalculation failures are now logged properly with the row number and the underlying error (#340)
  • The column mapping step never highlighted the columns you had mapped. Each mapped column was supposed to be marked in the preview table underneath; the highlight was looked up by column position while the mapping holds column names, so it silently matched nothing and no column was ever highlighted for any ordinary CSV (#340)
  • A transaction added "today" could be filed as a future payment and left out of the account balance. Whether a date counts as future was decided using the server's calendar, but the date comes from yours — the web form pre-fills your device's date, and a capture app sends the phone's. Whenever your local date ran ahead of the server's, everything you recorded was quietly marked scheduled, and scheduled transactions are deliberately excluded from the balance: you added a purchase and the balance did not move. On a UTC-hosted Nextcloud that is the hour after midnight for anyone in British Summer Time, and most of the working day for anyone in Australia or New Zealand. The date is now judged in your own timezone (the one Nextcloud already knows from your session), falling back to the instance's configured timezone, so today is today wherever you are — while genuinely future-dated payments are still scheduled and still stay out of the balance until their date arrives. Transactions already misfiled this way corrected themselves within a few hours through the existing scheduled-transaction job; nothing was lost
  • QIF import has never worked: it reported rows in the preview and then imported none of them. A QIF file's accounts are matched to yours by an identifier the QIF parser never actually produced, so every account in the file was skipped — the import finished reporting success, with zero transactions added and no error to explain it. Underneath that, the parser had no notion of where it was in the file: an !Account header block was read as though it were a transaction (importing a row dated with the account's description), and because a real Quicken export opens with its category list, that whole list was read as an extra account containing one bogus transaction per category. Accounts are now identified by their name in the file, !Account blocks set the account's name, type and description as they should, and the sections that never held transactions — the category list, classes, memorised payees, security prices — are skipped instead of being imported as data. A file that does not name its accounts shows them as Account 1, Account 2 in file order. Dates are also read properly now: Quicken pads them to a fixed width (12/ 4'98), which nothing recognised, and a date that cannot exist — a 13th month — was passed to the database as text rather than being rejected (#338)
  • Import rules could not match on "Import Source" for OFX, QIF or any non-CSV import. Only CSV imports recorded where a transaction came from, so a rule condition on Import Source was silently false for every OFX and QIF row — and, because an unknown field inverts under a NOT, a rule saying source is not … fired on all of them instead. OFX and QIF imports now record OFX Import and QIF Import, joining the existing CSV Import, Bank Sync and Toshl, and the values are listed in the rules guide. Note the source describes how a transaction arrived and is not stored on it, so this criterion still matches nothing when a rule is re-run over existing transactions — the guide now says so (#338)
  • The column mapping did nothing at all on OFX and QIF imports, and the memo was thrown away. Every field in the mapping step could be changed and none of them had any effect — the import silently ignored the mapping and always took the description from the OFX name field. Banks that put the real payee in the memo instead (a common Canadian pattern) had no way to import a usable description, and the memo itself was parsed, shown in the preview, and then discarded rather than saved anywhere. Worse, a statement whose entries carry only a memo and no name imported with a completely blank description. Now: Description, Notes, Vendor and Reference can each be pointed at any field the file actually contains, the memo is kept in the transaction's notes by default, and a missing name falls back to the memo instead of importing nothing. Date, amount and type come from the file's structure and are no longer offered as mappable, along with the income/expense, account and currency columns that these formats never had — those dropdowns are gone rather than left on screen doing nothing (#338)
  • The import preview showed every amount as a plain positive number, whichever way the row was going. The preview is sent each amount unsigned with the direction alongside it, and it drew the number while ignoring the direction — so a statement of nothing but expenses previewed as a column of figures indistinguishable from income, and the step whose whole purpose is to be checked before anything is written could not show the one thing most worth checking. Amounts in the preview are now signed and coloured: an expense reads -€91.29 in red, income €500.00 in green, and the column is right-aligned so the figures line up. What was imported was correct all along — only the preview was silent about it (#339)
  • A negative amount written any way other than a leading hyphen imported as income. Only -1234.56 was understood; every other notation had its sign thrown away with the currency symbols. That covers a trailing minus (1.234,56-, as written by a number of German and mainframe exports), brackets ((1,234.56), the accounting convention several US and UK banks follow), and a typographic minus or dash in place of an ASCII hyphen. A trailing minus was the worst of the three: left on the end of the number it also pushed the decimal separator out of place, so 91,29- imported as income of 9,129.00 — a hundred times the real figure, on the wrong side of the ledger. All three now import as expenses, and a lone - in an amount column still means "nothing here" rather than a negative. If you have already imported a file with trailing minuses, re-importing it will add the corrected rows rather than recognising them as duplicates, because the rows that went in were keyed on the wrong amount (#339)
  • Dialogs on the Assets, Pensions, Savings Goals, Debt Payoff, Tags and Import pages opened behind the sidebar. Fourteen dialogs — including Add Asset, Add Pension, New Scenario and Add Savings Goal — were written inside the page content area, which Nextcloud paints as its own layer. A dialog can never rise above the sidebar from in there, however high its own stacking order is set, so it appeared cut off behind the app navigation. They now sit alongside the dialogs that always worked, and cover the whole window like the rest
  • The remove button on a split row sat under the Description box instead of beside it. The row's Description input was written without its closing bracket, so the browser swallowed the tag that should have ended the field and folded the remove button into it — the row's fourth column stayed empty and the ✕ dropped onto its own line. It now sits at the end of the row where it belongs
  • A mapped Type column is no longer ignored, so unsigned exports stop importing as all income. Mapping a Type column (Expense/Income, Debit/Credit, DR/CR, Withdrawal/Deposit, …) had no effect: the direction was always taken from the sign of the amount. Files that write every amount as a positive number and state the direction in a separate column — Nextcloud Tables exports, and a number of banks and budgeting apps — therefore imported every single row as income, quietly moving the balance the wrong way by twice the amount. The mapped column now decides the direction; rows where it is blank or unrecognized still fall back to the sign (#333)
  • The import preview now warns before a batch goes in the wrong direction. Two new warnings appear above the preview summary: one when a mapped Type column is blank or unrecognized on some rows (naming how many), and one when nearly every row would be booked as income into an account whose history is nearly all expenses, or the reverse. Neither blocks the import (#333)
  • Every transaction showing "Unknown Account" after restoring a backup. Restoring a backup gives every account a new id, but a page that was already open kept the old ones, so nothing in the ledger could be matched to an account and the whole Account column read Unknown Account — with nothing in the browser console to explain it. The same happened in any second tab left open during a restore. The transaction list now notices that it is holding a stale account list and refreshes it by itself, and a restore finishes reloading its data before reporting success (#333)
  • A failed accounts request no longer blanks the Category column too. If the accounts request failed while the app was loading, the rest of the load was abandoned as well, so both the Account and Category columns fell back to Unknown Account and Uncategorized behind a generic "Failed to load data" message. The two lists now load independently, and the message names which one failed and says to reload the page when an expired session is the cause (#333)
  • Select all now counts during reconciliation. In a reconciliation session, the header select-all checkbox ticked the row checkboxes visually but the Ticked total and Difference didn't move, and the ticks never reached the server — so they were also silently lost when leaving and resuming the session. Select all now registers every row it ticks (or unticks) with the session exactly like a manual tick, and no longer wipes ticks made on other pages of the list (#337)
  • Deleting an account that still has transactions now offers to delete them too, instead of failing with an unhelpful message. The delete failed with "Failed to delete account: Failed to delete account" — the real reason (the account still has transactions) was being replaced by a generic message on its way to the browser. The prompt now says how many transactions the account has and offers to remove them along with it, which makes a bad import easy to undo; decline and nothing is deleted. Transfers pointing at the deleted transactions are unlinked, leaving the counterpart in the other account intact (#336)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureBbOGARv5bo0EfD87OHApDK4LSAVbklBnbu7Q0XNAXlA/b120kU9X1ByNzLNwChmoeOLSrKp+saviED0SZkaaD2VdC6KM+2NghhWl/8RsDzdjLnUS5mbhQ04KOXOClJ1iHzwKIRJvAkStGLPAP/McI7ol6QLHi3ABWXWDlBcT6bGKDC6v7cmbh9jOeoys4phwH0uJE9pOVlQg7SfHGd/VJKr6pcScapT9P5dOBj878vpqjYSc3KIFvQ5OfA9C836sCseYxi9jM8YPoaw+LzTfX5/t80Fv5I2woXsvXnwtjijARCotyD1uZ9QMAy7M5LLkEm6yUGjJYrEBMBpc3h8fiC7muLojTK+J9O7zk7oYNN8D6Q2YqdJ3e84cEagzf83gbKicTPX4kJ9C8bvUQzK5roVtgFwat/Ndu9c2uK/rwOUVmDKPHdzt3/SQQAl9712dX7lZTJVN9r3dm87AL1nfaJghemZOfQdcQwFkahMlHZOm+B0xKrSUqQWyfbw4xezPvVZEudqpPIhQ0lIlFro93ziB7KBUJvaJCx0UNMFr2Z4zCDY64wKLaq1sgSm8HQ4QxSdL1+bPWgTG+BVzchvbx6Cmh7DHmXTAr5XGPzEczdMWY0t16uZ4ZzftT5Ss+S/NKpV37SiFKPOKWzou4BFGU9qwl0DeYKy4E+/EDMX0W80=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.40.0
Release Details
UpdatedJuly 26, 2026, 9:40 p.m.
Changelog

Added

  • Keyboard shortcuts. Budget can now be driven from the keyboard. Press ? anywhere for a cheat sheet. Globally, / (or Ctrl/Cmd+K) focuses search and g then a letter jumps to any page in the sidebar (g d Dashboard, g t Transactions, and so on — every page has a letter). Any dialog now closes with Esc, traps Tab inside itself, focuses its first field on open, and saves with Enter. On the Transactions list, j/k move a row cursor, e (or Enter) edits the highlighted row, and x selects it. Shortcuts stay out of the way while you're typing in a field
  • Export and import your import rules as a file. New Export and Import buttons on the Rules page: Export downloads every rule you own as a single JSON file (a lightweight backup, or a way to move your rule set to another instance without a full data export); Import reads such a file back in and creates the rules. A rule referencing a category or account that doesn't exist on the target instance is rejected and reported rather than mis-filed. Rules shared with you are left out of the export, and rules remain part of the full data export too (#318)
  • Import rules can now be shared. Rules join the list of things you can share with another Nextcloud user (alongside accounts, categories, bills, income and goals) — pick which rules to share, read-only or read/write, from a share's Configure panel. Shared rules show a Shared badge on the Rules page, can be run and (with write) edited by the recipient, and run during their imports too; only the owner can delete one. A shared rule's set category/set account action only takes effect for the recipient when that category/account is also shared with them, so a transaction is never filed under something they can't see (#320)
  • Import rules can now match on the account. A new Account condition scopes a rule to a specific bank account (with NOT for "any account except this one"), and a companion Account Type condition matches by kind of account (checking, savings, credit card, …). Both work when importing into an account and when running rules over existing transactions (#322)
  • Tag sets now work on shared categories. Opening a category shared with you shows its tag sets; with write access you can add, edit and delete tag sets and tags on it just like your own categories, and read-only shares show them without edit controls. Previously any tag-set action on a shared category failed (#328)
  • Bulk edit can now clear a transaction's category. The Bulk Edit Transactions dialog's Category dropdown gained an Uncategorized option alongside Don't change, so you can un-categorize many transactions at once (#332)
  • Deleting a category that still has transactions now offers to reassign them. Instead of blocking with "reassign or delete them first", the delete prompt offers to move the category's transactions — and any in its subcategories — to Uncategorized and remove it in one step (#332)

Fixed

  • The browser Back button now moves between pages inside Budget. Switching pages (Dashboard, Transactions, Accounts, …) records a history entry and updates the address bar, so Back and Forward step through the pages you visited in the app instead of jumping straight out to whatever you were looking at before you opened Budget. The current page also survives a refresh, and links that deep-link into a page (e.g. from search) still work.
  • Bills with "Auto-pay when due" turned off could still auto-pay themselves. The auto-pay flag (and the other bill toggles) could be read as on when it arrived as text rather than a true/false value — the classic (bool)"false" trap — so a bill created or restored with auto-pay off could still be auto-paid. All bill toggles are now parsed strictly as booleans on create, edit and import (#335)
  • Cryptocurrency accounts and their transactions now keep full precision. Amounts were capped at 2 decimal places on entry and storage, so e.g. 0.00012345 BTC was rounded to 0.00. Account balances, transactions and splits now accept and store up to 8 decimals, following each currency's native precision (BTC 8dp, XRP 6dp, JOD 3dp, and so on); fiat currencies are unchanged and still 2dp. Amounts on bills, recurring income and savings goals denominated in crypto are not yet covered (#331)
  • Shared categories keep the owner's order, and editors can reorder them. Recipients saw shared categories in an arbitrary order and couldn't move them; they now appear in the owner's order, and a write-share recipient can drag to reorder (the new order applies for the owner and everyone it's shared with). Reordering no longer silently fails when sort positions collide — the whole sibling group is renumbered on each move (#328)
  • Shared categories now open for the recipient instead of doing nothing. A read-only shared category couldn't be selected in the list at all, and even when reached its detail/recent-transactions/spending endpoints returned 404 (they looked the category up under the viewer, so one owned by someone else was never found). Clicking a shared category now opens a read-only view showing the owner's transactions and analytics for it (#328)
  • Recording a bill's payment failed when the bill used a shared account. A bill can point at an account owned by another user — a partner's shared account — but marking it paid, and the one-click Record transaction repair, threw "Failed to record payment" (a DoesNotExistException in the log) because the transaction was booked against the person clicking rather than the account's owner. Bill payments are now recorded against the account owner, so a share recipient can mark shared bills paid; a bill whose account was since deleted now shows an actionable message instead of the generic failure (#334)
  • A one-time bill marked paid without a recorded transaction could not be reached to fix it. After a one-time bill is marked paid it deactivates and drops off the Bills list, yet it still appears in the Payments without a recorded transaction card telling you to assign an account first — with no way to open it. That prompt is now an Assign an account button that opens the bill for editing (#333)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureTlx5adQ84X1cU4v1VoYON+yY22etMZSb58OURK5dpJ/bpQdLjdhL6stjRFGshNhEHr1Ra/KTZs7/uCZLyvq+M0XBYGD+voy+pwmXwa6Wylyi99fJ2UhiXPHxKiExVq1EJY/PA7LcHAQy639r04gbQ4Q/BvDrOZYWAZuYCLrZrZFclfoIlzf/Ra5SFuCuWguuOd79cU/tXViv8xntJBIcIXoN58cadHF5iTo3Mt2XO7sNsUs7A8+1HDXsUldblvmLFFpH9ubJdYVDKqdzA104yRb0uPH08Zd6+y764r+uIsahSB/RwF3kJ20gcv5nurCaf9FvsI06PiyQnR73jMzlnoAaWxnSPZwGDa+gvQ/t56H+m+A9DlvVgnxexUa0C+Ga7cphcgVKWPWaRZFQzeofrcJ66wAH9uh338pw2R2Lq5F+s2NCOKuKo6uXocpf+VZ9GTsfRIrDEGL+4FwkFkxd0tHUBoohsOhROk/tXphvl/mIh5m4m3pRsjm7GviZASYoTXJe+kdclUUzpFMuXGrOFjSXCd1Plk2XsDMiHBzPEXAkaPlL9hdluXiuCCXrUYIF+S/U60qB1MuWRlwzTH80RovEgvyKGwZtzlDPtNLF0hM79iABKE5UgP1km9MRm7dyDWQDdogfWq+Oy97EJH8TDtYvuO2I79lQnppc9WrYB5E=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.39.1
Release Details
UpdatedJuly 11, 2026, 10:22 p.m.
Changelog

Fixed

  • Share recipients saw wrong dashboard totals. For a user whose accounts are all shared from someone else, the Income/Expenses This Month cards counted transactions in the owner's "Exclude from reports" categories — the exclusion list was built only from the viewer's own categories, so the owner's internal-transfer legs inflated the recipient's income and expenses while the owner's own dashboard was correct. Shared categories now keep their owner's exclusion for every viewer, and per-viewer "Hide from my reports" mutes are honored by these totals as well (#326)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignaturePTjw+Z1r+sKWQmZSlNfYPSTl5PFejqjMEgNyvQR1FXSKor9zNXxtxcAM0eYYthPn9YEprCKS9V6NC699ZbeWK6WbdRtprmP+rsvCifpjQyVtPDGLJ11LWzLVgw84pTHcolsdY756JO6KWW8hxp63bq3s4QE4rs3RTCEyHSpzpZ1pXSydTCTvheL1M/rtg3XyKpzBkoOqGh39Dnh9TH7JQt+cCB8VD84aeHcsvnxUkQJU3AmZwYGcP8wSNeLmDjt1S9yCv2h8NAReLQeTMbmdzNJtioLLiifkedz5bEgjVximgqI99mmV+8uhRBY0keT1hWXR6En4IrRkiJwlEyNZRHkukMa9jNmoNVvoRYCuQOVZ1wWGtkS8MCz5Ig63yPijEMh1bqnoi3+WA1g8s23dJVIziAHSKl0F+V7DKThsw2jBouMZeZ7bG0nMS9bFLcndAm1MbpWyuZATotUExNeYhEZEIwUOuF+esV5lnDoHTf0i/q6OJGa4hPPiNTE/rH4PS3Z4pdEZ4V9YhxYfsSs/9y+Y7xg/ZQWnLq2YVsTR7V8FgQwU4Bi8OGLsfbYZhSaUnHv60ObUB2U4WkD1mZZqDHKJXAIgVGulvHFAkXQVeGpRqbUCQNvgiVU8hfRaRmEr/y9Usub/3srDJn7qybeAxfOxA7rL+AlakEZBECHPJlY=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.39.0
Release Details
UpdatedJuly 11, 2026, 12:57 a.m.
Changelog

Added

  • The Bills page now flags payments without a recorded transaction. A warning card lists bills that were marked paid in the last 60 days without a transaction being created or linked — the situation where the app balance silently detaches from the bank. Each entry has a one-click Record transaction repair that books the missing payment (dated the day it was marked paid, both legs for transfers, splits applied). Deliberate skips via the Skip button are not flagged (#274)
  • QAR (Qatari Riyal) and JOD (Jordanian Dinar) are now available as account currencies. JOD amounts use the currency's native 3 decimal places. Automatic exchange rates cover both. Requested in #321

Fixed

  • Editing a monthly recurring income never saved the changes — the app showed "Income saved successfully" but the Expected Day (and every other field) kept its old value. Any update whose payload contained an empty field (a monthly income always sends its yearly-only "expected month" as empty) reloaded the entity mid-save and threw away the edits. Thanks to @redsteadz for the fix (#324, #325)
  • The "Exclude from forecast" checkbox on a transaction appeared unticked whenever the edit dialog was reopened, and saving the transaction again then really did reset the flag. The flag was stored correctly (including when set by an import rule) but the transaction list never sent it back to the browser, so the dialog always showed — and re-saved — it as off (#326)
  • Income/Expenses This Month (and the other report summary totals) deducted transactions in "Exclude from reports" categories without converting them to the base currency, so on multi-currency setups the deduction was applied at the wrong rate — and for a single selected account the deduction wrongly included every other account's excluded transactions too (#326)
  • Imports no longer bring in flagged duplicates by default. The preview's "Show duplicates" checkbox — on by default — secretly doubled as the skip-duplicates switch, so every import ran with duplicate-skipping off and rows flagged Duplicate were imported anyway. It is now purely a display filter; a new explicit "Import flagged duplicates too" option (off by default, resets each import) covers the deliberate re-import case. The preview's per-row checkboxes, which were never actually read by the import, are gone, and the New Transactions count no longer includes flagged duplicates (#327)
  • Marking a bill paid no longer suggests unrelated transactions as "existing" matches. The Existing Transaction Found dialog offered any unlinked same-day debit as a candidate — cigarettes could be presented as a "match" for a mortgage — steering people into marking bills paid without recording the payment, the classic source of app-vs-bank balance drift. Candidates now must match the bill by amount or name, a weak match is never pre-selected (the safe default is creating the transaction), and the "Don't create any transaction" option now states — and warns after — that the account balance will not reflect the payment (#274)
  • Overdue bills no longer double-book when marked paid. The scheduled placeholder pre-created for the next occurrence was written as an ordinary cleared transaction whenever the advanced due date was not in the future, so it counted toward the balance immediately — alongside the actual payment. Next-occurrence placeholders are now always scheduled, regardless of date
  • Restoring a backup preserves every bill setting. The data import dropped most bill fields: custom recurrence patterns (restored bills then advanced one day at a time instead of quarterly/etc.), transfer destination and description pattern, auto-pay, reminder days, tags, split templates, start/end dates, remaining payments, forecast exclusion and the future-transaction opt-out

Changed

  • The Match transfer dialog now also lists candidates from accounts in a different currency (any amount, within the date window), so cross-currency transfer pairs — e.g. imported from CSV — can finally be linked by hand. Automatic matching after imports is unchanged and still only links exact same-currency amounts (#326)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignaturegJm3RDjkvl1EBICN6Us5TsX5SdQbSGnRHvRIZmLsYaclkDVqW/mYCBjVgwjU50ifkv72zl3kxf5a8S3yxpo2WX6cnhkyyibLhs5Uzdrj9Egw47yYgMun8WH4647Y0uGP7QrX3Yf51SO7Ve+JWgdMRX+hWvG4K9hxUgAwWR3AmTYRsRXpmsNrOr97q2SPC3V0g9bAARDeSeWDGQ8SR05+OMIrQRj0Ct56fC1cTNWzHpPT+Qs17SJJcUUnK3tJWsM3wvGiwk62YMBy1cv1jx3JkOXnYvsa8bpSG3sL7aqr05QkAkvL9sSGxka6mDrC3CN1LHlwwQjPjWwoX9YDtOI04j0JPd0SzlhMYILaZNyouhoNTuY5YhDIG4aLjg737AAEBHgU3jvpWxaM8Oz2+9he9LkAJW6qA9DuzB/FmDNKxyJTmQ6S0LZ21d+Hkr0LD/2uKRSywlRBld+UNCWby8YrgIkyGomPH1rjDG28y1ApiqSozetcjSvDYwqULM2mLXU9OjD9a8UJk8B1R4Xd0TqgMmDCaAZrTdRLYYdTZEEaFbnDkbm8p4z2q+UGfn/UCNEOkg5pbu1WAsRubIKkPzNTz7gTSLI9u+qJfvoZg9c3Ae1OhXWDD9k/2Z+pCrbJhu8yDX+2JukXoAxNS+bnxaDxdoxRzIM+9jcbb0eyG3wJuLk=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.38.0
Release Details
UpdatedJuly 7, 2026, 1:07 a.m.
Changelog

Fixed

  • The account selector saved in the gear settings of insight tiles (Monthly Comparison, Large Transactions, Weekly Spending, Year-over-Year) was silently ignored — the tiles always showed all-accounts data. The saved account now actually scopes the tile's numbers
  • Importing transactions that trigger the Auto-Link as Transfer rule action no longer shows "Cannot use object of type Transaction as array" on the import screen. The import itself always completed — the error came from the transfer-linking step afterwards, which also means those transfers were never actually linked (#314)
  • The Recent Transactions dashboard tile now honors its "Rows to show" setting above 8 — the display respected the setting but the data fetch was hardcoded to 8 rows, so values of 9–20 silently showed only 8

Added

  • Edit auto-categorization rules as JSON. The rule editor gains a Builder / JSON toggle. The JSON view shows the raw rule structure — editable and paste-friendly — checked when you save, and switching back to Builder repopulates the visual widgets. A Copy JSON button makes it easy to move a rule between instances (category/account IDs are instance-specific, as noted in the view). Requested in #318

  • Hide shared categories from your own reports. Categories shared with you gain a per-viewer "Hide from my reports" toggle on the Categories page. Unlike the owner's "Exclude from reports" flag — which stays owner-only because it changes every viewer's reports at once — this only affects your own reports and dashboards; the owner and other viewers see no difference. Applied at the SQL layer through the same choke points as the owner flag, so every report and insight tile honors it consistently

  • "Exclude shared accounts" on the remaining dashboard tiles. The per-tile toggle added in v2.37 now also covers Budget Progress, Monthly Comparison, Large Transactions, Weekly Spending, Category Trends, Cash Flow Forecast and Year-over-Year (shown in the gear menu when you have shared accounts). Bills, income and pension tiles are deliberately not included — they show entity data, not account aggregates

  • Clickable spending charts. Clicking a slice (or bar) on the Spending by Category dashboard tile or the Reports page pie chart jumps to the transaction list filtered to that category, scoped to the chart's date range and account. Tiles set to "top-level only" include the subcategories in the filter so the listed transactions match the clicked amount (#317)

  • Per-bill opt-out of pre-created transactions. The "Create future transaction for this bill" checkbox is now a persistent bill setting instead of a one-shot option at creation. Bills with it unticked never get a scheduled placeholder — not at creation, not after marking paid, not after skipping — and toggling it on an existing bill adds or removes the pending placeholder immediately. Previously the checkbox only affected the moment a bill was created, while every payment re-enabled pre-booking unconditionally, so unticking it never actually opted a bill out (#311)

  • Convert a transaction into a transfer. The Match transfer dialog gains a "No match? Create the other side" section: pick one of your accounts and the app creates the opposite transaction there and links the pair as a transfer. Until now the dialog could only link two existing transactions, which left no way to correctly book payments to accounts that have nothing to import — e.g. a loan tracked as its own account (#313)

Changed

  • Scheduled (future-dated) transactions now show a Scheduled badge in the main transaction list, with a tooltip explaining they are not counted until they occur. Previously only the account detail view had the badge and the main list showed scheduled rows in italics alone, which made a bill's pre-created next occurrence easy to mistake for a duplicate booking (#311)
  • The transaction list Total no longer includes scheduled transactions — they are placeholders for money that has not moved yet (#311)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
Signatures/wP/jWqAxqTStZPLKWl/5nyJk/xpeAom+Kp7KakVOdJmzhNv/Z6KM/CUUOrGem4Qj5G1OEZ2tNrPkTneCVvfFU2S5aoayMDgcRaGquqwZisM/4a0KV9Husjq8mV0RVoqco16HBH8PUY+kYsbeWRcSp2q38Zq99L04zb1x5XY1rGe5YdP4/IydUoMpyzTtsGF00Tj6OUAMvlDTnJqCcetscuXX8yo33xm0dUfLxjZD2f9hsn8UTCwNN7v1+yBhwNN4jJsfyGTN+92XV2YDhRCfVWq/3bGqphHo+nYQvbyjndJRcaAwybOquX6MH7+wpDa5wpvNw9xzc2sYNm2FM08SYep3cX7uoXngifGZu2FBqyNHQ198dqEwqJbEVv2DrK5cAnQkbSS1glYYney/uXAlsqLEinHirrShNYRoq+ZEkxUhpdung3zSWwPe0Fd/mWh2chHiTV20A2tCrv7FRuRadpf75bq+y0xuIglVZQy5E1dT2nk3lPUUwB01w/ggmwrJ91hOchPoyoRoDhoBNxZJs903bQejWR/MdZ9pbXVmwxj1EOq8oWfWeQ5B+OEz/LbcplibODsNv6IUIYU++gxK8d2XCVzBgV2ayMqsRxFDxItgluqDcu4oTW8mh3A4z33PvbeCFFMsj2bKFbOslmuT2ZiVl58oTaQRTh61xeKEA=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.37.0
Release Details
UpdatedJune 27, 2026, 11:16 p.m.
Changelog

Added

  • Exclude shared accounts from reports. When other people have shared accounts with you, the Reports page gains an "Exclude shared accounts" toggle so you can see just your own accounts' figures. The same option is available per-tile (in the gear menu) on the account-based dashboard cards — Income vs Expenses, Spending by Category, Top Spending Categories and Recent Transactions. It's off by default (shared accounts are included, as before) and only appears when you actually have shared accounts. Note: a transfer between one of your accounts and a shared account can only be partly seen when shared accounts are excluded, so income/expense totals may be slightly overstated in that case.

Fixed

  • Saving share settings failed with "Some entities do not belong to you" (HTTP 400) when the "Auto-share new" toggle was enabled for a type, or after using Select All — the auto-share toggle (which shares the same data-type as the entity checkboxes) was being collected as a phantom entity and sent as a null id. Entity selection is now scoped precisely, so share settings save correctly with auto-share on (#306)

Changed

  • The Categories page now also lists categories that have been shared with you, shown read-only with a "Shared · <owner>" badge. Previously it showed only your own categories, so anyone using a budget made up entirely of shared categories saw an empty page even though the categories worked everywhere else (#306)
  • Categories shared with you at Edit permission are now editable — rename them and change their colour straight from the Categories page (they carry a "Shared (editable) · <owner>" badge). Read-only shares stay read-only, and a category's type, parent, budget, report visibility and deletion all remain owner-only (#306)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureFqJ17XG/szTfkAMsF+oCODYGClVjdeGArgFi3SrgeGhg4CFFzIVO98XEnYhxeCnwOcYGivzy0uhe60/Vv7kgml+lIVvRL1EZOxvjOES2KksQ50fqxGZSNz3EL54EA6R3Yvo6uLFBM9cbK0mmY5H+4i3UozKhKwzRa6PJLIZzpBsjtprJXHojWsQMR5KY7WDDbb9yD32uYzMnrXMxOiQ2PZGtG7aIhLS6DzC7Mtp/oLUgyRqBWoYMUWWLLi1qyeOr4/8Tdm9H5I36oxeoX2ZQlVuprpRjDPW5EITrljbyuIPy3CdAFn5tvvt8rkurEgCtPAaMv7gSXRZto6rJJqS4woUqX310+J0re9qa53Ls0J7Kezo5WpENoaFsvT6McjVG/4k6k4YN1/l74p97fFfR+1T2kC5VptpwVz4GZ2aSF9t226Sdkft7sv72aC3oQpa4PN3PIWj113aN2X5nnCGiD+NUW282/yAdacvMWVgB+t+Rbm0FIyWtGnbw0dKAlY3CAmQoBvqX9f2vqn1OFDxJhejg/i7+FAWQD83LIk6u2kNg/N4e2+hgLtO45wd5MU6TLXXTrb1mlikbbiP80Rla1p50fScosYTCqjJfz2lh5U6D2h/nquGHHvhf4R9q7eSkykmELHZUKiUyYlrLrOfiuxGRqaWSQWp9hm0CUog1HBE=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.36.0
Release Details
UpdatedJune 27, 2026, 1:15 p.m.
Changelog

Added

  • Auto-share new entities. Each person you share with now has an "Auto-share new" toggle per entity type (accounts, categories, bills, recurring income, savings goals) in their sharing settings. Turn it on and anything you create from then on is shared with them automatically, at the permission you choose — no more sharing each new bill or category by hand (#306)

Fixed

  • Code-integrity "Some files have not passed the integrity check" errors reporting FILE_MISSING for js/.htaccess and vendor/tecnickcom/tcpdf/tools/.htaccess. The app no longer ships any .htaccess files — the Nextcloud App Store strips them from the published archive, which left the signature expecting files that were no longer present. Neither file was needed (the JS one only set a redundant cache header) (#307)
  • Deprecation warning in the Nextcloud log — the notifier now throws UnknownNotificationException instead of InvalidArgumentException for unrecognised notifications, as required by Nextcloud 30+ (#308)
  • Reports and the dashboard summary were empty when a single account flagged "Exclude from reports" was the only account selected. Accounts flagged out of reports are now only dropped from the all-accounts views; explicitly selecting one shows its data as normal (#309)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureYxqf1NnAucAiXFVdwVmQJPaPUyuExQ8t/dwv4tDVpFb1kXDtGcIWoAdspiDz+HwdyPe+ul+/2GcDWiLPTF3TvIHwIaV+h+guDRYBEHMY95+Hy5W0BSuwBC7gto5dfsZEhL5xj5OsRIYrY/Fo8Tqj99kVzDK560o9NgI6Bp6ZkQpbwPRbTnbxUX27oF0oDjrg1ArS4IiE4ghZW1ct74Mlv4uoeg5zaVQlucrZK+rBJXixtpDnImHLPMkTvd+1bmkQTFtvArS1A37YkXkLKrKn4pzWvwv/q46ddih1NXBC7o6UoBwP1pWB1OxgNq3/98OdWyPs4GLumMmRdg+7PbY95Go97lBbNc/1mrBB9qQPXirFxYHMZWVDSRHSNRJ9cSMnZA/YzsVeOZOVkIwJWXhC5YGAEN8nq8HKIMBHzmi6UYdGM2VvGPmNZ+K3wlGMIkKlVfWfIJ7XIOCe6OLvQbwR/ATZ7pUyOE+AR21uu27zWGJ4iB4y/eCfCSE8vIxyPW7L0dwkzxU13iNNNxAUQgbNrs8EiQBLQlTCaBWCWp296Dds5nEGMEilQKX9vEXAhY9KRG5dzJjoZhZ14tWA3Hjp+5/Gs2AM4Bh3Rp1OGdhfQhFDmt/2GXcL16lfDcX28K1ub4FPYE8MEz6qDmLhqqwv9FeXQQbT/ZKdQn8NwuOlGFE=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.35.1
Release Details
UpdatedJune 25, 2026, 3:28 p.m.
Changelog

Fixed

  • Categories marked "Exclude from reports" are now consistently excluded everywhere, including the Income vs Expenses trend, Category Trends, Top Spending Categories and the monthly spending chart — not just the dashboard summary. Exclusion is now applied in the database query itself, so reports and dashboard insight tiles can no longer disagree about which categories count (#219)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignaturebX/9kwpiVjwDj0f2eU5xNE7zUpt8T/nkGCFg9HnDQoKynM7c1KaXhbh4isVQBbgy5kPGXSDP7DRfuSTYY5/M3PSv1JE8gOk/9lz2AGmTqlXrf4Kgq9oARAGcVHXB955dLvDkj6Vrk7zZ9cwrjq4aMBu02dW8ZgyAHStXybiWmkAbIxK768MHM4n5FXTRFw3P/ELVlDjCxgIpxVxD5EZaaA+n7RrjN9MRY2R8/GN7Og7yijcmnutMWtna4K19B9c3ShcfUkrwotvCUz3c+K10VQSfzUpN6RoindDB0j716jUZQ6IKzXBNNRiOjQ6N6s1MlmKwjyFyw0PY509hJY+dtjBEQBbFjK0pw7ZElfW4zDWteDzWRm7M1VjzUlRgPLsg7CJ980Rg8suZAMh3UH251vymCH0ykpMYqK1qiWDurz5GWdaDov6Z0YkQPQLnszzPa60kbO9VUHrYnG+6+KA6GoPW0EHFEqaUxXv+mRLr8Pm8BhjCiDghO7mlHZFN95hN5gkNyBdIPA9JmXAdnkrJBSQaDvZdejDwFJL+T+PgA2f9JomB8BQ/WkZ4uukyKUUFYToOhntQTe7dfE+I4VsD6BycbY7smaY/xGx6EvyXfntpYkgR7Fe2rYKaxBrcRcnhTmQBeLLz85M7fLKVjME72niQdRIZRaMZ+OmpCxKK2qU=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.35.0
Release Details
UpdatedJune 25, 2026, 12:36 a.m.
Changelog

Added

  • Pensions revamp. You can now record a contribution as a transfer from a bank account — the matching withdrawal is created automatically and kept out of your spending — and record withdrawals/drawdown back into an account (#304). Scheduled (recurring) contributions (monthly/quarterly/yearly) can post automatically or on demand (#251). DC pensions gained a configurable projection target with a progress indicator and a "today's money" (inflation-adjusted) view on the growth chart, plus an optional Pension Projection dashboard card. Bank legs that fund a pension show a Pension badge in the transaction list.

Fixed

  • Background-job "class does not exist" log spam that could appear after updating PHP/Nextcloud/the app: the app's autoloader is no longer "authoritative", so it falls back to PSR-4 and self-heals if PHP's cached class map is stale after an update (#305)
  • Newly-added dashboard widgets now load their data immediately instead of staying empty until the page is refreshed.
  • The pension detail panel's balance history and activity are no longer broken — those views called endpoints that didn't exist; they now show a proper balance chart and a merged timeline of contributions, withdrawals and balance updates, each removable (#251)
  • Editing a split transaction with three or more parts no longer zeroes or overwrites the other splits. The last split row is now a read-only "remaining" amount (transaction total minus the other parts), and the dialog blocks saving until the parts add up (#303)
  • Spending-anomaly notifications no longer crash with "The arguments array must contain 1 items, 0 given" — a stray % in the notification text made Nextcloud's translation layer fail, spamming the log every time notifications were rendered (#305)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureF/7pZ4sNzjJuqXXZoHmO+9OmUzkQz6ZDke3vkONfZ2uGfzBpwpDSIiGlfNv6gt40Ho8NTPNd0JuM+ESRohLlPAAftFoF+L4h+asH5s/lncoxgTZevEFl7NE14s+sPVdGdZqXGi0b3mohB+f1jOudpVbgB0bmCDvnZMEKiMSjB7XwH9iQqzu/8WyQNd28w+Bz2TbyAfu2PCtdD6jsmVCbvtCkmEdKOVJzRWuExH+vwvZ0ltX3mtorPl6HEzqKJWoDYG3tdbpSwml6w9F3qj8naVZ3tZYBrfvwABHoMD1LYpYwRss5C9UpJvu6UFfKQ4Xso1tBu5U+tYlAPKLbQ5J70o0C1aP66R+FvL8RlMHpY93duR32qZkT/6xV0NYQpd9xzXoLbB5YkZJuBLV8m3oP9k/pNEy8vwF5Kkb+/6zrJt4aSH/iiAqBoqvuT1itwScYsNpGHXWOrGHioCKiGkcMvamfr7her1fQ42wNiVIVWKaxNtjeYrVjmHCtWA2awjv3XRfcXdcL/4stuDpXxQ0Dnv2S/Ey9ZbGbqpc0DNyPZfKie5/QK5OnHPW9F8nHUsEhxDLbNezo11fKm1ykE0ja4nTZFKL3ml2D4aRDMYQe35MWJvW/fLcNW7dYOV969ZI52G8jTIUI/YphcNfCNK24fVkljrcBSybr8WavbELxVR0=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.34.0
Release Details
UpdatedJune 24, 2026, 12:34 p.m.
Changelog

Added

  • The transaction list filters now include a Reconciled filter (All / Reconciled / Not reconciled), so you can quickly see which transactions still need reconciling (#301)
  • A Budget alert threshold setting controls when a category appears on the Budget Alerts tile (default 80% of budget). Set it to 100% to be alerted only when a category actually goes over budget, rather than when it's merely approaching or fully used (#293)

Fixed

  • Creating a category (or account) no longer fails with "Unknown column 'excluded_from_reports'" on instances where an earlier upgrade was interrupted or restored from a mid-upgrade backup. A self-healing migration re-adds the affected columns automatically on update (#302)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
Signaturey+Qi2+U6CexZu8i+0DGrbLXwFbp+cHLVW62WRSfrovEAuJrnZy8paqAacEaE570GoHVd1b23Yihz4oDfOYStLASDVFk7xhVrarnlIqv4EH+Jyw0IR2iaLR+IvhJmSZc9N5nQ42i2z8UYetvQo0znzzNPmpT2FEJB1Sty9kCfHL7HiisG4hYwJp528McMVXgCYfn/XOZUQzOVY6rvis1hP8CiFbE4UMUQj/SgDpRjimcRCZy8fsRLgZHcfO2+BKYCSt5lqLDJSzsmewBFNMVWDdtZwPUxqyK8xaTwSnwWNBNXBRg5ZcDLJhhIJtk9cEezVTdJBZTw3wx7iCztR9RFQi9CZsRz9U9S4jLEdcV8m6OTa8XG22s2ZHt+I+hisGtlC1TOQ5fpPfSe9onWdA8jgC68RAFeOLJ+KmSkLQN1bbr9gUw47oB09Yd9sEtUDcFapfv+x9Zl3/s4ExwO6xDS/bwmRyZ/fq1z2jhVu/lMFd//+9ciOrCdty1p7440JVs/sx71Qcc0mRhZsMtIRYyBD2EFceUHx8cQCtOLL99+JtGkTakCMCwIxghuGoXnrq+9mRWjgROn1ysGEHDUyC8ZKCJ5f8TXOllqX2g+2fyOpFzHR66oP7lPwI5y3eW4VYJGT/lQzTavAtU148X2XaBUz+XA8Djuco3CCuGJuT9FhSU=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.33.1
Release Details
UpdatedJune 18, 2026, 3:03 p.m.
Changelog

Fixed

  • On some installs an earlier update was recorded as applied but didn't fully run (an interrupted upgrade, or a database restored from a backup taken mid-upgrade), leaving the excluded_from_forecast column missing — so every new transaction failed with "Unknown column 'excluded_from_forecast'". A migration now re-adds the column automatically on update. (Also surfaced by the new database-error detail field added in 2.32.0.) (#289)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignaturewGNDwrdOGHhLxiEiJQDsZrcL4BFQbGBTjeDU/3VJql8bIeDBHITKzJ3HH47kV1bFmsZ35q0o7xh/r4q6Kj9/SXM8gQCTxEtQ0q80MS85LGy5+9dUtJ0yBvrLfE6kwpNPDH+kqwBVcAGxmLr9vYau5uTFGdeB0WZ3gmesUvT5kuZfdREwJDQ19QWR40pJjHRcWqM5KnXCT1/wq7btWj9s/Vf9GVQvo85g9R7adODG1PVBr4gM6R9nTgsrn+60BJvNNO5f3W3wbuzvqaJhtVdknB9Z8fc7Vbq6mh6TgSPBmXgiK2VdCAWPaW2EmpVL8iwgOGazPGSajPkMZNNZDhzDNEpLcveJl61g/x5dVAxOevwFnN4CaX5c/YYppjcqtoWyYgoTNMv3enF3///tD0wS68iQzcU5UNmsOOKsAUVvRnf/oOX2b13NfsKPONAxcu4Q/UG8ybPqYwXT+T6Vs+IRmoLJLnOs/BUgbqmmRIG1Wfs2BusDFKNHHWoW1Z5t+GDLGx2cyNci7+rKPRh2seML8iPrt9lNv2M5NjzIJ9Wm0Xt0FKpIetR4gDpLSRvBtINaQ0jVuYVixt1yDKMUfE6GH4sNW9rNi2ZoKptz2MIxouBmLNXezA5Y0gvIlgA11Bi0YBrKPUAtmxNl8Jyxhle2Ll5bZbsupMy1otRB/+NGEOs=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.33.0
Release Details
UpdatedJune 18, 2026, 12:52 a.m.
Changelog

Added

  • Run reports on multiple accounts at once: the report Account filter is now a checklist — pick any set of accounts (e.g. all your credit cards, or all your checking accounts) or "All Accounts". Applies across the summary, spending, income, cash-flow, category-by-month and year-over-year reports and their CSV/PDF exports (#299)
  • Saved reports: save a report's settings (type, period, selected accounts, tags and options) under a name and re-run it later from the "Saved Reports" picker in the Reports view. The period is stored as the chosen preset (e.g. "Last 3 months") so a saved report always shows up-to-date data (#299)
  • Dashboard tiles that can be scoped to a specific account (Spending by Category, Income vs Expenses, Net Worth History, Recent Transactions, and the other account-aware widgets) now show a small label in their header naming the account they're analyzing — the account you picked in the tile's settings, or "All accounts" (#296)

Fixed

  • The Reports period selector didn't drive the report on reopen: the dropdown kept your last choice (e.g. "Last Year") but the report always reverted to "Last 3 Months", and clicking "Generate Report" used the reverted range instead of the shown period — you had to switch the dropdown away and back. The report now always matches the period shown in the selector (custom ranges are preserved) (#300)
  • The Quick Add Transaction dashboard widget couldn't be used on mobile — the lower fields and the "Add Transaction" button were clipped off the bottom of the tile, so a transaction could never be submitted. Its form is now condensed (each label sits beside its field with tighter spacing) so the whole form fits the tile, and it falls back to scrolling within the tile if it's resized very small (#298)
  • Editing a split transaction's amount (e.g. inline in the transaction list) left its splits at the old amounts, so they no longer summed to the transaction total. The splits are now rescaled proportionally to the new amount (the last split absorbs any rounding remainder)
  • In the edit-transaction dialog, changing one split amount now adjusts another split so the parts keep summing to the transaction total, instead of silently drifting out of balance
  • Split transactions weren't counted toward category budgets or spending. When a single transaction was split across categories (e.g. one $1,000 payment split into rent, parking and a deposit), each of those categories showed $0 spent. Split allocations now count toward category spending everywhere it's shown — the Budget view, the Spending by Category chart, and reports (#297)
  • Large amounts (e.g. values over 100,000) on the dashboard hero tiles (Net Worth, Income/Expenses This Month, Net Savings, Cash Flow) wrapped onto a second line, splitting the number mid-digits. The amount now stays on one line and its font scales down to fit narrow tiles instead of wrapping (#295)
  • The "Asset Value History" dashboard tile (and "Net Worth History") showed its empty-state message anchored near the bottom of the tile instead of vertically centered. When there's no data the message now fills and centers within the chart area (#294)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
Signaturejj+nUiPNSYYgtQ/7XYIkJNFo8vWIHaX28Q0XTtpN6RWmrW8qrJBIs2jTaaHwebC7SB5f7GP6vQxghh9+nCWfA+KlTKbm8YJg6yzah9xdTLo/JcUhTOinlH9yYoXxMiIY9EVwQLsPmef4sprTsS9oqBeSgZ7S8WRJYnxjAuljee9q0Sfai9AK+RQzBk6kgENhCAVt95ooZ3H5ukfFBSb/kyXa3IU+ngu6g5B9DgiJfBduecdkLEfc0dhYKelUyNaZa61qoG865podTGJFCFqzoSnlCXgRcJqJHjhdTERIeu/nHQAL/PhaPy0OSWK8l+kyrGveMEKDM6LvQ0Eo6B9Ul0ORobundabEat67f/hqaTmnDldOkkEm5a0WAYeQvYeeZCNLtiF26pWk66v6eQhXsrT6IwcJ/gxaC6oS8URm5yYub2iW9nVq6uZXRMJavJr8CmYl7MSqQRVvFKGlwHvD7X+YfEs+htKGYM017iWdICfQv/wbGi5JzIxqdm7QKrV9EGxgl4GFWvY/cyGZt4awfhoy4RljlFtsfJ02askgVFUloVGKOWeqZ5NbqXMDC+UonPONQ/RPM64u0L3NdVvmcXOwA8RBHCg1qgEiVkDBSsJyhK55+1J7Yn5fIC2emSU0BXOdzSFgg3BgUbYJQHgH30AwNf1iagO/WBOYDSu4jqs=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.32.0
Release Details
UpdatedJune 17, 2026, 3:02 p.m.
Changelog

Added

  • Category by Month report: a new report (Reports → Category by Month) showing income and expenses per category broken down by month, with a column per month and an overall total. Categories are listed alphabetically with sub-categories grouped under their parents, and parent rows include the totals of their sub-categories; a toggle switches to sorting by total instead. Defaults to year-to-date, follows the report date-range and account filters, and exports to CSV and PDF (#288)

Changed

  • API errors caused by the database now include the underlying driver message (e.g. a missing column) in a separate detail field of the error response, visible in the browser's network tab. The user-facing message is unchanged; this makes problems diagnosable on managed Nextcloud instances where admins can't read the server log. The executed SQL and any bound values are stripped from the detail (#289)

Fixed

  • The dashboard "Budget Alerts" tile showed a red "exceeded" alert (with "0% over") for a category whose spending exactly equalled its budget. Spending that fully uses the budget without going over is now treated as a "100% used" warning, not an over-budget alert; only spending that actually exceeds the budget shows as exceeded (#293)
  • PDF reports rendered non-Latin characters (Polish, Cyrillic, etc.) in account/category names as "?". The PDF exports used a built-in font limited to Western European characters; they now use an embedded Unicode font (DejaVu Sans), so names display correctly. Applies to the budget report, bills-calendar and year-over-year PDFs (#292)
  • Marking a recurring transfer as paid showed a success message but created no account entries. The Transfers screen was only updating the transfer's "last paid" date instead of calling the mark-paid action, so no transactions were recorded; it now creates the paired transfer transactions like the Bills screen does (#291)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureNKgPUY81JziKewMWFs4QeLNIwZ8JqGBZ6wvFlsItL4R47yoDLAn4+I1T/pwgEOi7KR2lCUFBckiAdI78FONIy+JyCFhY0w4WcGEltsQdsytRMQYAggOWw+OlYvlDMPI6zoMoRfVcIvC3d+4pUrP91cJIVwi+bu5OIYO0C7ErDFCyvMlHK+ifsGvBluQJ377z8wnBUQIWSfudOuXewIyBHCF1QXsRXsVe0CIGWPNnT3ibuwxjm92a4vzwqdTEYy2qQwzPgYWPhgZofSdEN6j08iuwUzM0i9yXWd0IVpRNLb8RIo9lTzhJsjolrNFGZd0iiQk5A/4NQ6VOLKItVhwXJKOZk7KzyYTZmEki+PaeHKSEjEzwYNqv2tL4VPrBjyq5Y3bRTnYS3uBBCOnkWwn6ozQ4PitvSgPpcqciCtrP1hYAa0oQ7FsP8+BVsepO8gn8+lIcVjx7mW+YvufESAyFRXgAy61QBNjcd34vtoEfLqhdP4f37gZ/jdmCicDQ3sLw/eUIL98BylXmNvOge43vnYuRgGl9gBO11ENaP3EhqhqsrVr5Gyu07MGlMhCRlBn21fRN5sMORHFNx6pL/DcpwC0xtpfWEtHTCcEcLvArqfSiQSMrJaDvqftcQNMWYt4hGZKMVR7SYZsAragHUiMfvWDu1mW7HLNsW8PwySZDrHA=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.31.0
Release Details
UpdatedJune 14, 2026, 7:05 p.m.
Changelog

Added

  • Exclude an account from totals: a per-account "Exclude from reports, dashboard & forecast" option (in the account's edit dialog) keeps the account fully tracked but leaves its transactions and balance out of every "all accounts" aggregation — reports, the dashboard, forecast, net worth, total balance and category budgets. The account still appears in your accounts list (with an "Excluded" badge) and on its own detail page, and selecting it explicitly in a report still works (#286)

Fixed

  • The account detail page's overview tiles only counted the transactions on the visible page (e.g. "50" for an account with 1,603). "Total Transactions", "This Month Income", "This Month Expenses" and "Avg. Transaction" are now aggregated server-side over the whole account, so they're correct regardless of paging (#285)
  • The dashboard spending chart's "Total Spending" figure (and each category's percentage) only summed the top 10 categories shown in the chart. It now reflects spending across all categories
  • The CSV import preview's "Auto-categorized" count was estimated from a 50-row sample and could be wrong for larger imports; it's now counted over the full file on the server
  • Editing an existing bill failed with "Failed to update bill" — saving the edit dialog (whether or not anything changed) returned a 400 error. The bill's start-date column, added with the limited-term bills feature, was missing from the list of updatable columns, so the always-sent start date was rejected before the save could run. Bills now save correctly, with a test guarding every persisted column (#284)
  • Opening an account's detail page returned a 500 error (the reconciliation-history request failed). The reconciliation controller was missing a trait it relied on, so it couldn't be constructed and every reconciliation endpoint failed; the account page surfaced it via the history sidebar. Now fixed and covered by tests (#283)
  • Starting an account reconciliation failed with a confusing "The string did not match the expected pattern" message (most visibly on Safari). The root cause was the reconciliation controller failing to construct (the #283 fix above resolves it); on top of that, the reconciliation screens now read error responses defensively, so any failure shows a clear message with the HTTP status instead of an opaque JSON-parsing error (#287)
  • The Budget Overview dashboard widget (and the digest, spending-anomaly and bill-reminder notifications) always showed amounts in US dollars regardless of your configured currency. The server-side amount formatter was reading the wrong settings key and falling back to USD; it now uses your default currency
  • The Budget Overview dashboard widget's "Total balance" now converts multi-currency accounts to your base currency instead of summing different currencies under one symbol (currencies without an exchange rate are excluded from the total and named)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureCseRrf2b0tfseaK8cBqqPjA8lhMT1C+aq6xVuP6vO3E6sRzawwkPNHdfK7CDaOro2TYW+agvm4g873WzOGVLIVa3FHEyFlnGRkFSwMz334bq1/Rcbw2WXdMbNUliZwdK76DNCauZ0JPz8FYIXr5cqkqbw80oHD/SWhWD5dTKRKJ2gpSvbNtXJfq32Sn04UVxrJq4StY11b5rJfCXR7P7RQxmFboIYJvhoVIfcebR+vighFLC9adkKVaF/xJ8tm1MVG6oJHJ4zKU87SV3+D8vB1xpxeWo2xRwseYSwg8Nk3ik6iXkcf4cHTACrCGyHhOXgCmltGkJ441alZ8kzOQCDe6Vw3Rx+zzgducfZGOQJPuIYcrpyZAAgN51xtDQJTWJNoT9jBrUmEv0r/ftZWj8QYnesnl8HgXUQPdLCsCaloLpISXkt7KzlHYlt4PgdMphbDBnuMROrXZtTeIwDCzwGAkatsK+l8HnM+FbMlpfszT7Ki1z2HYX/d+74aLRxkNUClx3fsQsxOtd0RxK9+/JPHW+W5Sv5kWbRSfiUrslL+pT7R15L9x4t3nFK8VUUEZSDcNynhSHxCVqrqOsV3mZ12eutyvQEPpN56qyLkaZmcoxOlOD2v4BKba8pBAL6YW05jx8hBWg9m0zAg4h3/qoA6zLDRrVfHi+LvUiiE1YDWs=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.30.2
Release Details
UpdatedJune 13, 2026, 6:03 p.m.
Changelog

Fixed

  • Dropdowns in the transaction list (the column-configuration gear menu and the in-cell category/tag/account editors) were cut off when the table had only a few rows, because the table area was shorter than the dropdowns. The transaction table now fills the available height, so every dropdown has room to open in full (#280)
  • The Tags column couldn't be shown/hidden — the Show/Hide Columns menu was missing a Tags entry, and the column wasn't wired into the visibility logic. Tags can now be toggled like the other columns (#281)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureRXpaKwi4ViRdeYM6mjC3JtrlDOFrm03LMBFc2gQMktdYfBEoyMrW3YBp+DPKezxnLOmETNnqjXAI+oswcQLQMkRbAcjuD1dpBBZi7x8kmvtc0lZUcrKRw2QKUzDD5luZaN7JE14o393XlPFxdqkaUbJvWTltA5xK/XO2H72GyvEO7/7de7HCcP2G4XTK5kGSeP3PHRNQ5MjiB49QlM7D95p7Od374Fbr0k52h0sWFHSA14LgJSyPXCgHxxJMqVy7O76LlS1Iedg8B4TFBbTJZVol/8emaHjBHvEwVVzSIIkr9wdtZ60aqrEhJfTqaRwdGS0ks53VE2ROoE829Jnc3Xkz4Xxc0WEqH5a4vxbUWnA8NbuaFNAsUcfXW+0TDTUeLT34IV8c6GZkwn0z4a1parjkif0yyEolfPhNomKX/JMl74aSG5i2BkKyDH3OXMg9oC0/czhOIxluUuFCwWJyd6cBOGd6r/R382SMMe+mCHDpuBxIY12gRo4bzcAfmYMQ3e6rrtgpFwxBllUaK8lC+yPy9x9502QHhZem922Tz7HokfuXuFxh1x9Z6doBSvoZOe2H2PIKRupmFf4I9epoRYdDQZjatpZpN3+oZnz6DmY7f9+g3gaZ7Dl9dkPydm96203Pox5SGz9vhOQaXeOIw+l+rLnXnbodzB3eyqz11Ig=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.28.3
Release Details
UpdatedJune 12, 2026, 1:14 a.m.
Changelog

Security

  • The recurring-income update endpoint no longer passes the raw request body through to the entity layer — a crafted payload could previously set internal fields such as the owning user (mass assignment, integrity only — no data disclosure). Update keys are now allowlisted like the other endpoints

Fixed

  • Auto-derived recurring budgets (#269) are now consistent across all surfaces: the dashboard "Budget Remaining" hero, Budget Progress/Breakdown widgets, Budget Health score, and budget alerts now apply the same recurring fallback as the Budget view — a category funded only by recurring bills can now trigger alerts and is counted in headline totals
  • Auto-derived budgets now respect bill start/end dates: a bill that hasn't started (or has ended) no longer counts toward today's budget, avoiding double-counting during a planned cost change (#268)
  • Recurring income summaries (Income view header, dashboard Income Tracking widget): semi-monthly income was counted at half its value, and a one-time income at full value every month until received
  • Transfers page monthly total: semi-monthly and semi-annual transfers were converted incorrectly
  • Live forecast cache: cache invalidation never matched the stored key (changes such as toggling "exclude from forecast" appeared to do nothing for up to 5 minutes), and the cache key ignored shared-account visibility, letting a share-restricted viewer briefly see the owner's totals
  • Editing a bill's amount without updating its split template is now rejected when the stored splits no longer match (the payment would have silently imported unsplit and uncategorized); setting a split template via the API now clears the bill-level category, matching creation
  • Multi-account import partial failures (e.g. a deleted destination account) are now reported in the UI instead of masquerading as a full success
  • Import preview now also flags repeated bank transaction IDs for accounts that will be created by the import
  • Long OFX FITID hashing threshold raised so every previously-imported FITID keeps its exact ID (re-import dedup continuity)
  • Auto-derived category budgets (#269) now handle every supported frequency correctly: semi-annual bills were over-counted 6×, semi-monthly halved, custom-schedule bills counted every month, and one-time bills inflated the budget monthly until marked paid (now excluded). Frequency math is delegated to the shared calculator, which also gained the missing semi-monthly conversion
  • Auto-derived budgets no longer apply to past months — they reflect today's recurring bills/income and were rewriting history (including overriding explicitly-zeroed snapshot budgets)
  • Multi-account import: an invalid destination account mid-import no longer aborts the batch, and deferred balance recomputes now always run for already-imported rows
  • Bank sync: the post-import balance recompute now keys on transaction creation, not the import counter, so a row persisted just before a non-fatal error still gets its balance update
  • The scheduled-transactions background job now recomputes balances from the ledger (it was the last remaining hand-computed balance delta, and could race concurrent imports)
  • Import preview now flags a repeated bank transaction ID (OFX FITID) within one file as the duplicate it is, matching what import actually does; per-account preview counts include rows that will import with skip-duplicates off
  • Marking a bill paid by linking an existing transaction now warns if the link silently failed (no money movement recorded)
  • Extremely long OFX FITIDs are hashed to stay within the import-ID column
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
Signaturefa7u8mWcwya82OCYZOh+XZFPRJH94oqiBM5WUtEtvU3Dh6Lq+pMs8A7e2aCOa0Y6AbwWH7TF6ZRtwanfSh2PjQMwAaDFlR5anBdAvr89L/fn3eK0uSrZetqNGmAT7Itlc0mT5KowbTvtWDRdK46oR4jjqgXKay6JeO7caGbAcKmyfhJARbfTXsb5etz/yhMX72X33ayUYtCo8nQrtxLTGO5AAPIcFbq1pa3W3d1SHuQ7Ibksv3WXrZe79ngT4pQpGp6xtz3ervqo86vrI8qH8DDg6g9IJE8D1iseOiVzRv/KI/N06LnY0OvUHNZwGrJph5Jh3BrYg2/5rSYzEP5VzaGyZm+AS0DO1bXf9BC5OqbRl3s/FsM+4UgowriYD0S2Zwc4/2j/W3mDRjOdGf0MJxd8SOxv7uW2P5JL0TImjA7mTgppSipw1ShGTl8BU7q11cCtFmuCmwGfvPlRLQtMqEdr93gNkY84rAja08K9Ro1/ySZtrEWVRh/lYzQqmpazsjlw1V4x+KYtn65LHr9Zxd46ToleV5kv1tEZJ1u7nFXeNnrfThyz78EqvLbVxzcqphrfrImGOD9/VhUwryM58KtVz7+tXmLjn3SsSmM8sz9DEljbEKK4zTV9mQgIxviGwzNuIGEFD+HaW6HRIsAzRNtXow5oT7Kgpqa3BnJ3HxM=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.28.2
Release Details
UpdatedJune 11, 2026, 6:33 p.m.
Changelog

Fixed

  • Dashboard could render half-empty (hero tiles only, widget grid invisible): a Chart.js resize on a hidden tile's detached canvas threw during initialization, and the widget grid was never revealed. Chart resizing now skips detached canvases and the grid is revealed before the resize pass. Likely also behind "nothing happens" reports after certain actions (#273)
  • Dashboard tiles with a saved account selection pointing at a deleted account (e.g. after factory reset + import re-numbered accounts) no longer error with 404s and stay empty — stale selections fall back to all accounts
  • Account balances are now derived from the ledger instead of running deltas — the root cause behind every historical balance-discrepancy report (#3, #89, #124, #163, #187, #194, #274). The stored balance was a running total that each transaction code path adjusted by hand; any missed or mis-signed delta corrupted it permanently. Every transaction create/update/delete (and retroactive rule run, repair action, import and bank sync) now recomputes balance = opening balance + net of non-scheduled transactions, making drift impossible and self-healing past inconsistencies on the next write. A one-time migration backfills the opening balance so displayed balances do not change on upgrade (#274)
  • Marking a bill as paid now warns loudly when no transaction was recorded (bill without an account, or transaction creation failed) — previously the bill was advanced silently and the account balance never reflected the payment, drifting from the real bank balance every cycle (#89, #274)
  • The app's own export→import now preserves transaction status (scheduled transactions no longer silently become balance-affecting after a migration) and restores the opening-balance invariant for imported accounts
  • "Skip Duplicate Transactions" off is now honored: previously rows whose import ID already existed were still rejected deeper in the stack (duplicate-ID guard + unique index), so parts of the batch silently failed to import. Intentional duplicates now get a uniquified import ID and the entire batch imports (#275)
  • Import duplicate detection no longer gives false positives for legitimately identical rows — e.g. two same-priced purchases on the same day with the same description. Identical rows within one file now import as distinct transactions (occurrence-aware import IDs), while re-importing the same statement still skips everything it already imported. Re-importing an older statement also recovers transactions the previous logic wrongly skipped (#276)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
Signaturekx2VkgWxozCE2LPp/nzgQQiqFxk/83sOdycv738Ly/uEwn/MhxF/kNtBlP4DMQbhmtkcHdt+kDIlQK1S5q1WHJWZQxjLc/ZCkj/ZEPkNBrDhHwdQCRh4TsRVJyfrIxXUTOCAKJLYk+0DXlnJB3kMhR81adns3wWNH9RkC4b62k3gXtzMR4n+jz/QJDGEAOXRpDUzxEm2TKqFot6sGRt3u0+rVo0bng6nogDJha0APeFI5Ujt+3mECw9MlxNt9nKbQlIGjAnraLVUFz0bXNLK7dbBS3PSzjLsUxhoNhAqMivfHEfLViOvIlCFNHzoWGxFnHK0flI2zJXUlOnaidOEyfhZWbqNpHZL4RZLIZWYQaztJgATNsK+L5aO0Md+Np1hgE8jkdY90gugiV06JqoPEWqCo/qSyaO9N3xYpeXrwfiL37JJqkigwg69RZN3OD1DfBT8ue7QlhT93dfg+39ERzbVY9QBu0gT+bwIs8tyE1MVXOaSjHKUkHab5dpGU3NQhvu/E1CO1BWA3dYvUUqvrvXKB96gm7IqNQEAkRi4JJHDPGtgzjERM+k8z/JA2xeJmPp7V3TZ/1WiKOoKMPz88soCJBMuj/LWnSpekLAGo4RJDy1JBlOm835e3ieJFVHwIwqG9YP7oRB/puFvYV6aaEXCnSkUcZV+z+2NXmHB8KM=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.28.1
Release Details
UpdatedJune 8, 2026, 12:13 p.m.
Changelog

Fixed

  • Install/upgrade aborted on Nextcloud 32 and earlier with "Primary index name on oc_budget_import_templates is too long". The budget_import_templates migration created its primary key without an explicit name, so Nextcloud derived a default name and hit the Oracle-compatibility identifier limit (the unprefixed table name is exactly 23 characters). The primary key now has an explicit short name. Thanks to @TheUnderdev for the report and fix (#272)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureXdUz/Pc10uA7L3R+vTa/cI52W9X8nDyH33zElCWeS/xWeYgonfr0GwLhn4ywE7rtUQF8e1Y8GhETbSd60otnPduP+4rXp7+5+b+iMTa3qfYi6gAd3Y1YJJrZqK0yx2Fdqld/nhQLfFpVkUSQl/JQ78RZanEh779Af5RejNl7lolRlJYg7ZNrLrFasWrpyrLNsg4+Tf74/vMpKWDXf0FEIqjnXZ0LKJm7Yjig4uazy+a5vDcDOrfq6fLU56d9ML/jBJK+9A2loT3I5HP7H2cngdLpwk6+MNLiYQDsdNzLGJJK9TK4hn0Cj+AV80mAQ45beagh4H0SmEoDTPvR/hC7LLlU5rtioE1Rg1tCvlZfHBuPcH9LZMq11Q3HVbZnvzkTdG3lKQlKeFhP86QOIjiAg1Frm0yuOt4nMSdG36N+k1C5szF7HrCoH+u1XgdY6fKI6WW71RkqXJ2IhwOorxcijLVQc2l3wyDLqoQrHtJA2yWGsI9NXlq+d5ZLJ03T7xvcLBPgSDTz91KqBABqJYRdCGhzAuQPe9M814mDu5XgdoCJNUKNrAl6YGvLvJXyj5j8I09qImqsQx09AmEBxi8YTZDbxuO8U/g3yKO14aBgGu3Z+v8+h6xyqJyNsPEbHHxpjfSbwAF/9FlvjA64nOTqPam3fPOjZAdqne5bgf05gFY=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.28.0
Release Details
UpdatedJune 7, 2026, 9:59 p.m.
Changelog

Added

  • Shared savings goals — share a savings goal with another Nextcloud user. Recipients see a "Shared" badge and can view progress; with write permission they can edit the goal and add money, while only the owner can delete it (#255)
  • Auto-derived budgets from recurring items — a (sub-)category with no manually-set budget now shows its committed recurring total (active recurring bills + recurring income, normalized to the budget period) as an automatic budget limit, marked "auto". Typing a value always overrides it (#269)
  • Exclude extraordinary/one-time items from the forecast — a per-transaction "exclude from forecast" flag (with a "No forecast" list badge), the same flag on recurring bills/income (propagated to generated transactions), and a matching import-rule action. Flagged amounts still affect your balance but are kept out of the projection averages (#270)
  • Reusable CSV import templates — save column mappings and import options and reapply them to future imports (#247)
  • OFX/QIF import account routing — route multi-account OFX/QIF files to the right Budget accounts, remembered across subsequent imports
  • Bank sync: pending transactions — option to import not-yet-posted (pending) transactions, automatically reconciled when they clear (#257)
  • Bill start dates — a bill only occurs on or after its start date, making it easy to change a recurring cost mid-year by ending one bill and starting another (#268)
  • "Shared with me" expenses view — recipients can now see expenses that have been shared with them (#248)
  • Dashboard period indicator — chart tiles now show a read-only indicator of the period they cover (#250)

Fixed

  • Dashboard now collapses to a single full-width column on phones, independent of your configured desktop column count (#249)
  • "Excluded from reports" categories no longer appear in the Budget view (#266, #267)
  • Category spending chart shows income as positive with the correct label (#265)
  • Tag-linked savings goals now sum net realized contributions (credits minus debits, excluding scheduled) (#264)
  • Recurring income description is now persisted on create (#263)
  • Transfers are now excluded from dashboard income/expense totals (#262)
  • Account Breakdown report now uses each account's own currency instead of a single assumed one (#256)
  • Fixed a PageController crash (TypeError) on unauthenticated requests (#259)
  • Quick Add date field normalization on iOS (#235)

Docs

  • Documented the standalone Quick Add page and the iOS home-screen workaround
  • Noted that GoCardless no longer accepts new bank-sync sign-ups; EU/UK self-hosters without an existing account are pointed to manual import (#271)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureiQMjVEdG/FWcc56MAPwvDd04E0ERl5pUWkrRWtdYdgbboBj0+7YAo+rDODFz5qC3EPqWBr7XRkjXOfvn9+m61v0w88Qy8SZQIZRHTAwRJuK5jDQbpfce5dropQgKW8btEIzI3BPE+DFBIDeV+qLNQEYT25ApMkUAz44PumVV0sJMibCGo0JBgIxHCPyem1NNjYaX3qQDt41eg8I5rH8wLCWGa7lNTtGyp8vaJ4ck0sh4J9sPuVzMdJoXQDHfGe5S8YY3GTwgvwyloNJQAFO+SQzm5WX6mC/IKAfpxwG82cQAEMm6B4geyHwaYGSFDEgrBuHOZj2fQmvQgzoarRN+U76bOhjQI0IqU76Pno3qM17eF+UKW8peDiqFBXpepGYfDoeyjQsF2GqxIK3C0bNUR5bp9RjNxkWckwvS2ihvP/2rg4lr05MuDDmIdBYG9Ny+PT9dEWBssQkXzIVX28Ox6P8xkorH0n5EoSRl3j+KMXbM34QteNMt1+jgsHAxcS8H57CwV3MC0uqZnhxUu/LbwIGHzvKbC6vN3F/3l6F+35rWM7UaQhdvr2W/1q5Swj5F2sp2Bq5jgrxbWIuUB9+pzftASgVUEmtd6blOUlJuuJj1wmaIrA9jx21+Bg8t/OmrQqB97ZHzint0WTdo7KTOviKZGnoZVXeoQthPmSyW7Wc=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath

Nextcloud 30

Budget 2.52.0
Release Details
UpdatedSept. 18, 2026, 11:44 a.m.
Changelog

Added

  • Import templates remember the character encoding. A statement in an encoding the importer cannot recognise on its own - an undeclared Cyrillic or Central European CSV reads as perfectly valid Western European text, just with the wrong letters - has to have its encoding picked by hand on the mapping screen, and that choice was lost on every import. A saved template now keeps it, and picking the template re-reads the file in that encoding straight away. Templates saved before this have no encoding stored and leave the picker as it is, so they cannot undo an encoding you have just chosen for the file in front of you. Contributed by @Saviq (#384)
  • Import rules can rewrite a transaction's description. A new Set Description action replaces the description a transaction arrived with - CARD PAYMENT TO TESCO STORES 2231 can become Groceries - either always or only when the description is empty. It runs on file imports, on bank sync and when rules are applied to existing transactions. Duplicate detection keeps using the description from the original file, so a statement imported again is still recognised after a rule has rewritten its descriptions. Contributed by @Saviq (#385)

  • The import review says which rows it cannot take, before you import. A file with an Account column can carry rows whose account cell is empty, and with Account for rows without one left on Skip rows without an account those rows are dropped. The review step never said so: a 75-row file whose last 29 rows had no account read as "Total 75, New 0, Duplicates 46", and the only mention of the missing 29 was a dialog after the import had already run. The reasons were there all along, the review step simply did not show them. A warning now sits above the statistics, in the same place as the direction warnings, saying how many of the file's rows will not be imported and why, with the row numbers behind each reason. Where the reason is an empty account cell it points at the fallback account select below it, which is what fixes it, and choosing an account there clears the warning and brings those rows back into the count. The row numbers also match between the review step and the dialog after the import now, the review step counted from 0 whilst the import counted from 1. Reported by @TerjeTM (#388)

  • The Budget Alerts tile can be told which categories it may alert about. Since 2.28.3 a category with no budget of its own falls back to the amount its bills and recurring income commit it to, so categories that were never budgeted against started appearing on the tile, and spending 190.00 against a 56.03 figure worked out from a bill reads as "239% over". The tile's settings, on the gear when the dashboard is unlocked, now offer Only categories with a budget I set, which leaves the derived budgets out and gives back what the tile showed before that fallback existed, and a list of every category with a budget in play that can be unticked one at a time. Rows whose budget came from a bill are marked, so it is clear which ones the checkbox covers. The filter is stored with your settings rather than with the tile, so budget alert notifications and the digest honour it as well, and the budget figures on the Budget page, the Nextcloud dashboard panel and the digest are untouched by it. With a filter on, a tile with nothing left to show stays up and says how many categories are muted rather than disappearing, which would take the gear with it. Reported by @TerjeTM (#389)

Changed

  • The mapping screen redraws as soon as you change the delimiter, the header toggle or the encoding. Changing the delimiter used to leave the columns and preview split the old way, with a note that the file would be re-parsed in the next step, and toggling Skip first row (headers) did not touch the preview at all - so neither could be checked before moving on. All three now re-read the uploaded file on the spot and redraw the column choices and the preview, keeping every column you had already picked that still exists. Picking a saved template does the same with the template's own delimiter and header setting, so its mapping lands on columns split the way it expects. Contributed by @Saviq (#383)
  • Translations. Ukrainian is now included, the Polish and Russian translations asked for in #382 are in, and German and French have been updated from Weblate.

Fixed

  • Expenses another user splits with you count towards your balance with them. When another Nextcloud user split an expense with you it showed under Shared with me as outstanding, however your contact for that person still read "Settled", opening it listed no expenses, and the totals at the top of Shared Expenses left it out. Each split is stored against the person who made it, and a contact card only ever read the splits you had made yourself. A contact linked to a Nextcloud user now also counts what that user has split with you, from your side, so their "owes you £40" is your "you owe £40", and where you have both split expenses with each other the card shows what is left once one is taken off the other. Their splits are listed in the contact's details marked split by with their name, and the payments they record show in the settlement history as payments from you. Only the person who split an expense can settle it, so Settle All and Record Payment still only reach your own splits, and are greyed out when none of yours are open. The contact has to be linked to their Nextcloud account, the same as for Shared with me. Reported by @Bow-Wow75 (#390)
  • A paid one-time bill keeps its due date. Marking a one-time bill paid cleared its next due date, and a bill created before 2.49.0 - when one-time bills gained a real Due Date - had nothing else to show, so a paid invoice read "No due date" in the list and opened with an empty Due Date beside the old Due Day and Due Month fields. The date a one-time bill was due is now kept when it is paid and the list shows it; bills paid before this release get their date back from the day and month they still hold, in the year nearest to the payment. The form no longer offers Due Day and Due Month for a one-time bill: the Due Date is its whole schedule, and it has to be filled in (#333)
  • The Bills Calendar no longer shows a bill as due for months it has moved past, or for months before it existed. Since 2.49.0 a month was struck through only when a payment was recorded against it, so a bill marked paid with Don't create any transaction - a yearly premium in February - stayed green in September as if still outstanding. Every bill was also projected back to January whatever day it was created, so a bill added on 8 September read as owed for the eight months before it, and those months inflated the monthly totals. A month the bill has moved past without a recorded payment is now struck through with a dashed line and its tooltip says no payment was recorded, and nothing is drawn before the bill's creation date unless a start date says the schedule began earlier - a bill with nothing left in the year drops out of the table rather than sitting there as a row of blanks. A payment linked from before then still shows as a paid month (#333)
  • Tab-separated CSV files can be imported. The Tab delimiter option sent the two characters \t instead of a tab, which the CSV reader refuses, so choosing it made the import fail - and a tab-separated file that was detected correctly showed a blank delimiter and was then read with commas. The option now sends a real tab, and a template saved from the old option is read as a tab too (#383)
  • The import review shows how many transactions the file holds. Total Transactions on the review step always read 0, whatever the file contained. The account page has a transaction counter with the same element id, and it sits earlier in the page, so every update meant for the import summary went to that hidden counter instead
  • Clicking quickly through months on the Budget page no longer shows another month's figures. Every month change starts its own loads of the spending and the budget amounts, and an earlier load that finished last replaced the newer figures, so June could show May's spending or May's budgets. Only the most recent load is shown now, and a budget load that fails leaves the base budgets rather than another month's. Contributed by @almeidandres (#387)
  • The dashboard follows your budget start day. With a Budget start day set, the income, expenses, savings and budget-remaining figures at the top of the dashboard still covered the calendar month, and Budget Progress set to the current budget period used the budgets of the month the period started in - a period from 28 August to 27 September was measured against August's budgets. The top figures now cover the current budget period and show its dates under their labels, and both use the budgets of the month the Budget page lists that period under, the month its 15th falls in. Envelope carryover, which the dashboard only added for whole calendar months, now counts for the budget period too. The six-month charts stay on calendar months. Contributed by @almeidandres (#386)
  • Every budget surface agrees on which month is running when you have a budget start day. A period is listed under the month its 15th falls in, so with a start day of the 10th, 5 September is still in August's period, and with the 28th, 29 September is already in October's. Budget alerts, and the Budget Health tile built on them, still used the budgets of the calendar month, the Budget page opened on the calendar month, and turning on envelope budgeting started the envelope in the calendar month too. All of them now use the period running today. The recurring-bill fallback and the "(projected)" carryover mark also treat that period as the current one, so a period that has already ended no longer borrows today's recurring figures. A category's details follow suit: This month, the trend and the monthly chart count spending per budget period instead of per calendar month, and the chart ends with the period running today. The same goes for the dashboard's Monthly Comparison tile, which now compares the running period with the one before, and for This Month Income and This Month Expenses on an account's page, and both show the dates they cover.
  • The Monthly Comparison and Weekly Spending tiles show the real figures. Both tiles looked for income and expenses at the top of the summary they load, however the summary keeps them under its totals, so they showed zeros whatever was in the accounts. They read the totals now.
  • An overdrawn envelope shows as over budget. When the overspend carried into a month is larger than that month's budget, nothing is left to spend, but the Budget page showed the row as "No budget set" with no remaining figure, and the dashboard's Budget Progress tile left it out. Both now show it as over budget, with what it owes as the remaining amount, as the alerts and reports already did.
  • The budget adjustment notice names the right month everywhere. "Budgets adjusted from ..." and its confirmation dialog read the month as midnight UTC, so anywhere west of UTC they named the month before the one being adjusted
  • The Budget page shows the right period for a start day of the 15th everywhere. The month picker's date was read as midnight UTC, which is still the 14th anywhere west of UTC, so in the Americas a budget start day of the 15th showed each month the period before the one it should
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureYjtb6oj/6u2vw+lMxUwTdqaoecbNZKr8zgforTdMu2KAUE/D7PJQiWgI+mlRDXOoDp++CZJkbkDwEIknVcN6Zl5rCfUtSvMwdVk4IvOKwG7AW2qqDhnHDplkWBwPMEFNNJdQxPnjsDTNYxTEtGnOXwl2gxc9NMIFSD3c/DeCbxzLZd61DaVpjQohgLF7EKuVeLohtjay574dEpwpXH9z50nYJ0bO65jUTxrnZmLoafqKyQRu7tqurEWjlkhUcZRBALUnDzc1KwA+7kP1K1SwVoJkiuJwqcZNju3hsz8US7leYtvEnQL0Qsp+TnCHKiGibv/G5kVVwgvGZ0ThI20UeIHQOMKDZXj+d+CKuskMLpBJTUZPJaQyTeyIfFQ858nZlHHKC1mSRno6XPO1pYQCvHBzf+TIZBtF9U7N9svhxDJ2eXRAXJbp+BrtfuVrBEFkXE/4kilamlMPdGi1nG0EkcnKB9tVaqryzKWgWb97hfuBftBulfa+kaGjJAH9ZMwf9GioTzOCSdLf32lC+XFlDFxf93nTrzfNPB3dU+v/F1ZiItBx3WvAcXbYdg2lYa8y/A8liLqYXj19o9GqDbhNFVhCVQNvfFn0nfq/otpkY6sMH+brtN4O1HQfNqOOn6Lp09HRh299sfO8kuCaQDIGfeyNb4qNNJALi6bewhAaORk=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.51.0
Release Details
UpdatedSept. 11, 2026, 1:17 p.m.
Changelog

Added

  • Accounts can be deleted in bulk. Tick the accounts you want gone and delete them in one go, from either the tile or the list view. This existed for transactions and categories but never for accounts, and the gap only really bites in the one situation that produces dozens of them at once - an import with the wrong column mapped to Account, which creates one account per distinct value in that column. Deleting those one at a time also ran into the delete endpoint's rate limit of ten calls a minute, and an account that still holds transactions costs two of them, so the clean-up stalled about five accounts in. The whole selection now goes in a single request. The destructive half is kept a separate decision: the first confirmation removes only the accounts that are already empty, and anything still holding transactions is kept back and asked about in a second dialog that names those accounts and totals their transactions, so nothing with history in it is deleted by a click meant for an empty account. Closed accounts can be selected too (#381)
  • The import preview warns when a column mapping is about to create a pile of accounts. Mapping the wrong column to Account creates one account per distinct value in it, and mapping the date column gives you one account per day. The preview did list what it was about to create, but as a comma-separated line among the statistics, which reads as a note rather than as a reason to go back. Above five new accounts it is now a proper warning, sitting above the stats where the direction warnings already sit, because it answers the same question - whether to import at all. When most of the new account names parse as dates it says so outright and points at the account column mapping, rather than leaving you to work out afterwards why you have forty accounts (#381)
  • Bulk edit can add and remove tags. Tagging a run of transactions meant opening each one in turn: the bulk editor only ever touched fields stored on the transaction row itself, and a tag is not one of them. Tags... in the bulk bar now adds and removes tags across the whole selection at once, a cross-page select all matching selection included. The two lists are deliberately separate rather than one set of checkboxes - a tag you leave unchecked is not touched either way, so adding one tag to a hundred transactions cannot quietly strip the tags those transactions already carry. Adding a tag a transaction already has does nothing, and neither does removing one it does not have, so the same change can be re-run over an overlapping selection without anything happening twice. Category tags are offered too, grouped under the category they belong to. A tag set belongs to one category, so across a selection spanning several it can only reach part of what you picked - rather than leave you to find that out afterwards, each group says how far it reaches (applies to 12 of 50), only the categories actually in your selection are offered at all, and the confirmation names any tag that fell short instead of claiming it did more. Anything the tags cannot cover is counted underneath, including split transactions, which have no category of their own once split. Removing is not restricted the same way: a transaction re-categorised after it was tagged keeps the old tag, and gating removal would leave that tag impossible to clear in bulk. Requested by @joeftiger (#379)

Fixed

  • Names with an ampersand or a quote come out right in confirmations and messages. A category called "Food & Dining" was named in its own delete confirmation as "Food &amp; Dining", and the same went for anything carrying a quote or an angle bracket - an account, a contact, a saved report. Translated text has its inserted values escaped for HTML by default, which is right for the many places that text is used as markup and wrong for the two that show it literally: the confirmations and the little messages that slide in at the top right. Both now undo that escaping, so a name reads the way it was typed. This was true of the old browser confirmations too; it is simply visible now that the dialogs are the app's own (#381)
  • Editing a reconciled transaction in the list no longer asks twice. Changing the amount, date or account of a reconciled transaction directly in the table warns you first, and that warning could appear a second time straight after you had answered it - once because opening it moved the cursor out of the cell you were editing, and once more when the table redrew behind it. Answering once is now enough (#381)
  • Confirmations stop working after a few of them in a row. Every confirmation in the app was a browser dialog, and browsers offer to switch those off: after a handful in quick succession, Chrome and Firefox add a Prevent this page from creating additional dialogs checkbox to the box, and once it is ticked every later confirmation is answered no instantly without anything being drawn. From that moment the app looked broken rather than cautious - Delete did nothing whatsoever, no dialog, no error, no message, and nothing short of reloading the page brought it back. Clearing up a handful of accounts left behind by a mis-mapped import was more than enough to trigger it, which is how this came to light: two accounts deleted fine, and every delete button after that appeared dead. Confirmations, prompts and alerts are now drawn by the app itself, so there is nothing left for a browser to suppress. They take the keyboard - Enter confirms, Escape cancels, Tab stays inside the dialog - and a confirmation for something that deletes data now says so with a red button rather than a neutral OK. Reported by @missunderstoodninja (#381)
  • Tag pickers can be reached with the keyboard. Every tag checkbox in the app was hidden outright rather than just visually, which takes it out of the tab order and out of what a screen reader can announce - the coloured badge was the only way to set a tag, and only with a mouse. The checkboxes are now hidden visually but still focusable, and a badge shows a focus ring when you tab onto it. Nothing looks different with a mouse (#379)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureomDWujOwOWa9L4Xhc5Xr+YxrNL/X4KJz7URuQ3oocoKImK3zBZp5nUdl464tQpzylxC8sTBVsN9SqEm6KKKsPGkY92c4QnEzKWsuAM1fVZDgAqU/8oCyq6pSlRTrxxmHFN+PmioiScBnhErLMyrvPWkjVSpve7kIb5v1QRqf4nqJFuxeSOJAX1JgOM1tVME5Loxrm6SFZOsXaEXpKgqGF9SSuWXPAd1qGAO+MkugHo6zEjelkCYAWzkq2/tCZHOtIExuhBUk/BuSCMd9AaYhLb2iRJVT4FYcf14uRWCdfHmbRkNuGZNV63hbwNXwvIdP0KB9ZJ3QLV82V7LFyWY+s0VfssxJnKzjm8afeKo6zxq5SeRZmTVZDAxX7+aogVVWIqB18uwCI0dYWbMZQgR6PRqig0lf8E1j6KOiMRimZeHw0mkKFDV6ytcZEHgS8PuCih1ol9XaF+tNz4QJkKu/49A23APwrCUanew/Fs0BOhH7ydCNAl7sM5xpXKx4/4hoLJrA9tzTRwQUn1dmjbRk0QjThANrvqu+m0Gz97XWEwyyj3zHQyWYNy0Ozg1W1P01U/iFGH96Nd2emV2OO63z/AAmHrGWyBVBK73VlNx1guwaf8//c6XYbrbSJdF/smvbQcMa1MikuJq4DMpItW8vmvC+YOvUycpSHDkl7Hf+TC4=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.50.1
Release Details
UpdatedSept. 10, 2026, 1:21 a.m.
Changelog

Fixed

  • Save stops working on the transaction form after the split editor has been used. Turning Split across categories on and back off - or switching the type to Transfer with it on - hid the split rows but left them sitting inside the form. A hidden field is still checked by the browser, and an empty one it cannot put on screen is one it will not report either: the form simply refused to submit, with no message, no request and no error in the console, for every transaction from then on until the page was reloaded. Firefox and Chrome at least log something; Safari says nothing at all. Putting the split editor away now empties it, and a split amount is no longer a field the browser polices - an incomplete split was already caught on save, and says what is wrong in a way you can actually see. Reported by @SGiersch (#380)
  • Adding a transaction from an account preselects that account. The Add Transaction button on an account's page was reading the account being viewed from the wrong object, so it always came through empty and the picker opened blank - on the one screen where there is no question which account you meant (#380)
  • Transfer matching finds the other half in a shared account. A transfer between an account you own and one your partner has shared with you could not be matched: the search for the opposite leg only ever looked at rows you own, and a transaction in a shared account belongs to that account's owner, so the match dialog reported nothing to match and the bulk scan skipped the pair entirely. Linking the two was already allowed - it was only finding them that was not. The match dialog, the bulk scan and bulk linking now search every account you can write to, shared ones included. Accounts shared with you read-only are left out, because linking writes to both legs and a candidate you cannot write to could never have been linked anyway. Reported by @lexiconzero (#378)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignaturebuZC6LMTRyNL1vila15DJJFe8dDZf/j3oCjxjP7KvrqebYszACpNqevFzP0b+HFTrgRwXMF7+ZnHeZDVV4l4KuZgfeI78fVJnNhQQeYNYqcIRiZZTKoqfm3zpU0OzCqWchvR7Mgslc6IIuBGjmM5EAx53O05t69k00ylo5G2YLfeMtyeg9hlqRERfuE5aMa7w5YhvBcskq9gIbtuGRU5ZfK++QikEJxZS9Quy9H7iDuuRBrPgumyJyURxaENIodcPhTuHjC/95LQWciAI6bj562mWuNglVdBEC+9+oNRN12vyMHerogSRRNpfqKwMb93Yzhlw3gkjkD9DsZvVuzuek98QAxEhTDZeEcZ5o4aAB2m+mRAmx77mj0OrfvLcyL7ekKUCr6G0/xJkU3XtEG3WDF20OupAcXsNbYBduRIoCvozx/pEGOkIipe4oQOlh6POT7MkXWfxBGJaG3N8SzmUqihyNgx8KuoxodhHsw09O8ncNlmkiBEGNn0+Hx/UXiijxE4ucigWPVSmUP6SU6F8dpjU2EU/jqbIdxPiyz3r/tt/vbVXDw41c7wd5nnkHyubljlBW6KL1uREbhrl7fdRCgjzJkPKA+fa4tdpa83af3llfzKcnyO6TXQ/nPL+xI0eLwRlXUIp4eW9xIeY0sZ3bOwjMdOemiR1Q9lGSloAZc=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.50.0
Release Details
UpdatedSept. 5, 2026, 11:16 p.m.
Changelog

Added

  • Budget alerts and forecast warnings actually notify you now. The two switches at the top of Settings → Notifications have been there since the first release and never did anything - nothing read them, and the app had no such notification to send, so the only place a budget alert ever appeared was a dashboard card you had to go and look at. Budget Alerts now sends a notification the first time a category reaches your alert threshold (80% by default) in a budget period, and a second one if that category goes on to exceed its budget. That is the most it will send per category per period, so the nightly check cannot turn into nightly noise; a category that drops back under its threshold is forgotten, so it can alert again if it climbs back. Forecast Warnings sends at most one notification a month when the six-month forecast projects your combined balance below zero, naming the month it happens and the figure it falls to. Both default to on and are switched off from those same two checkboxes

Fixed

  • The Bills Calendar never shows an occurrence as paid while the bill still says it is due. 2.49.0 placed each payment on the nearest due date, and a bill paid twice at the end of a month - or paid a few days before the next cycle - had the extra payment land on the following occurrence, so the calendar struck through September while the Bills page showed the same occurrence as upcoming. The bill already knows which occurrences are done: marking one paid moves its next due date on a cycle, so everything before that date is closed and everything from it on is still owed. Payments are now only ever placed on closed occurrences; a second payment in a month shows as that month's larger amount rather than as a month that was never paid. Reported within the hour by @TerjeTM (#375)
  • One-time bills with the same name share one calendar row. Now that paid one-time bills stay in the year's calendar, a garage that sent three invoices appeared three times, one cell each. They are folded into one row with a cell per invoice, each keeping its own amount, the way recurring bills already read (#375)
  • Exported reports come out in your language. The PDF and CSV a report exports to were written with English labels whatever language Nextcloud was set to - the exporter never asked the translator, so a German user got Total Income and Account Breakdown in an otherwise German app. Every label in the report, Year over Year and Bills Calendar exports now goes through the same translations the screen uses, month names included, and the monthly scheduled report is produced in its recipient's language rather than the server's. Labels that already exist on screen are translated straight away; the few headings that only ever appeared in the exports are new to translators and fill in as the translations arrive (#377)
  • A monthly digest can report unusual spending. Unusual-spending detection judges a month that is still in progress, so it stays quiet before the 10th - pro-rating the rent on the 2nd would flag it every time. The monthly digest is sent on the 1st, so its unusual-spending section was empty every single time it went out, and the weekly digest only filled it in on the weeks that happened to start after the 10th. The digest now asks about the period it is actually reporting on: a finished week or month, compared against the same six-month typical figure scaled to that period's length, with no early-month rule to apply because a finished period is not a partial one. That also settles a mismatch in what the digest was telling you - it reported this month's spending so far inside a summary of last week or month, and now reports the period it covers
  • The digest notification says how many categories are spending unusually. The count was being attached to the notification and then never shown, so a digest that had found something looked exactly like one that had not
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignaturekDEMKCHGsB6XHpH0lnwbdVN2PlHEz5a/0JU2HlikRqJOIHvusKOCEPzyqSYRH/8U5+wPMQcWAi6Zlb8pcjgNh3CwemL7dVDMnrV7w65ZbG5xhBtzlziNuhs1FCJzqYQshdgCJzd2xQFJYJOqTqFXqdFQK6US+0Tgm47K6ROYrFUL/9JEhdaoH3kUz8PAP2WOq+IYdRfeUBlXUslF6pbtDWQ9g6gVSTUDF1Kj0V6UU+/M+GqrHY4flUN5Q9k6lGRLri8eBRO2woA5jdLWxJ5tyonb6F9e65yjlOIYbC3QV+TaHwH5MLbj9lmkrbAjFUMaaSWQ0VuEaj8vupo46ebxm2V4dGN4oisWd0VKRmlpGpGdDLIDYT1aZwIrVIRWPIicpqiFkLdOOo+YOCIl3XHNu6lPLxdR/jNcEDORoRJq6yPVtWZTroXgXM3TznOcNLXKotj7v/o1MPxId8uMms/wiu8PRksNIlFeLnmV8czhjhI+ZLElYqwCyMJjCUZUUB3ebdvRtbDqvuJBwuYp36Oi5UKfBTXqYzbAAO8qr4nAH/gdQsA8X+YquAMuux31ilINMpOvFX71Yf7/E15pqYZfvEQS0hq1hV4xIcgVAreEOHbIIFGcVB5WdrvYNeNP366rB5WsKXUBDGFrTEIL5vtj8OHgLqVYoEgBZNg/RL9j/Fc=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.49.0
Release Details
UpdatedSept. 3, 2026, 11:53 p.m.
Changelog

Added

  • A one-time bill can be dated in the past. A bill only ever stored a day and a month, and every date it worked out from them was rolled forward past today - right for a schedule, useless for an invoice from last month, which became due next year the moment you saved it, and jumped again if you tried to edit it back. For one-time bills the schedule fields now give way to a single Due Date, taken literally: an August invoice entered in September is due in August, shows as overdue until you mark it paid, and lands in August on the Bills Calendar. The placeholder transaction a new bill pre-creates is always a scheduled one, whatever its date: with a past date it was being written as a cleared payment, booking the money as spent for a bill nobody had paid (#375)

Fixed

  • The import's fallback account is reachable when the file has its own account column. A blank account cell now falls back to the account you choose - but the select that chooses it was hidden the moment an Account column was mapped, so the fallback could never be set from the wizard and those rows still failed with "no account was chosen". On the preview step the select now stays, relabelled Account for rows without one, and is optional: leave it empty and such rows are skipped with that reason listed (#333)
  • On SQLite, a failed save now gets the unfinished-update hint too. The hint recognised MySQL's and PostgreSQL's error codes and SQLite's "no such column", but SQLite words a failed INSERT as table X has no column named Y - which is exactly the failed save the hint exists for - and that slipped through, leaving the bare SQL. Found by running the check in a browser against a dropped column (#333)
  • The Bills Calendar shows what was actually paid. Paid months were guessed in the browser from the bill's last payment date - every month up to it counted as paid - so a bill you started paying in September showed January to August paid too, and a one-time bill fell out of the calendar the moment paying it deactivated it. The cells now come from the payments recorded against each bill: a month with a payment is paid and shows the amount that actually went out, months still to come show the expected amount, and the monthly totals follow suit. A payment made a few days late counts for the month it was due, a payment with no scheduled month near it appears as an extra paid month rather than vanishing, and a bill that is inactive now but was paid this year stays in the year's picture (#375)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureUTnFglOyY//mXGi7y/LDtH4919NkTXqAr1p4PsIxsYx5fusaiKeFTWxlcugWVBcXNirEhMLHMF/hTpCv05X/jQ0yMlB2LW8Q4bUwppTjyg44BEEACZuQWr1FTs7KhmlbU/nCDKTIuC+Uk458xB8kdIiggZoDRqb4JoINSJ2tXL5KeNQgeyyq8hqOm5pwUBxlJRgx61f8EPP4+JWoAY3DWZUGJvpmk8i0VrNtxOvHT2BTdfMxLauNboowdmko+GQv3ZLEoAwP0D1UI4pjcwxcOQdAkQuM4wXwN6tywUjdmzPTmYSTxEMO1XAnc1v22KUA7bQxkHYcg5viQMbtAA459AsY2ImPJdxGyt0PbszsxOgomnZ6BHQdohkI3zbgX2XRtRc0RycVyzkDtnuk1Nr4k8nEyhimtNea3nOZ5S3yQhrC7CPqpeoXqc/gzl5b2QrO1bC07TxUIMs9knOBR/SMWsXcSq2pzYY9FCW9+XsUVQ2XKi8CQmYiAi+rO8/RNLCkyz8OHkQuMtpdmv1YI7INkGwTr0wU0TVw1bC9ozc2GWsDeJGSYJBDn43uQQ+dyCr8xMhzkURYqjcvMYsgPUjTMY2AB0mFYow2XlRK67AE9hXrLSK25TIVHBH1JMkDx65jmH5jGQwmG8vbHjIoEygsJBRvy0hmb8uK7Pq1u5OyqnI=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.48.0
Release Details
UpdatedSept. 3, 2026, 9:09 p.m.
Changelog

Added

  • Tags can be hidden once they have served their purpose. A tag for a trip you have taken or a project that has finished keeps its history, but has no business in the picker for every new transaction — and deleting it would strip it from everything it is on. Editing a tag, on the Tags page for a global tag or in the category view for a tag-set tag, now offers a Hidden checkbox. A hidden tag is no longer offered when tagging a new transaction, bill, transfer or rule action, or when linking a savings goal, and it shows dimmed with a Hidden label where tags are managed so it can be found and unhidden. Everything that already carries the tag keeps it: the transactions stay tagged, the transaction filter and reports still list it, and a hidden tag already on the item being edited stays in its form, checked, so editing something else does not strip it (#373)
  • An account can be closed. An old bank account you no longer hold can be marked closed from the Advanced section of its edit dialog. It keeps every transaction and still counts in reports, the dashboard and net worth, but it no longer appears in any picker for new activity — the transaction and quick-add forms, transfers, bills, recurring income, imports, import rules, bank-sync mappings, savings goals and pension contributions. Pickers that filter history keep listing it, so its past stays reachable, and opening an old transaction that sits in a closed account keeps that account selected, labelled (closed). The accounts page lists closed accounts in a collapsed section of their own, and the account's page shows a Closed badge and drops the reconcile and card-payment actions. Closing is refused, with the reason shown in the form, while the balance is not zero, while any transaction is dated after today, or while an active bill, transfer, recurring income, pension contribution, bank-sync mapping or import rule still pays into or out of the account — the message names each one so it can be reassigned first. The standalone quick-add page and the import's account auto-matching skip closed accounts too, the interest accrual job leaves them alone, and the public API's GET /accounts gains an additive closed field so a capture client can filter on it (#372)

Fixed

  • Restoring a backup keeps the "exclude from reports" flag. The restore rebuilt each account field by field and never copied the flag, so every restore since the option was added put excluded accounts straight back into every total, silently. The new closed flag is restored the same way (#372)
  • The account form shows the real reason when an edit is refused. A refused account update always came back as "Failed to update account", hiding the specific message — including the reload notice a stale page gets when saving a debt. Refusals that carry a reason now reach the form verbatim (#372)
  • The unfinished-update warning now checks the database itself, and names the exact fix. It used to compare the migration files on disk with the list Nextcloud had recorded as run, and that misses both ways an install can actually be broken: a migration recorded as applied whose column is nevertheless not there, and a migration file that never reached the server. The instance that prompted this had run the recommended occ app:disable && occ app:enable to the letter and still could not save a bill, because that only re-runs what is unrecorded. The check now reads the live schema and compares it with every column the app writes, lists what is missing by table and column, and - for a change that is recorded but absent - names the precise occ migrations:execute budget <version> to re-run it, with the debug toggle those commands need. A column no migration on the server adds is called out as an incomplete install instead. The warning appears on the app's pages, in the admin overview, and in the error a failed save shows, where it now bypasses the "already verified" shortcut because a save just failed. Not being able to read the schema warns about nothing, as before (#333)
  • Repair Data no longer deletes both halves of a duplicate pair, and no longer orphans what hangs off a transaction. Its duplicate cleanup removed rows straight from the database, so any splits, tags, attachments and shared-expense records on a deleted transaction were left behind with nothing to join back to - invisible, and beyond the reach of every cleanup the app has, factory reset included. It also had three detectors flagging the same rows, each free to pick a different keeper: two placeholders written by the same payment share a creation time, so which one counted as "the real payment" came down to sort order, and a pair flagged both ways had both halves deleted - the payment removed along with its duplicate. Deletions now go through the same cascade every other part of the app uses, and a row another finding is keeping is never deleted; anything left ambiguous is simply left for a second run
  • Reconciling an account no longer means ticking your way through the whole ledger. A first reconciliation has nothing earlier to anchor on, so it starts from the account's opening balance - which means every transaction since has to be ticked before the difference reaches zero. On a real account that was 860 rows at 25 to a page, against an unfiltered list that still included scheduled rows dated years ahead. Starting a session now narrows the list to the account, to transactions dated on or before the statement date, and to rows not already reconciled - those are inside the starting balance already, so ticking one would have counted it twice - and the bar offers Tick all N transactions up to \<date> to do the whole statement in one click, leaving you to untick what your bank has not taken yet. Nothing is written to the transactions until Finish, so it is a starting point to correct from. The Create adjustment button no longer appears until something has been ticked, since before that the "difference" is simply the account's entire history, and the starting balance now explains in its tooltip where its number came from. Leaving a session hands the list back unfiltered (#374)
  • Marking a bill paid without recording a transaction no longer leaves it looking due. Choosing Don't create any transaction or linking one that already existed left the pre-created row for the occurrence you had just paid sitting in the ledger, still scheduled - so the bill went on showing as upcoming - and at the same time suppressed the row for the next occurrence, so the forecast lost it. One flag was answering two different questions. Recording the payment is now about this payment alone, and whether the next occurrence is pre-created is the bill's own Create future transaction setting, which is how skipping an occurrence and editing a bill have always read it. Existing leftovers clear themselves the next time that bill is marked paid. The dialog also now says that the bill moves on to its next due date whichever option you pick (#376)
  • Rows with an empty account column are imported instead of thrown away. A file that carries its own account column had every row with that cell left blank dropped, even though the import screen had already been told which account the file belongs to - one reporter lost 14 of 27 rows that way, in silence, and only noticed because the balance was wrong. A blank cell now falls back to the account chosen for the import. A cell that names an account which cannot be resolved is still reported rather than guessed at, since that one would misfile the row (#333)
  • The importer no longer invents an account out of a file's header row. With "first row is a header" switched off, the header line is read as data - and because it holds the column titles, its account cell held the word "Account:", which the importer duly created as a real account in dollars. Only a row that would import as a transaction can name an account now, so a header line is ignored the same way the import itself ignores it. New accounts the importer creates also take your default currency rather than always US dollars (#333)
  • The import tells you why rows failed instead of pointing at the server log. A partly failed import said "%n rows could not be imported - check the server log for details" and put the actual reasons in the browser console, where nobody looks - and on an instance whose logging is misconfigured, or where the admin cannot read the log at all, there was nowhere left to find out. The reasons now open in a window as soon as the import finishes, one line per reason with the rows it applies to, so fourteen rows failing the same way read as one problem rather than fourteen (#333)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignaturewDpgdodKiAH0BJNKoHpu1H3xardvLeUHU4/1s4cGzs/N9ZfELYEXGP9FnFBY0fSJWBscyElRGGL3vR58ISgUep5I5P9aX+JA/uHMtjeyafCVQGj/YNbhZtz/hKtNb2zM+erfMrzq6pLkleaPsCFoe5tEt3ufMZKASjvCpU1R3j4Ec6bDjiom1fk90CImC26ZItTfc5Vu/dxGtACVerJ0IvZzQPvR1J2FY1xDlqCeeuapHMmB/z3V5Px9JQU0BC+nM5qF335DutR30cz0BP7ghkp7juBWtj5fBMe2bRYmqu+AOVdcbniqHtHvktQmMjv77gQzTupn8tfNtOSf4qLK5YbiqOfMXnIIai5qmrgJE1tsO17hPQmpxol9owkPC2gRa7TwHsS09K3cMrEjpKNORD5hkFlc2m9eQR2xRAu68dWQwXkhbnmu42PcpwqQsKdLhDbwBWRJHyFqsMSds4mjYhUN5+wvQbWSsQTXoO8Z9InCntaQsDxR1rTX6CWxAy0gHx+ZD0hGv0ttqWbJzEiOPrlYwLbDvserRhlotDAahPDxsdV3PEwj28+Jtv04Ie0vE/k9n56NsAFY3e8PGjJE156W6+qurFoiXi2OcJynyAmsOsoj8DTLKnMsVMVtlw16lNZZ6uAANdDUrG1QOE8F065BkQxwg69PR3qHL3jfsgY=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.47.0
Release Details
UpdatedAug. 29, 2026, 9:47 p.m.
Changelog

Added

  • The import screen can be told which character encoding a statement uses. Some files simply cannot be identified from their contents: every single-byte encoding accepts every possible byte, so an undeclared Cyrillic export is indistinguishable from a Western European one and any automatic answer is a guess. The mapping step now carries a Character Encoding picker, listing Western European, Central European, Cyrillic, Greek, Turkish, Hebrew, Japanese, Chinese and Korean options alongside Unicode, with the detected encoding named in the hint beneath it. It sits directly above the preview, so a wrong guess is visible as mojibake and correcting it redraws the columns and preview immediately. Uploads are now kept exactly as they arrived rather than converted on the way in, which is what makes the choice reversible — previously the original bytes were discarded at upload and a bad guess could not be undone (#371)

Fixed

  • A statement that isn't UTF-8 is no longer read as Latin-1 regardless. Files that aren't UTF-8 were run through a list of fallback encodings, but the first entry accepts every possible byte, so it always matched and the rest were never reached — every such upload was decoded as Latin-1 whatever it actually was, turning a Cyrillic statement into Ïÿò¸ðî÷êà and a Japanese one into ûÀ;út;àz, with no error to say anything had gone wrong. A file that declares its own encoding is now believed: OFX states it in its header and camt XML in its declaration. Anything undeclared falls back to Windows-1252 rather than ISO-8859-1 — the two agree except over the range holding the curly quotes, dashes and euro signs statements are full of. Converted XML also has its declaration corrected to match its new contents, which previously made the parser decode the file a second time and produce exactly the corruption the conversion was there to prevent. Note that an undeclared file in a non-Western encoding still can't be identified from its bytes alone — single-byte encodings are indistinguishable, and testing for the multi-byte ones proved worse than not trying, since ordinary German, Spanish and French text validates cleanly as GB18030. That case needs an encoding picker on the import screen (#371)
  • Statements written in your own language import again. A CSV, OFX or QIF holding a decent amount of non-ASCII text was refused outright as "File appears to be binary" — which took in Cyrillic, Greek, Hebrew, Arabic and CJK statements wholesale, and caught plain accented Latin too, so a French or Spanish export could trip it as easily as a Russian one. The binary check allowed the first byte of a multi-byte UTF-8 character but not the bytes that follow it, and every non-ASCII character has at least one, so roughly half the bytes of a Cyrillic file were counted as unprintable against a 10% limit. High bytes are simply what non-English text looks like, in UTF-8 and in the older 8-bit encodings banks still export, so they no longer count against a file at all; genuine binaries are caught by their null bytes and control characters, which text does not contain. Reported with a diagnosis and a fix by @ba1amut (#369)
  • "Auto-pay when due" can be switched on while editing a bill. The checkbox needs a pay-from account, and the only thing that worked that out hung off the account dropdown's own change event — but opening a bill fills that dropdown from code, which fires no such event. So every existing bill opened with auto-pay greyed out, however long it had had an account, and the only way to reach the checkbox was to re-pick the account by hand. Creating a bill was unaffected, which is why it went unnoticed. The state is now recomputed whenever the form opens (#370)
  • Editing a bill shared with you no longer strips its category and pay-from account. Sharing is granted per type, so a bill can be shared while the account it pays from is not — and both dropdowns can only list what you are allowed to see. The form silently fell back to "No specific account", and saving submitted that as no account, wiping the setting off the owner's bill; the same went for an unshared category. The real values now stay selected, shown as Unavailable (not shared with you) so it is clear why they cannot be changed, and they survive the save untouched. Auto-pay is also refused server-side when a bill would be left switched on with nothing to pay from — a pairing the create path has always rejected (#370)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignaturexHUL+LrtKQmEHZ8YQwsy+xFaIqzNZrPxOFdHD44Th6v2oSFX5rCCI2kmScHUejaVOt1t0nLiJ2qf5ZSRVvOmPPeeinPhoqGhwYlP0Nkgt8Rb0x1zPZTJj63Na8ESocx7CpajZTDxKc8pAFrQJ+H03K4UDks+/1F0qFF2NYa1soV6+c+fIuMPDaYC+DjO3aeWaJabhTUgUymMmqHLxqlhAyw+a8LJ2ABwYyT8P/rmIQ267T72D8ng0f8/ubS4mvfICaoAbtMA8H5Rnn7/gcPMDv1nJyTv97ShefnigmiykqBSWJsJQE8Ax/RYNfXWJ3Gl9uRxzXigxKYwpGtWMFnE9G2JN/eOh5oG042V5wn1QI0QcfWG2QFilp5uOD6ZVTfyPG+um2Y0FQLFe4PJnxyYpnrXmWglFFMyEVCVa0a7+AJmb7DVfjz/9vhBewTYCJ/j9XDlw8Efu28ZYWtsgZ5vZIlH4a90WalHLWHprUsNLDrUSyl+WRLTWDYDfEviRHJBCrrcz34Zyo8An0+sM9ccQalvH78w4X9PDIL5pMS90MHgyYrXVGyMPqSG65FliBn0qku7pP8wCqUabT9Ac3ofyztTlj0dy+tHyuu0OLPb+FxaLUoCgw5PaOSNSOXgDw8amDnleLNrZjvHIEsoYCS2jXtxU0rrTbmFXi4djM4jyTQ=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.46.0
Release Details
UpdatedAug. 29, 2026, 2:08 a.m.
Changelog

Added

  • A Money Flow diagram shows where the money went. Reports gains a Money Flow type that draws the period's cash as a flow diagram: income categories stream into a central Cash Flow node, which fans out into your expense categories and their subcategories, with what's left shown as a Surplus band — or a Deficit feeding in when spending exceeded income. Amounts label every node, category colors carry through, and the usual period and shared-account filters apply (#366)

Fixed

  • Bills and income shared with you can be opened again. Opening a bill your partner created failed with "Failed to load bill", and so did every action on it: editing, deleting, marking it paid or unpaid, skipping a payment, and the Record transaction repair. Sharing grants visibility, not identity, but each of those looked the bill up as the person clicking rather than as its owner, so the app approved the action and then could not find the bill to carry it out (a DoesNotExistException in the log). Bill actions now run against the bill's owner, so a shared bill behaves like one of your own, and Mark Unpaid is offered on shared bills for the first time. Shared recurring income had the identical fault and is fixed with it, and its Mark received action — which had no permission check at all, only the scoping that made it fail — now refuses a read-only share properly (#368)
  • A transfer between accounts shared with you now completes. Creating a transfer in an account owned by someone else booked both sides and then failed to join them, leaving two unconnected transactions behind every attempt and putting the raw database query on screen as the error message. Both rows belong to the account's owner, while the linking step went looking for them as the person clicking. Linking, unlinking and Create and link now work across shared accounts, and a transaction you cannot reach reports itself as not found — which also means it reaches the log, where this failure left no trace at all (#368)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
Signaturex0J8AUUfQbAJljP4bb8goctxFgu6woboHqgqhSLiZLzSNh4/bgeYYYsy4ubudGRmEAdnJZqL9XcqPKKaaVIxVXVRFVCS24iGpCdqXhCW0MMvoROv7VMao+dHMrfPhungZxdm+nKurDuI2drTpZLmbckIj6+PnjLP0Z6M+a/P7wRw/3gtdHcf1KoNmRGNIlqUUolPhYJJFQbhgsf8yg/nzDMjm0OKXYvOKWSI+GR1HFQoNSLVx9TPk2zrBOT/ARpvDEStnWWBZxhn2shkEVFNE1ntupx4AmkerIySit3CB5j4H7imaHsIYwPHDhL+MEj9afFllpMnogByvQ+nHCvJ3v7PeuNYGgQTxMvoVKpvtPDyo2610eVQDQlK8UEzmOdimk7shlkllXiE/ZEIaeFINp17VuQbYlTwuuZlNfTendUZirhPFK4xR3AL6cpTxJHq/Xc/npPYAYk8wPyYseNnFL5A3/d2UXiT/m57GQiIMkTMrayR6kYmYjGYT2EAVSRjhA0wESnCJb6jVMc6YTcBVQ3uFXnA5gR1hdulx1Qj2lRhJpBSCcXBCl/4QHDv4OIhk4Is5DWUxcw91iuaBhMCpoJLwU+kkuaibIrsiV2L3np7EeZzPtxOsRG4GyCZRyvTvCVO7HVHu///wPi1sfMH4R05Ri0AUfbqdpqPrE70mG0=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.45.0
Release Details
UpdatedAug. 29, 2026, 12:59 a.m.
Changelog

Added

  • Bi-weekly schedules can be anchored to a date. Bi-weekly income, bills and transfers used to lock onto whichever week you happened to create them in — pick "every other Friday" and the app silently decided which Friday from the creation date, with no way to say "no, the other week" (#363). Transfers were worse off still: the form only offered a day-of-month field, which means nothing to a bi-weekly schedule (#364). Income now takes a First payment date for weekly and bi-weekly frequencies, and the transfer form gains the same start-date field bills have had — the date pins both the weekday and the week, and every occurrence lands a clean 14 (or 7) days from it, whether the date you give is in the past or the future. While a start date is set the weekday field follows it and locks, so the form cannot claim a different day than the schedule runs on. Note for existing bills and transfers: a start date you set before this release only delayed the first occurrence; from now on it anchors the schedule, so a weekly or bi-weekly bill with a start date will settle onto that date's weekday and week
  • Bills can be marked unpaid. Marking a bill paid by mistake was final: the Undo button lived in a ten-second toast, and once it was gone nothing could revert the paid state — deleting the payment transaction left the bill still claiming to be paid (#365). Every payment now stores what it changed, so a Mark Unpaid action on the bill reverts the most recent one properly: the due date rolls back, a one-time bill comes back to life instead of staying vanished, a statement-amount bill gets its exact amount back (which cannot be recomputed after the fact), and the payment transactions are cleaned up — including when you already deleted one of them yourself. Auto-paid and import-matched bills get the same revert, which the toast never offered them — a payment that was linked to an imported transaction unlinks it rather than deleting money that genuinely left your bank. Recurring transfers can be reverted too, from the Transfers view. The stored revert applies to the most recent payment only, and editing the bill's amount or schedule discards it — reverting would otherwise restore values from before your edit

  • CSV files without a header row can be imported. The importer always treated the first row as a header and silently ate it — a headerless export lost its first transaction with no way to say otherwise. A First row is a header toggle (on by default, matching the old behaviour) now controls it, columns are matched by position, and blank or duplicate header cells get translated "Column N" placeholders in the mapping dropdowns instead of untranslated internal names. Saved templates keep working: they store your file's real header names where they exist, so they survive language changes and column reordering. Templates saved from files with duplicate blank headers ("Column N (2)") need their columns re-picked once. Contributed by @Saviq (#367)

  • The database-updates warning reaches the admin overview. The check that detects the app's own migrations never having run (the "Unknown column" trap, #333) now registers as a proper Nextcloud setup check, so it appears under Settings > Administration > Overview and in occ setupchecks — visible to the admin who can actually run the fix, not just to whoever next opens the app

Fixed

  • A category drill-down into subcategories now says so. Opening a parent category's transactions (from Category Details or a chart slice) applies the parent plus its subcategories, but the filter panel could only display the parent — and picking the parent to narrow down to just it did nothing. The category dropdown now shows a combined entry like "Groceries + 2 subcategories" for the applied scope, and choosing the plain parent genuinely narrows to it (#361)
  • The bills list stops fetching every dead bill. Keeping paid one-time bills reachable for Mark Unpaid meant fetching the whole bill history and discarding most of it in the browser. The server now returns active bills plus the revertible ones directly, so the payload stays small however old the install (#365)
  • A category's count badge and its panel agree on damaged rows. A row carrying both its own category and split parts (the old bulk-edit damage) was excluded from the tree's count badge but still listed in the Category Details panel — off by one on the same screen. The panel now applies the same rule; Repair Data remains the way to fix the rows themselves (#360)
  • The split flag's grey states are resolved once and for all. Two damaged states have haunted long-lived databases: rows from before the flag existed (held NULL), and rows whose restore claimed they were split while the parts never made it into the old backups (#351). A one-time update resolves every such row from the parts table — the single source of truth — and restores now do the same, so the states cannot return. This fixes three real casualties: rule runs categorize legacy transactions again (they had started skipping every pre-2026 row while reporting success), assigning a category to a damaged row now sticks instead of silently vanishing while the row stayed listed as uncategorized forever, and the Uncategorized filter no longer offers up split parents whose categorisation is exactly how such rows were created (#360)
  • Find Duplicates no longer loses a next-day duplicate at a group boundary. Groups anchor on their first transaction so distinct purchases cannot chain together — but a pair one day apart could straddle two groups and the second copy went unreported entirely. Rows near the boundary are now carried into the next group, so every pair within the window is reported together and the no-chaining rule still holds (#333)
  • A savings goal that has gone backwards shows an empty bar, not a full one. The Savings view's goal list was the last progress bar without the negative clamp the others got in v2.44.2 — withdrawals exceeding deposits painted the bar completely full
  • The Category Trends tile sticks to expense categories. It relied on a side effect of the old one-direction totals to keep income categories out; with netted figures an income category could slip into the spending list. It now filters by category type explicitly
  • The database-updates warning can no longer be silenced by a mid-deploy race. If the check ran at the exact moment app files were being replaced, a failed directory read followed by a successful one within the same page load could record the version as verified while updates were genuinely pending — permanently hiding the banner on exactly the instance it exists for. The verified marker and the pending list now come from the same scan
  • Editing a bi-weekly bill no longer silently shifts which week it falls in. The consistency check that runs on every edit recomputed the due date "from today", so changing an amount or a note in the off week flipped the schedule's parity — the bill quietly moved a week. With a start date set, the schedule now recomputes from its anchor, and an unrelated edit can never move it (#363, #364)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureV/r+TeR/H5y0TiUgo9apV0nHrv4yLWR3o2yHxeSCrwBr87AyJBO6EphcfUm/aNNDYHbJfh2Nk4ghsMvljrNWPCgMFZdwynngNS3IbrSFauamMsnuvkxDcO5h+R5aAIyBfyog9idiDesDMJF2B1dDbe3COOlxDq5i8xiiP+BGqLpoeOYZKT2dpqoaYB9j16sGk5BSE07vSFnF8kz2PGcpgExtfEqMMVCDRGQUvU02KgLqNb6oFx0abf5NhRGTpNZPMyOMwWH0CVTATrZj7r9LBp8+HQqHUjCRqPTwsYbAVBZZKYwyrtU3Wd/4VaSpKW2bMS7OWA/663hc74b0Rt/QTy0brPK2oiQyM6PisiwlZHAz6nuQWRDUiyezWVS9yLBiVDavZxby7XJAIrb49a8dSESUj7/7eRaO9xAb21oULrp39o0d0GKWBxFf2fuV/uBJ/tQh1pgj7n5PHQ01kZ3Dy1znPGH//sIfsw5nBLeKQQGZvcp4ell+s19FJr2SoKe+HgY8Wo/eCobVpai8GbpeA1HsNc7ixuKIPdxpAsY7X/mNg92GEndFExIDBkUgQfbPYd+LkmjlJdtXqluxB24WdVIVdKDJakxk860CHTUo+k7UgVroJUffjXXwXvFKQCWZG8f/5Tt4eh3QpRfaqQGWpAjQ0lw/AURkUdA0FlN4ELo=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.44.2
Release Details
UpdatedAug. 28, 2026, 3:19 p.m.
Changelog

Fixed

  • The Budget page's Spent really does net refunds now. v2.44.0 said a refund comes off what you have spent, and it did — on the budget report, the dashboard tiles, the alerts and the digest. The Budget page itself reads a different query, which kept the old one-direction sum, so the very page the issue was reported against still showed $216.90 where Category Details showed $58.29. That query now nets the same way as everywhere else. A month whose refunds exceed its spending shows the true negative figure instead of being flipped into looking like money spent, and its progress bar sits empty rather than painting full — on the dashboard's Budget Progress tile and the savings-goal tiles too, where a negative used to render as a completely full bar. Changing a category's budget period also refreshes its row with the right direction and the selected month, instead of flipping an income category's Spent to a large negative until the next reload (#361)
  • "View All Transactions" on a category lists the transactions its figures are built from. The button quietly filtered to money-out only (money-in for income categories), so an expense category's refunds were missing from the very list the netted figures above it summarise — the panel said $58.29 and the list it opened could only add up to $216.90. It also ignored the panel's period and account selection, listing everything ever recorded. It now applies no direction filter and opens scoped to the same date window and account the panel is showing (#361)
  • The transaction filters panel shows the filters that are actually applied. Arriving at the Transactions view through a category's "View All Transactions" or a chart drill-down replaced the applied filters but left the panel's controls showing whatever they held before, so the list and the dropdowns above it disagreed — and because any change to one control re-reads all of them, a stale control could silently re-apply an old filter. The panel now rewrites every control whenever the filters are set for you, clearing the ones that no longer apply (#361)
  • The last places that ignored split transactions now count them. A split carries its categories on its individual parts, and five surfaces were still reading the transaction's own category, which a split never has. Year over Year compared a year of split receipts against a year that predated splitting and called the difference a collapse. The Forecast's category trends dropped every split into Uncategorized and showed nothing against the categories the money actually went to. The count beside each category on the Categories page read 0 for a category funded entirely by splits, next to a panel listing its transactions. Find Duplicates showed a dash where the category belonged. And a CSV export with no category filter left the Category cell empty on exactly the transactions someone had taken the trouble to itemise -- it now names them, and a category is named once however many parts of the receipt went to it (#360)
  • Find Duplicates no longer chains separate purchases into one giant "duplicate" group. Each candidate was compared against the previous row added to the group rather than the first, so five identical-amount purchases a few days apart -- a regular coffee order, a repeated fare -- linked end to end into a single group spanning far more than the 3-day window, and the tool told you to delete transactions that were nothing of the sort. A row now joins a group only when it is within the window of the group's first transaction (#333)
  • Deleting a category no longer leaves split parts pointing at it. The delete guard is deliberately blind to splits (a category used only by split parts must stay deletable), but nothing cleaned those parts up afterwards, so they kept referencing a category id that no longer existed. Deleting a category -- with or without reassigning its transactions -- now degrades its split parts to uncategorized, which is what the reassignment already did for ordinary transactions. Find Duplicates also names a split Split now instead of showing a dash (#360)
  • Splits from before the split feature existed are counted once, everywhere. A transaction whose split flag was never written -- imports predating the column, and backups restored from those versions -- was in a grey state: some queries treated it as a split, others as an ordinary transaction, so depending on the screen its money was counted twice, or not at all, or it was offered up for categorisation, which is how a transaction ends up claiming a category and carrying its own breakdown. Every query pair now agrees on one rule -- a transaction with split parts counts through its parts, full stop -- covering the budget carryovers, the monthly report, Year over Year, the forecast, per-account totals, uncategorized listings and rule runs. Restoring a backup now re-marks the transactions that actually received split parts, whatever the archive claimed, and the very large id lists a restore or a year-long report can produce are processed in batches instead of one oversized query (#360)
  • The app now notices when its own database updates never ran, and says so before anything fails. If Nextcloud replaces the app's files without finishing the upgrade, the database changes that came with the new version are skipped. Nothing looks wrong -- reading data does not touch the new columns -- and then the first thing you save fails with a database error nobody can act on. Every page now checks whether any of its database updates are missing and, if so, shows a banner naming how many and the command an administrator can run to finish them. Checking costs nothing once a version has been confirmed complete, and the banner clears itself as soon as the updates are applied (#333)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureDm8DKf6I3AofLr0FMZsDKeE4q19LhQ2NgVNbRwtRNtCcfcpkF7RWros6LUOJacOmyNa9EuRDVUGQJtTGSasNt4dXxhwDjw7hDsmm2NUaTTrnoLoY32V9zyBLZqtSLb30uZTr6O8q03UGO0MsNQr5IsOcNbi7KflfjmUbYY99cIycOm/FBoLBm+LWQlDH+eQZigjqEk5GMvsLgyY2LuYQE6226WS1W96gI3neUzwICij5OWn/hdkl4axB6Y2Ei7bWofiMRSwY4oeiLF1mmgk1C4OfyoZomZEhsytxXok5wt38K4SMQBL4A+zpVoQBp0cBdFrGUynC/eNtmQjS9nsJSs0woZ3H6+QrlMCmJ+PRqSbn5kEO7PBzXMXUYNg9mqd0mUeYjH0mW1SKpF51FsBKjMHNmi1ReNqQhiRAJq+9JzyiaUuCv/gigDXOaLCR5NvRld0RbMYfnWN9XZ18k8/b+oKwzBG/oY6mqmgR0mUl24lXHK7djSHbhfmCIAG6hpOxgrL6cFguUdqNuoCGhBvUaUBJn742J4Hh4Lx4jq+zQJE1rJf4xpNhcT6VKLJNS7DrSd62oPm80FBXSu9colzmlv3C67SDYwL5TxqdM8OCsPTJvH0IWnr9R+qrrPh5MMqy3XMDyYvzDMjiK0OWmzob4ZxMCg2gi1asdtcjd5PqNgU=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.44.1
Release Details
UpdatedAug. 28, 2026, 12:44 a.m.
Changelog

Fixed

  • When the app's update has not finished, the app now says so and how to finish it. If Nextcloud updates the files but never runs the app upgrade, the migrations that add new columns never run -- the app carries on reading fine, because reads do not notice a missing column, and then the first thing you save fails. Until now that surfaced as the database's own words, "Unknown column 'amount_type'", which is accurate and no use to anyone. Any missing column or table now comes with the command that fixes it: occ app:disable budget && occ app:enable budget. Reproduced against MariaDB, where neither occ upgrade (which upgrades the server) nor occ app:update (which looks for a newer release in the app store) does anything about it (#333)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureJfhfoodWHfhncS8NhWVo/wOO4gi2kDEn4S8M8TzZg5Qfbjwxmkmh4Pn294Og1wL1uIp5gbCGyS2aIzcDN0HoEf7DhN98hxRaZ5P5/5CBFLgTGTNwJmDX9A4Xtwk81o4/3jbeLAPUJspX2OkQKGzyNtFqrCi5aDG/JF5D0Yf49WBnYG3BZp5rSaEOmrD2Scm8D3EmE5wDsIIKg+Zl1iCVHsUX/Z7TG6lVzPxeW4JVIU4NX8hhUziOOGMXthSBM5GxZX4okbtfGm9uVeUOe49rT/kXcm7mTG2Xb/4Phywh7vFqMckiOTSwP2fLttq7LFUv0XtUoaOhxjfhFJBdQIDi9qhtJRMcRvXE8kPbswzpyN9W/nC6lv44Q0Bxse967DXVQ8ZoxIWCByl6/5Z4Ooi978d0lWc/HsZYqMX5SXTb3KoALYNCG2+8WfkXwF+kZ0kPc//K6Uh/r+lgO7Gx55xaR2XkmDhClY7u/PMhLOsc0segdjc4obFyHns/iTeKJjV+aEaOvlbNq5aDKioozMZr2vQhL9XfEv4rKLq5VTxaD0s/WOv4dMJxhA/7LRpC53OlPrFN1IKPgmXUS2v2gTtP7fF9eDvZ6u66ra9zTe/j+R7y2y8mMo0zcUMnPPUxJ5fgX5saIPC2svL65fawwwghOMQTiydg6jEmbipPDU38RJQ=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.44.0
Release Details
UpdatedAug. 26, 2026, 12:34 a.m.
Changelog

Added

  • Dashboard tiles can follow your budget period. Spending by Category, Top Spending Categories and Budget Progress gain a Current budget period date range in their gear settings, which tracks the Budget start day you set in Settings. If your money arrives on the 25th, the tile now covers the 25th to the 24th like the rest of the budget surfaces do, instead of cutting your cycle in half at the month boundary. Spending by Category's header chip names the days it is actually showing — "25 Aug – 24 Sept" — rather than repeating the setting back at you. The other tiles are unchanged: a balance-history chart and the income-vs-expenses series cover a span rather than one cycle, so the option is not offered there (#333)
  • Cash Flow Forecast and Year-over-Year now actually draw. Both tiles have been in the Add Tiles menu with a card, a chart area and a working server request behind them — and no code to draw the result, so they sat blank however long you waited. Both are off by default, which is why this went unnoticed. Cash Flow Forecast now plots your projected balance month by month, starting from today's balance so each step reads as a change, with that month's income and expenses in the tooltip; choose Next 3 / 6 / 12 months in its gear settings. Year-over-Year plots income against expenses for each of the last 2, 3 or 5 years, matching the chart on the Reports page so the two cannot disagree (#333)
  • The bills tiles let you choose how far ahead to look. Upcoming Bills and Bills Due Soon now take a Look ahead setting of the next 30, 60 or 90 days. Upcoming Bills previously showed whatever came first with no horizon at all, and Bills Due Soon was fixed at 14 days. Both still include bills up to a week overdue, so an unpaid bill does not vanish from the tile that exists to chase it — Upcoming Bills previously had no such cutoff and would show a bill overdue by months right alongside this week's, and now drops anything more than seven days overdue the same way Bills Due Soon already did (#333)

Fixed

  • "Last 30 days" on a dashboard tile now means the last 30 days. It meant the month so far: on the 24th you saw 24 days, and on the 1st of a month the tile charted a single day. "Last year" behaved the same way — the year so far, so on 3 January it showed three days. This is why a tile could flatly disagree with the budget alerts sitting above it on the same screen, and it hit anyone whose spending does not line up with the calendar month hardest, because the biggest bills of the cycle fell outside the window entirely. Affects Spending by Category, Top Spending Categories and Budget Progress. "Last 90 days" and "Last 6 months" were near enough but drifted by a day around month ends — six months back from 31 March landed on 1 October — and are now exact (#333)
  • Every Date Range dropdown on the dashboard now does something. Ten tiles offered one and ignored it: you could pick a range, it saved, and the tile carried on showing its own hardcoded window. Large Transactions had no date filter whatsoever — it ranked your biggest transactions over all time — and now honours the range. Weekly Spending was pinned to the last 7 days, and its daily average divided by 7 regardless; both now follow the range you pick, and its label — which always read "This week" — now names the range it is actually showing. That default week is now an explicit Last 7 days setting rather than a hardcoded one, so it is both the tile's starting point and a choice you can change like any other range. Category Trends compared this calendar month against last, and now compares the range you chose against the equal-length stretch immediately before it, so the two figures are like for like at any range. Where a range could never apply, the dropdown is gone rather than lying: Monthly Comparison is this month against last by definition, Debt Chart is a payoff projection with no window, and Income Tracking's headline is a monthly rate that cannot vary with one (#333)
  • The Cash Flow Forecast tile was asking the server for the wrong thing. It sent a days value the forecast endpoint does not accept, so the parameter was discarded and the default horizon used every time (#333)
  • When something fails to save, the app now tells you why. Errors across the app showed a fixed message -- "Failed to create bill", "Failed to save transaction" -- whatever had actually gone wrong, so a validation problem and a database problem looked identical and neither was actionable. Where a failure comes from the database the server already attaches a short, sanitised description of it, a missing column for instance, specifically so the cause is visible to people who cannot read their server's log. Nothing in the interface was reading it. That description now appears alongside the message everywhere a save, delete or update can fail -- transactions, accounts, categories, bills, rules, pensions, assets, transfers, income and bank sync (#362)
  • Bills with a statement or minimum-payment amount explain themselves when rejected. Those amount types only work on a transfer pointing at a credit card, and the two rules enforcing that were being replaced by the generic "Failed to create bill" instead of being shown. Genuinely unexpected failures still stay generic (#362)
  • Repair Data can clear the stray categories off your split transactions. The rows the old bulk edit and the rule runs left behind are still there, each claiming a category it should never have had. Settings > Repair Data gains Split Transactions Carrying a Category, listing every one it finds with the category currently stuck to it. Repairing removes only that stray category: the split stays a split, and every part of it is left exactly as it was. Genuine splits, ordinary transactions, and a transaction explicitly marked unsplit are all left alone, and the scan drains to empty once run rather than reporting the same rows forever (#360)
  • Rules no longer break a split transaction by categorising it. A split's categories live on its parts, and its own category is deliberately left empty -- so writing one onto it produces a row that claims a category and carries its own breakdown, which every per-category total then counts twice. Bulk edit was stopped from doing this a while back, but Run rule now and Run group rules write straight to the database and went around that guard, so rules were still quietly creating the damage. A rule now leaves a split's category alone while still applying everything else it does -- vendor, notes, tags and the rest -- so splits stay covered by your rules. The preview and the results list name such a row Split instead of showing it as Uncategorized, which read as a change that was never going to happen (#360)
  • A transaction damaged by the old bulk-edit bug is no longer counted twice. Before it was fixed, "filter by Uncategorized, select all, set a category" wrote a category onto split transactions without removing the parts underneath, leaving rows that claim to be in a category and carry their own breakdown. Nothing has ever cleaned those up, so they are still sitting in databases -- and the queries behind Spending by Category, the Reports charts and the Category Details panel added up both, reporting a split receipt at its full amount plus each of its parts, and counting it as two transactions. A category could therefore show more spending than the transactions underneath it actually came to. Each transaction is now counted once, through its parts where it has them (#360)
  • Budgets count the money you spent through a split. A split transaction holds no category of its own -- its categories sit on the individual parts -- and the query behind every budget figure only ever looked at the transaction's own category. So a receipt split between Groceries and Household added nothing to either budget: the progress bars read low, remaining read high, and the budget report agreed with them. Budget alerts have counted split money since they were added and the spending charts since v2.33.0, so a category could raise an over-budget alert while the bar right next to it showed room to spare. Affects Budget Progress, Budget Breakdown and Budget Remaining on the dashboard, the Budget view, Reports > Budget and its CSV and PDF, the scheduled monthly report email, and the Unusual spending section of the digest along with its notifications. Splits restored from a backup made before v2.41.0, which lost the flag marking a transaction as split, are counted too, and a transaction damaged by the old bulk-edit bug -- which stamped a category onto a split parent without removing its parts -- now counts through its parts rather than dumping the whole receipt into the one category it was stamped with (#360)
  • A refund now comes off what you have spent. Spent on the Budget page counted only money going out, so a bill that was refunded, a returned purchase or a reimbursed expense left the category looking fully spent -- a $216.90 phone bill with $158.61 credited back read as $216.90 spent, and the bar sat at 100% over a $120 budget. It now reads $58.29, which is the figure Category Details has always shown for the same category: the two screens disagreed, and the budget was the one that was wrong. The same net figure now feeds Reports > Budget and its exports, the Budget Progress, Budget Breakdown and Budget Remaining tiles, the budget alerts -- which is what stops a category raising an over-budget alert while the bar beside it shows room to spare -- and the Unusual spending digest, where a purchase you sent back no longer reads as a spike. Income categories are measured by what came in, with anything paid back out subtracted; Reports > Budget was previously asking for money-out on those too, so an income category with a budget reported nothing against it (#361)
  • A split transaction on the dashboard names the categories you sorted it into. Recent Transactions read each row's own category, and splitting a transaction moves the categories onto its individual parts -- so however carefully a receipt had been divided up, the tile called it Uncategorized. It now names the categories the parts went to, with a coloured dot for each and the part-by-part breakdown on hover, the way the transactions list and the account register have since v2.43.1. Where the tile is too narrow for all of them the names run to an ellipsis rather than pushing the amount off the row, and a split that arrives without its parts is called a Split, which is at least true (#360)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureQHxBHmyBaONUhmqkujdb3Z0HaVDO5kl4378wYHWJgtW/QHl6D1QNcKQzzhB2nVoXZz322zCDeUae1eIk3C+EX4X5q2MolNnL9UAL0TvS0oSfQcAtWTFCAO1Z79C1uYbCxM6CUNNrGmZdoZ41ivw9OJQOICFu5nd0RHQ+w25DUCKK0SOEQXWia7LN5o0RnpTwKYxSxQHIb4dajJvbWsW+oibyBkP/yZsbfJRls3Z2zWYvEEnQhWiKTaJC4Ijfz6DgP6U/M9Z5DjhIZgyxPy5OGTOLd9aZl64K3JzcQqKDKJJ8wTDz9iUXb+bCitxDyq0chgLG4tbSyFyK7+aAcWchHZXufXDmPmAsTikDVgc6srYeKyqv2VFpa/IBA1m0GeAzN2KqIRzDbiyttRGgQQ5i2VPH4owiA8un5ak46XVpD+q5Xy/SwEZVmjCY8AZsZePmPvM9gESC+hBy6P5YuNksSar/dD++REsQCeFkCIiqf4y61wyD0WY3qHYF4yDpWzH8vVhbKSMy0x9W1JR3ZUmv0MbidSvgiOwxpPPtWVuPPRDbLKg3ENzv4bq8IK8PzR0t5jHNSFKWu7C1jrJ3gE7yoxJ5zMnsw6v3HJhedy2Jfx2C2EZsZv1XCzaXYxKBr0uaHVcOSn9/4Rn9OXf95th7bgRN6aCrU34M1ELL3RmocKs=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.43.0
Release Details
UpdatedAug. 24, 2026, 1:27 a.m.
Changelog

Added

  • Liability accounts now ask what a positive balance means instead of guessing. Editing a credit card, loan, mortgage or line of credit shows an Amount owed field that takes a plain positive number — the app adds the minus sign — with a separate This account is in credit tick for the case where you have overpaid and the lender owes you. Switching an account between a debt type and a savings type converts the figure for you and shows the resulting current balance before you save. Creating a liability works the same way. The choice is recorded with the account, so an export and restore keeps it (#353)
  • Several CSV columns can feed one text field. Banks often split what belongs together — a merchant column and a details column, say, or a reference spread over two. On the import mapping step, Description, Notes, Vendor and Reference are now checklists: tick every column that belongs in the field and the values are joined with a comma, in the order the columns appear in the file, with blank cells skipped. The same works for those four fields on OFX, QIF and camt files, and a saved import template keeps the whole selection. A single ticked column imports exactly as it always has, so re-importing an overlapping statement still recognises its transactions. Thanks to @Saviq for the feature (#355)
  • Category trees can be exported and imported. The Categories page has Export and Import buttons next to Add Category. Export downloads your whole tree as a readable JSON file; Import takes that file back, or a CSV of Parent > Child paths, shows exactly what would be created before anything is written, and leaves categories that already exist untouched while adding whatever is missing underneath them. Handy for backing up a carefully built structure, sharing it, or having a spreadsheet or an AI assistant draft one and loading it in a single step (#354)

Fixed

  • Editing a loan or credit card no longer turns your debt into an asset. Typing your statement balance as a positive number into the Opening Balance field stored it as a positive number, which the app reads as "the lender owes you this" — so a £5,000 loan quietly added £5,000 to your net worth instead of subtracting it, a £10,000 swing, and every later recalculation re-derived the wrong balance from it. Nothing on screen said so. Positive balances on a debt stay supported, because a genuine overpayment is a real thing, but the app now asks which you mean rather than reading it off the sign. If this already happened to you, Settings › Repair Data will find it: run Scan for Issues and the new Debts Recorded as Being in Credit section lists every affected account with what it reads now and what it will read afterwards — untick any you really have overpaid, and those are recorded as genuine credits and left out of future scans. Two related consequences are fixed alongside it: an account you have overpaid no longer appears in the debt payoff planner as something to pay off, and it no longer counts towards Total Liabilities on the Accounts page, where it was pulling net worth down by twice the credit (#353)
  • An account edit that does not touch the opening balance no longer rewrites the balance. Renaming an account, changing its institution or ticking a checkbox resubmitted the opening balance every time, so an unrelated edit depended on that value round-tripping through the form perfectly. It is now sent only when you actually change it (#353)
  • Reopening a split transaction no longer scrambles its parts, and saving it no longer throws them away. A split of 10 into 1, 3 and 6 came back as 1, 9.00 and 0.00 — the second part had swallowed the rest and the third was empty. The parts were always safe in the database; the editor was overwriting them as it drew them. It fills the last row automatically with whatever is left over, and it was doing that after adding each row, so every stored amount was recalculated away the moment the next row appeared. It now draws all the rows first and works out the remainder once, which is what it should have been doing. If you saved a transaction from that scrambled view, the parts you saw are what got stored — the third one was dropped for being 0.00, quietly, because the total still added up. Worth re-checking any split of three or more parts you edited recently; their categories will have been wrong in reports for the months involved. Splits of four or more parts had a second symptom — Save appeared to do nothing at all, with no message — which is fixed by the same change (#358)
  • Filtering transactions by Uncategorized no longer lists your split transactions. A split transaction has no category of its own by design — its categories live on the individual parts — and the filter was reading that as "not categorised yet", so every split you had ever made turned up in a list meant for things needing attention. Split transactions are now left out of it, and out of the dashboard's uncategorised list and the "only uncategorised transactions" option when running import rules, which read the same way. The bulk-edit consequence is the one worth knowing about: filtering by Uncategorized, selecting all and setting a category used to write that category onto the split transactions caught up in the list, after which they were counted twice in reports — once for the whole transaction and again for each of its parts. Setting a category on a split transaction is now ignored rather than obeyed; unsplitting one still assigns a category as it always has (#356)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignaturelQsdNi/Ed5bU8/Ch8iyHVXKdX+l8qhRm8fCwRYfB/ObxW6pncVobhw57Bzvu/2yio4Wb+MyJ+DZ8T75pZ9+ugVmWX+q/VSLx4PEAmnr9upL0m7AvJN33BXARoFWBzKVFHnfEy/RuYgtxnNfOmoiblZXbAeBs5zyxxeQKrYSMSHfdwdG/t9HZNFNvFEyp7k7XEU1xQ5HaAo6kResw+25vTU/lkvJNXYmNnmWr3ZxUo7qphCOw/ZJU4aMi+g8RjrWIp86biPeM8mIr57Oacrm3fIQnGTgfk7lqX5FGTjhjLTnDKin+AyFQCpkuki47leJ+W4VwS/LvObLDHn/WcYhjmkdmGXTGFZGhVYAHz3VcPklRmERDkafXZ7lPk0tWZjma/W4SCf6u8Pu3Ni5fVeZ9Zp7qiCjNomRBmMl2nlW2EC/GYJAW7c78TM1Gq9qw6EAAweO5/7JMtOMaA4Klm1XKmE6CpDmu6Ox4E0+RiaDZJ6lHnC7JcfNweMtbgZb4tK/1nAXqum2v4vIQcIDpfk2ROqxkvthclKe05z2p1oe2qg/mEWqwx51ZHR0PvMhmNYGh9VVi3F7KiT0v1K6D06CAAOJu6TeJTMKX5asGJ8K2PkVKk0E7uVWGKp7+WRBU4ILvUftG5d8Pz7ChCY35XVwknHbY/Rx7DNno+1h3YzkblIU=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.42.0
Release Details
UpdatedAug. 21, 2026, 9:23 p.m.
Changelog

Added

  • Receipts can be filed wherever you keep your app data. Uploaded receipts have always landed in Budget/Receipts/<year>/<month>/ in your Files; a new Receipts folder setting lets you point that anywhere inside your own Files instead — Applications/Budget, say, to sit alongside other apps' folders. The year and month subfolders are still created underneath, and receipts attached before the change stay exactly where they are: the app never moves or deletes your files. Applies to uploads from the web form, the API and receipt scanning alike (#352)
  • Bank statements in camt.053 XML can now be imported. Many European banks — Swiss ones in particular — export statements as ISO 20022 camt.053 (and intraday camt.052) XML rather than CSV or OFX. Drop one on the Import page and it behaves like an OFX file: every account in the statement is listed with its IBAN, auto-matched to the account of yours carrying that IBAN, and routed there. The parser reads what the payer wrote (the remittance text), who the other side was (the counterparty, which becomes the vendor), the bank's own entry text, and the transaction type code, and a batch entry such as a collective payment is split into its individual transactions with their own counterparties. Duplicate detection uses the bank's own entry reference — more reliable than the CSV content hash — except where a bank stamps the same reference on every entry, in which case the hash is used rather than collapsing the statement into one transaction. Every camt.053 schema version parses, including files with the namespace stripped (#350)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureRhkTM0z3ZXIpnFc2BJ0widME7KmhTp6jnd/kaHn42N1eiC9JQhiDUCGmqbCweHhswB3HBwwBoG37XE5L/9s97L13vmrIT+19EVx+f3o2xHXeVe0J19F0BKOxyW5mKYt7xQqo/dwCQ+qDk06kH89XPta+ppz28+qcfaEnBiEtnnzlyeOqyXgs6qWuM/sZW/WUau5dPKZxfkK57IgPaBIfx/R8cttcyokpplD5kV+rmGz8+AvAbvqcT06aGCzjQQtK4/ADbBe7PiGxy7Yy64B9LhgphkHuXqk1hzJiuC0exn+8z02QXGq5g2nDbATK6ZF6n6v6wIrSnEZtvRBvd2rloAQe5K5aiP6Ae6TPyILrunKGTL7Je1d/sqWO+103WdwcfLSI2rYHM00CUOdmxRttecjkJvc+sarc7m1M+fFIePC4SC5RlKJin/v9tUf/m+ie0+/UvqrcReF6hjCfN7jp8LBNjJQGsbpOBm+WO6v2i5GSKV/vNWLw4qln0rQXobu0jdSIhraqes84wPmF1z7U/eQorqmB9Q+ig4mfTtR3zxVfcd6vVT5fseiDTVhbaLf144zLTSxWpgVscFSQitXsVnA3FHkHuXsy8OqYeGgtQHOPjwMocSN1udnp59Wth/jd6qxj9Gf9KjFYFi/fwjc+QcvHaTuGCycDo+4xny+evpE=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.41.0
Release Details
UpdatedAug. 19, 2026, 10:30 p.m.
Changelog

Added

  • The Help & Docs page now says how to support the project. A small section with the GitHub Sponsors and PayPal links — the same ones listed on the app store — for people who installed the app and never see either. The floating help panel carries the links too. Nothing nags: it sits in Help, and the app works fully without donating
  • A recurring transfer can now pay a credit card the way the card itself would, with the amount resolved fresh at every payment. Card payments have always been representable as recurring transfers, but only at a fixed amount — useless for a bill that is different every month, which left people faking it with duplicate bills or typing the figure in by hand each time. A transfer whose destination is a credit card (or line of credit) now offers an Amount type choice mirroring what card issuers offer: Fixed amount as before; Statement balance, which pays what was owed as of the due date — everything charged since the previous due date plus any remainder an underpayment carried forward, with later charges rolling to the next statement; Current balance, which clears everything owed at the moment of payment; or Minimum payment, which pays the minimum set on the card's account (never more than is actually owed). The figure is worked out from the card's own ledger when you mark the payment made (or auto-pay makes it), so it is never stale; the amount shown on the transfer between payments is the last one resolved, and the pre-booked next occurrence carries it as the forecast estimate. Reminders, the bills calendar and auto-pay all work unchanged, because the payment is an ordinary recurring transfer. The card's own account page joins in: a Statement due day field on credit-card and line-of-credit accounts records which day of the month the payment falls due — shown on the card's page as account information in its own right — and a Set up payment button appears on a card with no payment transfer, opening the form pre-filled with the card and that due day. Once a payment transfer exists, the page shows when the next payment is due (#347)

  • Subscribing to hosted receipt scanning, and managing that subscription, now happen from the settings page. With the Otherworld relay selected as the scanning provider, the admin settings show the plans with a Subscribe button that opens Stripe checkout in a new tab — the licence key is shown once after payment, emailed as a backup, and pasted into the field above. Once a key is saved the block flips to a Manage subscription button: your server asks the relay for a billing-portal link tied to that key, so changing plan, updating the card or cancelling needs no separate account and the key itself never reaches the browser. A hand-issued key (a trial, or one minted directly) is told plainly there is no subscription behind it rather than being bounced off a portal that would refuse it (#537)

  • A CSV export of every transaction you're looking at, not just the page on screen. The account Export button built its file out of the rows the browser had already loaded, so it silently stopped at 50 — a year-end export of 800 bookings produced a file of 50 that looked complete, which is worse than an error. The export is now built on the server from the same filters the view is using, so it covers the whole result set however many pages that is. The Transactions page gains its own Export button too, which with no filters set means every booking across every account in one file: previously the only export was per-account, so a club treasurer with three accounts had to stitch three files together. Filters still apply, so you can export one category, one date range or one tag set just as easily (#344)
  • The exported CSV now says which way the money went. Amounts carry a sign — expenses negative, income positive — so the Amount column totals correctly the moment you drop it into a spreadsheet, rather than adding your outgoings to your income. The Type column reads Income and Expense instead of the stored debit and credit. Transfers between your own accounts appear as they always have, one leg of each, which now means they cancel out in the total instead of inflating both sides. The file also gained Vendor, Account, Currency, Reference, Notes and Status columns — enough to do the books from without opening the app (#344)
  • A new Income & Expenses report, for the year-end job of showing what came in and what went out. Pick it under Reports and you get two tables — income by category and expenses by category — with each side's own total and the net between them, over whatever period you select. It exports to CSV and PDF like every other report, the CSV keeping the two tables as separate labelled sections so a treasurer's spreadsheet can take them straight. Like the other reports it respects accounts and categories you've marked as excluded from reports; unlike the transaction export, which is a plain ledger of what you filtered (#344)
  • The Belarusian ruble (BYN) is now one of the currencies you can pick. It appears wherever a currency is chosen — the default in Settings, an account's currency, a manual exchange rate — and amounts are written with the symbol after the number (1,234.56 Br), as they are in Belarus. Its daily rate is fetched alongside the other fiat currencies, though the historical series is not: the 90-day history comes from the ECB reference rates, which don't cover BYN, so a converted figure for a past date falls back the same way it does for any other currency the ECB doesn't publish (#343)
  • The API can split transactions, so capture apps can categorise receipt items too. POST /api/v1/transactions/{id}/splits sets the parts of a transaction, and POST /api/v1/transactions now takes an optional splits field so a phone can record the transaction, attach the photo and set the per-item categories in a single request. /api/v1/ocr/extract additionally reports the receipt's subtotal and tax, without which a client could not make the items reconcile to the total — splits must sum exactly, and most receipts print tax on its own line. GET /api/v1/capabilities gains splits_available so a client can gate its per-item screen on a boolean rather than parsing the version. All four are additions: no existing field was renamed or removed, so clients built against the previous shape are unaffected
  • Receipts with loyalty savings can be split too. A Clubcard, coupon or multibuy line means the items on a receipt legitimately add up to more than you paid — and that gap used to make the whole receipt look misread, so it was refused for splitting and flagged with a mismatch warning. The savings are now read from the receipt and become their own line in the split, at the printed amount but negative, exactly as tax gets its own line. Four shapes now reconcile: items alone, items plus tax, items minus savings, and both together. The mismatch warning still fires when the gap is genuinely unexplained, which is the case it exists for. Two robustness details, because the reader is a vision model that occasionally slips: when it under-reads the savings by a line, the server closes the gap from the printed total so the receipt still splits rather than being refused over a saving it half-missed; and an impossible negative tax or subtotal from the reader is dropped rather than trusted into the arithmetic
  • Turn a scanned receipt into per-item splits. After a scan, if the items on the receipt add up, the scan box offers to split the transaction into one line per item so each can carry its own category — useful when one shop trip covers groceries, household and a treat. Where the receipt prints tax separately, the tax becomes its own line at the printed amount rather than being smeared across the items, so every figure still matches the receipt in your hand. The offer only appears when the arithmetic actually reconciles (items alone, or items plus tax, equalling the total); a receipt with a discount line or an unreadable item is left as a single transaction instead of producing splits that would be rejected on save. Splits carry categories, not tags — tags remain per transaction
  • Receipts are filed by month and named after the transaction. They now land in Budget/Receipts/2026/08/ rather than one folder per year, and an uploaded photo is named 2026-08-05 The Corner Deli 23.77.jpg instead of keeping whatever the camera or capture app called it (often a UUID). That sorts chronologically in the folder and makes a receipt findable by shop or amount in Nextcloud's own search. Existing receipts are left exactly where they are. A file attached from your own Files keeps its name — it's your file, and renaming it isn't ours to do
  • Receipts can now be attached while you are still adding the transaction. The Receipts section used to appear only after saving — the attach endpoints need a transaction id — so adding a purchase with its receipt meant save, reopen, attach. Files you choose (or pick from your Files) are now held and listed with an "on save" tag, then attached the moment the transaction is created. If one fails to attach, the transaction is still saved and you are told which — re-submitting would only have duplicated it
  • Scan a receipt straight into the transaction form. When your administrator has set up receipt scanning, the Add Transaction dialog gains a drop zone: drop a photo on it (or click to pick one) and the date, amount, merchant and a suggested category are filled in for you to check. The photo is attached to the transaction when you save, so a receipt is one action rather than three. The box tells you exactly which fields it filled, how many items it read, and whether those items add up to the total — nothing is saved until you press Save, so a bad read costs a retype rather than a wrong record. Scanning also works when editing an existing transaction, where it only fills fields you have left empty: a scan is a suggestion, never an overwrite. The whole section stays hidden on servers with no OCR provider configured, rather than offering a button that cannot work
  • Receipt scanning can be configured from the command line: occ budget:ocr. Run it bare to see which provider is set, whether a key is stored, and — the useful part — whether the server can actually serve a scan right now. occ budget:ocr set --provider=custom --endpoint=… --model=… changes it, and --api-key-stdin reads a key from a pipe so it never reaches your shell history. It matters that this exists rather than reaching for occ config:app:set budget ocr_…: the raw config route looks equivalent but skips the provider and URL validation, and would store your API key in plaintext, since the encryption lives in the app rather than in Nextcloud's config layer. The command takes exactly the same path as the settings page, so a rejected value changes nothing and a key is always encrypted
  • A CSV column can now be mapped to a transaction's Notes. Bank exports often carry a line of extra information — a payment reference, a booking note, the counterparty's message — that belongs in neither the description nor the reference field, and until now it was simply dropped: the only way to keep it was to edit every imported transaction by hand. Notes now sits in the column mapping alongside Description, Vendor and Reference, and whatever you point it at is stored on the transaction. It also earns its own column in the import preview whenever something is mapped into it, so you can see you picked the right column before anything is written, and it can be saved in a template like every other mapping. Over-long values are truncated to what the field accepts rather than being imported into a transaction you could no longer edit (#340)
  • The API can now read a receipt photo into a draft transaction. POST /api/v1/ocr/extract takes a photographed receipt (JPEG, PNG or WebP) and returns a draft for the user to confirm: merchant, date, printed total, line items, and — on the vision-model providers — the currency when one is legible; nothing is recorded until the client saves it through the ordinary create call, so retrying costs nothing but another scan. The reading is done by whichever OCR provider the administrator configured (below); failures carry a stable machine code (ocr_not_configured, ocr_quota_exhausted, ocr_extraction_failed) so a client reacts to what happened rather than parsing prose, and ocr_available on the new GET /capabilities reports the real state so clients hide the flow instead of hitting the error. A category is suggested by running your own categorisation rules against the extracted merchant — computed on your server, so the provider sees the image and nothing else, ever. When the line items don't add up to the printed total the draft says so rather than silently trusting either side. Documented in the REST API guide and the OpenAPI description (#533)
  • Recording a transaction over the API is now retry-safe, and can carry the receipt with it. POST /api/v1/transactions accepts an optional idempotency_key: a client that times out on mobile data cannot know whether its POST committed, so a repeat of the same key within a week answers with the transaction the first attempt recorded instead of inserting a duplicate — the single most damaging failure a capture client can produce, closed server-side. The same call now takes an optional photo part, recording the transaction and attaching the receipt in one request, plus a merchant field and a type that defaults to money-out. A new GET /transactions/recent returns the newest activity flat and merchant-first for a capture app's glanceable list. Wire field names across v1 settled on snake_case (account_id, parent_id, line_items) before anything ships against it
  • Receipt scanning can now be set up, and it is off until you do. A new Receipt scanning block in Settings → Admin Settings chooses which OCR backend reads a photographed receipt: this Nextcloud's own configured AI provider, any OpenAI-compatible endpoint — a vision model on your own network is a first-class option, not a footnote — or Otherworld's hosted relay with a license key. The choice is server-wide and an administrator's to make, because it decides who else sees your receipts. Until one is chosen the app sends receipt images nowhere at all: there is no default backend and no fallback. Your server makes the request rather than your phone or browser, so an API key never leaves the server and a backend that isn't reachable from the internet works perfectly well. Keys are stored encrypted and are never shown again after saving — leave the field blank to keep the stored one. Only the image is ever sent; account names, balances and other transactions are not. The Receipt Scanning guide sets out exactly what goes where for each option. With the API endpoint above, scanning works for capture clients as soon as a provider is configured; the scan button in the web interface arrives in the next release
  • A documented REST API, so Budget can be reached from outside the web UI. A versioned, read-and-capture API now lives at /ocs/v2.php/apps/budget/api/v1 — list your accounts and categories, browse and filter transactions, record a new one, and attach a receipt photo to it. It authenticates with an ordinary Nextcloud app password (or a token from Nextcloud's Login flow v2), so there is no separate credential to manage and revoking the entry under Settings > Security cuts off whatever was using it. That makes a phone capture app, a shell script or an n8n workflow a matter of configuration rather than code — the REST API guide has worked examples, and a machine-readable OpenAPI description ships with the app. Version 1 deliberately stops at reading and appending: editing, deleting and everything else stays in the web UI, which keeps the contract small enough to hold still. Fields will be added to it, never removed or renamed. Every amount crosses the wire as an exact decimal string ("42.50") rather than a JSON number, so a client cannot lose a penny to floating point on the way in or out. Note this is quite separate from the internal endpoints the web UI calls, which follow the database and change without notice
  • The accounts page can now be tailored to what you actually want to see. A gear button next to the tile/list switcher opens display settings for the page. Tick which attributes appear on each account — account type, institution, (masked) account number, last reconciled date, converted balance, and, on tiles, the 7-day balance trend and the status dot. Drag those same attributes into the column order you want for the list view (Alt+/Alt+ does it from the keyboard); name and balance can be moved as well, they just can't be hidden. And choose how accounts are ordered: by name, balance, type, institution, last reconciled or date added, ascending or descending. Tiles follow the same attribute order as the list columns, hiding an attribute drops its column so the rest can spread out, and everything is remembered in your browser alongside the tile/list preference
  • Categories can now be left out of budgeting without being left out of everything else. A new Exclude from budgeting checkbox sits alongside Exclude from reports on a category. Where the reports flag removes a category from all spending figures, this one is budget-only: the category keeps counting in reports, the dashboard, insights and every total, and simply drops out of the Budget page, the summary cards, budget alerts, the budget vs. actual report and envelope rollover. Meant for spending you want to see but can't sensibly budget — gifts, medical bills, home repairs — so you stop being told you're over budget on a figure you never set. Excluding a parent excludes its subcategories too, and like the reports flag it stays with the owner on a shared category
  • Select every transaction matching the current filter, not just one page. Ticking the header checkbox on the Transactions list now offers "Select all N matching transactions" when more rows match than fit on the page, so a bulk delete or edit can cover thousands of rows in one go instead of 250 at a time. The selection is dropped if you change the filter, so a mass action can never silently include rows you're no longer looking at, and bulk deletes of many rows are much faster (the account balance is recomputed once per account instead of once per row) (#336)
  • A Help & Docs page, in the app. The sidebar's Help & Docs entry used to throw you straight out to GitHub. It now opens a real page listing every guide with a one-line summary, a shortcut to the keyboard cheat sheet, the Quick Add page URL, and the System Info panel for pasting into a bug report. The floating ? button still gives you the short version for whatever page you're on, and now links through to the full page

Changed

  • A saved OFX/QIF template now remembers your field mapping as well as your account routing. These templates stored the routing only, so a bank that puts the payee in the memo had to have Description and Notes re-pointed on every single import — the choice was silently reset to the format defaults each time. Picking a saved template now restores both. Templates you saved earlier carry no mapping and are unaffected: their routing applies exactly as before and the mapping keeps the defaults (#340)
  • A reference longer than 100 characters is now refused when you type it, instead of failing when it is saved. The field was validated against a 255-character limit while the database column holds 100, so anything in between passed every check and then broke on the way to disk — a clean "too long" message is a better outcome than a server error. Nothing already stored is affected (#340)
  • A rule condition saying an import source is not something will start behaving differently on OFX and QIF imports. Because those imports never recorded a source at all, a negated Import Source condition matched every row from them; now that they do record one, it is evaluated for real. If you have a rule along the lines of source is not "Bank Sync", check it still does what you meant on your next OFX or QIF import (#338)
  • An import rule that sets notes "only if empty" no longer fires on OFX rows that carry a memo. With the memo now kept in the transaction's notes (above), the field is genuinely no longer empty on those rows, so an if empty rule correctly leaves it alone; an append rule adds to the memo rather than replacing it. Rules set to always overwrite are unaffected (#338)
  • The bill, transfer, savings goal, debt scenario, pension, asset and contact dialogs now use the same layout. Each was a narrow single-column form that had to be scrolled; they are now laid out in columns sized to what they actually hold — three for a bill (Bill, Payment, Schedule) and a debt scenario (Scenario, Payments, Debts), two for a transfer, goal, pension and asset, and a compact single column for a contact. Everything in them is visible at once, with Save and Cancel pinned below the fields. A bill's split rows span the full width of the dialog rather than being squeezed into a column, and a pension shows the pot fields or the income fields depending on its type, without leaving a gap where the other one would be
  • The four tag dialogs now match the rest. Add Tag, Edit Tag, Add Tag Set and Edit Tag Set are two-field dialogs, so they stay compact rather than being stretched into columns — but they pick up the same chrome as the bigger dialogs: a rule under the title, and Save/Cancel on a divided bar at the bottom right instead of loose against the left edge
  • The category dialog gets the same treatment. Naming fields (name, type, parent, colour) sit under Details on the left, the two exclusion options under Options on the right, and Tag Sets spans the full width below them — no scrolling, and the two checkboxes now read as ordinary checkbox rows instead of a bold heading with a stray box floating above it
  • The transaction dialog gets the same three-column desktop layout as the account dialog. Adding or editing a transaction was a 500-pixel-wide strip roughly a screen and a half tall, with a line of help text under every field restating its label. It is now laid out as Transaction (date, account, type, amount), Details (description, vendor, category, split toggle, tags) and Extras (receipts, notes, exclude from forecast), all visible at once with nothing to scroll for. Switching on Split across categories opens the split table across the full width of the dialog instead of squeezing it into a narrow column
  • The account dialog now fits on one screen. Adding or editing an account meant scrolling through roughly two screens of form in a narrow 700-pixel strip — eighteen fields, most of them empty, each with a line of help text underneath repeating what its label already said, and the Save button stranded at the very bottom. The dialog is now laid out for a desktop screen: three columns — Details, Banking, and Rates & limits with Advanced beneath it — showing every field at once with nothing to scroll for and nothing hidden. A column block with nothing to offer your account type, such as rates and limits on a Cash account, doesn't appear at all; Save and Cancel are pinned below the fields; the help text that merely restated its label is gone; and the current balance is shown as the calculated figure it is rather than a text box you can't type into. The columns reflow to two and then to a single stack on narrow windows and phones
  • The documentation has a home of its own: budget.otherworld.dev/docs. Every link that used to send you to raw Markdown files on GitHub — the in-app help panel and Help & Docs page, the README, the install guide and the app store listing — now opens the rendered site, which is searchable and readable on a phone
  • The Settings page is tidier. The Save Changes / Reset All to Defaults buttons were stranded in the middle of the page, with the Quick Add Page and System Info sections stuck below them, and Danger Zone was not the last thing on the page. Sections now run in a sensible order, with Admin Settings and Danger Zone at the end and the buttons at the very bottom. Quick Add Page and System Info have moved to the new Help & Docs page, since neither was a setting
  • The action buttons on an account row in the list view no longer sit flush against the last column

Fixed

  • The backup now actually contains your data — all of it. The export/import zip under Settings → Migration carried only categories, accounts, transactions, bills, import rules and settings; everything else silently vanished when moving servers. Reported for tags (#351), but the full list of what a migration used to lose is sobering: tags and their assignments, tag sets, transaction splits, recurring income, savings goals, assets and their value history, pensions with contributions and snapshots, per-account interest-rate history, manual exchange rates, import templates and remembered account links, saved reports, net-worth and budget history, reconciliation history, debt payoff scenarios, muted categories, shared-expense contacts with their shares and settlements — and on transactions, the links joining transfer pairs (so every transfer fell apart into an income and an expense), bill references, the split flag, and reconciliation/pension links. All of it now exports, and imports with every cross-reference remapped to the new server's ids. Old backups still import exactly as before; new backups are format 1.2.0. Deliberately still excluded, and now stated in the archive's manifest: bank-sync connections (provider agreements are instance-specific and must be re-established), shares with other users (they reference people on the old server), receipt files (stored in Nextcloud Files, not in the app), and the fetched exchange-rate cache (your manually set rates are included)
  • Marking a recurring transfer paid no longer loses the deposit half of its pre-booked transactions. When a transfer had its next occurrence pre-booked as a scheduled pair, marking it paid cleared the withdrawal leg but deleted the deposit leg — the source account paid out and the destination account never received the money, quietly understating it by one payment each cycle. Both legs of the pair are now cleared together. Payments already recorded this way are missing their deposit; the Convert to transfer action on the surviving withdrawal recreates the other half
  • Transfers no longer count as income and spending in the analysis reports. The dashboard's income and expense totals have left transfers between your own accounts out since 2.28.0, but the Reports page never got the same treatment: a £500 transfer appeared as £500 of income in Income Analysis (grouped by month, source or category) and £500 of spending in Expense Analysis (by month, vendor, account or tag) — and in the new Income & Expenses report only the incoming half was counted, overstating the net by the full amount moved. Every report view now excludes linked transfers, matching the dashboard, so shuffling money between your accounts changes no report figure. Two things are unchanged by design: a report filtered to a single account still shows that account's own transfer legs, because the money genuinely entered or left it; and only transfers the app knows to be transfers are excluded — ones created with the Transfer type, recurring transfers, and rows joined with Match transfer. Two unlinked rows entered by hand still count as ordinary income and spending (#349)
  • "Use Default Categories" failed with "A category with this name already exists" whenever any default was still present. The button seeds the whole catalogue in one go and gave up on the first name it found already taken — creating nothing at all. Easy to hit without doing anything odd: the category list shows one side at a time, so emptying the Expense view put the button on screen while the Income tree still existed in full, and pressing it failed on Income before a single expense category was created. Seeding now fills in exactly what is missing — an existing category is kept as it is, its missing subcategories are added underneath it, and everything else is created around it — so the button always finishes what it can instead of refusing the lot. A double-click while the first request was still running could also race itself into duplicates; the button now ignores the second click (#348)
  • Amounts in Kazakhstani tenge were shown with the code rather than the symbol. KZT was selectable and priced correctly, but it was missing from the front-end's symbol table, so every figure came out as KZT1,234.56 where the rest of the app would have written ₸1,234.56
  • Envelope budgets ignored everything you spent in a category's subcategories, so the whole budget rolled over untouched. The carryover looked for spending filed against the budgeted category itself and nowhere else. Budget €300 on Groceries and file the receipts under Groceries › Supermarket — the ordinary way of using subcategories — and it found nothing to subtract: July carried the full €300, August carried €600, September €900, growing by the untouched budget every month. The same screen said so in two contradictory ways, because the Groceries row itself has always added its children up: "spent €250 of €300" sat directly beside "+€300 carried". An envelope now covers the whole branch — the category and everything filed underneath it — so the amount carried forward is the leftover you'd work out by hand. A subcategory with its own envelope still keeps its own chain and is left out of its parent's rather than counted twice. Subcategories stay out of a parent's envelope when you've excluded them from budgeting or from reports, when they budget on a different period (a quarterly amount can't be added to a monthly envelope), or when they're income categories — and so does anything filed underneath those. Budget alerts and the budget-vs-actual report read the same corrected figure. Nothing was stored wrong: the carryover is recalculated from your budgets and transactions every time it's shown, so the numbers correct themselves as soon as you update (#341)
  • Envelope budgets also ignored anything you spent in a shared account, with the same result. The two queries the carryover uses to total up spending were scoped to the accounts you own, while every other budget figure on the page is scoped to the accounts you can see. So a category you fund out of an account shared with you looked untouched to the envelope: the full budget rolled forward each month, next to a row that correctly showed the money as spent. Budget alerts had the same split — they now measure spending over the same accounts as the budget they compare it against, including their split transactions (#341)
  • A long CSV column could import a transaction you were then unable to edit. Text taken from a CSV was stored exactly as the file wrote it, with no regard for what the field can hold. A notes column over 2,000 characters — easy to hit with a bank that packs a whole payment reference into one cell — imported perfectly happily and then failed validation the moment you opened that transaction, so no change to it could be saved until you shortened the note by hand. Over-long Vendor and Reference values were worse on MySQL and PostgreSQL: the row was rejected outright and counted as an error rather than imported. Imported text is now truncated to the field's limit, exactly as OFX and QIF imports already were, and leading or trailing whitespace is stripped rather than stored (#340)
  • "Check the server log for details" pointed at a log with nothing in it. When rows failed to import the warning told you to look in the server log, but the import never wrote there — the only record was in the browser's developer console, which is not where anybody was being sent. Failed rows, unresolvable accounts and balance recalculation failures are now logged properly with the row number and the underlying error (#340)
  • The column mapping step never highlighted the columns you had mapped. Each mapped column was supposed to be marked in the preview table underneath; the highlight was looked up by column position while the mapping holds column names, so it silently matched nothing and no column was ever highlighted for any ordinary CSV (#340)
  • A transaction added "today" could be filed as a future payment and left out of the account balance. Whether a date counts as future was decided using the server's calendar, but the date comes from yours — the web form pre-fills your device's date, and a capture app sends the phone's. Whenever your local date ran ahead of the server's, everything you recorded was quietly marked scheduled, and scheduled transactions are deliberately excluded from the balance: you added a purchase and the balance did not move. On a UTC-hosted Nextcloud that is the hour after midnight for anyone in British Summer Time, and most of the working day for anyone in Australia or New Zealand. The date is now judged in your own timezone (the one Nextcloud already knows from your session), falling back to the instance's configured timezone, so today is today wherever you are — while genuinely future-dated payments are still scheduled and still stay out of the balance until their date arrives. Transactions already misfiled this way corrected themselves within a few hours through the existing scheduled-transaction job; nothing was lost
  • QIF import has never worked: it reported rows in the preview and then imported none of them. A QIF file's accounts are matched to yours by an identifier the QIF parser never actually produced, so every account in the file was skipped — the import finished reporting success, with zero transactions added and no error to explain it. Underneath that, the parser had no notion of where it was in the file: an !Account header block was read as though it were a transaction (importing a row dated with the account's description), and because a real Quicken export opens with its category list, that whole list was read as an extra account containing one bogus transaction per category. Accounts are now identified by their name in the file, !Account blocks set the account's name, type and description as they should, and the sections that never held transactions — the category list, classes, memorised payees, security prices — are skipped instead of being imported as data. A file that does not name its accounts shows them as Account 1, Account 2 in file order. Dates are also read properly now: Quicken pads them to a fixed width (12/ 4'98), which nothing recognised, and a date that cannot exist — a 13th month — was passed to the database as text rather than being rejected (#338)
  • Import rules could not match on "Import Source" for OFX, QIF or any non-CSV import. Only CSV imports recorded where a transaction came from, so a rule condition on Import Source was silently false for every OFX and QIF row — and, because an unknown field inverts under a NOT, a rule saying source is not … fired on all of them instead. OFX and QIF imports now record OFX Import and QIF Import, joining the existing CSV Import, Bank Sync and Toshl, and the values are listed in the rules guide. Note the source describes how a transaction arrived and is not stored on it, so this criterion still matches nothing when a rule is re-run over existing transactions — the guide now says so (#338)
  • The column mapping did nothing at all on OFX and QIF imports, and the memo was thrown away. Every field in the mapping step could be changed and none of them had any effect — the import silently ignored the mapping and always took the description from the OFX name field. Banks that put the real payee in the memo instead (a common Canadian pattern) had no way to import a usable description, and the memo itself was parsed, shown in the preview, and then discarded rather than saved anywhere. Worse, a statement whose entries carry only a memo and no name imported with a completely blank description. Now: Description, Notes, Vendor and Reference can each be pointed at any field the file actually contains, the memo is kept in the transaction's notes by default, and a missing name falls back to the memo instead of importing nothing. Date, amount and type come from the file's structure and are no longer offered as mappable, along with the income/expense, account and currency columns that these formats never had — those dropdowns are gone rather than left on screen doing nothing (#338)
  • The import preview showed every amount as a plain positive number, whichever way the row was going. The preview is sent each amount unsigned with the direction alongside it, and it drew the number while ignoring the direction — so a statement of nothing but expenses previewed as a column of figures indistinguishable from income, and the step whose whole purpose is to be checked before anything is written could not show the one thing most worth checking. Amounts in the preview are now signed and coloured: an expense reads -€91.29 in red, income €500.00 in green, and the column is right-aligned so the figures line up. What was imported was correct all along — only the preview was silent about it (#339)
  • A negative amount written any way other than a leading hyphen imported as income. Only -1234.56 was understood; every other notation had its sign thrown away with the currency symbols. That covers a trailing minus (1.234,56-, as written by a number of German and mainframe exports), brackets ((1,234.56), the accounting convention several US and UK banks follow), and a typographic minus or dash in place of an ASCII hyphen. A trailing minus was the worst of the three: left on the end of the number it also pushed the decimal separator out of place, so 91,29- imported as income of 9,129.00 — a hundred times the real figure, on the wrong side of the ledger. All three now import as expenses, and a lone - in an amount column still means "nothing here" rather than a negative. If you have already imported a file with trailing minuses, re-importing it will add the corrected rows rather than recognising them as duplicates, because the rows that went in were keyed on the wrong amount (#339)
  • Dialogs on the Assets, Pensions, Savings Goals, Debt Payoff, Tags and Import pages opened behind the sidebar. Fourteen dialogs — including Add Asset, Add Pension, New Scenario and Add Savings Goal — were written inside the page content area, which Nextcloud paints as its own layer. A dialog can never rise above the sidebar from in there, however high its own stacking order is set, so it appeared cut off behind the app navigation. They now sit alongside the dialogs that always worked, and cover the whole window like the rest
  • The remove button on a split row sat under the Description box instead of beside it. The row's Description input was written without its closing bracket, so the browser swallowed the tag that should have ended the field and folded the remove button into it — the row's fourth column stayed empty and the ✕ dropped onto its own line. It now sits at the end of the row where it belongs
  • A mapped Type column is no longer ignored, so unsigned exports stop importing as all income. Mapping a Type column (Expense/Income, Debit/Credit, DR/CR, Withdrawal/Deposit, …) had no effect: the direction was always taken from the sign of the amount. Files that write every amount as a positive number and state the direction in a separate column — Nextcloud Tables exports, and a number of banks and budgeting apps — therefore imported every single row as income, quietly moving the balance the wrong way by twice the amount. The mapped column now decides the direction; rows where it is blank or unrecognized still fall back to the sign (#333)
  • The import preview now warns before a batch goes in the wrong direction. Two new warnings appear above the preview summary: one when a mapped Type column is blank or unrecognized on some rows (naming how many), and one when nearly every row would be booked as income into an account whose history is nearly all expenses, or the reverse. Neither blocks the import (#333)
  • Every transaction showing "Unknown Account" after restoring a backup. Restoring a backup gives every account a new id, but a page that was already open kept the old ones, so nothing in the ledger could be matched to an account and the whole Account column read Unknown Account — with nothing in the browser console to explain it. The same happened in any second tab left open during a restore. The transaction list now notices that it is holding a stale account list and refreshes it by itself, and a restore finishes reloading its data before reporting success (#333)
  • A failed accounts request no longer blanks the Category column too. If the accounts request failed while the app was loading, the rest of the load was abandoned as well, so both the Account and Category columns fell back to Unknown Account and Uncategorized behind a generic "Failed to load data" message. The two lists now load independently, and the message names which one failed and says to reload the page when an expired session is the cause (#333)
  • Select all now counts during reconciliation. In a reconciliation session, the header select-all checkbox ticked the row checkboxes visually but the Ticked total and Difference didn't move, and the ticks never reached the server — so they were also silently lost when leaving and resuming the session. Select all now registers every row it ticks (or unticks) with the session exactly like a manual tick, and no longer wipes ticks made on other pages of the list (#337)
  • Deleting an account that still has transactions now offers to delete them too, instead of failing with an unhelpful message. The delete failed with "Failed to delete account: Failed to delete account" — the real reason (the account still has transactions) was being replaced by a generic message on its way to the browser. The prompt now says how many transactions the account has and offers to remove them along with it, which makes a bad import easy to undo; decline and nothing is deleted. Transfers pointing at the deleted transactions are unlinked, leaving the counterpart in the other account intact (#336)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureBbOGARv5bo0EfD87OHApDK4LSAVbklBnbu7Q0XNAXlA/b120kU9X1ByNzLNwChmoeOLSrKp+saviED0SZkaaD2VdC6KM+2NghhWl/8RsDzdjLnUS5mbhQ04KOXOClJ1iHzwKIRJvAkStGLPAP/McI7ol6QLHi3ABWXWDlBcT6bGKDC6v7cmbh9jOeoys4phwH0uJE9pOVlQg7SfHGd/VJKr6pcScapT9P5dOBj878vpqjYSc3KIFvQ5OfA9C836sCseYxi9jM8YPoaw+LzTfX5/t80Fv5I2woXsvXnwtjijARCotyD1uZ9QMAy7M5LLkEm6yUGjJYrEBMBpc3h8fiC7muLojTK+J9O7zk7oYNN8D6Q2YqdJ3e84cEagzf83gbKicTPX4kJ9C8bvUQzK5roVtgFwat/Ndu9c2uK/rwOUVmDKPHdzt3/SQQAl9712dX7lZTJVN9r3dm87AL1nfaJghemZOfQdcQwFkahMlHZOm+B0xKrSUqQWyfbw4xezPvVZEudqpPIhQ0lIlFro93ziB7KBUJvaJCx0UNMFr2Z4zCDY64wKLaq1sgSm8HQ4QxSdL1+bPWgTG+BVzchvbx6Cmh7DHmXTAr5XGPzEczdMWY0t16uZ4ZzftT5Ss+S/NKpV37SiFKPOKWzou4BFGU9qwl0DeYKy4E+/EDMX0W80=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.40.0
Release Details
UpdatedJuly 26, 2026, 9:40 p.m.
Changelog

Added

  • Keyboard shortcuts. Budget can now be driven from the keyboard. Press ? anywhere for a cheat sheet. Globally, / (or Ctrl/Cmd+K) focuses search and g then a letter jumps to any page in the sidebar (g d Dashboard, g t Transactions, and so on — every page has a letter). Any dialog now closes with Esc, traps Tab inside itself, focuses its first field on open, and saves with Enter. On the Transactions list, j/k move a row cursor, e (or Enter) edits the highlighted row, and x selects it. Shortcuts stay out of the way while you're typing in a field
  • Export and import your import rules as a file. New Export and Import buttons on the Rules page: Export downloads every rule you own as a single JSON file (a lightweight backup, or a way to move your rule set to another instance without a full data export); Import reads such a file back in and creates the rules. A rule referencing a category or account that doesn't exist on the target instance is rejected and reported rather than mis-filed. Rules shared with you are left out of the export, and rules remain part of the full data export too (#318)
  • Import rules can now be shared. Rules join the list of things you can share with another Nextcloud user (alongside accounts, categories, bills, income and goals) — pick which rules to share, read-only or read/write, from a share's Configure panel. Shared rules show a Shared badge on the Rules page, can be run and (with write) edited by the recipient, and run during their imports too; only the owner can delete one. A shared rule's set category/set account action only takes effect for the recipient when that category/account is also shared with them, so a transaction is never filed under something they can't see (#320)
  • Import rules can now match on the account. A new Account condition scopes a rule to a specific bank account (with NOT for "any account except this one"), and a companion Account Type condition matches by kind of account (checking, savings, credit card, …). Both work when importing into an account and when running rules over existing transactions (#322)
  • Tag sets now work on shared categories. Opening a category shared with you shows its tag sets; with write access you can add, edit and delete tag sets and tags on it just like your own categories, and read-only shares show them without edit controls. Previously any tag-set action on a shared category failed (#328)
  • Bulk edit can now clear a transaction's category. The Bulk Edit Transactions dialog's Category dropdown gained an Uncategorized option alongside Don't change, so you can un-categorize many transactions at once (#332)
  • Deleting a category that still has transactions now offers to reassign them. Instead of blocking with "reassign or delete them first", the delete prompt offers to move the category's transactions — and any in its subcategories — to Uncategorized and remove it in one step (#332)

Fixed

  • The browser Back button now moves between pages inside Budget. Switching pages (Dashboard, Transactions, Accounts, …) records a history entry and updates the address bar, so Back and Forward step through the pages you visited in the app instead of jumping straight out to whatever you were looking at before you opened Budget. The current page also survives a refresh, and links that deep-link into a page (e.g. from search) still work.
  • Bills with "Auto-pay when due" turned off could still auto-pay themselves. The auto-pay flag (and the other bill toggles) could be read as on when it arrived as text rather than a true/false value — the classic (bool)"false" trap — so a bill created or restored with auto-pay off could still be auto-paid. All bill toggles are now parsed strictly as booleans on create, edit and import (#335)
  • Cryptocurrency accounts and their transactions now keep full precision. Amounts were capped at 2 decimal places on entry and storage, so e.g. 0.00012345 BTC was rounded to 0.00. Account balances, transactions and splits now accept and store up to 8 decimals, following each currency's native precision (BTC 8dp, XRP 6dp, JOD 3dp, and so on); fiat currencies are unchanged and still 2dp. Amounts on bills, recurring income and savings goals denominated in crypto are not yet covered (#331)
  • Shared categories keep the owner's order, and editors can reorder them. Recipients saw shared categories in an arbitrary order and couldn't move them; they now appear in the owner's order, and a write-share recipient can drag to reorder (the new order applies for the owner and everyone it's shared with). Reordering no longer silently fails when sort positions collide — the whole sibling group is renumbered on each move (#328)
  • Shared categories now open for the recipient instead of doing nothing. A read-only shared category couldn't be selected in the list at all, and even when reached its detail/recent-transactions/spending endpoints returned 404 (they looked the category up under the viewer, so one owned by someone else was never found). Clicking a shared category now opens a read-only view showing the owner's transactions and analytics for it (#328)
  • Recording a bill's payment failed when the bill used a shared account. A bill can point at an account owned by another user — a partner's shared account — but marking it paid, and the one-click Record transaction repair, threw "Failed to record payment" (a DoesNotExistException in the log) because the transaction was booked against the person clicking rather than the account's owner. Bill payments are now recorded against the account owner, so a share recipient can mark shared bills paid; a bill whose account was since deleted now shows an actionable message instead of the generic failure (#334)
  • A one-time bill marked paid without a recorded transaction could not be reached to fix it. After a one-time bill is marked paid it deactivates and drops off the Bills list, yet it still appears in the Payments without a recorded transaction card telling you to assign an account first — with no way to open it. That prompt is now an Assign an account button that opens the bill for editing (#333)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureTlx5adQ84X1cU4v1VoYON+yY22etMZSb58OURK5dpJ/bpQdLjdhL6stjRFGshNhEHr1Ra/KTZs7/uCZLyvq+M0XBYGD+voy+pwmXwa6Wylyi99fJ2UhiXPHxKiExVq1EJY/PA7LcHAQy639r04gbQ4Q/BvDrOZYWAZuYCLrZrZFclfoIlzf/Ra5SFuCuWguuOd79cU/tXViv8xntJBIcIXoN58cadHF5iTo3Mt2XO7sNsUs7A8+1HDXsUldblvmLFFpH9ubJdYVDKqdzA104yRb0uPH08Zd6+y764r+uIsahSB/RwF3kJ20gcv5nurCaf9FvsI06PiyQnR73jMzlnoAaWxnSPZwGDa+gvQ/t56H+m+A9DlvVgnxexUa0C+Ga7cphcgVKWPWaRZFQzeofrcJ66wAH9uh338pw2R2Lq5F+s2NCOKuKo6uXocpf+VZ9GTsfRIrDEGL+4FwkFkxd0tHUBoohsOhROk/tXphvl/mIh5m4m3pRsjm7GviZASYoTXJe+kdclUUzpFMuXGrOFjSXCd1Plk2XsDMiHBzPEXAkaPlL9hdluXiuCCXrUYIF+S/U60qB1MuWRlwzTH80RovEgvyKGwZtzlDPtNLF0hM79iABKE5UgP1km9MRm7dyDWQDdogfWq+Oy97EJH8TDtYvuO2I79lQnppc9WrYB5E=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.39.1
Release Details
UpdatedJuly 11, 2026, 10:22 p.m.
Changelog

Fixed

  • Share recipients saw wrong dashboard totals. For a user whose accounts are all shared from someone else, the Income/Expenses This Month cards counted transactions in the owner's "Exclude from reports" categories — the exclusion list was built only from the viewer's own categories, so the owner's internal-transfer legs inflated the recipient's income and expenses while the owner's own dashboard was correct. Shared categories now keep their owner's exclusion for every viewer, and per-viewer "Hide from my reports" mutes are honored by these totals as well (#326)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignaturePTjw+Z1r+sKWQmZSlNfYPSTl5PFejqjMEgNyvQR1FXSKor9zNXxtxcAM0eYYthPn9YEprCKS9V6NC699ZbeWK6WbdRtprmP+rsvCifpjQyVtPDGLJ11LWzLVgw84pTHcolsdY756JO6KWW8hxp63bq3s4QE4rs3RTCEyHSpzpZ1pXSydTCTvheL1M/rtg3XyKpzBkoOqGh39Dnh9TH7JQt+cCB8VD84aeHcsvnxUkQJU3AmZwYGcP8wSNeLmDjt1S9yCv2h8NAReLQeTMbmdzNJtioLLiifkedz5bEgjVximgqI99mmV+8uhRBY0keT1hWXR6En4IrRkiJwlEyNZRHkukMa9jNmoNVvoRYCuQOVZ1wWGtkS8MCz5Ig63yPijEMh1bqnoi3+WA1g8s23dJVIziAHSKl0F+V7DKThsw2jBouMZeZ7bG0nMS9bFLcndAm1MbpWyuZATotUExNeYhEZEIwUOuF+esV5lnDoHTf0i/q6OJGa4hPPiNTE/rH4PS3Z4pdEZ4V9YhxYfsSs/9y+Y7xg/ZQWnLq2YVsTR7V8FgQwU4Bi8OGLsfbYZhSaUnHv60ObUB2U4WkD1mZZqDHKJXAIgVGulvHFAkXQVeGpRqbUCQNvgiVU8hfRaRmEr/y9Usub/3srDJn7qybeAxfOxA7rL+AlakEZBECHPJlY=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.39.0
Release Details
UpdatedJuly 11, 2026, 12:57 a.m.
Changelog

Added

  • The Bills page now flags payments without a recorded transaction. A warning card lists bills that were marked paid in the last 60 days without a transaction being created or linked — the situation where the app balance silently detaches from the bank. Each entry has a one-click Record transaction repair that books the missing payment (dated the day it was marked paid, both legs for transfers, splits applied). Deliberate skips via the Skip button are not flagged (#274)
  • QAR (Qatari Riyal) and JOD (Jordanian Dinar) are now available as account currencies. JOD amounts use the currency's native 3 decimal places. Automatic exchange rates cover both. Requested in #321

Fixed

  • Editing a monthly recurring income never saved the changes — the app showed "Income saved successfully" but the Expected Day (and every other field) kept its old value. Any update whose payload contained an empty field (a monthly income always sends its yearly-only "expected month" as empty) reloaded the entity mid-save and threw away the edits. Thanks to @redsteadz for the fix (#324, #325)
  • The "Exclude from forecast" checkbox on a transaction appeared unticked whenever the edit dialog was reopened, and saving the transaction again then really did reset the flag. The flag was stored correctly (including when set by an import rule) but the transaction list never sent it back to the browser, so the dialog always showed — and re-saved — it as off (#326)
  • Income/Expenses This Month (and the other report summary totals) deducted transactions in "Exclude from reports" categories without converting them to the base currency, so on multi-currency setups the deduction was applied at the wrong rate — and for a single selected account the deduction wrongly included every other account's excluded transactions too (#326)
  • Imports no longer bring in flagged duplicates by default. The preview's "Show duplicates" checkbox — on by default — secretly doubled as the skip-duplicates switch, so every import ran with duplicate-skipping off and rows flagged Duplicate were imported anyway. It is now purely a display filter; a new explicit "Import flagged duplicates too" option (off by default, resets each import) covers the deliberate re-import case. The preview's per-row checkboxes, which were never actually read by the import, are gone, and the New Transactions count no longer includes flagged duplicates (#327)
  • Marking a bill paid no longer suggests unrelated transactions as "existing" matches. The Existing Transaction Found dialog offered any unlinked same-day debit as a candidate — cigarettes could be presented as a "match" for a mortgage — steering people into marking bills paid without recording the payment, the classic source of app-vs-bank balance drift. Candidates now must match the bill by amount or name, a weak match is never pre-selected (the safe default is creating the transaction), and the "Don't create any transaction" option now states — and warns after — that the account balance will not reflect the payment (#274)
  • Overdue bills no longer double-book when marked paid. The scheduled placeholder pre-created for the next occurrence was written as an ordinary cleared transaction whenever the advanced due date was not in the future, so it counted toward the balance immediately — alongside the actual payment. Next-occurrence placeholders are now always scheduled, regardless of date
  • Restoring a backup preserves every bill setting. The data import dropped most bill fields: custom recurrence patterns (restored bills then advanced one day at a time instead of quarterly/etc.), transfer destination and description pattern, auto-pay, reminder days, tags, split templates, start/end dates, remaining payments, forecast exclusion and the future-transaction opt-out

Changed

  • The Match transfer dialog now also lists candidates from accounts in a different currency (any amount, within the date window), so cross-currency transfer pairs — e.g. imported from CSV — can finally be linked by hand. Automatic matching after imports is unchanged and still only links exact same-currency amounts (#326)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignaturegJm3RDjkvl1EBICN6Us5TsX5SdQbSGnRHvRIZmLsYaclkDVqW/mYCBjVgwjU50ifkv72zl3kxf5a8S3yxpo2WX6cnhkyyibLhs5Uzdrj9Egw47yYgMun8WH4647Y0uGP7QrX3Yf51SO7Ve+JWgdMRX+hWvG4K9hxUgAwWR3AmTYRsRXpmsNrOr97q2SPC3V0g9bAARDeSeWDGQ8SR05+OMIrQRj0Ct56fC1cTNWzHpPT+Qs17SJJcUUnK3tJWsM3wvGiwk62YMBy1cv1jx3JkOXnYvsa8bpSG3sL7aqr05QkAkvL9sSGxka6mDrC3CN1LHlwwQjPjWwoX9YDtOI04j0JPd0SzlhMYILaZNyouhoNTuY5YhDIG4aLjg737AAEBHgU3jvpWxaM8Oz2+9he9LkAJW6qA9DuzB/FmDNKxyJTmQ6S0LZ21d+Hkr0LD/2uKRSywlRBld+UNCWby8YrgIkyGomPH1rjDG28y1ApiqSozetcjSvDYwqULM2mLXU9OjD9a8UJk8B1R4Xd0TqgMmDCaAZrTdRLYYdTZEEaFbnDkbm8p4z2q+UGfn/UCNEOkg5pbu1WAsRubIKkPzNTz7gTSLI9u+qJfvoZg9c3Ae1OhXWDD9k/2Z+pCrbJhu8yDX+2JukXoAxNS+bnxaDxdoxRzIM+9jcbb0eyG3wJuLk=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.38.0
Release Details
UpdatedJuly 7, 2026, 1:07 a.m.
Changelog

Fixed

  • The account selector saved in the gear settings of insight tiles (Monthly Comparison, Large Transactions, Weekly Spending, Year-over-Year) was silently ignored — the tiles always showed all-accounts data. The saved account now actually scopes the tile's numbers
  • Importing transactions that trigger the Auto-Link as Transfer rule action no longer shows "Cannot use object of type Transaction as array" on the import screen. The import itself always completed — the error came from the transfer-linking step afterwards, which also means those transfers were never actually linked (#314)
  • The Recent Transactions dashboard tile now honors its "Rows to show" setting above 8 — the display respected the setting but the data fetch was hardcoded to 8 rows, so values of 9–20 silently showed only 8

Added

  • Edit auto-categorization rules as JSON. The rule editor gains a Builder / JSON toggle. The JSON view shows the raw rule structure — editable and paste-friendly — checked when you save, and switching back to Builder repopulates the visual widgets. A Copy JSON button makes it easy to move a rule between instances (category/account IDs are instance-specific, as noted in the view). Requested in #318

  • Hide shared categories from your own reports. Categories shared with you gain a per-viewer "Hide from my reports" toggle on the Categories page. Unlike the owner's "Exclude from reports" flag — which stays owner-only because it changes every viewer's reports at once — this only affects your own reports and dashboards; the owner and other viewers see no difference. Applied at the SQL layer through the same choke points as the owner flag, so every report and insight tile honors it consistently

  • "Exclude shared accounts" on the remaining dashboard tiles. The per-tile toggle added in v2.37 now also covers Budget Progress, Monthly Comparison, Large Transactions, Weekly Spending, Category Trends, Cash Flow Forecast and Year-over-Year (shown in the gear menu when you have shared accounts). Bills, income and pension tiles are deliberately not included — they show entity data, not account aggregates

  • Clickable spending charts. Clicking a slice (or bar) on the Spending by Category dashboard tile or the Reports page pie chart jumps to the transaction list filtered to that category, scoped to the chart's date range and account. Tiles set to "top-level only" include the subcategories in the filter so the listed transactions match the clicked amount (#317)

  • Per-bill opt-out of pre-created transactions. The "Create future transaction for this bill" checkbox is now a persistent bill setting instead of a one-shot option at creation. Bills with it unticked never get a scheduled placeholder — not at creation, not after marking paid, not after skipping — and toggling it on an existing bill adds or removes the pending placeholder immediately. Previously the checkbox only affected the moment a bill was created, while every payment re-enabled pre-booking unconditionally, so unticking it never actually opted a bill out (#311)

  • Convert a transaction into a transfer. The Match transfer dialog gains a "No match? Create the other side" section: pick one of your accounts and the app creates the opposite transaction there and links the pair as a transfer. Until now the dialog could only link two existing transactions, which left no way to correctly book payments to accounts that have nothing to import — e.g. a loan tracked as its own account (#313)

Changed

  • Scheduled (future-dated) transactions now show a Scheduled badge in the main transaction list, with a tooltip explaining they are not counted until they occur. Previously only the account detail view had the badge and the main list showed scheduled rows in italics alone, which made a bill's pre-created next occurrence easy to mistake for a duplicate booking (#311)
  • The transaction list Total no longer includes scheduled transactions — they are placeholders for money that has not moved yet (#311)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
Signatures/wP/jWqAxqTStZPLKWl/5nyJk/xpeAom+Kp7KakVOdJmzhNv/Z6KM/CUUOrGem4Qj5G1OEZ2tNrPkTneCVvfFU2S5aoayMDgcRaGquqwZisM/4a0KV9Husjq8mV0RVoqco16HBH8PUY+kYsbeWRcSp2q38Zq99L04zb1x5XY1rGe5YdP4/IydUoMpyzTtsGF00Tj6OUAMvlDTnJqCcetscuXX8yo33xm0dUfLxjZD2f9hsn8UTCwNN7v1+yBhwNN4jJsfyGTN+92XV2YDhRCfVWq/3bGqphHo+nYQvbyjndJRcaAwybOquX6MH7+wpDa5wpvNw9xzc2sYNm2FM08SYep3cX7uoXngifGZu2FBqyNHQ198dqEwqJbEVv2DrK5cAnQkbSS1glYYney/uXAlsqLEinHirrShNYRoq+ZEkxUhpdung3zSWwPe0Fd/mWh2chHiTV20A2tCrv7FRuRadpf75bq+y0xuIglVZQy5E1dT2nk3lPUUwB01w/ggmwrJ91hOchPoyoRoDhoBNxZJs903bQejWR/MdZ9pbXVmwxj1EOq8oWfWeQ5B+OEz/LbcplibODsNv6IUIYU++gxK8d2XCVzBgV2ayMqsRxFDxItgluqDcu4oTW8mh3A4z33PvbeCFFMsj2bKFbOslmuT2ZiVl58oTaQRTh61xeKEA=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.37.0
Release Details
UpdatedJune 27, 2026, 11:16 p.m.
Changelog

Added

  • Exclude shared accounts from reports. When other people have shared accounts with you, the Reports page gains an "Exclude shared accounts" toggle so you can see just your own accounts' figures. The same option is available per-tile (in the gear menu) on the account-based dashboard cards — Income vs Expenses, Spending by Category, Top Spending Categories and Recent Transactions. It's off by default (shared accounts are included, as before) and only appears when you actually have shared accounts. Note: a transfer between one of your accounts and a shared account can only be partly seen when shared accounts are excluded, so income/expense totals may be slightly overstated in that case.

Fixed

  • Saving share settings failed with "Some entities do not belong to you" (HTTP 400) when the "Auto-share new" toggle was enabled for a type, or after using Select All — the auto-share toggle (which shares the same data-type as the entity checkboxes) was being collected as a phantom entity and sent as a null id. Entity selection is now scoped precisely, so share settings save correctly with auto-share on (#306)

Changed

  • The Categories page now also lists categories that have been shared with you, shown read-only with a "Shared · <owner>" badge. Previously it showed only your own categories, so anyone using a budget made up entirely of shared categories saw an empty page even though the categories worked everywhere else (#306)
  • Categories shared with you at Edit permission are now editable — rename them and change their colour straight from the Categories page (they carry a "Shared (editable) · <owner>" badge). Read-only shares stay read-only, and a category's type, parent, budget, report visibility and deletion all remain owner-only (#306)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureFqJ17XG/szTfkAMsF+oCODYGClVjdeGArgFi3SrgeGhg4CFFzIVO98XEnYhxeCnwOcYGivzy0uhe60/Vv7kgml+lIVvRL1EZOxvjOES2KksQ50fqxGZSNz3EL54EA6R3Yvo6uLFBM9cbK0mmY5H+4i3UozKhKwzRa6PJLIZzpBsjtprJXHojWsQMR5KY7WDDbb9yD32uYzMnrXMxOiQ2PZGtG7aIhLS6DzC7Mtp/oLUgyRqBWoYMUWWLLi1qyeOr4/8Tdm9H5I36oxeoX2ZQlVuprpRjDPW5EITrljbyuIPy3CdAFn5tvvt8rkurEgCtPAaMv7gSXRZto6rJJqS4woUqX310+J0re9qa53Ls0J7Kezo5WpENoaFsvT6McjVG/4k6k4YN1/l74p97fFfR+1T2kC5VptpwVz4GZ2aSF9t226Sdkft7sv72aC3oQpa4PN3PIWj113aN2X5nnCGiD+NUW282/yAdacvMWVgB+t+Rbm0FIyWtGnbw0dKAlY3CAmQoBvqX9f2vqn1OFDxJhejg/i7+FAWQD83LIk6u2kNg/N4e2+hgLtO45wd5MU6TLXXTrb1mlikbbiP80Rla1p50fScosYTCqjJfz2lh5U6D2h/nquGHHvhf4R9q7eSkykmELHZUKiUyYlrLrOfiuxGRqaWSQWp9hm0CUog1HBE=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.36.0
Release Details
UpdatedJune 27, 2026, 1:15 p.m.
Changelog

Added

  • Auto-share new entities. Each person you share with now has an "Auto-share new" toggle per entity type (accounts, categories, bills, recurring income, savings goals) in their sharing settings. Turn it on and anything you create from then on is shared with them automatically, at the permission you choose — no more sharing each new bill or category by hand (#306)

Fixed

  • Code-integrity "Some files have not passed the integrity check" errors reporting FILE_MISSING for js/.htaccess and vendor/tecnickcom/tcpdf/tools/.htaccess. The app no longer ships any .htaccess files — the Nextcloud App Store strips them from the published archive, which left the signature expecting files that were no longer present. Neither file was needed (the JS one only set a redundant cache header) (#307)
  • Deprecation warning in the Nextcloud log — the notifier now throws UnknownNotificationException instead of InvalidArgumentException for unrecognised notifications, as required by Nextcloud 30+ (#308)
  • Reports and the dashboard summary were empty when a single account flagged "Exclude from reports" was the only account selected. Accounts flagged out of reports are now only dropped from the all-accounts views; explicitly selecting one shows its data as normal (#309)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureYxqf1NnAucAiXFVdwVmQJPaPUyuExQ8t/dwv4tDVpFb1kXDtGcIWoAdspiDz+HwdyPe+ul+/2GcDWiLPTF3TvIHwIaV+h+guDRYBEHMY95+Hy5W0BSuwBC7gto5dfsZEhL5xj5OsRIYrY/Fo8Tqj99kVzDK560o9NgI6Bp6ZkQpbwPRbTnbxUX27oF0oDjrg1ArS4IiE4ghZW1ct74Mlv4uoeg5zaVQlucrZK+rBJXixtpDnImHLPMkTvd+1bmkQTFtvArS1A37YkXkLKrKn4pzWvwv/q46ddih1NXBC7o6UoBwP1pWB1OxgNq3/98OdWyPs4GLumMmRdg+7PbY95Go97lBbNc/1mrBB9qQPXirFxYHMZWVDSRHSNRJ9cSMnZA/YzsVeOZOVkIwJWXhC5YGAEN8nq8HKIMBHzmi6UYdGM2VvGPmNZ+K3wlGMIkKlVfWfIJ7XIOCe6OLvQbwR/ATZ7pUyOE+AR21uu27zWGJ4iB4y/eCfCSE8vIxyPW7L0dwkzxU13iNNNxAUQgbNrs8EiQBLQlTCaBWCWp296Dds5nEGMEilQKX9vEXAhY9KRG5dzJjoZhZ14tWA3Hjp+5/Gs2AM4Bh3Rp1OGdhfQhFDmt/2GXcL16lfDcX28K1ub4FPYE8MEz6qDmLhqqwv9FeXQQbT/ZKdQn8NwuOlGFE=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.35.1
Release Details
UpdatedJune 25, 2026, 3:28 p.m.
Changelog

Fixed

  • Categories marked "Exclude from reports" are now consistently excluded everywhere, including the Income vs Expenses trend, Category Trends, Top Spending Categories and the monthly spending chart — not just the dashboard summary. Exclusion is now applied in the database query itself, so reports and dashboard insight tiles can no longer disagree about which categories count (#219)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignaturebX/9kwpiVjwDj0f2eU5xNE7zUpt8T/nkGCFg9HnDQoKynM7c1KaXhbh4isVQBbgy5kPGXSDP7DRfuSTYY5/M3PSv1JE8gOk/9lz2AGmTqlXrf4Kgq9oARAGcVHXB955dLvDkj6Vrk7zZ9cwrjq4aMBu02dW8ZgyAHStXybiWmkAbIxK768MHM4n5FXTRFw3P/ELVlDjCxgIpxVxD5EZaaA+n7RrjN9MRY2R8/GN7Og7yijcmnutMWtna4K19B9c3ShcfUkrwotvCUz3c+K10VQSfzUpN6RoindDB0j716jUZQ6IKzXBNNRiOjQ6N6s1MlmKwjyFyw0PY509hJY+dtjBEQBbFjK0pw7ZElfW4zDWteDzWRm7M1VjzUlRgPLsg7CJ980Rg8suZAMh3UH251vymCH0ykpMYqK1qiWDurz5GWdaDov6Z0YkQPQLnszzPa60kbO9VUHrYnG+6+KA6GoPW0EHFEqaUxXv+mRLr8Pm8BhjCiDghO7mlHZFN95hN5gkNyBdIPA9JmXAdnkrJBSQaDvZdejDwFJL+T+PgA2f9JomB8BQ/WkZ4uukyKUUFYToOhntQTe7dfE+I4VsD6BycbY7smaY/xGx6EvyXfntpYkgR7Fe2rYKaxBrcRcnhTmQBeLLz85M7fLKVjME72niQdRIZRaMZ+OmpCxKK2qU=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.35.0
Release Details
UpdatedJune 25, 2026, 12:36 a.m.
Changelog

Added

  • Pensions revamp. You can now record a contribution as a transfer from a bank account — the matching withdrawal is created automatically and kept out of your spending — and record withdrawals/drawdown back into an account (#304). Scheduled (recurring) contributions (monthly/quarterly/yearly) can post automatically or on demand (#251). DC pensions gained a configurable projection target with a progress indicator and a "today's money" (inflation-adjusted) view on the growth chart, plus an optional Pension Projection dashboard card. Bank legs that fund a pension show a Pension badge in the transaction list.

Fixed

  • Background-job "class does not exist" log spam that could appear after updating PHP/Nextcloud/the app: the app's autoloader is no longer "authoritative", so it falls back to PSR-4 and self-heals if PHP's cached class map is stale after an update (#305)
  • Newly-added dashboard widgets now load their data immediately instead of staying empty until the page is refreshed.
  • The pension detail panel's balance history and activity are no longer broken — those views called endpoints that didn't exist; they now show a proper balance chart and a merged timeline of contributions, withdrawals and balance updates, each removable (#251)
  • Editing a split transaction with three or more parts no longer zeroes or overwrites the other splits. The last split row is now a read-only "remaining" amount (transaction total minus the other parts), and the dialog blocks saving until the parts add up (#303)
  • Spending-anomaly notifications no longer crash with "The arguments array must contain 1 items, 0 given" — a stray % in the notification text made Nextcloud's translation layer fail, spamming the log every time notifications were rendered (#305)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureF/7pZ4sNzjJuqXXZoHmO+9OmUzkQz6ZDke3vkONfZ2uGfzBpwpDSIiGlfNv6gt40Ho8NTPNd0JuM+ESRohLlPAAftFoF+L4h+asH5s/lncoxgTZevEFl7NE14s+sPVdGdZqXGi0b3mohB+f1jOudpVbgB0bmCDvnZMEKiMSjB7XwH9iQqzu/8WyQNd28w+Bz2TbyAfu2PCtdD6jsmVCbvtCkmEdKOVJzRWuExH+vwvZ0ltX3mtorPl6HEzqKJWoDYG3tdbpSwml6w9F3qj8naVZ3tZYBrfvwABHoMD1LYpYwRss5C9UpJvu6UFfKQ4Xso1tBu5U+tYlAPKLbQ5J70o0C1aP66R+FvL8RlMHpY93duR32qZkT/6xV0NYQpd9xzXoLbB5YkZJuBLV8m3oP9k/pNEy8vwF5Kkb+/6zrJt4aSH/iiAqBoqvuT1itwScYsNpGHXWOrGHioCKiGkcMvamfr7her1fQ42wNiVIVWKaxNtjeYrVjmHCtWA2awjv3XRfcXdcL/4stuDpXxQ0Dnv2S/Ey9ZbGbqpc0DNyPZfKie5/QK5OnHPW9F8nHUsEhxDLbNezo11fKm1ykE0ja4nTZFKL3ml2D4aRDMYQe35MWJvW/fLcNW7dYOV969ZI52G8jTIUI/YphcNfCNK24fVkljrcBSybr8WavbELxVR0=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.34.0
Release Details
UpdatedJune 24, 2026, 12:34 p.m.
Changelog

Added

  • The transaction list filters now include a Reconciled filter (All / Reconciled / Not reconciled), so you can quickly see which transactions still need reconciling (#301)
  • A Budget alert threshold setting controls when a category appears on the Budget Alerts tile (default 80% of budget). Set it to 100% to be alerted only when a category actually goes over budget, rather than when it's merely approaching or fully used (#293)

Fixed

  • Creating a category (or account) no longer fails with "Unknown column 'excluded_from_reports'" on instances where an earlier upgrade was interrupted or restored from a mid-upgrade backup. A self-healing migration re-adds the affected columns automatically on update (#302)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
Signaturey+Qi2+U6CexZu8i+0DGrbLXwFbp+cHLVW62WRSfrovEAuJrnZy8paqAacEaE570GoHVd1b23Yihz4oDfOYStLASDVFk7xhVrarnlIqv4EH+Jyw0IR2iaLR+IvhJmSZc9N5nQ42i2z8UYetvQo0znzzNPmpT2FEJB1Sty9kCfHL7HiisG4hYwJp528McMVXgCYfn/XOZUQzOVY6rvis1hP8CiFbE4UMUQj/SgDpRjimcRCZy8fsRLgZHcfO2+BKYCSt5lqLDJSzsmewBFNMVWDdtZwPUxqyK8xaTwSnwWNBNXBRg5ZcDLJhhIJtk9cEezVTdJBZTw3wx7iCztR9RFQi9CZsRz9U9S4jLEdcV8m6OTa8XG22s2ZHt+I+hisGtlC1TOQ5fpPfSe9onWdA8jgC68RAFeOLJ+KmSkLQN1bbr9gUw47oB09Yd9sEtUDcFapfv+x9Zl3/s4ExwO6xDS/bwmRyZ/fq1z2jhVu/lMFd//+9ciOrCdty1p7440JVs/sx71Qcc0mRhZsMtIRYyBD2EFceUHx8cQCtOLL99+JtGkTakCMCwIxghuGoXnrq+9mRWjgROn1ysGEHDUyC8ZKCJ5f8TXOllqX2g+2fyOpFzHR66oP7lPwI5y3eW4VYJGT/lQzTavAtU148X2XaBUz+XA8Djuco3CCuGJuT9FhSU=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.33.1
Release Details
UpdatedJune 18, 2026, 3:03 p.m.
Changelog

Fixed

  • On some installs an earlier update was recorded as applied but didn't fully run (an interrupted upgrade, or a database restored from a backup taken mid-upgrade), leaving the excluded_from_forecast column missing — so every new transaction failed with "Unknown column 'excluded_from_forecast'". A migration now re-adds the column automatically on update. (Also surfaced by the new database-error detail field added in 2.32.0.) (#289)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignaturewGNDwrdOGHhLxiEiJQDsZrcL4BFQbGBTjeDU/3VJql8bIeDBHITKzJ3HH47kV1bFmsZ35q0o7xh/r4q6Kj9/SXM8gQCTxEtQ0q80MS85LGy5+9dUtJ0yBvrLfE6kwpNPDH+kqwBVcAGxmLr9vYau5uTFGdeB0WZ3gmesUvT5kuZfdREwJDQ19QWR40pJjHRcWqM5KnXCT1/wq7btWj9s/Vf9GVQvo85g9R7adODG1PVBr4gM6R9nTgsrn+60BJvNNO5f3W3wbuzvqaJhtVdknB9Z8fc7Vbq6mh6TgSPBmXgiK2VdCAWPaW2EmpVL8iwgOGazPGSajPkMZNNZDhzDNEpLcveJl61g/x5dVAxOevwFnN4CaX5c/YYppjcqtoWyYgoTNMv3enF3///tD0wS68iQzcU5UNmsOOKsAUVvRnf/oOX2b13NfsKPONAxcu4Q/UG8ybPqYwXT+T6Vs+IRmoLJLnOs/BUgbqmmRIG1Wfs2BusDFKNHHWoW1Z5t+GDLGx2cyNci7+rKPRh2seML8iPrt9lNv2M5NjzIJ9Wm0Xt0FKpIetR4gDpLSRvBtINaQ0jVuYVixt1yDKMUfE6GH4sNW9rNi2ZoKptz2MIxouBmLNXezA5Y0gvIlgA11Bi0YBrKPUAtmxNl8Jyxhle2Ll5bZbsupMy1otRB/+NGEOs=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.33.0
Release Details
UpdatedJune 18, 2026, 12:52 a.m.
Changelog

Added

  • Run reports on multiple accounts at once: the report Account filter is now a checklist — pick any set of accounts (e.g. all your credit cards, or all your checking accounts) or "All Accounts". Applies across the summary, spending, income, cash-flow, category-by-month and year-over-year reports and their CSV/PDF exports (#299)
  • Saved reports: save a report's settings (type, period, selected accounts, tags and options) under a name and re-run it later from the "Saved Reports" picker in the Reports view. The period is stored as the chosen preset (e.g. "Last 3 months") so a saved report always shows up-to-date data (#299)
  • Dashboard tiles that can be scoped to a specific account (Spending by Category, Income vs Expenses, Net Worth History, Recent Transactions, and the other account-aware widgets) now show a small label in their header naming the account they're analyzing — the account you picked in the tile's settings, or "All accounts" (#296)

Fixed

  • The Reports period selector didn't drive the report on reopen: the dropdown kept your last choice (e.g. "Last Year") but the report always reverted to "Last 3 Months", and clicking "Generate Report" used the reverted range instead of the shown period — you had to switch the dropdown away and back. The report now always matches the period shown in the selector (custom ranges are preserved) (#300)
  • The Quick Add Transaction dashboard widget couldn't be used on mobile — the lower fields and the "Add Transaction" button were clipped off the bottom of the tile, so a transaction could never be submitted. Its form is now condensed (each label sits beside its field with tighter spacing) so the whole form fits the tile, and it falls back to scrolling within the tile if it's resized very small (#298)
  • Editing a split transaction's amount (e.g. inline in the transaction list) left its splits at the old amounts, so they no longer summed to the transaction total. The splits are now rescaled proportionally to the new amount (the last split absorbs any rounding remainder)
  • In the edit-transaction dialog, changing one split amount now adjusts another split so the parts keep summing to the transaction total, instead of silently drifting out of balance
  • Split transactions weren't counted toward category budgets or spending. When a single transaction was split across categories (e.g. one $1,000 payment split into rent, parking and a deposit), each of those categories showed $0 spent. Split allocations now count toward category spending everywhere it's shown — the Budget view, the Spending by Category chart, and reports (#297)
  • Large amounts (e.g. values over 100,000) on the dashboard hero tiles (Net Worth, Income/Expenses This Month, Net Savings, Cash Flow) wrapped onto a second line, splitting the number mid-digits. The amount now stays on one line and its font scales down to fit narrow tiles instead of wrapping (#295)
  • The "Asset Value History" dashboard tile (and "Net Worth History") showed its empty-state message anchored near the bottom of the tile instead of vertically centered. When there's no data the message now fills and centers within the chart area (#294)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
Signaturejj+nUiPNSYYgtQ/7XYIkJNFo8vWIHaX28Q0XTtpN6RWmrW8qrJBIs2jTaaHwebC7SB5f7GP6vQxghh9+nCWfA+KlTKbm8YJg6yzah9xdTLo/JcUhTOinlH9yYoXxMiIY9EVwQLsPmef4sprTsS9oqBeSgZ7S8WRJYnxjAuljee9q0Sfai9AK+RQzBk6kgENhCAVt95ooZ3H5ukfFBSb/kyXa3IU+ngu6g5B9DgiJfBduecdkLEfc0dhYKelUyNaZa61qoG865podTGJFCFqzoSnlCXgRcJqJHjhdTERIeu/nHQAL/PhaPy0OSWK8l+kyrGveMEKDM6LvQ0Eo6B9Ul0ORobundabEat67f/hqaTmnDldOkkEm5a0WAYeQvYeeZCNLtiF26pWk66v6eQhXsrT6IwcJ/gxaC6oS8URm5yYub2iW9nVq6uZXRMJavJr8CmYl7MSqQRVvFKGlwHvD7X+YfEs+htKGYM017iWdICfQv/wbGi5JzIxqdm7QKrV9EGxgl4GFWvY/cyGZt4awfhoy4RljlFtsfJ02askgVFUloVGKOWeqZ5NbqXMDC+UonPONQ/RPM64u0L3NdVvmcXOwA8RBHCg1qgEiVkDBSsJyhK55+1J7Yn5fIC2emSU0BXOdzSFgg3BgUbYJQHgH30AwNf1iagO/WBOYDSu4jqs=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.32.0
Release Details
UpdatedJune 17, 2026, 3:02 p.m.
Changelog

Added

  • Category by Month report: a new report (Reports → Category by Month) showing income and expenses per category broken down by month, with a column per month and an overall total. Categories are listed alphabetically with sub-categories grouped under their parents, and parent rows include the totals of their sub-categories; a toggle switches to sorting by total instead. Defaults to year-to-date, follows the report date-range and account filters, and exports to CSV and PDF (#288)

Changed

  • API errors caused by the database now include the underlying driver message (e.g. a missing column) in a separate detail field of the error response, visible in the browser's network tab. The user-facing message is unchanged; this makes problems diagnosable on managed Nextcloud instances where admins can't read the server log. The executed SQL and any bound values are stripped from the detail (#289)

Fixed

  • The dashboard "Budget Alerts" tile showed a red "exceeded" alert (with "0% over") for a category whose spending exactly equalled its budget. Spending that fully uses the budget without going over is now treated as a "100% used" warning, not an over-budget alert; only spending that actually exceeds the budget shows as exceeded (#293)
  • PDF reports rendered non-Latin characters (Polish, Cyrillic, etc.) in account/category names as "?". The PDF exports used a built-in font limited to Western European characters; they now use an embedded Unicode font (DejaVu Sans), so names display correctly. Applies to the budget report, bills-calendar and year-over-year PDFs (#292)
  • Marking a recurring transfer as paid showed a success message but created no account entries. The Transfers screen was only updating the transfer's "last paid" date instead of calling the mark-paid action, so no transactions were recorded; it now creates the paired transfer transactions like the Bills screen does (#291)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureNKgPUY81JziKewMWFs4QeLNIwZ8JqGBZ6wvFlsItL4R47yoDLAn4+I1T/pwgEOi7KR2lCUFBckiAdI78FONIy+JyCFhY0w4WcGEltsQdsytRMQYAggOWw+OlYvlDMPI6zoMoRfVcIvC3d+4pUrP91cJIVwi+bu5OIYO0C7ErDFCyvMlHK+ifsGvBluQJ377z8wnBUQIWSfudOuXewIyBHCF1QXsRXsVe0CIGWPNnT3ibuwxjm92a4vzwqdTEYy2qQwzPgYWPhgZofSdEN6j08iuwUzM0i9yXWd0IVpRNLb8RIo9lTzhJsjolrNFGZd0iiQk5A/4NQ6VOLKItVhwXJKOZk7KzyYTZmEki+PaeHKSEjEzwYNqv2tL4VPrBjyq5Y3bRTnYS3uBBCOnkWwn6ozQ4PitvSgPpcqciCtrP1hYAa0oQ7FsP8+BVsepO8gn8+lIcVjx7mW+YvufESAyFRXgAy61QBNjcd34vtoEfLqhdP4f37gZ/jdmCicDQ3sLw/eUIL98BylXmNvOge43vnYuRgGl9gBO11ENaP3EhqhqsrVr5Gyu07MGlMhCRlBn21fRN5sMORHFNx6pL/DcpwC0xtpfWEtHTCcEcLvArqfSiQSMrJaDvqftcQNMWYt4hGZKMVR7SYZsAragHUiMfvWDu1mW7HLNsW8PwySZDrHA=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.31.0
Release Details
UpdatedJune 14, 2026, 7:05 p.m.
Changelog

Added

  • Exclude an account from totals: a per-account "Exclude from reports, dashboard & forecast" option (in the account's edit dialog) keeps the account fully tracked but leaves its transactions and balance out of every "all accounts" aggregation — reports, the dashboard, forecast, net worth, total balance and category budgets. The account still appears in your accounts list (with an "Excluded" badge) and on its own detail page, and selecting it explicitly in a report still works (#286)

Fixed

  • The account detail page's overview tiles only counted the transactions on the visible page (e.g. "50" for an account with 1,603). "Total Transactions", "This Month Income", "This Month Expenses" and "Avg. Transaction" are now aggregated server-side over the whole account, so they're correct regardless of paging (#285)
  • The dashboard spending chart's "Total Spending" figure (and each category's percentage) only summed the top 10 categories shown in the chart. It now reflects spending across all categories
  • The CSV import preview's "Auto-categorized" count was estimated from a 50-row sample and could be wrong for larger imports; it's now counted over the full file on the server
  • Editing an existing bill failed with "Failed to update bill" — saving the edit dialog (whether or not anything changed) returned a 400 error. The bill's start-date column, added with the limited-term bills feature, was missing from the list of updatable columns, so the always-sent start date was rejected before the save could run. Bills now save correctly, with a test guarding every persisted column (#284)
  • Opening an account's detail page returned a 500 error (the reconciliation-history request failed). The reconciliation controller was missing a trait it relied on, so it couldn't be constructed and every reconciliation endpoint failed; the account page surfaced it via the history sidebar. Now fixed and covered by tests (#283)
  • Starting an account reconciliation failed with a confusing "The string did not match the expected pattern" message (most visibly on Safari). The root cause was the reconciliation controller failing to construct (the #283 fix above resolves it); on top of that, the reconciliation screens now read error responses defensively, so any failure shows a clear message with the HTTP status instead of an opaque JSON-parsing error (#287)
  • The Budget Overview dashboard widget (and the digest, spending-anomaly and bill-reminder notifications) always showed amounts in US dollars regardless of your configured currency. The server-side amount formatter was reading the wrong settings key and falling back to USD; it now uses your default currency
  • The Budget Overview dashboard widget's "Total balance" now converts multi-currency accounts to your base currency instead of summing different currencies under one symbol (currencies without an exchange rate are excluded from the total and named)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureCseRrf2b0tfseaK8cBqqPjA8lhMT1C+aq6xVuP6vO3E6sRzawwkPNHdfK7CDaOro2TYW+agvm4g873WzOGVLIVa3FHEyFlnGRkFSwMz334bq1/Rcbw2WXdMbNUliZwdK76DNCauZ0JPz8FYIXr5cqkqbw80oHD/SWhWD5dTKRKJ2gpSvbNtXJfq32Sn04UVxrJq4StY11b5rJfCXR7P7RQxmFboIYJvhoVIfcebR+vighFLC9adkKVaF/xJ8tm1MVG6oJHJ4zKU87SV3+D8vB1xpxeWo2xRwseYSwg8Nk3ik6iXkcf4cHTACrCGyHhOXgCmltGkJ441alZ8kzOQCDe6Vw3Rx+zzgducfZGOQJPuIYcrpyZAAgN51xtDQJTWJNoT9jBrUmEv0r/ftZWj8QYnesnl8HgXUQPdLCsCaloLpISXkt7KzlHYlt4PgdMphbDBnuMROrXZtTeIwDCzwGAkatsK+l8HnM+FbMlpfszT7Ki1z2HYX/d+74aLRxkNUClx3fsQsxOtd0RxK9+/JPHW+W5Sv5kWbRSfiUrslL+pT7R15L9x4t3nFK8VUUEZSDcNynhSHxCVqrqOsV3mZ12eutyvQEPpN56qyLkaZmcoxOlOD2v4BKba8pBAL6YW05jx8hBWg9m0zAg4h3/qoA6zLDRrVfHi+LvUiiE1YDWs=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.30.2
Release Details
UpdatedJune 13, 2026, 6:03 p.m.
Changelog

Fixed

  • Dropdowns in the transaction list (the column-configuration gear menu and the in-cell category/tag/account editors) were cut off when the table had only a few rows, because the table area was shorter than the dropdowns. The transaction table now fills the available height, so every dropdown has room to open in full (#280)
  • The Tags column couldn't be shown/hidden — the Show/Hide Columns menu was missing a Tags entry, and the column wasn't wired into the visibility logic. Tags can now be toggled like the other columns (#281)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureRXpaKwi4ViRdeYM6mjC3JtrlDOFrm03LMBFc2gQMktdYfBEoyMrW3YBp+DPKezxnLOmETNnqjXAI+oswcQLQMkRbAcjuD1dpBBZi7x8kmvtc0lZUcrKRw2QKUzDD5luZaN7JE14o393XlPFxdqkaUbJvWTltA5xK/XO2H72GyvEO7/7de7HCcP2G4XTK5kGSeP3PHRNQ5MjiB49QlM7D95p7Od374Fbr0k52h0sWFHSA14LgJSyPXCgHxxJMqVy7O76LlS1Iedg8B4TFBbTJZVol/8emaHjBHvEwVVzSIIkr9wdtZ60aqrEhJfTqaRwdGS0ks53VE2ROoE829Jnc3Xkz4Xxc0WEqH5a4vxbUWnA8NbuaFNAsUcfXW+0TDTUeLT34IV8c6GZkwn0z4a1parjkif0yyEolfPhNomKX/JMl74aSG5i2BkKyDH3OXMg9oC0/czhOIxluUuFCwWJyd6cBOGd6r/R382SMMe+mCHDpuBxIY12gRo4bzcAfmYMQ3e6rrtgpFwxBllUaK8lC+yPy9x9502QHhZem922Tz7HokfuXuFxh1x9Z6doBSvoZOe2H2PIKRupmFf4I9epoRYdDQZjatpZpN3+oZnz6DmY7f9+g3gaZ7Dl9dkPydm96203Pox5SGz9vhOQaXeOIw+l+rLnXnbodzB3eyqz11Ig=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.28.3
Release Details
UpdatedJune 12, 2026, 1:14 a.m.
Changelog

Security

  • The recurring-income update endpoint no longer passes the raw request body through to the entity layer — a crafted payload could previously set internal fields such as the owning user (mass assignment, integrity only — no data disclosure). Update keys are now allowlisted like the other endpoints

Fixed

  • Auto-derived recurring budgets (#269) are now consistent across all surfaces: the dashboard "Budget Remaining" hero, Budget Progress/Breakdown widgets, Budget Health score, and budget alerts now apply the same recurring fallback as the Budget view — a category funded only by recurring bills can now trigger alerts and is counted in headline totals
  • Auto-derived budgets now respect bill start/end dates: a bill that hasn't started (or has ended) no longer counts toward today's budget, avoiding double-counting during a planned cost change (#268)
  • Recurring income summaries (Income view header, dashboard Income Tracking widget): semi-monthly income was counted at half its value, and a one-time income at full value every month until received
  • Transfers page monthly total: semi-monthly and semi-annual transfers were converted incorrectly
  • Live forecast cache: cache invalidation never matched the stored key (changes such as toggling "exclude from forecast" appeared to do nothing for up to 5 minutes), and the cache key ignored shared-account visibility, letting a share-restricted viewer briefly see the owner's totals
  • Editing a bill's amount without updating its split template is now rejected when the stored splits no longer match (the payment would have silently imported unsplit and uncategorized); setting a split template via the API now clears the bill-level category, matching creation
  • Multi-account import partial failures (e.g. a deleted destination account) are now reported in the UI instead of masquerading as a full success
  • Import preview now also flags repeated bank transaction IDs for accounts that will be created by the import
  • Long OFX FITID hashing threshold raised so every previously-imported FITID keeps its exact ID (re-import dedup continuity)
  • Auto-derived category budgets (#269) now handle every supported frequency correctly: semi-annual bills were over-counted 6×, semi-monthly halved, custom-schedule bills counted every month, and one-time bills inflated the budget monthly until marked paid (now excluded). Frequency math is delegated to the shared calculator, which also gained the missing semi-monthly conversion
  • Auto-derived budgets no longer apply to past months — they reflect today's recurring bills/income and were rewriting history (including overriding explicitly-zeroed snapshot budgets)
  • Multi-account import: an invalid destination account mid-import no longer aborts the batch, and deferred balance recomputes now always run for already-imported rows
  • Bank sync: the post-import balance recompute now keys on transaction creation, not the import counter, so a row persisted just before a non-fatal error still gets its balance update
  • The scheduled-transactions background job now recomputes balances from the ledger (it was the last remaining hand-computed balance delta, and could race concurrent imports)
  • Import preview now flags a repeated bank transaction ID (OFX FITID) within one file as the duplicate it is, matching what import actually does; per-account preview counts include rows that will import with skip-duplicates off
  • Marking a bill paid by linking an existing transaction now warns if the link silently failed (no money movement recorded)
  • Extremely long OFX FITIDs are hashed to stay within the import-ID column
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
Signaturefa7u8mWcwya82OCYZOh+XZFPRJH94oqiBM5WUtEtvU3Dh6Lq+pMs8A7e2aCOa0Y6AbwWH7TF6ZRtwanfSh2PjQMwAaDFlR5anBdAvr89L/fn3eK0uSrZetqNGmAT7Itlc0mT5KowbTvtWDRdK46oR4jjqgXKay6JeO7caGbAcKmyfhJARbfTXsb5etz/yhMX72X33ayUYtCo8nQrtxLTGO5AAPIcFbq1pa3W3d1SHuQ7Ibksv3WXrZe79ngT4pQpGp6xtz3ervqo86vrI8qH8DDg6g9IJE8D1iseOiVzRv/KI/N06LnY0OvUHNZwGrJph5Jh3BrYg2/5rSYzEP5VzaGyZm+AS0DO1bXf9BC5OqbRl3s/FsM+4UgowriYD0S2Zwc4/2j/W3mDRjOdGf0MJxd8SOxv7uW2P5JL0TImjA7mTgppSipw1ShGTl8BU7q11cCtFmuCmwGfvPlRLQtMqEdr93gNkY84rAja08K9Ro1/ySZtrEWVRh/lYzQqmpazsjlw1V4x+KYtn65LHr9Zxd46ToleV5kv1tEZJ1u7nFXeNnrfThyz78EqvLbVxzcqphrfrImGOD9/VhUwryM58KtVz7+tXmLjn3SsSmM8sz9DEljbEKK4zTV9mQgIxviGwzNuIGEFD+HaW6HRIsAzRNtXow5oT7Kgpqa3BnJ3HxM=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.28.2
Release Details
UpdatedJune 11, 2026, 6:33 p.m.
Changelog

Fixed

  • Dashboard could render half-empty (hero tiles only, widget grid invisible): a Chart.js resize on a hidden tile's detached canvas threw during initialization, and the widget grid was never revealed. Chart resizing now skips detached canvases and the grid is revealed before the resize pass. Likely also behind "nothing happens" reports after certain actions (#273)
  • Dashboard tiles with a saved account selection pointing at a deleted account (e.g. after factory reset + import re-numbered accounts) no longer error with 404s and stay empty — stale selections fall back to all accounts
  • Account balances are now derived from the ledger instead of running deltas — the root cause behind every historical balance-discrepancy report (#3, #89, #124, #163, #187, #194, #274). The stored balance was a running total that each transaction code path adjusted by hand; any missed or mis-signed delta corrupted it permanently. Every transaction create/update/delete (and retroactive rule run, repair action, import and bank sync) now recomputes balance = opening balance + net of non-scheduled transactions, making drift impossible and self-healing past inconsistencies on the next write. A one-time migration backfills the opening balance so displayed balances do not change on upgrade (#274)
  • Marking a bill as paid now warns loudly when no transaction was recorded (bill without an account, or transaction creation failed) — previously the bill was advanced silently and the account balance never reflected the payment, drifting from the real bank balance every cycle (#89, #274)
  • The app's own export→import now preserves transaction status (scheduled transactions no longer silently become balance-affecting after a migration) and restores the opening-balance invariant for imported accounts
  • "Skip Duplicate Transactions" off is now honored: previously rows whose import ID already existed were still rejected deeper in the stack (duplicate-ID guard + unique index), so parts of the batch silently failed to import. Intentional duplicates now get a uniquified import ID and the entire batch imports (#275)
  • Import duplicate detection no longer gives false positives for legitimately identical rows — e.g. two same-priced purchases on the same day with the same description. Identical rows within one file now import as distinct transactions (occurrence-aware import IDs), while re-importing the same statement still skips everything it already imported. Re-importing an older statement also recovers transactions the previous logic wrongly skipped (#276)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
Signaturekx2VkgWxozCE2LPp/nzgQQiqFxk/83sOdycv738Ly/uEwn/MhxF/kNtBlP4DMQbhmtkcHdt+kDIlQK1S5q1WHJWZQxjLc/ZCkj/ZEPkNBrDhHwdQCRh4TsRVJyfrIxXUTOCAKJLYk+0DXlnJB3kMhR81adns3wWNH9RkC4b62k3gXtzMR4n+jz/QJDGEAOXRpDUzxEm2TKqFot6sGRt3u0+rVo0bng6nogDJha0APeFI5Ujt+3mECw9MlxNt9nKbQlIGjAnraLVUFz0bXNLK7dbBS3PSzjLsUxhoNhAqMivfHEfLViOvIlCFNHzoWGxFnHK0flI2zJXUlOnaidOEyfhZWbqNpHZL4RZLIZWYQaztJgATNsK+L5aO0Md+Np1hgE8jkdY90gugiV06JqoPEWqCo/qSyaO9N3xYpeXrwfiL37JJqkigwg69RZN3OD1DfBT8ue7QlhT93dfg+39ERzbVY9QBu0gT+bwIs8tyE1MVXOaSjHKUkHab5dpGU3NQhvu/E1CO1BWA3dYvUUqvrvXKB96gm7IqNQEAkRi4JJHDPGtgzjERM+k8z/JA2xeJmPp7V3TZ/1WiKOoKMPz88soCJBMuj/LWnSpekLAGo4RJDy1JBlOm835e3ieJFVHwIwqG9YP7oRB/puFvYV6aaEXCnSkUcZV+z+2NXmHB8KM=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.28.1
Release Details
UpdatedJune 8, 2026, 12:13 p.m.
Changelog

Fixed

  • Install/upgrade aborted on Nextcloud 32 and earlier with "Primary index name on oc_budget_import_templates is too long". The budget_import_templates migration created its primary key without an explicit name, so Nextcloud derived a default name and hit the Oracle-compatibility identifier limit (the unprefixed table name is exactly 23 characters). The primary key now has an explicit short name. Thanks to @TheUnderdev for the report and fix (#272)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureXdUz/Pc10uA7L3R+vTa/cI52W9X8nDyH33zElCWeS/xWeYgonfr0GwLhn4ywE7rtUQF8e1Y8GhETbSd60otnPduP+4rXp7+5+b+iMTa3qfYi6gAd3Y1YJJrZqK0yx2Fdqld/nhQLfFpVkUSQl/JQ78RZanEh779Af5RejNl7lolRlJYg7ZNrLrFasWrpyrLNsg4+Tf74/vMpKWDXf0FEIqjnXZ0LKJm7Yjig4uazy+a5vDcDOrfq6fLU56d9ML/jBJK+9A2loT3I5HP7H2cngdLpwk6+MNLiYQDsdNzLGJJK9TK4hn0Cj+AV80mAQ45beagh4H0SmEoDTPvR/hC7LLlU5rtioE1Rg1tCvlZfHBuPcH9LZMq11Q3HVbZnvzkTdG3lKQlKeFhP86QOIjiAg1Frm0yuOt4nMSdG36N+k1C5szF7HrCoH+u1XgdY6fKI6WW71RkqXJ2IhwOorxcijLVQc2l3wyDLqoQrHtJA2yWGsI9NXlq+d5ZLJ03T7xvcLBPgSDTz91KqBABqJYRdCGhzAuQPe9M814mDu5XgdoCJNUKNrAl6YGvLvJXyj5j8I09qImqsQx09AmEBxi8YTZDbxuO8U/g3yKO14aBgGu3Z+v8+h6xyqJyNsPEbHHxpjfSbwAF/9FlvjA64nOTqPam3fPOjZAdqne5bgf05gFY=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath
Budget 2.28.0
Release Details
UpdatedJune 7, 2026, 9:59 p.m.
Changelog

Added

  • Shared savings goals — share a savings goal with another Nextcloud user. Recipients see a "Shared" badge and can view progress; with write permission they can edit the goal and add money, while only the owner can delete it (#255)
  • Auto-derived budgets from recurring items — a (sub-)category with no manually-set budget now shows its committed recurring total (active recurring bills + recurring income, normalized to the budget period) as an automatic budget limit, marked "auto". Typing a value always overrides it (#269)
  • Exclude extraordinary/one-time items from the forecast — a per-transaction "exclude from forecast" flag (with a "No forecast" list badge), the same flag on recurring bills/income (propagated to generated transactions), and a matching import-rule action. Flagged amounts still affect your balance but are kept out of the projection averages (#270)
  • Reusable CSV import templates — save column mappings and import options and reapply them to future imports (#247)
  • OFX/QIF import account routing — route multi-account OFX/QIF files to the right Budget accounts, remembered across subsequent imports
  • Bank sync: pending transactions — option to import not-yet-posted (pending) transactions, automatically reconciled when they clear (#257)
  • Bill start dates — a bill only occurs on or after its start date, making it easy to change a recurring cost mid-year by ending one bill and starting another (#268)
  • "Shared with me" expenses view — recipients can now see expenses that have been shared with them (#248)
  • Dashboard period indicator — chart tiles now show a read-only indicator of the period they cover (#250)

Fixed

  • Dashboard now collapses to a single full-width column on phones, independent of your configured desktop column count (#249)
  • "Excluded from reports" categories no longer appear in the Budget view (#266, #267)
  • Category spending chart shows income as positive with the correct label (#265)
  • Tag-linked savings goals now sum net realized contributions (credits minus debits, excluding scheduled) (#264)
  • Recurring income description is now persisted on create (#263)
  • Transfers are now excluded from dashboard income/expense totals (#262)
  • Account Breakdown report now uses each account's own currency instead of a single assumed one (#256)
  • Fixed a PageController crash (TypeError) on unauthenticated requests (#259)
  • Quick Add date field normalization on iOS (#235)

Docs

  • Documented the standalone Quick Add page and the iOS home-screen workaround
  • Noted that GoCardless no longer accepts new bank-sync sign-ups; EU/UK self-hosters without an existing account are pointed to manual import (#271)
Licenses GNU Affero General Public License v3.0 or later
Certificate-----BEGIN CERTIFICATE-----
MIIEATCCAukCAhNXMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNVBAYTAkRFMRswGQYD
VQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxFzAVBgNVBAoMDk5leHRjbG91ZCBHbWJI
MTYwNAYDVQQDDC1OZXh0Y2xvdWQgQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBB
dXRob3JpdHkwHhcNMjYwNjAzMTA1MDE5WhcNMzYwOTA4MTA1MDE5WjARMQ8wDQYD
VQQDDAZidWRnZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDNKchk
gsYxcNMufIP/m82JAeIA/fFibi4mGwKEkXwWLXDDAMiwaHmrpkCcC7BYNw0iOk/K
/xYMlEw738UrhQtu5PHAi/fecIAwh7H/ij7jGcwROe7cOcwK0sdmT76po8Ry4Of0
1wE8f+/Rmw9+rRPLE5dRluuHhiO0Eg6pO+KnqxgWID7CY4Ij7xuQtyUsYKkArjEq
irooV6OPmvQHDyQHMbgKhYr+47LZZ0YuNzZd0jhd5JIMWXV6aUgW9R23c9T7JgMG
pPOhHSWxZOBlRWzRVtCEzSug3J39n9eZqVP1PFIZI/pq0mOOt7LTz5IUX0xF0lJ+
JM7lPsTuJibESiWXKo9neTvy9BUWDIV9D/i8CH1uz0+xVala0uQRSNbrdWV4cN4v
oVaYwoXm+kYeGSz27f9CxJgLEA5sxuFWlbmm2+AXOFQPyyUDVXDCvAB/rzDZpFNo
HxM0OxyfmbmLmu+j31qW3JnvJvb6eroYxlvwgVeOCTihhIh6HKQzNFKv0iq3qc4Z
2a2czDyqt5h52CO+hwjsB5jjGNgS7AIxgBmDiw2V10meNGR/ZBVP9zew4FA3IEdY
GVuFBP52xdStrDgFpE3RK799n2i0fXvZE+9zzRlZ7DNRxZXMvBBpR35IhmyqVPDF
PbUmCKV8/Rm7ryZPanmAt78CrI5RVmPz+rrGHQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCD72IK7rP8TSFVLvja0VU56do2E6q4UTVAtUikqVnVszEv6lJUNqcHT+it
vgD3JtuybukU1pRsbjdu2iLjx2fStYfvapmjMa8rHqAiD6IKVkjOsq5w4Jc4HSR4
JTU9u40YR0Ly1+lHZmGDbBjK9JqJPZBHzPWlJ1sDE+DmgR9Fid9Dfv/uavkx3uuc
FPnWzoxoQx8JQs6DAHzBL6qHfbFoncPRrztRbTmkrAUhJI98nuEGUD1+T51qU5cu
pj8q262ZYKwYWvOyk1AmiokbMiBVd0Obewqj7IiY6T5S+zORLOj1IhzaZ83P9pgM
mq0/oJk8aQYC3vgYCmY2aNWXUX18
-----END CERTIFICATE-----
SignatureiQMjVEdG/FWcc56MAPwvDd04E0ERl5pUWkrRWtdYdgbboBj0+7YAo+rDODFz5qC3EPqWBr7XRkjXOfvn9+m61v0w88Qy8SZQIZRHTAwRJuK5jDQbpfce5dropQgKW8btEIzI3BPE+DFBIDeV+qLNQEYT25ApMkUAz44PumVV0sJMibCGo0JBgIxHCPyem1NNjYaX3qQDt41eg8I5rH8wLCWGa7lNTtGyp8vaJ4ck0sh4J9sPuVzMdJoXQDHfGe5S8YY3GTwgvwyloNJQAFO+SQzm5WX6mC/IKAfpxwG82cQAEMm6B4geyHwaYGSFDEgrBuHOZj2fQmvQgzoarRN+U76bOhjQI0IqU76Pno3qM17eF+UKW8peDiqFBXpepGYfDoeyjQsF2GqxIK3C0bNUR5bp9RjNxkWckwvS2ihvP/2rg4lr05MuDDmIdBYG9Ny+PT9dEWBssQkXzIVX28Ox6P8xkorH0n5EoSRl3j+KMXbM34QteNMt1+jgsHAxcS8H57CwV3MC0uqZnhxUu/LbwIGHzvKbC6vN3F/3l6F+35rWM7UaQhdvr2W/1q5Swj5F2sp2Bq5jgrxbWIuUB9+pzftASgVUEmtd6blOUlJuuJj1wmaIrA9jx21+Bg8t/OmrQqB97ZHzint0WTdo7KTOviKZGnoZVXeoQthPmSyW7Wc=
Signature digestsha512
Dependencies
Required Nextcloud versions >=30.0.0,<36.0.0
Minimum Integer bits32
PHP>=8.1.0
PHP extensions bcmath