This release gives the cash-flow calendar a second question to answer. It already showed what your balance will be; it now also shows how much actually came in and went out each day, with forecasts kept visually separate from settled money. Alongside that, a rule saved with a blank condition value no longer quietly matches every transaction you own, OFX 2.x statements with accented characters import instead of crashing, and CSV imports survive the ragged files real banks export while finally letting you map payee, transaction ID and notes columns. The Helm chart is now built, validated and published on every release.
Features
- Activity mode for the cash-flow calendar. The calendar gains a
Balance | Activitytoggle, independent fromCompact | Detailed, with Balance unchanged as the default. Balance answers "what will I have?"; Activity answers "how much moved?", which previously meant opening each day and adding rows up by hand, easy to miscount because projections sit in the same list as settled transactions. In Activity mode the trend strip becomes daily bars with income above the axis and expenses below, day cells report the real amounts that moved, and the day panel leads with the actual net. Projections are never mixed into those figures: they get their own violet line, their own dashed bars, and their own block in the panel. Transfers keep their marker and their rows but never count as income or expense. The preference persists, and switching modes never moves the selected day or your filters. Closes #484 reported by and contributed by @DannyFeliz (#485) ๐ - Map payee, transaction ID and notes columns when importing a CSV. Bank exports carry more than a date, description and amount, but there was no way to bring the rest across. Payee and notes are auto-detected from the usual headers in English and Portuguese, and can be mapped explicitly like every other column. Transaction ID is deliberately explicit-only, never guessed, because it drives duplicate detection and a wrong guess would silently drop rows. The same import also stopped being fragile: a row with fewer columns than the header, a row with more, or an unquoted comma inside an amount each used to abort the entire import with an
AttributeError, and15.01.2026style dates are now understood. Contributed by @jorishaenseler15 (#474) ๐ - The transfer dialog shows which transaction is on the other side. The banner said a transaction was a transfer but never which one it was linked to, so an automatic link could not be checked without going and finding the counterpart yourself. One line now sits under the message:
Linked to: Revolut ยท 26/07/2026 ยท +โฌ 300,00. Both legs share atransfer_pair_id, butTransactionReadonly ever exposed the bare UUID, so atransfer-pairendpoint was added next to the existingtransfer-candidatesone, fetched lazily and only when the transaction is actually a transfer. Closes #453 reported by @ingridmachado (#487) ๐ - Ukrainian Hryvnia. UAH is now a supported currency, with the โด symbol and
uk-UAformatting, matching the interface language that already shipped. Closes #457 reported by @fx-a (#486) ๐
Fixes
- A rule with a blank condition value no longer matches everything. A blank value is a tautology:
""is a substring of every string, every string starts and ends with it, an empty regex always matches, and a blank numeric value fell back toDecimal("0"), soamount greater thanmatched every transaction. Nothing validated it on any path, becauseRuleCondition.valueis typedAny. An active rule saved this way recategorised the entire ledger the next time rules were applied, which is exactly what was reported. Blank and whitespace-only values are now rejected on create and update, the evaluator treats one as a non-match rather than a match if it somehow reaches it, and existing rules in this state can no longer do damage. Closes #438 reported by @mjneto (#488) ๐ - OFX 2.x statements with accented characters import.
ofxparseonly looks for an encoding hint in the bytes before a file's first<. OFX 2.x is plain XML and has no legacy SGML header block there, so the library silently assumed ASCII and aborted the whole import withUnicodeDecodeErroron the first non-ASCII byte, an upstream bug open since 2017. Any statement containing an umlaut or an accent failed, which for European exports is most of them. A synthetic header now routes those files through the decode path that works, declaring whichever encoding the content actually decoded as rather than trusting what the file claims. Files that omit the optional XML declaration entirely are covered too. Closes #479 reported by and contributed by @Jyasapara (#480) ๐ - Asset transaction dates can be edited.
PATCH /api/assets/transactions/{tx_id}rejected any request containing adatewith a 422, so a transaction's date could never be corrected once entered. The schema field shadowed itself: Python binds the default before evaluating the annotation, sodate: Optional[date] = Noneresolved toNoneTypeand Pydantic required the field to always be null. The service layer had always handled date changes correctly, including revalidating the position and recomputing the average price in the new order; only the schema was blocking. Closes #481 reported by and contributed by @Jyasapara (#482) ๐
Under the hood
- The Helm chart is now built, validated and published automatically. Every pull request that touches the chart runs
helm lint,helm templateandkubeconform, so a chart with broken syntax or invalid Kubernetes objects cannot be merged. Every release packages it and pushes it to GHCR as an OCI artifact with the release version injected into both the image tags and the chart metadata, so the published chart deploys the images from that same release rather thanlatest. Installing no longer requires cloning the repository:helm install securo oci://ghcr.io/securo-finance/charts/securo --version <VERSION>. The chart is also registered on Artifact Hub. Contributed by @jorishaenseler15 (#458) ๐
Big thanks to @DannyFeliz, @Jyasapara and @jorishaenseler15 for the code, and to @mjneto, @ingridmachado and @fx-a for the reports that shaped this release ๐
Full Changelog: v0.13.11...v0.13.12