mirror of
https://github.com/we-promise/sure.git
synced 2026-04-18 19:44:09 +00:00
97eacc515ceea3da44d3c28aa1b5c4e19669931f
9 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
0870ebb56b |
Add Quick Categorize Wizard (#1386)
* Add Quick Categorize Wizard (iteration 1) Adds a step-by-step wizard for bulk-categorizing uncategorized transactions and optionally creating auto-categorization rules, reducing friction after connecting a new bank account. New files: - Transaction::Grouper abstraction + ByMerchantOrName strategy (groups by merchant name when present, falls back to entry name; sorted by count desc) - Transactions::CategorizesController (GET show / POST create) - Wizard view at app/views/transactions/categorizes/show.html.erb - Stimulus categorize_controller.js (Enter-key-to-select-first) - Tests for grouper and controller Modified files: - routes.rb: resource :categorize inside namespace :transactions - transactions_controller.rb: expose @uncategorized_count to index - transactions/index.html.erb: Categorize (N) button in header - family.rb: uncategorized_transaction_count query - rules_controller.rb: return_to param support for wizard → rule editor flow - rules/_form.html.erb, rules/new.html.erb: pass return_to through form - i18n: categorizes show/create keys + rules.create.success Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Quick Categorize Wizard — iteration 2 polish Six improvements from live testing: - Breadcrumb: Home > Transactions > Categorize - Layout: category picker + confirmation dialog above transaction list - Inline confirmation dialog: clicking a category pill shows a <dialog> summarising what will happen (N transactions → category, rule if checked) with Confirm and Cancel buttons — no redirect to rule editor - Direct rule creation: rule created with active: true in the controller instead of redirecting to the rule editor; revert return_to plumbing from RulesController, rules/_form, rules/new, rules/en.yml - Individual row assignment: per-row category <select> submits via PATCH /transactions/categorize/assign_entry and removes the row via Turbo Stream (assign_entry action + route) - Enter key guard: selectFirst only fires when exactly 1 pill is visible after filtering Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Quick Categorize Wizard — iteration 3 reliability fixes and UX polish - Fix Stimulus controller not loading: remove invalid `@hotwired/turbo` named import (not in importmap); use global `Turbo.renderStreamMessage` instead - Fix Enter key submitting form with wrong category when search field is unfocused: move keydown listener to document so it fires regardless of focus - Prevent Enter from submitting when multiple categories are visible - Clear search filter after bulk category assignment (pill click or Enter), but not after individual row dropdown assignment - Update group transaction count and total amount live as entries are assigned via row dropdown or partial bulk assignment - Add turbo frames for remaining count and group summary so they update without a full page reload Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Quick categorization polish * refactoring * Remove unused GROUPS_PER_BATCH constant, fix ERB self-closing tags Wizard only ever uses one group at a time so limit: 1 is correct and more honest than fetching 20 and discarding 19. ERB linter fixes are whitespace/void-element corrections with no functional change. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Move Categorize button into ... menu on transactions index Reduces header clutter by putting it in the overflow menu at the bottom, where it only appears when there are uncategorized transactions. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Scope categorize wizard to accessible entries only Fixes a security issue where users with restricted account access via account sharing could view and categorize transactions from accounts they cannot access through normal transaction flows. - Pass Current.accessible_entries to Transaction::Grouper so the wizard only displays groups from accounts the user can see - Use Current.accessible_entries on all write paths in create and assign_entry, matching the pattern in TransactionCategoriesController - Refactor Grouper to accept an entries scope instead of a family object, keeping authorization concerns in the controller - Add tests verifying inaccessible entries are hidden from the wizard and cannot be categorized via forged POST/PATCH params Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Clamp position param to >= 0 to guard against negative offset Prevents ArgumentError from Array#drop when a negative position is passed via a tampered query string or form value. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Surface rule creation failure and add accessible names to entry row - Capture Rule.create_from_grouping! return value; set flash[:alert] when nil so users who checked "Create Rule" know it wasn't created (e.g. a duplicate already exists); stream the notification for partial updates - Add aria-label to the per-row checkbox and category select in _entry_row so screen readers can identify which transaction each control belongs to Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Localize breadcrumb labels in categorizes controller Follows the pattern used by FamilyExportsController and ImportsController. Adds 'transactions' and 'categorize' keys to the breadcrumbs locale file. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Add error handling to categorize controller fetch calls Check response.ok before parsing the body and add .catch handlers so network failures and non-2xx responses are logged rather than silently swallowed. On assignment failure the per-row select is reset to empty so the user can retry. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Scope preview_rule to accessible entries only Entry.uncategorized_matching now accepts an entries scope instead of a family object, matching the same pattern used for Transaction::Grouper. The preview_rule action passes Current.accessible_entries so rule previews respect account sharing permissions. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Scope remaining count to accessible entries Adds Entry.uncategorized_count(entries) following the same pattern as uncategorized_matching. Replaces all three uses of Current.family.uncategorized_transaction_count in the categorize controller so the remaining-count badge reflects only the transactions the current user can actually access and categorize. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Comments got separated from their function * Remove quick-categorize-wizard dev notes This was a planning document used during development, not intended for the final branch. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Recompute remaining entries from server state after writes Adds uncategorized_entries_for helper that reloads remaining entries from the DB with a category_id IS NULL filter after each write, so the partial-update Turbo Stream reflects server-side state rather than trusting the client-provided remaining_ids. This handles the case where a concurrent request has categorized one of the remaining entries between page render and form submit. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Rename create_from_grouping! to create_from_grouping The method rescues RecordInvalid and returns nil, which contradicts the bang convention. Dropping the ! correctly signals that callers should check the return value. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Clamp offset in grouper to guard against negative values The controller already clamps position before passing it as offset, but clamping in the grouper itself prevents ArgumentError from Array#drop if the grouper is ever called directly with a negative offset. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> Co-authored-by: Juan José Mata <jjmata@jjmata.com> |
||
|
|
e99e38a91c |
fix: Handle empty compound conditions on rules index (#965)
* fix: Handle empty compound conditions on rules index * fix: avoid contradictory rule condition summary on /rules * refactor: move rules condition display logic from view to model * fix: localize rule title fallback and preload conditions in rules index |
||
|
|
e37c03d1d4 | Implement Run all rules (#582) | ||
|
|
70b050e4a4 |
Rules: Fix no action conditions (#447)
* Fix Rules page when no action on rule * Reject new rules without actions * Rule with no action translation * Easy one to keep translations going * Fix tests * Learn something new every day --------- Co-authored-by: Juan José Mata <juanjo.mata@gmail.com> |
||
|
|
bf90cad9a0 |
Add Recent Runs visibility for rule executions (#376)
* Add Recent Runs visibility for rule executions Adds a comprehensive tracking system for rule execution history with the following features: - Creates RuleRun model to track execution metadata: * Date/time of execution * Execution type (manual/scheduled) * Success/failure status * Rule reference * Transaction counts (processed and modified) * Error messages for failed runs - Updates RuleJob to automatically record execution results: * Captures transaction processing statistics * Handles success/failure states * Stores error details for debugging - Adds "Recent Runs" section to rules index page: * Paginated display (20 runs per page) * Columnar layout similar to LLM usage page * Visual status indicators (success/failed badges) * Error tooltips for failed runs * Responsive design with design system tokens - Includes i18n translations for all user-facing strings This provides users with visibility into rule execution history, making it easier to debug issues and monitor rule performance. * Update schema.rb with rule_runs table definition * Linter noise * Separate transaction counts into Queued, Processed, and Modified Previously, the code eagerly reported transactions as "processed" when they were only queued for processing. This commit separates the counts into three distinct metrics: - Transactions Queued: Count of transactions matching the rule's filter conditions before any processing begins - Transactions Processed: Count of transactions that were actually processed and modified by the rule actions - Transactions Modified: Count of transactions that had their values changed (currently same as Processed, but allows for future differentiation) Changes: - Add transactions_queued column to rule_runs table - Update RuleJob to track all three counts separately - Update action executors to return count of modified transactions - Update Rule#apply to aggregate modification counts from actions - Add transactions_queued label to locales - Update Recent Runs view to display new column - Add validation for transactions_queued in RuleRun model The tracking now correctly reports: 1. How many transactions matched the filter (queued) 2. How many were actually modified (processed/modified) 3. Distinguishes between matching and modifying transactions * Add Pending status to track async rule execution progress Introduced a new "pending" status for rule runs to properly track async AI operations. The system now: - Tracks pending async jobs with a counter that decrements as jobs complete - Updates transactions_modified incrementally as each job finishes - Only counts transactions that were actually modified (not just queued) - Displays pending status with yellow badge in the UI - Automatically transitions from pending to success when all jobs complete This provides better visibility into long-running AI categorization and merchant detection operations, showing real-time progress as Sidekiq processes the batches. * Fix migration version to 7.2 as per project standards * Consolidate rule_runs migrations into single migration file Merged three separate migrations (create, add_transactions_queued, add_pending_jobs_count) into a single CreateRuleRuns migration. This provides better clarity and maintains a clean migration history. Changes: - Updated CreateRuleRuns migration to include all columns upfront - Removed redundant add_column migrations - Updated schema version to 2025_11_24_000000 * Linter and test fixes * Space optimization * LLM l10n is better than no l10n * Fix implementation for tags/AI rules * Fix tests * Use batch_size * Consider jobs "unknown" status sometimes * Rabbit suggestion * Rescue block for RuleRun.create! --------- Co-authored-by: Claude <noreply@anthropic.com> |
||
|
|
e5ed946959 |
Add rules import/export support (#424)
* Add full import/export support for rules with versioned JSON schema This commit implements comprehensive import/export functionality for rules, allowing users to back up and restore their rule definitions. Key features: - Export rules to both CSV and NDJSON formats with versioned schema (v1) - Import rules from CSV with full support for nested conditions and actions - UUID to name mapping for categories and merchants for portability - Support for compound conditions with sub-conditions - Comprehensive test coverage for export and import functionality - UI integration for rules import in the imports interface Technical details: - Extended Family::DataExporter to generate rules.csv and include rules in all.ndjson - Created RuleImport model following the existing Import STI pattern - Added migration for rule-specific columns in import_rows table - Implemented serialization helpers to map UUIDs to human-readable names - Added i18n support for the new import option - Included versioning in NDJSON export to support future schema evolution The implementation ensures rules can be safely exported from one family and imported into another, even when category/merchant IDs differ, by mapping between names and IDs during export/import. * Fix AR migration version * Mention support for rules export * Rabbit suggestion * Fix tests * Missed schema.rb * Fix sample CSV download for rule import * Fix parsing in Rules import * Fix tests * Rule import message i18n * Export tag names, not UUIDs * Make sure tags are created if needed at import * Avoid test errors when running in parallel --------- Co-authored-by: Claude <noreply@anthropic.com> |
||
|
|
bebe7b40d6 |
Improve rules - add name, allow sorting, improve UI (#2177)
* Add ability to name a rule * Add sorting by name and date, * Improve rule page and form design * Small header tweak * Improve sorting click areas by including icon * Fix brakeman * Use icon helper instead of lucide_icon helper * Fix double headers with new DialogComponent * Use updated_at for sorting instead of created_at * Use copy-plus icon for compound rules * Remove icons and change IF/THEN/FOR font in edit form * Use text-secondary on disabled rules * First pass at redesigning the sorting menu * New rule list * Borders instead of shadows * Apply proper text color to TO in edit form * Improve dark mode with proper background color classes * Use border-secondary * Add touch: true to conditions and actions of a rule, so updated_at works as expected * Fix db schema * Change sort direction to be a LinkComponent outside of the form for better sort behavior * Clean up dropdown design to match figma * Match tags/categories design * Fix name text color, add bg-divider background for dividers * Fix family subscription tests (thanks zach!) |
||
|
|
30d3eef67f |
Fix AND prefix on rule form (#2234)
* Fix AND prefix on rule form This new condition prefix data target is used to ensure the AND prefix is added/removed to additional conditions/groups when there aren't any saved conditions yet. * Ensure the condition group "Add condition" button is type button to avoid form submission * Add prefix update when removing a subcondition * Use data condition to update the prefix on conditions, condition groups, and subconditions * Use condition remove instead of element remove for condition groups so prefix logic runs * Add back explicit show_prefixes to ensure subconditions never have a prefix * Run the prefix update runs on a load of a form, which handles prefixes on an edit since no conditions change * Ensure saved items that are marked for removal don't impact the index * Simplify logic since we don't process subconditions * Clean up comments * Add primary_condition_title field to rule model |
||
|
|
297a695d0f |
Transaction rules engine V1 (#1900)
* Domain model sketch * Scaffold out rules domain * Migrations * Remove existing data enrichment for clean slate * Sketch out business logic and basic tests * Simplify rule scope building and action executions * Get generator working again * Basic implementation + tests * Remove manual merchant management (rules will replace) * Revert "Remove manual merchant management (rules will replace)" This reverts commit 83dcbd9ff0aa7bbee211796b71aa48b71df5e57e. * Family and Provider merchants model * Fix brakeman warnings * Fix notification loader * Update notification position * Add Rule action and condition registries * Rule form with compound conditions and tests * Split out notification types, add CTA type * Rules form builder and Stimulus controller * Clean up rule registry domain * Clean up rules stimulus controller * CTA message for rule when user changes transaction category * Fix tests * Lint updates * Centralize notifications in Notifiable concern * Implement category rule prompts with auto backoff and option to disable * Fix layout bug caused by merge conflict * Initialize rule with correct action for category CTA * Add rule deletions, get rules working * Complete dynamic rule form, split Stimulus controllers by resource * Fix failing tests * Change test password to avoid chromium conflicts * Update integration tests * Centralize all test password references * Add re-apply rule action * Rule confirm modal * Run migrations * Trigger rule notification after inline category updates * Clean up rule styles * Basic attribute locking for rules * Apply attribute locks on user edits * Log data enrichments, only apply rules to unlocked attributes * Fix merge errors * Additional merge conflict fixes * Form UI improvements, ignore attribute locks on manual rule application * Batch AI auto-categorization of transactions * Auto merchant detection, ai enrichment in batches * Fix Plaid merchant assignments * Plaid category matching * Cleanup 1 * Test cleanup * Remove stale route * Fix desktop chat UI issues * Fix mobile nav styling issues |