[PR #7317] [WIP] [AI] feat: Added Forecast Module #48901

Open
opened 2026-04-26 10:46:44 -05:00 by GiteaMirror · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/actualbudget/actual/pull/7317
Author: @AveragePiglet
Created: 3/29/2026
Status: 🔄 Open

Base: masterHead: master


📝 Commits (7)

  • 1e1bda4 [AI] Add schedule forecast page
  • a463496 [AI] Enhance schedule forecast: toolbar, granularity, account scope, table columns
  • 5237dc9 Merge pull request #1 from AveragePiglet/feat/schedule-forecast
  • ed8d0e8 [AI] Fix infinite loop in forecast for weekend-adjusted recurring schedules
  • ea981f4 Merge pull request #2 from AveragePiglet/feat/schedule-forecast
  • 81f2d53 Merge branch 'master' into master
  • 5b5b992 Update VRT screenshots

📊 Changes

163 files changed (+829 additions, -0 deletions)

View changed files

📝 packages/desktop-client/e2e/accounts.test.ts-snapshots/Accounts-Import-Transactions-import-csv-file-twice-1-chromium-linux.png (+0 -0)
📝 packages/desktop-client/e2e/accounts.test.ts-snapshots/Accounts-Import-Transactions-import-csv-file-twice-2-chromium-linux.png (+0 -0)
📝 packages/desktop-client/e2e/accounts.test.ts-snapshots/Accounts-Import-Transactions-import-csv-file-twice-3-chromium-linux.png (+0 -0)
📝 packages/desktop-client/e2e/accounts.test.ts-snapshots/Accounts-Import-Transactions-imports-transactions-from-a-CSV-file-1-chromium-linux.png (+0 -0)
📝 packages/desktop-client/e2e/accounts.test.ts-snapshots/Accounts-Import-Transactions-imports-transactions-from-a-CSV-file-2-chromium-linux.png (+0 -0)
📝 packages/desktop-client/e2e/accounts.test.ts-snapshots/Accounts-Import-Transactions-imports-transactions-from-a-CSV-file-3-chromium-linux.png (+0 -0)
📝 packages/desktop-client/e2e/accounts.test.ts-snapshots/Accounts-closes-an-account-1-chromium-linux.png (+0 -0)
📝 packages/desktop-client/e2e/accounts.test.ts-snapshots/Accounts-closes-an-account-2-chromium-linux.png (+0 -0)
📝 packages/desktop-client/e2e/accounts.test.ts-snapshots/Accounts-closes-an-account-3-chromium-linux.png (+0 -0)
📝 packages/desktop-client/e2e/accounts.test.ts-snapshots/Accounts-closes-an-account-4-chromium-linux.png (+0 -0)
📝 packages/desktop-client/e2e/accounts.test.ts-snapshots/Accounts-closes-an-account-5-chromium-linux.png (+0 -0)
📝 packages/desktop-client/e2e/accounts.test.ts-snapshots/Accounts-closes-an-account-6-chromium-linux.png (+0 -0)
📝 packages/desktop-client/e2e/accounts.test.ts-snapshots/Accounts-creates-a-new-account-and-views-the-initial-balance-transaction-1-chromium-linux.png (+0 -0)
📝 packages/desktop-client/e2e/accounts.test.ts-snapshots/Accounts-creates-a-new-account-and-views-the-initial-balance-transaction-2-chromium-linux.png (+0 -0)
📝 packages/desktop-client/e2e/accounts.test.ts-snapshots/Accounts-creates-a-new-account-and-views-the-initial-balance-transaction-3-chromium-linux.png (+0 -0)
📝 packages/desktop-client/e2e/bank-sync.test.ts-snapshots/Bank-Sync-checks-the-page-visuals-1-chromium-linux.png (+0 -0)
📝 packages/desktop-client/e2e/bank-sync.test.ts-snapshots/Bank-Sync-checks-the-page-visuals-2-chromium-linux.png (+0 -0)
📝 packages/desktop-client/e2e/bank-sync.test.ts-snapshots/Bank-Sync-checks-the-page-visuals-3-chromium-linux.png (+0 -0)
📝 packages/desktop-client/e2e/budget.test.ts-snapshots/Budget-renders-the-summary-information-available-funds-overspent-budgeted-and-for-next-month-1-chromium-linux.png (+0 -0)
📝 packages/desktop-client/e2e/budget.test.ts-snapshots/Budget-renders-the-summary-information-available-funds-overspent-budgeted-and-for-next-month-2-chromium-linux.png (+0 -0)

...and 80 more files

📄 Description

Adds a new top-level Forecast page (/forecast) that projects future cash flow based on all active scheduled
transactions.

The page appears in the sidebar between Schedules and More (Chart icon) and includes:

  • Summary cards: Current Balance, Projected Income, Projected Expenses, Net over period, Ending Balance
  • Composed chart: income/expense bars + running balance line, with configurable granularity (Day/Week/Month/Year) and
    a 1/3/6/12-month window
  • Account scope filter: All accounts, On-budget only, or Off-budget only
  • Monthly breakdown table: expandable rows showing Name, Payee, Account, Date, and Amount per scheduled occurrence

Missed non-recurring schedule dates are bucketed into the current month rather than dropped.

Related issue(s)

Testing

  1. Open the app and click Forecast in the sidebar (between Schedules and More)
  2. Verify summary cards reflect current account balances and projected schedule totals
  3. Change the Granularity dropdown (Day/Week/Month/Year) and confirm the chart re-buckets accordingly
  4. Change the Window dropdown (1/3/6/12 months) and confirm the projection range updates
  5. Change Account scope between All / On-budget / Off-budget and verify balances and schedule rows filter correctly
  6. Expand rows in the monthly breakdown table and confirm Name, Payee, Account, Date, and Amount are correct
  7. Confirm no regressions on the /schedules page (Forecast button removed; everything else unchanged)

▎ Tip: Use "View demo" on the setup screen to load pre-populated sample data for realistic testing.

Checklist

  • Release notes added (see link above)
  • No obvious regressions in affected areas
  • Self-review has been performed

Note

Sorry in advance if this is poor, I don't normally contribute here on GitHub, I just needed this purely for my own personal use, if anyone thinks its worth anything they can use it.


Bundle Stats

Bundle Files count Total bundle size % Changed
desktop-client 27 12.09 MB → 12.14 MB (+50.92 kB) +0.41%
loot-core 1 4.83 MB 0%
api 4 4.06 MB 0%
cli 1 7.88 MB 0%
View detailed bundle stats

desktop-client

Total

Files count Total bundle size % Changed
27 12.09 MB → 12.14 MB (+50.92 kB) +0.41%
Changeset
File Δ Size
src/components/schedules/ScheduleForecast.tsx 🆕 +23.25 kB 0 B → 23.25 kB
node_modules/recharts/es6/component/Legend.js 🆕 +6.68 kB 0 B → 6.68 kB
node_modules/recharts/es6/component/DefaultLegendContent.js 🆕 +5.49 kB 0 B → 5.49 kB
src/components/schedules/scheduleForecastUtils.ts 🆕 +2.54 kB 0 B → 2.54 kB
node_modules/es-toolkit/dist/function/debounce.js 🆕 +1.53 kB 0 B → 1.53 kB
node_modules/es-toolkit/dist/compat/function/debounce.js 🆕 +1.26 kB 0 B → 1.26 kB
node_modules/es-toolkit/dist/compat/function/throttle.js 🆕 +502 B 0 B → 502 B
node_modules/es-toolkit/compat/throttle.js 🆕 +187 B 0 B → 187 B
node_modules/recharts/es6/context/legendPayloadContext.js 🆕 +164 B 0 B → 164 B
node_modules/recharts/es6/component/ResponsiveContainer.js 📈 +6.28 kB (+2115.79%) 304 B → 6.58 kB
node_modules/recharts/es6/component/responsiveContainerUtils.js 📈 +1.82 kB (+752.63%) 247 B → 2.06 kB
node_modules/recharts/es6/context/legendPortalContext.js 📈 +79 B (+52.32%) 151 B → 230 B
src/components/sidebar/PrimaryButtons.tsx 📈 +329 B (+7.92%) 4.06 kB → 4.38 kB
node_modules/d3-shape/src/math.js 📈 +10 B (+5.49%) 182 B → 192 B
node_modules/recharts/es6/context/chartLayoutContext.js 📈 +83 B (+2.96%) 2.73 kB → 2.82 kB
node_modules/d3-shape/src/symbol/circle.js 📈 +6 B (+2.94%) 204 B → 210 B
node_modules/d3-shape/src/symbol/star.js 📈 +12 B (+2.14%) 562 B → 574 B
src/components/FinancesApp.tsx 📈 +249 B (+1.51%) 16.13 kB → 16.37 kB
node_modules/dnd-core/dist/contracts.js 📈 +14 B (+1.38%) 1015 B → 1 kB
node_modules/d3-shape/src/symbol/triangle.js 📈 +4 B (+1.34%) 299 B → 303 B
node_modules/d3-shape/src/symbol/diamond.js 📈 +4 B (+1.16%) 345 B → 349 B
node_modules/d3-shape/src/symbol/square.js 📈 +2 B (+1.05%) 191 B → 193 B
node_modules/recharts/es6/chart/AreaChart.js 📈 +4 B (+0.93%) 432 B → 436 B
node_modules/d3-shape/src/symbol.js 📈 +8 B (+0.85%) 942 B → 950 B
node_modules/d3-shape/src/symbol/wye.js 📈 +6 B (+0.84%) 716 B → 722 B
node_modules/@react-dnd/invariant/dist/index.js 📈 +6 B (+0.82%) 734 B → 740 B
node_modules/react-dnd/dist/hooks/useDrag/useDragType.js 📈 +2 B (+0.73%) 275 B → 277 B
node_modules/react-dnd/dist/hooks/useDragDropManager.js 📈 +2 B (+0.71%) 282 B → 284 B
node_modules/recharts/es6/shape/Sector.js 📈 +46 B (+0.65%) 6.87 kB → 6.91 kB
node_modules/react-dnd/dist/hooks/useDrop/useAccept.js 📈 +2 B (+0.65%) 308 B → 310 B
node_modules/recharts/es6/state/selectors/areaSelectors.js 📈 +24 B (+0.62%) 3.79 kB → 3.81 kB
node_modules/dnd-core/dist/actions/dragDrop/hover.js 📈 +10 B (+0.61%) 1.61 kB → 1.62 kB
node_modules/recharts/es6/component/Dots.js 📈 +24 B (+0.57%) 4.08 kB → 4.11 kB
src/components/banksync/AccountsHeader.tsx 📈 +8 B (+0.56%) 1.38 kB → 1.39 kB
node_modules/recharts/es6/shape/Dot.js 📈 +4 B (+0.56%) 709 B → 713 B
node_modules/recharts/es6/util/ActiveShapeUtils.js 📈 +20 B (+0.51%) 3.84 kB → 3.86 kB
src/components/admin/UserAccess/UserAccessHeader.tsx 📈 +6 B (+0.46%) 1.27 kB → 1.28 kB
node_modules/dnd-core/dist/classes/HandlerRegistryImpl.js 📈 +16 B (+0.46%) 3.42 kB → 3.43 kB
src/components/admin/UserDirectory/UserDirectoryHeader.tsx 📈 +12 B (+0.44%) 2.65 kB → 2.67 kB
node_modules/recharts/es6/component/ActivePoints.js 📈 +13 B (+0.43%) 2.96 kB → 2.98 kB
node_modules/d3-shape/src/symbol/cross.js 📈 +2 B (+0.41%) 493 B → 495 B
node_modules/dnd-core/dist/actions/dragDrop/beginDrag.js 📈 +8 B (+0.35%) 2.23 kB → 2.24 kB
node_modules/dnd-core/dist/actions/dragDrop/endDrag.js 📈 +2 B (+0.35%) 574 B → 576 B
node_modules/react-error-boundary/dist/react-error-boundary.js 📈 +8 B (+0.35%) 2.24 kB → 2.25 kB
node_modules/recharts/es6/cartesian/getCartesianPosition.js 📈 +20 B (+0.34%) 5.76 kB → 5.78 kB
node_modules/recharts/es6/component/LabelList.js 📈 +12 B (+0.34%) 3.46 kB → 3.47 kB
node_modules/react-dnd/dist/hooks/useDrag/useDrag.js 📈 +2 B (+0.30%) 661 B → 663 B
node_modules/dnd-core/dist/classes/DragDropMonitorImpl.js 📈 +12 B (+0.30%) 3.9 kB → 3.91 kB
node_modules/recharts/es6/component/Label.js 📈 +32 B (+0.30%) 10.48 kB → 10.51 kB
node_modules/recharts/es6/state/cartesianAxisSlice.js 📈 +12 B (+0.29%) 4 kB → 4.01 kB
node_modules/dnd-core/dist/actions/dragDrop/drop.js 📈 +6 B (+0.28%) 2.06 kB → 2.06 kB
node_modules/recharts/es6/shape/Trapezoid.js 📈 +17 B (+0.28%) 5.97 kB → 5.99 kB
src/components/tags/TagsHeader.tsx 📈 +4 B (+0.28%) 1.42 kB → 1.42 kB
src/components/rules/RulesHeader.tsx 📈 +4 B (+0.25%) 1.54 kB → 1.55 kB
src/components/banksync/FieldMapping.tsx 📈 +20 B (+0.24%) 8.12 kB → 8.13 kB
src/components/banksync/AccountRow.tsx 📈 +10 B (+0.23%) 4.27 kB → 4.28 kB
src/components/admin/UserDirectory/UserDirectoryRow.tsx 📈 +14 B (+0.22%) 6.16 kB → 6.17 kB
node_modules/recharts/es6/polar/Pie.js 📈 +37 B (+0.19%) 18.79 kB → 18.83 kB
node_modules/recharts/es6/state/selectors/lineSelectors.js 📈 +4 B (+0.17%) 2.28 kB → 2.28 kB
node_modules/react-dnd/dist/internals/DragSourceMonitorImpl.js 📈 +4 B (+0.15%) 2.57 kB → 2.58 kB
src/components/Background.tsx 📈 +2 B (+0.15%) 1.32 kB → 1.32 kB
node_modules/recharts/es6/cartesian/CartesianGrid.js 📈 +17 B (+0.14%) 11.97 kB → 11.99 kB
node_modules/recharts/es6/cartesian/XAxis.js 📈 +8 B (+0.12%) 6.48 kB → 6.49 kB
node_modules/react-dnd/dist/internals/DropTargetMonitorImpl.js 📈 +2 B (+0.12%) 1.65 kB → 1.65 kB
src/components/admin/UserAccess/UserAccessRow.tsx 📈 +6 B (+0.12%) 5.01 kB → 5.01 kB
node_modules/recharts/es6/cartesian/CartesianAxis.js 📈 +14 B (+0.11%) 12.09 kB → 12.1 kB
src/components/AppBackground.tsx 📈 +2 B (+0.11%) 1.77 kB → 1.77 kB
node_modules/cmdk/dist/index.mjs 📈 +16 B (+0.11%) 14.39 kB → 14.4 kB
node_modules/react-dnd/dist/internals/wrapConnectorHooks.js 📈 +2 B (+0.11%) 1.82 kB → 1.82 kB
node_modules/recharts/es6/component/Text.js 📈 +7 B (+0.09%) 7.34 kB → 7.35 kB
src/components/accounts/AccountEmptyMessage.tsx 📈 +2 B (+0.08%) 2.47 kB → 2.47 kB
src/components/tags/TagRow.tsx 📈 +4 B (+0.05%) 7.87 kB → 7.87 kB
src/components/rules/RuleRow.tsx 📈 +4 B (+0.04%) 9.73 kB → 9.74 kB
src/components/modals/SelectLinkedAccountsModal.tsx 📈 +14 B (+0.04%) 38.84 kB → 38.85 kB
src/components/modals/LoadBackupModal.tsx 📈 +2 B (+0.03%) 6.05 kB → 6.05 kB
node_modules/recharts/es6/cartesian/Line.js 📈 +4 B (+0.02%) 15.84 kB → 15.84 kB
node_modules/recharts/es6/shape/Rectangle.js 📈 +2 B (+0.02%) 9.84 kB → 9.84 kB
src/components/payees/PayeeTableRow.tsx 📈 +2 B (+0.02%) 12.27 kB → 12.27 kB
src/components/payees/ManagePayees.tsx 📈 +2 B (+0.01%) 14.74 kB → 14.74 kB
src/components/transactions/SelectedTransactionsButton.tsx 📈 +2 B (+0.01%) 16.79 kB → 16.79 kB
src/components/schedules/SchedulesTable.tsx 📈 +2 B (+0.01%) 17.71 kB → 17.71 kB
src/components/reports/graphs/tableGraph/ReportTableRow.tsx 📉 -12 B (-0.09%) 12.73 kB → 12.72 kB
node_modules/recharts/es6/chart/PieChart.js 📉 -4 B (-0.20%) 1.96 kB → 1.96 kB
src/components/reports/graphs/tableGraph/ReportTableHeader.tsx 📉 -12 B (-0.28%) 4.23 kB → 4.22 kB
node_modules/recharts/es6/state/selectors/pieSelectors.js 📉 -20 B (-0.54%) 3.63 kB → 3.62 kB
node_modules/recharts/es6/shape/Symbols.js 📉 -39 B (-0.89%) 4.26 kB → 4.22 kB
View detailed bundle breakdown

Added
No assets were added

Removed
No assets were removed

Bigger

Asset File Size % Changed
static/js/index.js 3.23 MB → 3.37 MB (+143.51 kB) +4.34%

Smaller

Asset File Size % Changed
static/js/ReportRouter.js 1.02 MB → 953.17 kB (-92.59 kB) -8.85%

Unchanged

Asset File Size % Changed
static/js/BackgroundImage.js 119.98 kB 0%
static/js/FormulaEditor.js 846.44 kB 0%
static/js/TransactionList.js 81.29 kB 0%
static/js/ca.js 182.91 kB 0%
static/js/da.js 104.66 kB 0%
static/js/de.js 174.79 kB 0%
static/js/en-GB.js 7.16 kB 0%
static/js/en.js 170.76 kB 0%
static/js/es.js 182.09 kB 0%
static/js/fr.js 177.47 kB 0%
static/js/indexeddb-main-thread-worker-e59fee74.js 13.46 kB 0%
static/js/it.js 166.25 kB 0%
static/js/narrow.js 354.27 kB 0%
static/js/nb-NO.js 152.2 kB 0%
static/js/nl.js 108.93 kB 0%
static/js/pl.js 88.34 kB 0%
static/js/pt-BR.js 177.84 kB 0%
static/js/resize-observer.js 18.03 kB 0%
static/js/sv.js 80.58 kB 0%
static/js/th.js 179.94 kB 0%
static/js/theme.js 30.68 kB 0%
static/js/uk.js 213.14 kB 0%
static/js/useTransactionBatchActions.js 4.29 MB 0%
static/js/wide.js 418 B 0%
static/js/workbox-window.prod.es5.js 7.28 kB 0%

loot-core

Total

Files count Total bundle size % Changed
1 4.83 MB 0%
View detailed bundle breakdown

Added
No assets were added

Removed
No assets were removed

Bigger
No assets were bigger

Smaller
No assets were smaller

Unchanged

Asset File Size % Changed
kcab.worker.CwpE34S5.js 4.83 MB 0%

api

Total

Files count Total bundle size % Changed
4 4.06 MB 0%
View detailed bundle breakdown

Added
No assets were added

Removed
No assets were removed

Bigger
No assets were bigger

Smaller
No assets were smaller

Unchanged

Asset File Size % Changed
index.js 3.84 MB 0%
from-Bl-Hslp4.js 167.73 kB 0%
multipart-parser-BnDysoMr.js 8.1 kB 0%
src-iMkUmuwR.js 43.64 kB 0%

cli

Total

Files count Total bundle size % Changed
1 7.88 MB 0%
View detailed bundle breakdown

Added
No assets were added

Removed
No assets were removed

Bigger
No assets were bigger

Smaller
No assets were smaller

Unchanged

Asset File Size % Changed
cli.js 7.88 MB 0%

🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/actualbudget/actual/pull/7317 **Author:** [@AveragePiglet](https://github.com/AveragePiglet) **Created:** 3/29/2026 **Status:** 🔄 Open **Base:** `master` ← **Head:** `master` --- ### 📝 Commits (7) - [`1e1bda4`](https://github.com/actualbudget/actual/commit/1e1bda48cf14bfb7fedfce4cffd1a572ee67bdfc) [AI] Add schedule forecast page - [`a463496`](https://github.com/actualbudget/actual/commit/a463496aca8f514a5ff37bd8dba1d41c2e291b16) [AI] Enhance schedule forecast: toolbar, granularity, account scope, table columns - [`5237dc9`](https://github.com/actualbudget/actual/commit/5237dc969a7821a41ee535e95468072a2cfaac2e) Merge pull request #1 from AveragePiglet/feat/schedule-forecast - [`ed8d0e8`](https://github.com/actualbudget/actual/commit/ed8d0e889041708439eaf93dd3d14dd9348beab1) [AI] Fix infinite loop in forecast for weekend-adjusted recurring schedules - [`ea981f4`](https://github.com/actualbudget/actual/commit/ea981f4755764e9257d5c4c365d33597c2732611) Merge pull request #2 from AveragePiglet/feat/schedule-forecast - [`81f2d53`](https://github.com/actualbudget/actual/commit/81f2d53211604959f442fa737b0ae1f423694eaa) Merge branch 'master' into master - [`5b5b992`](https://github.com/actualbudget/actual/commit/5b5b99207fcba0f41470c159c80ab8594258be81) Update VRT screenshots ### 📊 Changes **163 files changed** (+829 additions, -0 deletions) <details> <summary>View changed files</summary> 📝 `packages/desktop-client/e2e/accounts.test.ts-snapshots/Accounts-Import-Transactions-import-csv-file-twice-1-chromium-linux.png` (+0 -0) 📝 `packages/desktop-client/e2e/accounts.test.ts-snapshots/Accounts-Import-Transactions-import-csv-file-twice-2-chromium-linux.png` (+0 -0) 📝 `packages/desktop-client/e2e/accounts.test.ts-snapshots/Accounts-Import-Transactions-import-csv-file-twice-3-chromium-linux.png` (+0 -0) 📝 `packages/desktop-client/e2e/accounts.test.ts-snapshots/Accounts-Import-Transactions-imports-transactions-from-a-CSV-file-1-chromium-linux.png` (+0 -0) 📝 `packages/desktop-client/e2e/accounts.test.ts-snapshots/Accounts-Import-Transactions-imports-transactions-from-a-CSV-file-2-chromium-linux.png` (+0 -0) 📝 `packages/desktop-client/e2e/accounts.test.ts-snapshots/Accounts-Import-Transactions-imports-transactions-from-a-CSV-file-3-chromium-linux.png` (+0 -0) 📝 `packages/desktop-client/e2e/accounts.test.ts-snapshots/Accounts-closes-an-account-1-chromium-linux.png` (+0 -0) 📝 `packages/desktop-client/e2e/accounts.test.ts-snapshots/Accounts-closes-an-account-2-chromium-linux.png` (+0 -0) 📝 `packages/desktop-client/e2e/accounts.test.ts-snapshots/Accounts-closes-an-account-3-chromium-linux.png` (+0 -0) 📝 `packages/desktop-client/e2e/accounts.test.ts-snapshots/Accounts-closes-an-account-4-chromium-linux.png` (+0 -0) 📝 `packages/desktop-client/e2e/accounts.test.ts-snapshots/Accounts-closes-an-account-5-chromium-linux.png` (+0 -0) 📝 `packages/desktop-client/e2e/accounts.test.ts-snapshots/Accounts-closes-an-account-6-chromium-linux.png` (+0 -0) 📝 `packages/desktop-client/e2e/accounts.test.ts-snapshots/Accounts-creates-a-new-account-and-views-the-initial-balance-transaction-1-chromium-linux.png` (+0 -0) 📝 `packages/desktop-client/e2e/accounts.test.ts-snapshots/Accounts-creates-a-new-account-and-views-the-initial-balance-transaction-2-chromium-linux.png` (+0 -0) 📝 `packages/desktop-client/e2e/accounts.test.ts-snapshots/Accounts-creates-a-new-account-and-views-the-initial-balance-transaction-3-chromium-linux.png` (+0 -0) 📝 `packages/desktop-client/e2e/bank-sync.test.ts-snapshots/Bank-Sync-checks-the-page-visuals-1-chromium-linux.png` (+0 -0) 📝 `packages/desktop-client/e2e/bank-sync.test.ts-snapshots/Bank-Sync-checks-the-page-visuals-2-chromium-linux.png` (+0 -0) 📝 `packages/desktop-client/e2e/bank-sync.test.ts-snapshots/Bank-Sync-checks-the-page-visuals-3-chromium-linux.png` (+0 -0) 📝 `packages/desktop-client/e2e/budget.test.ts-snapshots/Budget-renders-the-summary-information-available-funds-overspent-budgeted-and-for-next-month-1-chromium-linux.png` (+0 -0) 📝 `packages/desktop-client/e2e/budget.test.ts-snapshots/Budget-renders-the-summary-information-available-funds-overspent-budgeted-and-for-next-month-2-chromium-linux.png` (+0 -0) _...and 80 more files_ </details> ### 📄 Description Adds a new top-level Forecast page (/forecast) that projects future cash flow based on all active scheduled transactions. The page appears in the sidebar between Schedules and More (Chart icon) and includes: - Summary cards: Current Balance, Projected Income, Projected Expenses, Net over period, Ending Balance - Composed chart: income/expense bars + running balance line, with configurable granularity (Day/Week/Month/Year) and a 1/3/6/12-month window - Account scope filter: All accounts, On-budget only, or Off-budget only - Monthly breakdown table: expandable rows showing Name, Payee, Account, Date, and Amount per scheduled occurrence Missed non-recurring schedule dates are bucketed into the current month rather than dropped. Related issue(s) - https://github.com/actualbudget/actual/issues/4244 Testing 1. Open the app and click Forecast in the sidebar (between Schedules and More) 2. Verify summary cards reflect current account balances and projected schedule totals 3. Change the Granularity dropdown (Day/Week/Month/Year) and confirm the chart re-buckets accordingly 4. Change the Window dropdown (1/3/6/12 months) and confirm the projection range updates 5. Change Account scope between All / On-budget / Off-budget and verify balances and schedule rows filter correctly 6. Expand rows in the monthly breakdown table and confirm Name, Payee, Account, Date, and Amount are correct 7. Confirm no regressions on the /schedules page (Forecast button removed; everything else unchanged) ▎ Tip: Use "View demo" on the setup screen to load pre-populated sample data for realistic testing. Checklist - Release notes added (see link above) - No obvious regressions in affected areas - Self-review has been performed Note Sorry in advance if this is poor, I don't normally contribute here on GitHub, I just needed this purely for my own personal use, if anyone thinks its worth anything they can use it. <!--- actual-bot-sections ---> <hr /> <!--- bundlestats-action-comment key:combined start ---> ### Bundle Stats Bundle | Files count | Total bundle size | % Changed ------ | ----------- | ----------------- | --------- desktop-client | 27 | 12.09 MB → 12.14 MB (+50.92 kB) | +0.41% loot-core | 1 | 4.83 MB | 0% api | 4 | 4.06 MB | 0% cli | 1 | 7.88 MB | 0% <details> <summary>View detailed bundle stats</summary> #### desktop-client **Total** Files count | Total bundle size | % Changed ----------- | ----------------- | --------- 27 | 12.09 MB → 12.14 MB (+50.92 kB) | +0.41% <details> <summary>Changeset</summary> File | Δ | Size ---- | - | ---- `src/components/schedules/ScheduleForecast.tsx` | 🆕 +23.25 kB | 0 B → 23.25 kB `node_modules/recharts/es6/component/Legend.js` | 🆕 +6.68 kB | 0 B → 6.68 kB `node_modules/recharts/es6/component/DefaultLegendContent.js` | 🆕 +5.49 kB | 0 B → 5.49 kB `src/components/schedules/scheduleForecastUtils.ts` | 🆕 +2.54 kB | 0 B → 2.54 kB `node_modules/es-toolkit/dist/function/debounce.js` | 🆕 +1.53 kB | 0 B → 1.53 kB `node_modules/es-toolkit/dist/compat/function/debounce.js` | 🆕 +1.26 kB | 0 B → 1.26 kB `node_modules/es-toolkit/dist/compat/function/throttle.js` | 🆕 +502 B | 0 B → 502 B `node_modules/es-toolkit/compat/throttle.js` | 🆕 +187 B | 0 B → 187 B `node_modules/recharts/es6/context/legendPayloadContext.js` | 🆕 +164 B | 0 B → 164 B `node_modules/recharts/es6/component/ResponsiveContainer.js` | 📈 +6.28 kB (+2115.79%) | 304 B → 6.58 kB `node_modules/recharts/es6/component/responsiveContainerUtils.js` | 📈 +1.82 kB (+752.63%) | 247 B → 2.06 kB `node_modules/recharts/es6/context/legendPortalContext.js` | 📈 +79 B (+52.32%) | 151 B → 230 B `src/components/sidebar/PrimaryButtons.tsx` | 📈 +329 B (+7.92%) | 4.06 kB → 4.38 kB `node_modules/d3-shape/src/math.js` | 📈 +10 B (+5.49%) | 182 B → 192 B `node_modules/recharts/es6/context/chartLayoutContext.js` | 📈 +83 B (+2.96%) | 2.73 kB → 2.82 kB `node_modules/d3-shape/src/symbol/circle.js` | 📈 +6 B (+2.94%) | 204 B → 210 B `node_modules/d3-shape/src/symbol/star.js` | 📈 +12 B (+2.14%) | 562 B → 574 B `src/components/FinancesApp.tsx` | 📈 +249 B (+1.51%) | 16.13 kB → 16.37 kB `node_modules/dnd-core/dist/contracts.js` | 📈 +14 B (+1.38%) | 1015 B → 1 kB `node_modules/d3-shape/src/symbol/triangle.js` | 📈 +4 B (+1.34%) | 299 B → 303 B `node_modules/d3-shape/src/symbol/diamond.js` | 📈 +4 B (+1.16%) | 345 B → 349 B `node_modules/d3-shape/src/symbol/square.js` | 📈 +2 B (+1.05%) | 191 B → 193 B `node_modules/recharts/es6/chart/AreaChart.js` | 📈 +4 B (+0.93%) | 432 B → 436 B `node_modules/d3-shape/src/symbol.js` | 📈 +8 B (+0.85%) | 942 B → 950 B `node_modules/d3-shape/src/symbol/wye.js` | 📈 +6 B (+0.84%) | 716 B → 722 B `node_modules/@react-dnd/invariant/dist/index.js` | 📈 +6 B (+0.82%) | 734 B → 740 B `node_modules/react-dnd/dist/hooks/useDrag/useDragType.js` | 📈 +2 B (+0.73%) | 275 B → 277 B `node_modules/react-dnd/dist/hooks/useDragDropManager.js` | 📈 +2 B (+0.71%) | 282 B → 284 B `node_modules/recharts/es6/shape/Sector.js` | 📈 +46 B (+0.65%) | 6.87 kB → 6.91 kB `node_modules/react-dnd/dist/hooks/useDrop/useAccept.js` | 📈 +2 B (+0.65%) | 308 B → 310 B `node_modules/recharts/es6/state/selectors/areaSelectors.js` | 📈 +24 B (+0.62%) | 3.79 kB → 3.81 kB `node_modules/dnd-core/dist/actions/dragDrop/hover.js` | 📈 +10 B (+0.61%) | 1.61 kB → 1.62 kB `node_modules/recharts/es6/component/Dots.js` | 📈 +24 B (+0.57%) | 4.08 kB → 4.11 kB `src/components/banksync/AccountsHeader.tsx` | 📈 +8 B (+0.56%) | 1.38 kB → 1.39 kB `node_modules/recharts/es6/shape/Dot.js` | 📈 +4 B (+0.56%) | 709 B → 713 B `node_modules/recharts/es6/util/ActiveShapeUtils.js` | 📈 +20 B (+0.51%) | 3.84 kB → 3.86 kB `src/components/admin/UserAccess/UserAccessHeader.tsx` | 📈 +6 B (+0.46%) | 1.27 kB → 1.28 kB `node_modules/dnd-core/dist/classes/HandlerRegistryImpl.js` | 📈 +16 B (+0.46%) | 3.42 kB → 3.43 kB `src/components/admin/UserDirectory/UserDirectoryHeader.tsx` | 📈 +12 B (+0.44%) | 2.65 kB → 2.67 kB `node_modules/recharts/es6/component/ActivePoints.js` | 📈 +13 B (+0.43%) | 2.96 kB → 2.98 kB `node_modules/d3-shape/src/symbol/cross.js` | 📈 +2 B (+0.41%) | 493 B → 495 B `node_modules/dnd-core/dist/actions/dragDrop/beginDrag.js` | 📈 +8 B (+0.35%) | 2.23 kB → 2.24 kB `node_modules/dnd-core/dist/actions/dragDrop/endDrag.js` | 📈 +2 B (+0.35%) | 574 B → 576 B `node_modules/react-error-boundary/dist/react-error-boundary.js` | 📈 +8 B (+0.35%) | 2.24 kB → 2.25 kB `node_modules/recharts/es6/cartesian/getCartesianPosition.js` | 📈 +20 B (+0.34%) | 5.76 kB → 5.78 kB `node_modules/recharts/es6/component/LabelList.js` | 📈 +12 B (+0.34%) | 3.46 kB → 3.47 kB `node_modules/react-dnd/dist/hooks/useDrag/useDrag.js` | 📈 +2 B (+0.30%) | 661 B → 663 B `node_modules/dnd-core/dist/classes/DragDropMonitorImpl.js` | 📈 +12 B (+0.30%) | 3.9 kB → 3.91 kB `node_modules/recharts/es6/component/Label.js` | 📈 +32 B (+0.30%) | 10.48 kB → 10.51 kB `node_modules/recharts/es6/state/cartesianAxisSlice.js` | 📈 +12 B (+0.29%) | 4 kB → 4.01 kB `node_modules/dnd-core/dist/actions/dragDrop/drop.js` | 📈 +6 B (+0.28%) | 2.06 kB → 2.06 kB `node_modules/recharts/es6/shape/Trapezoid.js` | 📈 +17 B (+0.28%) | 5.97 kB → 5.99 kB `src/components/tags/TagsHeader.tsx` | 📈 +4 B (+0.28%) | 1.42 kB → 1.42 kB `src/components/rules/RulesHeader.tsx` | 📈 +4 B (+0.25%) | 1.54 kB → 1.55 kB `src/components/banksync/FieldMapping.tsx` | 📈 +20 B (+0.24%) | 8.12 kB → 8.13 kB `src/components/banksync/AccountRow.tsx` | 📈 +10 B (+0.23%) | 4.27 kB → 4.28 kB `src/components/admin/UserDirectory/UserDirectoryRow.tsx` | 📈 +14 B (+0.22%) | 6.16 kB → 6.17 kB `node_modules/recharts/es6/polar/Pie.js` | 📈 +37 B (+0.19%) | 18.79 kB → 18.83 kB `node_modules/recharts/es6/state/selectors/lineSelectors.js` | 📈 +4 B (+0.17%) | 2.28 kB → 2.28 kB `node_modules/react-dnd/dist/internals/DragSourceMonitorImpl.js` | 📈 +4 B (+0.15%) | 2.57 kB → 2.58 kB `src/components/Background.tsx` | 📈 +2 B (+0.15%) | 1.32 kB → 1.32 kB `node_modules/recharts/es6/cartesian/CartesianGrid.js` | 📈 +17 B (+0.14%) | 11.97 kB → 11.99 kB `node_modules/recharts/es6/cartesian/XAxis.js` | 📈 +8 B (+0.12%) | 6.48 kB → 6.49 kB `node_modules/react-dnd/dist/internals/DropTargetMonitorImpl.js` | 📈 +2 B (+0.12%) | 1.65 kB → 1.65 kB `src/components/admin/UserAccess/UserAccessRow.tsx` | 📈 +6 B (+0.12%) | 5.01 kB → 5.01 kB `node_modules/recharts/es6/cartesian/CartesianAxis.js` | 📈 +14 B (+0.11%) | 12.09 kB → 12.1 kB `src/components/AppBackground.tsx` | 📈 +2 B (+0.11%) | 1.77 kB → 1.77 kB `node_modules/cmdk/dist/index.mjs` | 📈 +16 B (+0.11%) | 14.39 kB → 14.4 kB `node_modules/react-dnd/dist/internals/wrapConnectorHooks.js` | 📈 +2 B (+0.11%) | 1.82 kB → 1.82 kB `node_modules/recharts/es6/component/Text.js` | 📈 +7 B (+0.09%) | 7.34 kB → 7.35 kB `src/components/accounts/AccountEmptyMessage.tsx` | 📈 +2 B (+0.08%) | 2.47 kB → 2.47 kB `src/components/tags/TagRow.tsx` | 📈 +4 B (+0.05%) | 7.87 kB → 7.87 kB `src/components/rules/RuleRow.tsx` | 📈 +4 B (+0.04%) | 9.73 kB → 9.74 kB `src/components/modals/SelectLinkedAccountsModal.tsx` | 📈 +14 B (+0.04%) | 38.84 kB → 38.85 kB `src/components/modals/LoadBackupModal.tsx` | 📈 +2 B (+0.03%) | 6.05 kB → 6.05 kB `node_modules/recharts/es6/cartesian/Line.js` | 📈 +4 B (+0.02%) | 15.84 kB → 15.84 kB `node_modules/recharts/es6/shape/Rectangle.js` | 📈 +2 B (+0.02%) | 9.84 kB → 9.84 kB `src/components/payees/PayeeTableRow.tsx` | 📈 +2 B (+0.02%) | 12.27 kB → 12.27 kB `src/components/payees/ManagePayees.tsx` | 📈 +2 B (+0.01%) | 14.74 kB → 14.74 kB `src/components/transactions/SelectedTransactionsButton.tsx` | 📈 +2 B (+0.01%) | 16.79 kB → 16.79 kB `src/components/schedules/SchedulesTable.tsx` | 📈 +2 B (+0.01%) | 17.71 kB → 17.71 kB `src/components/reports/graphs/tableGraph/ReportTableRow.tsx` | 📉 -12 B (-0.09%) | 12.73 kB → 12.72 kB `node_modules/recharts/es6/chart/PieChart.js` | 📉 -4 B (-0.20%) | 1.96 kB → 1.96 kB `src/components/reports/graphs/tableGraph/ReportTableHeader.tsx` | 📉 -12 B (-0.28%) | 4.23 kB → 4.22 kB `node_modules/recharts/es6/state/selectors/pieSelectors.js` | 📉 -20 B (-0.54%) | 3.63 kB → 3.62 kB `node_modules/recharts/es6/shape/Symbols.js` | 📉 -39 B (-0.89%) | 4.26 kB → 4.22 kB </details> <details> <summary>View detailed bundle breakdown</summary> <div> **Added** No assets were added **Removed** No assets were removed **Bigger** Asset | File Size | % Changed ----- | --------- | --------- static/js/index.js | 3.23 MB → 3.37 MB (+143.51 kB) | +4.34% **Smaller** Asset | File Size | % Changed ----- | --------- | --------- static/js/ReportRouter.js | 1.02 MB → 953.17 kB (-92.59 kB) | -8.85% **Unchanged** Asset | File Size | % Changed ----- | --------- | --------- static/js/BackgroundImage.js | 119.98 kB | 0% static/js/FormulaEditor.js | 846.44 kB | 0% static/js/TransactionList.js | 81.29 kB | 0% static/js/ca.js | 182.91 kB | 0% static/js/da.js | 104.66 kB | 0% static/js/de.js | 174.79 kB | 0% static/js/en-GB.js | 7.16 kB | 0% static/js/en.js | 170.76 kB | 0% static/js/es.js | 182.09 kB | 0% static/js/fr.js | 177.47 kB | 0% static/js/indexeddb-main-thread-worker-e59fee74.js | 13.46 kB | 0% static/js/it.js | 166.25 kB | 0% static/js/narrow.js | 354.27 kB | 0% static/js/nb-NO.js | 152.2 kB | 0% static/js/nl.js | 108.93 kB | 0% static/js/pl.js | 88.34 kB | 0% static/js/pt-BR.js | 177.84 kB | 0% static/js/resize-observer.js | 18.03 kB | 0% static/js/sv.js | 80.58 kB | 0% static/js/th.js | 179.94 kB | 0% static/js/theme.js | 30.68 kB | 0% static/js/uk.js | 213.14 kB | 0% static/js/useTransactionBatchActions.js | 4.29 MB | 0% static/js/wide.js | 418 B | 0% static/js/workbox-window.prod.es5.js | 7.28 kB | 0% </div> </details> --- #### loot-core **Total** Files count | Total bundle size | % Changed ----------- | ----------------- | --------- 1 | 4.83 MB | 0% <details> <summary>View detailed bundle breakdown</summary> <div> **Added** No assets were added **Removed** No assets were removed **Bigger** No assets were bigger **Smaller** No assets were smaller **Unchanged** Asset | File Size | % Changed ----- | --------- | --------- kcab.worker.CwpE34S5.js | 4.83 MB | 0% </div> </details> --- #### api **Total** Files count | Total bundle size | % Changed ----------- | ----------------- | --------- 4 | 4.06 MB | 0% <details> <summary>View detailed bundle breakdown</summary> <div> **Added** No assets were added **Removed** No assets were removed **Bigger** No assets were bigger **Smaller** No assets were smaller **Unchanged** Asset | File Size | % Changed ----- | --------- | --------- index.js | 3.84 MB | 0% from-Bl-Hslp4.js | 167.73 kB | 0% multipart-parser-BnDysoMr.js | 8.1 kB | 0% src-iMkUmuwR.js | 43.64 kB | 0% </div> </details> --- #### cli **Total** Files count | Total bundle size | % Changed ----------- | ----------------- | --------- 1 | 7.88 MB | 0% <details> <summary>View detailed bundle breakdown</summary> <div> **Added** No assets were added **Removed** No assets were removed **Bigger** No assets were bigger **Smaller** No assets were smaller **Unchanged** Asset | File Size | % Changed ----- | --------- | --------- cli.js | 7.88 MB | 0% </div> </details> </details> <!--- bundlestats-action-comment key:combined end ---> --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
GiteaMirror added the pull-request label 2026-04-26 10:46:44 -05:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/actual#48901