2092 Commits
Author SHA1 Message Date
Herculino Trotta 448e9c8f5c fix(api): save income categories, tags and entities on account create and update
AccountSerializer assigned the many-to-many fields with setattr, which Django rejects, so any write that included them returned a 500. The default ModelSerializer create/update already handles them.
2026-11-08 17:57:56 -03:00
eitchtee e7665103c0 chore(locale): update translation files
[skip ci] Automatically generated by Django makemessages workflow
0.26.0
2026-11-08 20:20:28 +00:00
Herculino Trotta bdbcf3ea70 Merge pull request #655 from eitchtee/feat/demo-investments
feat(demo): add investment examples to the demo data
2026-11-08 17:20:04 -03:00
Herculino Trotta b6cb1e8b52 Merge pull request #654 from eitchtee/fix/transfer-account-name-width
fix(transactions): let transfer account names use the free row space
2026-11-08 17:19:55 -03:00
Herculino Trotta d9c296c26b Merge pull request #653 from eitchtee/fix/transfer-form-fields
fix(transfers): entities, paid state and inactive items in the transfer form
2026-11-08 17:19:41 -03:00
Herculino Trotta 78cb61b0b6 feat(demo): add investment examples to the demo data
Investments landed without demo data. The ETF, Bitcoin and savings accounts become investments, and new accounts cover the rest of the tracker: Apple shares (dividends paid into checking, a partial sale, gifted shares with an estimated cost), a retirement fund tracked by value (quarterly gains and a loss, a yearly fee) and gold. Asset classes have targets that add up to 100%, plus one without a target to show how rebalancing leaves it out.

The investment examples use their own random seed, so the rest of the demo is unchanged. The demo test now renders the investment pages and checks each kind of holding has figures.
2026-11-08 17:17:16 -03:00
Herculino Trotta 52eae5180f fix(transactions): let transfer account names use the free row space
Account names on a combined transfer were cut at a fixed 14rem even when the row had room. On large screens the row now stays on one line and the account side can grow up to half of it, so names only truncate past that.
2026-11-08 17:17:05 -03:00
Herculino Trotta 122f0b7a28 fix(transfers): entities, paid state and inactive items in the transfer form
The transfer form had no entities field and always created paid transfers. Each side now has its own entities, shown as from -> to in the list like category and tags, and a Projected/Paid toggle applies to both sides.

Editing a transfer also offered only active categories, tags and entities and non-archived accounts, so saving silently dropped a deactivated tag or failed on an archived account. The transfer's own items stay selectable, as in the transaction form.
2026-11-08 17:16:49 -03:00
Herculino Trotta b561ec7d77 Merge pull request #652 from eitchtee/weblate
Translations update from Weblate
2026-11-08 16:44:06 -03:00
Herculino Trotta cdc112fa00 locale(Portuguese (Brazil)): update translation
Currently translated at 100.0% (958 of 958 strings)

Translation: WYGIWYH/App
Translate-URL: https://translations.herculino.com/projects/wygiwyh/app/pt_BR/
2026-11-08 19:40:42 +00:00
eitchtee 90df6227cb chore(locale): update translation files
[skip ci] Automatically generated by Django makemessages workflow
2026-11-08 19:20:48 +00:00
Herculino Trotta 1c7be36ebb Merge pull request #650 from eitchtee/feat/bank-sync-2
feat: bank sync with external providers (Lunch Flow, SimpleFIN, Pluggy)
2026-11-08 16:20:11 -03:00
Herculino Trotta 1369c3edbf Merge remote-tracking branch 'origin/main' into feat/bank-sync-2
# Conflicts:
#	app/apps/export_app/views.py
#	app/templates/includes/sidebar.html
2026-11-08 16:17:06 -03:00
Herculino Trotta cc4c58b676 feat(bank-sync): add Pluggy provider
Brazilian banks through Open Finance. Users give their Pluggy client
credentials and the ids of their connections (items), from Meu Pluggy.

- Uses the cursor-paginated /v2/transactions; /transactions is removed
  after 2026-12-31. Our own filters are sent again with each cursor.
- The direction comes from `type`, not the amount's sign: credit cards
  keep the card's sign, purchases are positive. Checked against a real
  Meu Pluggy card and checking account; the sandbox data doesn't match
  production here.
- Pending transactions keep their id once they post (a card's open bill
  stays pending until it closes), so they're imported unpaid and settled
  later. Future-dated ones (installments, scheduled payments) wait for
  their date. Installments already come dated in their own month.
- Foreign purchases use the account's amount, with the original amount
  in the notes.
- Connections that need the user to log in again show as an error.
2026-11-08 16:10:38 -03:00
Herculino Trotta 2a4202118b feat(bank-sync): import pending transactions and settle them when they post
Providers can now return pending transactions, flagged as such, when
their ids survive posting. They're imported unpaid right away and, once
the bank posts them, marked paid with their final amount and date.

- Settling happens once, so later edits stick, and one marked paid by
  hand is left alone. It goes through save() so a transfer's other side
  follows; no rules run again. reference_date moves only if it still
  followed the date.
- Each sync looks back to the oldest unpaid synced transaction, since a
  card purchase can post weeks later when the bill closes. Pending ones
  older than 60 days are taken as cancelled and no longer followed.
2026-11-08 16:09:23 -03:00
Herculino Trotta 9238c48bb5 feat(bank-sync): add SimpleFIN provider
Users paste a one-time setup token. On save it's claimed and the access
URL it returns is stored; credentials go in a header, never the URL, so
errors don't leak them.

- Providers can validate or transform their settings (clean_settings),
  run by the service form once every other field is valid, so a token
  isn't spent on a form that fails anyway.
- Providers can declare a minimum sync interval. SimpleFIN Bridge
  disables tokens that go much past ~24 requests a day, so it's 6 hours.
- Tokens and access URLs are user input pointing the server at a host:
  only SimpleFIN Bridge is allowed unless SIMPLEFIN_ALLOWED_HOSTS says
  otherwise. Checked again on every request, for restored settings.
- Transactions are fetched per account in 90-day windows, Bridge's
  limit per request. Pending ones are skipped.
2026-11-08 16:08:37 -03:00
eitchtee 58e2aa3c8a chore(locale): update translation files
[skip ci] Automatically generated by Django makemessages workflow
2026-11-08 18:27:34 +00:00
Herculino Trotta cc30a1cf37 Merge pull request #651 from eitchtee/feat/investments
feat(investments): investment tracker with asset classes and rebalancing
2026-11-08 15:27:09 -03:00
Herculino Trotta 8ed2c98074 fix(currencies): renumber retention migration after main's 0026 2026-11-08 15:06:14 -03:00
Herculino Trotta 76090ceb4a Merge remote-tracking branch 'origin/main' into feat/investments 2026-11-08 15:01:22 -03:00
Herculino Trotta 6ed0ba4efa feat(api): asset class endpoints
- /api/investment-classes/ to list, create, edit and delete asset classes
- Accounts return their asset class and take investment_class_id, filterable
  by investment_class
- Unique names and targets up to 100% are checked in the model, shared by the
  form and the API
2026-11-08 14:55:42 -03:00
Herculino Trotta 25a2326cf6 feat(export): include bank sync services and account links in export and restore 2026-11-08 12:39:17 -03:00
Herculino Trotta 77ee56f7a3 feat(bank-sync): add sidebar entry 2026-11-08 12:39:17 -03:00
Herculino Trotta 620e7df015 feat(bank-sync): sync bank transactions from external providers
Provider registry modeled after automatic exchange rates: each provider
declares its own settings fields, rendered dynamically in the service form.
Lunch Flow is the first provider.

- Map provider accounts to WYGIWYH accounts with a start date and an
  optional currency filter
- Hourly task syncs due services; manual sync from the list
- Deduplicates through Transaction.internal_id, optionally matching
  transactions already entered by hand
- Per account errors and provider reported connection problems

Refs #498
2026-11-08 12:39:16 -03:00
Herculino Trotta 5964d80e73 Merge pull request #649 from jeonghun917/fix/dcr-token-non-ascii
Compare the DCR initial access token as bytes so a non-ASCII token ge…
2026-11-08 10:29:10 -03:00
eitchtee b0351ae5ac chore(locale): update translation files
[skip ci] Automatically generated by Django makemessages workflow
2026-11-08 13:20:01 +00:00
Herculino Trotta f894464ca7 Merge pull request #648 from eitchtee/feat/transaction-picker
feat(transactions): better transaction picker for DCA and rules
2026-11-08 10:19:26 -03:00
Herculino Trotta 7385c77437 Merge pull request #647 from eitchtee/fix/dca-create-transaction-layout
fix(dca): repair the create transaction section layout
2026-11-08 10:19:13 -03:00
eitchtee d3f652ad87 chore(locale): update translation files
[skip ci] Automatically generated by Django makemessages workflow
2026-11-08 13:18:54 +00:00
Herculino Trotta a1718b711c Merge pull request #646 from eitchtee/fix/toast-close-button
fix(toasts): space the close button from the text and edges
2026-11-08 10:18:30 -03:00
Jeonghun Mun 97d5c05a3c Compare the DCR initial access token as bytes so a non-ASCII token gets a 401, not a 500
hmac.compare_digest raises TypeError when two str values hold non-ASCII
characters, and the bearer value comes from the request.
2026-11-08 08:46:34 +00:00
Herculino Trotta 9f9146aaec feat(transactions): search transactions by date, amount, entity and account
Each word of the query must match something, and words can match
different fields: description, notes, category, tags, entities, account
and account group, a date in the user's format (the year is optional),
or an amount in the user's number format, where a whole number like 234
matches 234.00 to 234.99.

Matching through an id subquery also stops transactions with several
matching tags from showing up more than once.
2026-11-08 03:27:21 -03:00
Herculino Trotta 8482c85a76 fix(transactions): keep transaction picker results in monthly view order
Results come back as today, tomorrow, yesterday, upcoming (soonest first)
and then past (newest first); past dates used to be oldest first. The
endpoint is now capped at 100 results, as its docstring already claimed.

tom-select also re-scored and re-sorted the server's results on the
client, which scrambled the order while searching. Load-based selects now
keep the server's order, drop the previous query's results, and preload
recent transactions on focus.
2026-11-08 03:27:15 -03:00
Herculino Trotta aa3ffe9b3e feat(transactions): render the transaction picker as a mini transaction
TransactionSelect options now look like a compact version of the
transaction item: paid state, type colour, date, description, category,
tags, entities, amount and account. The search endpoint returns that data
as JSON, and pre-selected options carry it in data-data so edit forms
render the same way.
2026-11-08 03:27:01 -03:00
Herculino Trotta 48afe0b7b3 fix(dca): repair the create transaction section layout
Nesting Row(Column(Row(Column))) shrank every field to a quarter of the
width, since Column defaults to half, and rounded-3 is a Bootstrap class
that doesn't exist here. Use the same card layout as the transfer form:
account at full width with category and tags side by side.
2026-11-08 03:26:21 -03:00
Herculino Trotta 03f2b0aeb4 fix(toasts): space the close button from the text and edges
Lay the alert out as an icon | text | button grid so the close button gets
a consistent gap from the message and the same visual inset as the icon.
Long messages now wrap instead of pushing the button, and the aria-label
is quoted.
2026-11-08 03:26:11 -03:00
Herculino Trotta 34f6066187 docs(readme): give IMPORT_TEMP_ROOT a literal default and move path vars up
List the Docker path as the default like the other rows do, and move
both rows out from under the dev-only Vite settings.
2026-11-08 03:17:33 -03:00
eitchtee de1df9d13c chore(locale): update translation files
[skip ci] Automatically generated by Django makemessages workflow
2026-11-08 06:13:26 +00:00
Herculino Trotta 56c37d0012 Merge pull request #643 from officialasishkumar/fix/configurable-app-paths
fix(import): stop hardcoding the Docker image's paths
2026-11-08 03:13:03 -03:00
Herculino Trotta e0c1e4d5ff fix(import): resolve symlinks when checking the upload path
The temp root is resolve()d in settings but the file path was only
abspath()ed, so a symlink inside the temp folder could point outside it
and still pass the check. Resolve both sides the same way.

Also drop the unused /temp folder from the prod image.
2026-11-08 03:09:04 -03:00
eitchtee a42265ba49 chore(locale): update translation files
[skip ci] Automatically generated by Django makemessages workflow
2026-11-08 06:01:38 +00:00
Herculino Trotta 03900ab4d1 Merge pull request #642 from cahthuranag/feat/allratestoday-provider
feat(automatic-exchange-rates): add central bank tables as a provider
2026-11-08 03:01:13 -03:00
Herculino Trotta 6a335b1a63 fix(automatic-exchange-rates): skip bad AllRatesToday rows individually
A non-numeric, NaN or infinite value raised while parsing and threw away
the whole table. Each bad row is now skipped on its own.

Log a warning when a table has rows but none of a usable rate type, so a
bank with unknown types does not fail silently.
2026-11-08 02:57:07 -03:00
Herculino Trotta 43145be24d feat(automatic-exchange-rates): add provider options field
Add an Options field to exchange rate services. Providers get the raw
text, can validate it on save through clean_options, and describe it
with options_help.

The service form now shows API Key only for providers that require one,
and Options only for providers that read it, with that provider's help.

AllRatesToday reads its bank code from Options instead of API Key.
2026-11-08 02:57:07 -03:00
Herculino Trotta 38118c56d3 Merge remote-tracking branch 'origin/main' into fix/configurable-app-paths 2026-11-08 02:53:53 -03:00
Herculino Trotta a50bdb10ff Merge remote-tracking branch 'origin/main' into feat/allratestoday-provider 2026-11-08 02:53:53 -03:00
Herculino Trotta c17f03775c Merge remote-tracking branch 'origin/main' into feat/investments 2026-11-08 02:53:52 -03:00
Herculino Trotta 23acf85a6b Merge pull request #645 from eitchtee/chore/worktree-dev-setup
chore(dev): run the dev stack in multiple git worktrees
2026-11-08 02:51:05 -03:00
Herculino Trotta a691da7523 chore(dev): run the dev stack in multiple git worktrees
Drop fixed container names so each worktree gets its own containers,
add docker/dev/worktree.sh to set up and tear down a worktree, and
document it under a new Development section in the README.
2026-11-08 02:48:59 -03:00
Herculino Trotta 914c665faf Merge pull request #644 from officialasishkumar/fix/datepicker-mobile-overlay
fix(datepicker): keep the mobile overlay attached after boosted navigation
2026-11-08 02:33:13 -03:00