* Add Flutter web support and web-safe storage
* Update mobile/web/index.html
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Signed-off-by: Juan José Mata <jjmata@jjmata.com>
* Product name instead of placeholder
---------
Signed-off-by: Juan José Mata <jjmata@jjmata.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
The bump-pre_release-version job was hardcoded to push to main, which
caused version bumps to land on main even when tags were created from
release branches (e.g., v0.6.7-rc.2).
This fix:
- Adds a step to detect which branch contains the tagged commit
- Prefers non-main branches (release branches) over main
- Checks out and pushes to the detected source branch
https://claude.ai/code/session_01XsxnhP8ZaGbWUMsQwA5F5V
Co-authored-by: Claude <noreply@anthropic.com>
* Add import row generation from PDF extracted data
- Add generate_rows_from_extracted_data method to PdfImport
- Add import! method to create transactions from PDF rows
- Update ProcessPdfJob to generate rows after extraction
- Update configured?, cleaned?, publishable? for PDF workflow
- Add column_keys, required_column_keys, mapping_steps
- Set bank statements to pending status for user review
- Add tests for new functionality
Closes#844
* Add tests for BankStatementExtractor
- Test transaction extraction from PDF content
- Test deduplication across chunk boundaries
- Test amount normalization for various formats
- Test graceful handling of malformed JSON responses
- Test error handling for empty/nil PDF content
* Fix supports_pdf_processing? to validate effective model
The validation was always checking @default_model, but process_pdf
allows overriding the model via parameter. This could cause a
vision-capable override model to be rejected, or a non-vision-capable
override to pass validation only to fail during processing.
Changes:
- supports_pdf_processing? now accepts optional model parameter
- process_pdf passes effective model to validation
- Raise Provider::Openai::Error inside with_provider_response for
consistent error handling
Addresses review feedback from PR#808
* Fix insert_all! bug: explicitly set import_id
Rails insert_all! on associations does NOT auto-set the foreign key.
Added import_id explicitly and use Import::Row.insert_all! directly.
Also reload rows before counting to ensure accurate count.
* Fix pending status showing as processing for bank statements with rows
When bank statement PDF imports have extracted rows, show a 'Ready for Review'
screen with a link to the confirm path instead of the 'Processing' spinner.
This addresses the PR feedback that users couldn't reach the review flow even
though rows were created.
* Gate publishable? on account.present? to prevent import failure
PDF imports are created without an account, and import! raises if account
is missing. This prevents users from hitting publish and having the job fail.
* Wrap generate_rows_from_extracted_data in transaction for atomicity
- Clear rows and reset count even when no transactions extracted
- Use transaction block to prevent partial updates on failure
- Use mapped_rows.size instead of reload for count
* Localize transactions count string with i18n helper
* Add AccountMapping step for PDF imports when account is nil
PDF imports need account selection before publishing. This adds
Import::AccountMapping to mapping_steps when account is nil,
matching the behavior of TransactionImport and TradeImport.
Addresses PR#846 feedback about account selection for PDF imports.
* Only include CategoryMapping when rows have non-empty categories
PDF extraction doesn't extract categories from bank statements,
so the CategoryMapping step would show empty. Now we only include
CategoryMapping if rows actually have non-empty category values.
This prevents showing an empty mapping step for PDF imports.
* Fix PDF import UI flow and account selection
- Add direct account selection in PDF import UI instead of AccountMapping
- AccountMapping designed for CSV imports with multiple account values
- PDF imports need single account for all transactions
- Add update action and route for imports controller
- Fix controller to handle pdf_import param format from form_with
- Show Publish button when import is publishable (account set)
- Fix stepper nav: Upload/Configure/Clean non-clickable for PDF imports
- Redirect PDF imports from configuration step (auto-configured)
- Improve AI prompt to recognize M-PESA/mobile money as bank statements
- Fix migration ordering for import_rows table columns
* Add guard for invalid account_id in imports#update
Prevents silently clearing account when invalid ID is passed.
Returns error message instead of confusing 'Account saved' notice.
* Localize step names in import nav and add account guard
- Use t() helper for all step names (Upload, Configure, Clean, Map, Confirm)
- Add guard for invalid account_id in imports#update
- Prevents silently clearing account when invalid ID is passed
* Make category column migrations idempotent
Check if columns exist before adding to prevent duplicate column
errors when migrations are re-run with new timestamps.
* Add match_path for PDF import step highlighting
Fixes step detection when path is nil by using separate match_path
for current step highlighting while keeping links disabled.
* Rename category migrations and update to Rails 7.2
- Rename class to EnsureCategoryFieldsOnImportRows to avoid conflicts
- Rename class to EnsureCategoryIconOnImportRows
- Update migration version from 7.1 to 7.2 per guidelines
- Rename files to match class names
- Add match_path for PDF import step highlighting
* Use primary (black) style for Create Account and Save buttons
* Remove match_path from auto-completed PDF steps
Only step 4 (Confirm) needs match_path for active-step detection.
Steps 1-3 are purely informational and always complete.
* Add fallback for document type translation
Handles nil or unexpected document_type values gracefully.
Also removes match_path from auto-completed PDF steps.
* Use index-based step number for mobile indicator
Fixes 'Step 5 of 4' issue when Map step is dynamically removed.
* Fix hostings_controller_test: use blank? instead of nil
Setting returns empty string not nil for unset values.
* Localize step progress label and use design token
* Fix button styling: use design system Tailwind classes
btn--primary and btn--secondary CSS classes don't exist.
Use actual design system classes from DS::Buttonish.
* Fix CRLF line endings in tags_controller_test.rb
---------
Co-authored-by: mkdev11 <jaysmth689+github@users.noreply.github.com>
* feat(mobile): optimize asset/liability display with filters
- Add NetWorthCard widget with placeholder for future net worth API
- Add side-by-side Assets/Liabilities display with tap-to-filter
- Implement CurrencyFilter widget for multi-select currency filtering
- Replace old _SummaryCard with new unified design
- Remove _CollapsibleSectionHeader in favor of filter-based navigation
The net worth section shows a placeholder as the API endpoint is not yet available.
Users can now filter accounts by type (assets/liabilities) and by currency.
https://claude.ai/code/session_01W8cQSCzmgTmTqwRJ8Ycpx3
* fix(mobile): remove unused variables and add const
- Remove unused _totalAssets, _totalLiabilities, _getPrimaryCurrency
- Add const to Text('All') widget
https://claude.ai/code/session_01W8cQSCzmgTmTqwRJ8Ycpx3
* feat(mobile): enhance dashboard with icons, long-press breakdown, and grouped view
- NetWorthCard: replace text labels with trending icons, add colored
bottom borders for asset (green) and liability (red) sections
- Add long-press gesture on asset/liability areas to show full currency
breakdown in a bottom sheet popup
- Add collapsible account type grouping (Crypto, Bank, Investment, etc.)
with type-specific icons and expand/collapse headers
- Add PreferencesService for persisting display settings
- Add "Group by Account Type" toggle in Settings screen
- Wire settings change to dashboard via GlobalKey for live updates
https://claude.ai/code/session_01W8cQSCzmgTmTqwRJ8Ycpx3
* refactor(mobile): remove welcome header from dashboard
Strip the Welcome greeting and subtitle to let the financial
overview take immediate focus.
https://claude.ai/code/session_01W8cQSCzmgTmTqwRJ8Ycpx3
* feat(mobile): compact filter buttons with scroll-wheel currency switcher
- Remove trending icons from asset/liability filter buttons
- Increase amount font size to titleMedium bold
- Reduce Net Worth section and filter button padding
- Show single currency at a time with ListWheelScrollView for
scrolling between currencies (wheel-picker style)
- Absorb scroll events via NotificationListener to prevent
triggering pull-to-refresh
- Keep icons in the long-press currency breakdown popup
https://claude.ai/code/session_01W8cQSCzmgTmTqwRJ8Ycpx3
* fix(mobile): prevent bottom sheet overflow with ConstrainedBox
Use ConstrainedBox + ListView.separated with shrinkWrap for the
currency breakdown popup. Few currencies: sheet sizes to content.
Many currencies: caps at 50% screen height and scrolls.
Also add isScrollControlled and useSafeArea to showModalBottomSheet.
https://claude.ai/code/session_01W8cQSCzmgTmTqwRJ8Ycpx3
* fix(mobile): reload dashboard preferences on any tab switch to Home
Previously only reloaded when navigating directly from Settings to
Home. Now reloads whenever the Home tab is selected, covering paths
like Settings -> More -> Home.
https://claude.ai/code/session_01W8cQSCzmgTmTqwRJ8Ycpx3
* chore(mobile): simplify net worth placeholder to single line
Replace the two-line Net Worth / -- placeholder with a compact
"Net Worth — coming soon" label while the API endpoint is pending.
https://claude.ai/code/session_01W8cQSCzmgTmTqwRJ8Ycpx3
---------
Co-authored-by: Claude <noreply@anthropic.com>
* style: adjust the bottom position of the transaction selection bar and remove unnecessary padding from transaction forms
* fix: prevent overlap with the navbar in PWA mode
* fix: prevent selection bar overlap with navbar in PWA mode
* Update _selection_bar.html.erb
Signed-off-by: Number Eight <55629655+CylonN8@users.noreply.github.com>
* Update _selection_bar.html.erb
Signed-off-by: Number Eight <55629655+CylonN8@users.noreply.github.com>
---------
Signed-off-by: Number Eight <55629655+CylonN8@users.noreply.github.com>
* fix: lunchflow parity with simplefin/plaid pending behaviour
* fix: don't suggest duplicate if both entries are pending
* refactor: reuse the same external_id for re-synced pending transactions
* chore: replace illogical duplicate collision test with multiple sync test
* fix: prevent duplicates when users edit pending lunchflow transactions
* chore: add test for preventing duplicates when users edit pending lunchflow transactions
* fix: normalise extra hash keys for pending detection
* feat(mobile): Add transaction display on calendar date tap
Implement two-tap interaction for calendar dates:
- First tap selects a date (highlighted with thicker primary color border)
- Second tap on same date shows AlertDialog with transactions for that day
Each transaction displays with:
- Color-coded icon (red minus for expenses, green plus for income)
- Transaction name as title
- Notes as subtitle (if present)
- Amount with color matching expense/income
Selection is cleared when changing account, account type, or month.
https://claude.ai/code/session_019m7ZrCakU6h9xLwD1NTx9i
* feat(mobile): optimize asset/liability display with filters
- Add NetWorthCard widget with placeholder for future net worth API
- Add side-by-side Assets/Liabilities display with tap-to-filter
- Implement CurrencyFilter widget for multi-select currency filtering
- Replace old _SummaryCard with new unified design
- Remove _CollapsibleSectionHeader in favor of filter-based navigation
The net worth section shows a placeholder as the API endpoint is not yet available.
Users can now filter accounts by type (assets/liabilities) and by currency.
https://claude.ai/code/session_01W8cQSCzmgTmTqwRJ8Ycpx3
* fix(mobile): remove unused variables and add const
- Remove unused _totalAssets, _totalLiabilities, _getPrimaryCurrency
- Add const to Text('All') widget
https://claude.ai/code/session_01W8cQSCzmgTmTqwRJ8Ycpx3
* feat(mobile): enhance dashboard with icons, long-press breakdown, and grouped view
- NetWorthCard: replace text labels with trending icons, add colored
bottom borders for asset (green) and liability (red) sections
- Add long-press gesture on asset/liability areas to show full currency
breakdown in a bottom sheet popup
- Add collapsible account type grouping (Crypto, Bank, Investment, etc.)
with type-specific icons and expand/collapse headers
- Add PreferencesService for persisting display settings
- Add "Group by Account Type" toggle in Settings screen
- Wire settings change to dashboard via GlobalKey for live updates
https://claude.ai/code/session_01W8cQSCzmgTmTqwRJ8Ycpx3
* refactor(mobile): remove welcome header from dashboard
Strip the Welcome greeting and subtitle to let the financial
overview take immediate focus.
https://claude.ai/code/session_01W8cQSCzmgTmTqwRJ8Ycpx3
* feat(mobile): compact filter buttons with scroll-wheel currency switcher
- Remove trending icons from asset/liability filter buttons
- Increase amount font size to titleMedium bold
- Reduce Net Worth section and filter button padding
- Show single currency at a time with ListWheelScrollView for
scrolling between currencies (wheel-picker style)
- Absorb scroll events via NotificationListener to prevent
triggering pull-to-refresh
- Keep icons in the long-press currency breakdown popup
https://claude.ai/code/session_01W8cQSCzmgTmTqwRJ8Ycpx3
* feat: Add API key login option to mobile app
Add a "Via API Key Login" button on the login screen that opens a
dialog for entering an API key. The API key is validated by making a
test request to /api/v1/accounts with the X-Api-Key header, and on
success is persisted in secure storage. All HTTP services now use a
centralized ApiConfig.getAuthHeaders() helper that returns the correct
auth header (X-Api-Key or Bearer) based on the current auth mode.
https://claude.ai/code/session_01DnyCzdMjVpSsbBZK3XbzUH
* fix: Improve API key dialog context handling and controller disposal
- Use outer context for SnackBar so it displays on the main screen
instead of behind the dialog
- Explicitly dispose TextEditingController to prevent memory leaks
- Close dialog on failure before showing error SnackBar for better UX
- Avoid StatefulBuilder context parameter shadowing
https://claude.ai/code/session_01DnyCzdMjVpSsbBZK3XbzUH
* fix: Use user-friendly error message in API key login catch block
Log the technical exception details via LogService.instance.error and
show a generic "Unable to connect" message to the user instead of
exposing the raw exception string.
https://claude.ai/code/session_01DnyCzdMjVpSsbBZK3XbzUH
* fix: Use getValidAccessToken() in connectivity banner sync button
Replace direct authProvider.tokens?.accessToken access with
getValidAccessToken() so the Sync Now button works in API-key
auth mode where _tokens is null.
https://claude.ai/code/session_01DnyCzdMjVpSsbBZK3XbzUH
* Revert "fix: Use getValidAccessToken() in connectivity banner sync button"
This reverts commit 7015c160f0.
* Reapply "fix: Use getValidAccessToken() in connectivity banner sync button"
This reverts commit b29e010de3.
* fix: Use getValidAccessToken() in connectivity banner sync button
Replace direct authProvider.tokens?.accessToken access with
getValidAccessToken() so the Sync Now button works in API-key
auth mode where _tokens is null.
https://claude.ai/code/session_01DnyCzdMjVpSsbBZK3XbzUH
* fix(mobile): prevent bottom sheet overflow with ConstrainedBox
Use ConstrainedBox + ListView.separated with shrinkWrap for the
currency breakdown popup. Few currencies: sheet sizes to content.
Many currencies: caps at 50% screen height and scrolls.
Also add isScrollControlled and useSafeArea to showModalBottomSheet.
https://claude.ai/code/session_01W8cQSCzmgTmTqwRJ8Ycpx3
* fix: Prevent multiple syncs and handle auth errors in connectivity banner
Set _isSyncing immediately on tap to disable the button during token
refresh, wrap getValidAccessToken() in try/catch with user-facing error
snackbar, and await _handleSync so errors propagate correctly.
https://claude.ai/code/session_01GgVgjqwyXhWMZN3eWfaMCk
---------
Signed-off-by: Lazy Bone <89256478+dwvwdv@users.noreply.github.com>
Co-authored-by: Claude <noreply@anthropic.com>
Implement two-tap interaction for calendar dates:
- First tap selects a date (highlighted with thicker primary color border)
- Second tap on same date shows AlertDialog with transactions for that day
Each transaction displays with:
- Color-coded icon (red minus for expenses, green plus for income)
- Transaction name as title
- Notes as subtitle (if present)
- Amount with color matching expense/income
Selection is cleared when changing account, account type, or month.
https://claude.ai/code/session_019m7ZrCakU6h9xLwD1NTx9i
Co-authored-by: Claude <noreply@anthropic.com>
* test: Add tests for uncategorized filter across all locales
Adds two tests to catch the bug where filtering for "Uncategorized"
transactions fails when the user's locale is not English:
1. Tests that filtering with the locale-specific uncategorized name
works correctly in all SUPPORTED_LOCALES
2. Tests that filtering with the English "Uncategorized" parameter
works regardless of the current locale (catches the French bug)
https://claude.ai/code/session_01JcKj4776k5Es8Cscbm4kUo
* fix: Fix uncategorized filter for French, Catalan, and Dutch locales
The uncategorized filter was failing when the URL parameter contained
"Uncategorized" (English) but the user's locale was different. This
affected 3 locales with non-English translations:
- French: "Non catégorisé"
- Catalan: "Sense categoria"
- Dutch: "Ongecategoriseerd"
The fix adds Category.all_uncategorized_names which returns all possible
uncategorized name translations across supported locales, and updates
the search filter to check against all variants instead of just the
current locale's translation.
https://claude.ai/code/session_01JcKj4776k5Es8Cscbm4kUo
---------
Co-authored-by: Claude <noreply@anthropic.com>
* feat: Add API key login option to mobile app
Add a "Via API Key Login" button on the login screen that opens a
dialog for entering an API key. The API key is validated by making a
test request to /api/v1/accounts with the X-Api-Key header, and on
success is persisted in secure storage. All HTTP services now use a
centralized ApiConfig.getAuthHeaders() helper that returns the correct
auth header (X-Api-Key or Bearer) based on the current auth mode.
https://claude.ai/code/session_01DnyCzdMjVpSsbBZK3XbzUH
* fix: Improve API key dialog context handling and controller disposal
- Use outer context for SnackBar so it displays on the main screen
instead of behind the dialog
- Explicitly dispose TextEditingController to prevent memory leaks
- Close dialog on failure before showing error SnackBar for better UX
- Avoid StatefulBuilder context parameter shadowing
https://claude.ai/code/session_01DnyCzdMjVpSsbBZK3XbzUH
* fix: Use user-friendly error message in API key login catch block
Log the technical exception details via LogService.instance.error and
show a generic "Unable to connect" message to the user instead of
exposing the raw exception string.
https://claude.ai/code/session_01DnyCzdMjVpSsbBZK3XbzUH
---------
Co-authored-by: Claude <noreply@anthropic.com>
* Fix budget category totals to net refunds against expenses
Budget spending calculations now subtract refunds (negative transactions
classified as income) from expense totals in the same category. Previously,
refunds were excluded entirely, causing budgets to show gross spending
instead of net spending.
Fixes#314
* Handle missing git binary in commit_sha initializer
Rescues Errno::ENOENT when git is not installed, falling back to
BUILD_COMMIT_SHA env var or "unknown". Fixes crash in Docker
development containers that lack git.
* Revert "Handle missing git binary in commit_sha initializer"
This reverts commit 7e58458faa.
* Subtract uncategorized refunds from overall budget spending
Uncategorized refunds were not being netted against actual_spending
because the synthetic uncategorized category has no persisted ID and
wasn't matched by the budget_categories ID set. Now checks for
category.uncategorized? in addition to the ID lookup.
* perf: optimize budget category actual spending calculation
* feat: Add PDF import with AI-powered document analysis
This enhances the import functionality to support PDF files with AI-powered
document analysis. When a PDF is uploaded, it is processed by AI to:
- Identify the document type (bank statement, credit card statement, etc.)
- Generate a summary of the document contents
- Extract key metadata (institution, dates, balances, transaction count)
After processing, an email is sent to the user asking for next steps.
Key changes:
- Add PdfImport model for handling PDF document imports
- Add Provider::Openai::PdfProcessor for AI document analysis
- Add ProcessPdfJob for async PDF processing
- Add PdfImportMailer for user notification emails
- Update imports controller to detect and handle PDF uploads
- Add PDF import option to the new import page
- Add i18n translations for all new strings
- Add comprehensive tests for the new functionality
* Add bank statement import with AI extraction
- Create ImportBankStatement assistant function for MCP
- Add BankStatementExtractor with chunked processing for small context windows
- Register function in assistant configurable
- Make PdfImport#pdf_file_content public for extractor access
- Increase OpenAI request timeout to 600s for slow local models
- Increase DB connection pool to 20 for concurrent operations
Tested with M-Pesa bank statement via remote Ollama (qwen3:8b):
- Successfully extracted 18 transactions
- Generated CSV and created TransactionImport
- Works with 3000 char chunks for small context windows
* Add pdf-reader gem dependency
The BankStatementExtractor uses PDF::Reader to parse bank statement
PDFs, but the gem was not properly declared in the Gemfile. This would
cause NameError in production when processing bank statements.
Added pdf-reader ~> 2.12 to Gemfile dependencies.
* Fix transaction deduplication to preserve legitimate duplicates
The previous deduplication logic removed ALL duplicate transactions based
on [date, amount, name], which would drop legitimate same-day duplicates
like multiple ATM withdrawals or card authorizations.
Changed to only deduplicate transactions that appear in consecutive chunks
(chunking artifacts) while preserving all legitimate duplicates within the
same chunk or non-adjacent chunks.
* Refactor bank statement extraction to use public provider method
Address code review feedback:
- Add public extract_bank_statement method to Provider::Openai
- Remove direct access to private client via send(:client)
- Update ImportBankStatement to use new public method
- Add require 'set' to BankStatementExtractor
- Remove PII-sensitive content from error logs
- Add defensive check for nil response.error
- Handle oversized PDF pages in chunking logic
- Remove unused process_native and process_generic methods
- Update email copy to reflect feature availability
- Add guard for nil document_type in email template
- Document pdf-reader gem rationale in Gemfile
Tested with both OpenAI (gpt-4o) and Ollama (qwen3:8b):
- OpenAI: 49 transactions extracted in 30s
- Ollama: 40 transactions extracted in 368s
- All encapsulation and error handling working correctly
* Update schema.rb with ai_summary and document_type columns
* Address PR #808 review comments
- Rename :csv_file to :import_file across controllers/views/tests
- Add PDF test fixture (sample_bank_statement.pdf)
- Add supports_pdf_processing? method for graceful degradation
- Revert unrelated database.yml pool change (600->3)
- Remove month_start_day schema bleed from other PR
- Fix PdfProcessor: use .strip instead of .strip_heredoc
- Add server-side PDF magic byte validation
- Conditionally show PDF import option when AI provider available
- Fix ProcessPdfJob: sanitize errors, handle update failure
- Move pdf_file attachment from Import to PdfImport
- Document deduplication logic limitations
- Fix ImportBankStatement: catch specific exceptions only
- Remove unnecessary require 'set'
- Remove dead json_schema method from PdfProcessor
- Reduce default OpenAI timeout from 600s to 60s
- Fix nil guard in text mailer template
- Add require 'csv' to ImportBankStatement
- Remove Gemfile pdf-reader comment
* Fix RuboCop indentation in ProcessPdfJob
* Refactor PDF import check to use model predicate method
Replace is_a?(PdfImport) type check with requires_csv_workflow? predicate
that leverages STI inheritance for cleaner controller logic.
* Fix missing 'unknown' locale key and schema version mismatch
- Add 'unknown: Unknown Document' to document_types locale
- Fix schema version to match latest migration (2026_01_24_180211)
* Document OPENAI_REQUEST_TIMEOUT env variable
Added to .env.local.example and docs/hosting/ai.md
* Rename ALLOWED_MIME_TYPES to ALLOWED_CSV_MIME_TYPES for clarity
* Add comment explaining requires_csv_workflow? predicate
* Remove redundant required_column_keys from PdfImport
Base class already returns [] by default
* Add ENV toggle to disable PDF processing for non-vision endpoints
OPENAI_SUPPORTS_PDF_PROCESSING=false can be used for OpenAI-compatible
endpoints (e.g., Ollama) that don't support vision/PDF processing.
* Wire up transaction extraction for PDF bank statements
- Add extracted_data JSONB column to imports
- Add extract_transactions method to PdfImport
- Call extraction in ProcessPdfJob for bank statements
- Store transactions in extracted_data for later review
* Fix ProcessPdfJob retry logic, sanitize and localize errors
- Allow retries after partial success (classification ok, extraction failed)
- Log sanitized error message instead of raw message to avoid data leakage
- Use i18n for user-facing error messages
* Add vision-capable model validation for PDF processing
* Fix drag-and-drop test to use correct field name csv_file
* Schema bleedover from another branch
* Fix drag-drop import form field name to match controller
* Add vision capability guard to process_pdf method
---------
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: mkdev11 <jaysmth689+github@users.noreply.github.com>
Co-authored-by: Juan José Mata <jjmata@jjmata.com>
* feat: add valuations API endpoints for managing account reconciliations
* refactor: formatting
* fix: make account extraction clearer
* feat: validation and error handling improvements
* feat: transaction
* feat: error handling
* Add API documentation LLM context
* Make it easier for people
* feat: transaction in creation
* feat: add OpenAPI spec for Valuations API
* fix: update notes validation to check for key presence
* Prevent double render
* All other docs use `apiKeyAuth`
* More `apiKeyAuth`
* Remove testing assertions from API doc specs
* fix: correct valuation entry references
---------
Signed-off-by: Juan José Mata <juanjo.mata@gmail.com>
Co-authored-by: Juan José Mata <juanjo.mata@gmail.com>
* Preserve existing demo data by default
Add SKIP_CLEAR environment variable to demo_data rake tasks.
Defaults to true (preserving existing data). Set SKIP_CLEAR=0
to wipe data before generating new demo data.
https://claude.ai/code/session_01GcoMc2SH3czPrbeGkHbmpE
* Add deterministic instatus.com API key for demo data
Create a read-only API key named "instatus.com" with a fixed value
when generating demo data. This allows uptime monitoring tools to
use a hardcoded API key that doesn't change between demo data runs.
The key is idempotent - if it already exists, it will be reused.
https://claude.ai/code/session_01GcoMc2SH3czPrbeGkHbmpE
* OK to name instatus to a point
* Remove all Instatus references
* Rename to create_monitoring_api_key! and scope lookup to admin_user
- Rename create_instatus_api_key! to create_monitoring_api_key! (snake_case)
- Scope API key lookup to admin_user instead of global ApiKey lookup
- Each family's admin now has their own monitoring API key
https://claude.ai/code/session_01GcoMc2SH3czPrbeGkHbmpE
---------
Co-authored-by: Claude <noreply@anthropic.com>
* pwa(cleanup): enforce LF, head meta + icons, manifest orientation, remove static webmanifest
* pwa(cleanup): add gitattributes, head meta/icons, manifest orientation; remove static manifest; small nav & dashboard fixes
* pwa(cleanup): improve transaction drawer header layout with inline close button
* fix: address PR review feedback
- Add dom_id to transaction header for Turbo Stream updates (Codex)
- Add pending badge next to date when transaction is pending (CodeRabbit)
- Make close button keyboard-focusable by removing tabindex=-1 (CodeRabbit)
- Fix settings nav horizontal scroll with flex-nowrap space-x-1 (CodeRabbit)
* fix: localize 'Linked with Plaid' tooltip string (CodeRabbit)
* Update .gitattributes
Better comment smh
* fix: align transaction/transfer dialog icons and update transfer drawer pattern
- Fix icon alignment in transaction header (items-center instead of items-start)
- Make transfer/linked icons consistent size and color
- Update transfers/show.html.erb to use frame: drawer with hide_close_icon pattern
- Match transfer dialog header layout with transaction details
* fix: enhance header layout
This in the transaction and transfer views, with consistent icon placement
* fix: remove fixed height from HTML document class
basically a regression issue pretty sure
* fix: update dialog rendering to use 'frame' and hide close icon in headers
* fix: update transaction type tabs layout for improved responsiveness
* fix: conditionally render transaction type tabs based on account type
* feat: Add CORS support for Flutter mobile client
Add rack-cors gem and configure CORS for API and OAuth endpoints
to enable cross-origin requests from mobile clients and other
external applications.
https://claude.ai/code/session_01RJ6MKLkjBv7x5AQLEUn8AF
* feat: Add /sessions/* to CORS for webview authentication
Enable CORS for session endpoints to support webview-based
authentication flows in the Flutter mobile client.
https://claude.ai/code/session_01RJ6MKLkjBv7x5AQLEUn8AF
* test: Add integration tests for CORS configuration
Test that CORS middleware is configured and returns proper headers
for API, OAuth, and session endpoints including preflight requests.
https://claude.ai/code/session_01RJ6MKLkjBv7x5AQLEUn8AF
* Gemfile.lock
---------
Co-authored-by: Claude <noreply@anthropic.com>
* Add warning for TwelveData plan-restricted tickers
Fixes#800
- Add Security::PlanRestrictionTracker concern using Rails cache
- Detect plan upgrade errors during Security::Price::Importer sync
- Display amber warning on /settings/hosting with affected tickers
- Include unit tests for the new functionality
* Scope plan restriction cache by provider
Addresses review feedback:
- Cache key now includes provider name to support multiple data providers
- Methods now require provider parameter for proper scoping
- Added tests for provider-scoped restrictions
- Added documentation explaining instance-level API key architecture
* Fix RuboCop array bracket spacing
* Fix empty array bracket spacing
* Move plan upgrade detection to Provider::TwelveData
* Fix provider scoping tests to use direct cache writes
---------
Co-authored-by: mkdev11 <jaysmth689+github@users.noreply.github.com>
* feat: Move upcoming transactions in a dedicated tab
* Adjust formatting
* feat: adjust visibility on mobile
* feat: change translation label
* feat: show only upcoming transactions expected in the next 10 days
* feat: show upcoming transactions tab only when option enabled
* feat: render empty partial when there are no recurring transactions
* feat: align icon sizing and spacing between transactions and upcoming sections
* feat: add missing localitazion labels
* fix: move filter on upcoming transactions in controller
* fix: add missing localitazion labels
* fix: Handle uncategorized transactions filter correctly
When filtering for 'Uncategorized' transactions, the filter was not working
because 'Uncategorized' is a virtual category (Category.uncategorized returns
a non-persisted Category object) and does not exist in the database.
The filter was attempting to match 'categories.name IN (Uncategorized)' which
returned zero results.
This fix removes 'Uncategorized' from the category names array before querying
the database, allowing the existing 'category_id IS NULL' condition to work
correctly.
Fixes filtering for uncategorized transactions while maintaining backward
compatibility with all other category filters.
* test: Add comprehensive tests for Uncategorized filter
- Test filtering for only uncategorized transactions
- Test combining uncategorized with real categories
- Test excluding uncategorized when not in filter
- Ensures fix prevents regression
* refactor: Use Category.uncategorized.name for i18n support
- Replace hard-coded 'Uncategorized' string with Category.uncategorized.name
- Conditionally build SQL query based on include_uncategorized flag
- Avoid adding category_id IS NULL clause when not needed
- Update tests to use Category.uncategorized.name for consistency
- Cleaner logic: only include uncategorized condition when requested
Addresses code review feedback on i18n support and query optimization.
* test: Fix travel category fixture error
Create travel category dynamically instead of using non-existent fixture
* style: Fix rubocop spacing in array brackets
---------
Co-authored-by: Charsel <charsel@charsel.com>
* Update chart version in pre-release bump
Keep Helm chart version and appVersion aligned with app releases.
* Publish Helm chart with releases
Package the Helm chart on tag releases, upload it to GitHub Pages, and attach it to the GitHub Release assets.
* Move Helm chart release to helm workflow
Publish Helm chart packages from the helm-release workflow on tags and keep publish.yml focused on app release assets.
* Derive nightly chart version from latest release
Use the most recent v* tag as the base for nightly Helm chart versions.
* Add transaction type condition filter for rules
Add ability to filter rules by transaction type (income, expense, transfer).
This allows users to create rules that differentiate between transactions
with the same name but different types.
- Add Rule::ConditionFilter::TransactionType with select dropdown
- Register in TransactionResource condition_filters
- Add tests for income, expense, and transfer filtering
Closes#373
* Address PR review feedback for transaction type filter
- Fix income filter to exclude transfers and investment_contribution
- Fix expense filter to include investment_contribution regardless of sign
- Add i18n for option and operator labels
- Add tests for edge cases (transfer inflows, investment contributions)
Logic now matches Transaction::Search#apply_type_filter for consistency.
- Move family-scoped queries to models via family_scope class method
- Remove hardcoded model names from Enrichable concern
- Replace inline rescue with proper respond_to? check
- Add count tracking for better logging
- Preserve user locks: Only unlock attributes where current value still matches
what AI set. If user changed the value, they took ownership.
- Add nil guard clause for family parameter in ClearAiCacheJob
- Add partial failure handling so one model's failure doesn't block the other
Add ClearAiCacheJob for async cache clearing with low priority. Extend Enrichable concern with clear_ai_cache methods to unlock AI-enriched attributes and delete AI enrichment records. Trigger automatic cache clearing when OpenAI model setting changes.
* Generalize pre-release bump workflow
Handle alpha, beta, and rc tags when incrementing the version.
* Change commit message for version bump in workflow
Signed-off-by: Juan José Mata <juanjo.mata@gmail.com>
---------
Signed-off-by: Juan José Mata <juanjo.mata@gmail.com>
* First commit
* Use subscription flow for monetary contributions
* Removed only part of the SPAN
* Localize Stripe payments message
* More localization of contribution strings
* Missed two billing to payment changes
* Fix tests
* Localization of "Open Demo" strings
* Fix grammar error
* Update for consistency
* Localize CTA
* More localilzation strings
---------
Signed-off-by: Juan José Mata <juanjo.mata@gmail.com>