* feat: adjust padding and icon sizing in outflows chart
* fix: Remove extra div in reports page to fix layout issues on mobile
* fix: Padding adjustments to keep pages consistent
* fix: Align report page with main
- Introduced `update_access_url!` method to reuse existing SimpleFIN items during reconnections, preserving account linkages.
- Refactored `SimplefinConnectionUpdateJob` to update access URLs in place without creating new items or transferring accounts.
- Adjusted sync logic to leverage `repair_stale_linkages` for seamless reconnections.
- Enhanced `SimplefinItem::Importer` to auto-recover the `good` status if no auth errors are found during sync.
- Updated tests to validate in-place updates and preserved account relationships.
Co-authored-by: Josh Waldrep <joshua.waldrep5+github@gmail.com>
- Added a new test to validate how dormant credit cards with zero balance and negative available balance are processed.
- Updated processor logic to ensure `current_balance` takes precedence when explicitly set to zero, preventing incorrect usage of `available_balance`.
Co-authored-by: Josh Waldrep <joshua.waldrep5+github@gmail.com>
Mobile and desktop transaction category menus now use
variant-specific DOM IDs and the turbo stream response
updates both targets. This prevents duplicate IDs that
caused the menu not to close on first click on desktop.
- Updated `PLAID_TYPE_TO_LABEL` in `TransactionsProcessor` to consolidate labels ("Cancel" and "Cash" now mapped to "Other").
- Adjusted `label_from_plaid_type` to return "Other" as the default fallback.
- Enhanced tests to include additional valid activity labels and ensure label consistency.
- Minor fixes to locale keys for transaction views.
- Removed `exclude_from_cashflow` attribute across models, controllers, and views.
- Updated queries to rely solely on the `excluded` flag for filtering transactions and entries.
- Simplified migration by consolidating `exclude_from_cashflow` functionality into the existing `excluded` toggle.
- Refactored related tests to remove outdated logic and ensured compatibility with the updated implementation.
- Deleted the `InvestmentActivityDetector` and associated tests.
- Removed rake tasks for backfilling and clearing investment activity labels.
- Simplified transaction processing in `SimplefinEntry::Processor` by removing inferred activity label logic.
- Added new rule `SetInvestmentActivityLabel` for setting labels using rules.
- Updated `Rule::Registry::TransactionResource` to include the new rule executor.
- Introduced `InvestmentActivityDetector` to mark internal investment activity as excluded from cashflow and assign appropriate labels.
- Added `exclude_from_cashflow` flag to `entries` and `investment_activity_label` to `transactions` with migrations.
- Implemented rake tasks to backfill and clear investment activity labels.
- Updated `PlaidAccount::Investments::TransactionsProcessor` to map Plaid transaction types to labels.
- Included comprehensive test coverage for new functionality.
* Print initial impl
* Try to keep the bigger section together
* /* Tufte-inspired Print Report Styles */
* styling
* I8n
* Move print styling out.
* FIX unrelated test ordering
on line 53 - import.rows.first doesn't guarantee ordering. Without an explicit ORDER BY, the database may return rows in any order.
* Update print-report.css
* Update print.html.erb
* pass data to view
* Update index.html.erb
* Fix ERB helpers
* Update reports_helper.rb
* Add cost basis tracking and management to holdings
- Added migration to introduce `cost_basis_source` and `cost_basis_locked` fields to `holdings`.
- Implemented backfill for existing holdings to set `cost_basis_source` based on heuristics.
- Introduced `Holding::CostBasisReconciler` to manage cost basis resolution logic.
- Added user interface components for editing and locking cost basis in holdings.
- Updated `materializer` to integrate reconciliation logic and respect locked holdings.
- Extended tests for cost basis-related workflows to ensure accuracy and reliability.
* Fix cost basis calculation in holdings controller
- Ensure `cost_basis` is converted to decimal for accurate arithmetic.
- Fix conditional check to properly validate positive `cost_basis`.
* Improve cost basis validation and error handling in holdings controller
- Allow zero as a valid cost basis for gifted/inherited shares.
- Add error handling with user feedback for invalid cost basis values.
---------
Co-authored-by: Josh Waldrep <joshua.waldrep5+github@gmail.com>
- Refactored `persist_holdings` to separate and conditionally upsert holdings with and without cost_basis.
- Updated `avg_cost` logic to treat 0 cost_basis as unknown and return nil when cost_basis cannot be determined.
- Modified trend and investment calculation to exclude holdings with unknown cost_basis.
- Adjusted `average_cost` formatting to handle nil values in API responses and views.
- Added comprehensive tests to ensure cost_basis preservation and fallback behavior.
- Localized `unknown` label for display when cost_basis is unavailable.
Co-authored-by: Josh Waldrep <joshua.waldrep5+github@gmail.com>
Backend fixes:
- Fix duplicate AssistantResponseJob triggering causing duplicate AI responses
- UserMessage model already handles job triggering via after_create_commit callback
- Remove redundant job enqueue in chats_controller and messages_controller
Mobile app features:
- Implement complete AI chat interface and conversation management
- Add Chat, Message, and ToolCall data models
- Add ChatProvider for state management with polling mechanism
- Add ChatService to handle all chat-related API requests
- Add chat list screen (ChatListScreen)
- Add conversation detail screen (ChatConversationScreen)
- Refactor navigation structure with bottom navigation bar (MainNavigationScreen)
- Add settings screen (SettingsScreen)
- Optimize TransactionsProvider to support account filtering
Technical details:
- Implement message polling mechanism for real-time AI responses
- Support chat creation, deletion, retry and other operations
- Integrate Material Design 3 design language
- Improve user experience and error handling
Co-authored-by: dwvwdv <dwvwdv@protonmail.com>
* Generic LLMs improvements
1. app/models/provider/openai/auto_categorizer.rb:535-540
- If description is blank, now falls back to merchant name
2. app/models/provider/openai/auto_merchant_detector.rb:492-498
- Now includes merchant first, then description (joined with " - ")
* FIX linter
The TotalsRow struct was expanded from 5 to 6 fields in commit a4f70f4
(adding is_uncategorized_investment), but cached data from the old
5-field struct causes "struct size differs" errors when deserialized.
This adds a cache version ("v2") to the totals_query cache key to
invalidate all old cached structs and force recalculation with the
new 6-field definition.
Fixes: TypeError (struct IncomeStatement::Totals::TotalsRow not compatible (struct size differs))
Co-authored-by: Claude <noreply@anthropic.com>
* feat(zh-TW): add Traditional Chinese localization support
Integrates comprehensive zh-TW locale files across UI, models, emails, and helpers.
Updates language mapping for Chinese (Traditional) and adds translations for various modules.
Establishes full Traditional Chinese support in the app.
* feat(locales): add zh-TW translations
Add comprehensive Traditional Chinese (zh-TW) translations for UI, defaults,
Doorkeeper, mailers, models, and views to provide full Taiwanese localization
and improve wording consistency.
Replace and update several existing zh-TW entries for clarity and consistency.
Also expose the Postgres port in the example compose for easier local
development and apply minor locale/typo/whitespace fixes.
* feat(locales): add zh-TW translations
Add Traditional Chinese (zh-TW) locale files across many views and settings
to provide Taiwanese localization. Introduce updated translations for
authentication, onboarding, settings, integrations (Plaid, SimpleFin,
Lunch Flow), accounts, reports, and various resource pages.
Remove or replace legacy locale files to align with the revamped i18n
structure and copy organization. This enables full zh-TW support for the UI.
* chore(docker): remove published Postgres port
Remove the published Postgres port mapping (5432) from the example
docker-compose file to avoid exposing the database to the host and to
prevent accidental port conflicts. Keeps the example more secure and
focused on internal service networking.
* docs(i18n): 統一 SimpleFIN 在繁體中文翻譯的大小寫
將 zh-TW 翻譯中所有出現的 "SimpleFin" 更新為品牌正確的 "SimpleFIN",
包含標題、提示文字、成功/錯誤訊息及表單標籤,以維持品牌名稱一致性
並提升使用者介面的翻譯準確性。
* Add pending transaction handling and duplicate reconciliation logic
- Implemented logic to exclude pending transactions from budgets and analytics calculations.
- Introduced mechanisms for reconciling pending transactions with posted versions.
- Added duplicate detection with support for merging or dismissing matches.
- Updated transaction search filters to include a `status_filter` for pending/confirmed transactions.
- Introduced UI elements for reviewing and resolving duplicates.
- Enhanced `ProviderSyncSummary` with stats for reconciled and stale pending transactions.
* Refactor translation handling and enhance transaction and sync logic
- Moved hardcoded strings to locale files for improved translation support.
- Refined styling for duplicate transaction indicators and sync summaries.
- Improved logic for excluding stale pending transactions and updating timestamps on batch exclusion.
- Added unique IDs to status filters for better element targeting in UI.
- Optimized database queries to avoid N+1 issues in stale pending calculations.
* Add sync settings and enhance pending transaction handling
- Introduced a new "Sync Settings" section in hosting settings with UI to toggle inclusion of pending transactions.
- Updated handling of pending transactions with improved inference logic for `posted=0` and `transacted_at` in processors.
- Added priority order for pending transaction inclusion: explicit argument > environment variable > runtime configurable setting.
- Refactored settings and controllers to store updated sync preferences.
* Refactor sync settings and pending transaction reconciliation
- Extracted logic for pending transaction reconciliation, stale exclusion, and unmatched tracking into dedicated methods for better maintainability.
- Updated sync settings to infer defaults from multiple provider environment variables (`SIMPLEFIN_INCLUDE_PENDING`, `PLAID_INCLUDE_PENDING`).
- Refined UI and messaging to handle multi-provider configurations in sync settings.
# Conflicts:
# app/models/simplefin_item/importer.rb
* Debounce transaction reconciliation during imports
- Added per-run reconciliation debouncing to prevent repeated scans for the same account during chunked history imports.
- Trimmed size of reconciliation stats to retain recent details only.
- Introduced error tracking for reconciliation steps to improve UI visibility of issues.
* Apply ABS() in pending transaction queries and improve error handling
- Updated pending transaction logic to use ABS() for consistent handling of negative amounts.
- Adjusted amount bounds calculations to ensure accuracy for both positive and negative values.
- Refined exception handling in `merge_duplicate` to log failures and update user alert.
- Replaced `Date.today` with `Date.current` in tests to ensure timezone consistency.
- Minor optimization to avoid COUNT queries by loading limited records directly.
* Improve error handling in duplicate suggestion and dismissal logic
- Added exception handling for `store_duplicate_suggestion` to log failures and prevent crashes during fuzzy/low-confidence matches.
- Enhanced `dismiss_duplicate` action to handle `ActiveRecord::RecordInvalid` and display appropriate user alerts.
---------
Co-authored-by: Josh Waldrep <joshua.waldrep5+github@gmail.com>
* Add liability balance normalization logic with comprehensive tests
- Updated `SimplefinAccount::Processor` to normalize liability balances based on observed values, ensuring correct handling of debts and overpayments.
- Enhanced `SimplefinItem::Importer` to apply similar normalization rules during imports, improving consistency.
- Added multiple test cases in `SimplefinAccountProcessorTest` to validate edge cases for liabilities and mixed-sign scenarios.
- Introduced helper methods (`to_decimal`, `same_sign?`) to simplify numeric operations in normalization logic.
* Add overpayment detection for liabilities with heuristic-based classification
- Introduced `SimplefinAccount::Liabilities::OverpaymentAnalyzer` to classify liability balances as credit, debt, or unknown using transaction history.
- Updated `SimplefinAccount::Processor` and `SimplefinItem::Importer` to integrate heuristic-based balance normalization with fallback logic for ambiguous cases.
- Added comprehensive unit tests in `OverpaymentAnalyzerTest` to validate classification logic and edge cases.
- Enhanced logging and observability around classification results and fallback scenarios.
* Refactor liability handling for better fallback consistency
- Updated `sticky_key` method in `OverpaymentAnalyzer` to handle missing `@sfa.id` with a default value.
- Enhanced `SimplefinAccount::Processor` to use `with_indifferent_access` for `raw_payload` and `org_data`, improving robustness in liability type inference.
* Extract numeric helper methods into `SimplefinNumericHelpers` concern and apply across models
- Moved `to_decimal` and `same_sign?` methods into a new `SimplefinNumericHelpers` concern for reuse.
- Updated `OverpaymentAnalyzer`, `Processor`, and `Importer` to include the concern and remove redundant method definitions.
- Added empty fixtures for `simplefin_accounts` and `simplefin_items` to ensure test isolation.
- Refactored `OverpaymentAnalyzerTest` to reduce fixture dependencies and ensure cleanup of created records.
* Refactor overpayment detection logic for clarity and fallback consistency
- Simplified `enabled?` method in `OverpaymentAnalyzer` for clearer precedence order (Setting > ENV > default).
- Added `parse_bool` helper to streamline boolean parsing.
- Enhanced error handling with detailed logging for transaction gathering failures.
- Improved `sticky_key` method to use a temporary object ID fallback when `@sfa.id` is missing.
---------
Co-authored-by: Josh Waldrep <joshua.waldrep5+github@gmail.com>
* Implement API v1 Imports controller
- Add Api::V1::ImportsController with index, show, and create actions
- Add Jbuilder views for index and show
- Add integration tests
- Implement row generation logic in create action
- Update routes
* Validate import account belongs to family
- Add validation to Import model to ensure account belongs to the same family
- Add regression test case in Api::V1::ImportsControllerTest
* updating docs to be more detailed
* Rescue StandardError instead of bare rescue in ImportsController
* Optimize Imports API and fix documentation
- Implement rows_count counter cache for Imports
- Preload rows in Api::V1::ImportsController#show
- Update documentation to show correct OAuth scopes
* Fix formatting in ImportsControllerTest
* Permit all import parameters and fix unknown attribute error
* Restore API routes for auth, chats, and messages
* removing pr summary
* Fix trailing whitespace and configured? test failure
- Update Import#configured? to use rows_count for performance and consistency
- Mock rows_count in TransactionImportTest
- Fix trailing whitespace in migration
* Harden security and fix mass assignment in ImportsController
- Handle type and account_id explicitly in create action
- Rename import_params to import_config_params for clarity
- Validate type against Import::TYPES
* Fix MintImport rows_count update and migration whitespace
- Update MintImport#generate_rows_from_csv to update rows_count counter cache
- Fix trailing whitespace and final newline in AddRowsCountToImports migration
* Implement full-screen Drag and Drop CSV import on Transactions page
- Add DragAndDropImport Stimulus controller listening on document
- Add full-screen overlay with icon and text to Transactions index
- Update ImportsController to handle direct file uploads via create action
- Add system test for drag and drop functionality
* Implement Drag and Drop CSV upload on Import Upload page
- Add drag-and-drop-import controller to import/uploads/show
- Add full-screen overlay to import/uploads/show
- Annotate upload form and input with drag-and-drop targets
- Add PR_SUMMARY.md
* removing pr summary
* Add file validation to ImportsController
- Validate file size (max 10MB) and MIME type in create action
- Prevent memory exhaustion and invalid file processing
- Defined MAX_CSV_SIZE and ALLOWED_MIME_TYPES in Import model
* Refactor dragLeave logic with counter pattern to prevent flickering
* Extract shared drag-and-drop overlay partial
- Create app/views/imports/_drag_drop_overlay.html.erb
- Update transactions/index and import/uploads/show to use the partial
- Reduce code duplication in views
* Update Brakeman and harden ImportsController security
- Update brakeman to 7.1.2
- Explicitly handle type assignment in ImportsController#create to avoid mass assignment
- Remove :type from permitted import parameters
* Fix trailing whitespace in DragAndDropImportTest
* Don't commit LLM comments as file
* FIX add api validation
---------
Co-authored-by: Carlos Adames <cj@Carloss-MacBook-Air.local>
Co-authored-by: Juan José Mata <jjmata@jjmata.com>
Co-authored-by: sokie <sokysrm@gmail.com>
* FIX issue with stock price retrieval on weekend
* make weekend provisional and increase lookback
* FIX query error
* fix gap fill
The bug: When a price is provisional but the provider doesn't return a new value (weekends), we fall back to the existing DB value instead of gap-filling from Friday's correct price.
* Update importer.rb
Align provider fetch to use PROVISIONAL_LOOKBACK_DAYS for consistency. In the DB fallback, derive currency from provider_prices or db_prices and filter the query accordingly.
* Update 20260110122603_mark_suspicious_prices_provisional.rb
* Delete db/migrate/20260110122603_mark_suspicious_prices_provisional.rb
Signed-off-by: soky srm <sokysrm@gmail.com>
* Update importer.rb
* FIX tests
* FIX last tests
* Update importer_test.rb
The test doesn't properly force effective_start_date to skip old dates because there are many missing dates between the old date and recent dates. Let me fix it to properly test the subset processing scenario.
---------
Signed-off-by: soky srm <sokysrm@gmail.com>
* Add shared sync statistics collection and provider sync summary UI
- Introduced `SyncStats::Collector` concern to centralize sync statistics logic, including account, transaction, holdings, and health stats collection.
- Added collapsible `ProviderSyncSummary` component for displaying sync summaries across providers.
- Updated syncers (e.g., `LunchflowItem::Syncer`) to use the shared collector methods for consistent stats calculation.
- Added rake tasks under `dev:sync_stats` for testing and development purposes, including fake stats generation with optional issues.
- Enhanced provider-specific views to include sync summaries using the new shared component.
* Refactor `ProviderSyncSummary` to improve maintainability
- Extracted `severity_color_class` to simplify severity-to-CSS mapping.
- Replaced `holdings_label` with `holdings_label_key` for streamlined localization.
- Updated locale file to separate `found` and `processed` translations for clarity.
---------
Signed-off-by: Juan José Mata <juanjo.mata@gmail.com>
Co-authored-by: Josh Waldrep <joshua.waldrep5+github@gmail.com>
Co-authored-by: Juan José Mata <juanjo.mata@gmail.com>