Compare commits

...

350 Commits

Author SHA1 Message Date
Zach Gollwitzer
9fa3698823 Bump to v0.5.0
Signed-off-by: Zach Gollwitzer <zach@maybe.co>
2025-04-11 11:57:02 -04:00
Josh Pigford
88a6373e84 Implement dark mode (#2078)
* User theme settings

* Initial rough pass on colors

* More progress on dark mode
2025-04-11 09:28:00 -05:00
Zach Gollwitzer
52d170e36c Mobile responsive template preparation (#2071)
* Mobile responsive template

* Fix sidebar mobile conflict

* Lint fix
2025-04-09 12:42:46 -04:00
Akshay Birajdar
2bc3887262 Fix currency symbol for Uncategorized budget to match budget currency (#2058)
Previously, the symbol for the 'Uncategorized' segment defaulted to `$`, which is incorrect for non-USD budgets. This change ensures the correct currency symbol is shown based on the budget's currency.

Co-authored-by: Zach Gollwitzer <zach@maybe.co>
2025-04-08 12:02:05 -04:00
dependabot[bot]
0da057b792 Bump sidekiq from 8.0.1 to 8.0.2 (#2059)
Bumps [sidekiq](https://github.com/sidekiq/sidekiq) from 8.0.1 to 8.0.2.
- [Changelog](https://github.com/sidekiq/sidekiq/blob/main/Changes.md)
- [Commits](https://github.com/sidekiq/sidekiq/compare/v8.0.1...v8.0.2)

---
updated-dependencies:
- dependency-name: sidekiq
  dependency-version: 8.0.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Zach Gollwitzer <zach@maybe.co>
2025-04-08 11:48:14 -04:00
dependabot[bot]
0e1c902b63 Bump selenium-webdriver from 4.30.1 to 4.31.0 (#2060)
Bumps [selenium-webdriver](https://github.com/SeleniumHQ/selenium) from 4.30.1 to 4.31.0.
- [Release notes](https://github.com/SeleniumHQ/selenium/releases)
- [Changelog](https://github.com/SeleniumHQ/selenium/blob/trunk/rb/CHANGES)
- [Commits](https://github.com/SeleniumHQ/selenium/commits/selenium-4.31.0)

---
updated-dependencies:
- dependency-name: selenium-webdriver
  dependency-version: 4.31.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Zach Gollwitzer <zach@maybe.co>
2025-04-08 11:47:53 -04:00
dependabot[bot]
bb0f0239fb Bump faraday-retry from 2.3.0 to 2.3.1 (#2061)
Bumps [faraday-retry](https://github.com/lostisland/faraday-retry) from 2.3.0 to 2.3.1.
- [Release notes](https://github.com/lostisland/faraday-retry/releases)
- [Changelog](https://github.com/lostisland/faraday-retry/blob/main/CHANGELOG.md)
- [Commits](https://github.com/lostisland/faraday-retry/compare/v2.3.0...v2.3.1)

---
updated-dependencies:
- dependency-name: faraday-retry
  dependency-version: 2.3.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Zach Gollwitzer <zach@maybe.co>
2025-04-08 11:47:46 -04:00
dependabot[bot]
e6c1c5f368 Bump vernier from 1.6.0 to 1.7.0 (#2062)
Bumps [vernier](https://github.com/jhawthorn/vernier) from 1.6.0 to 1.7.0.
- [Release notes](https://github.com/jhawthorn/vernier/releases)
- [Commits](https://github.com/jhawthorn/vernier/compare/v1.6.0...v1.7.0)

---
updated-dependencies:
- dependency-name: vernier
  dependency-version: 1.7.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Zach Gollwitzer <zach@maybe.co>
2025-04-08 11:47:36 -04:00
dependabot[bot]
02bbeeaec5 Bump stripe from 13.5.0 to 14.0.0 (#2063)
Bumps [stripe](https://github.com/stripe/stripe-ruby) from 13.5.0 to 14.0.0.
- [Release notes](https://github.com/stripe/stripe-ruby/releases)
- [Changelog](https://github.com/stripe/stripe-ruby/blob/master/CHANGELOG.md)
- [Commits](https://github.com/stripe/stripe-ruby/compare/v13.5.0...v14.0.0)

---
updated-dependencies:
- dependency-name: stripe
  dependency-version: 14.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Zach Gollwitzer <zach@maybe.co>
2025-04-08 11:25:49 -04:00
dependabot[bot]
1649e991b4 Bump brakeman from 7.0.1 to 7.0.2 (#2064)
Bumps [brakeman](https://github.com/presidentbeef/brakeman) from 7.0.1 to 7.0.2.
- [Release notes](https://github.com/presidentbeef/brakeman/releases)
- [Changelog](https://github.com/presidentbeef/brakeman/blob/main/CHANGES.md)
- [Commits](https://github.com/presidentbeef/brakeman/compare/v7.0.1...v7.0.2)

---
updated-dependencies:
- dependency-name: brakeman
  dependency-version: 7.0.2
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-08 11:00:11 -04:00
Akshay Birajdar
7096eefa2b Fix transfers#update to save notes (#2053) 2025-04-04 12:15:47 -04:00
Zach Gollwitzer
4c72231312 Update brakeman 2025-04-04 12:15:10 -04:00
Joseph Ho
d86ccd36b6 provider: Ensure data provider exist before fetching for price. (#2045) 2025-04-04 12:14:28 -04:00
Zach Gollwitzer
02bfa9f251 Fix AI sidebar overflow when user hasn't enabled or created a chat yet (#2044) 2025-04-01 14:36:34 -04:00
Josh Pigford
f2020a816a Apparently capitalization matters 2025-04-01 08:21:46 -05:00
dependabot[bot]
5f2a031d4c Bump ruby-openai from 8.0.0 to 8.1.0 (#2036)
Bumps [ruby-openai](https://github.com/alexrudall/ruby-openai) from 8.0.0 to 8.1.0.
- [Release notes](https://github.com/alexrudall/ruby-openai/releases)
- [Changelog](https://github.com/alexrudall/ruby-openai/blob/main/CHANGELOG.md)
- [Commits](https://github.com/alexrudall/ruby-openai/compare/v8.0.0...v8.1.0)

---
updated-dependencies:
- dependency-name: ruby-openai
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-01 09:11:56 -04:00
Zach Gollwitzer
939244bd3e Use faraday retry, move retry logic to concrete provider level (#2042) 2025-04-01 08:41:49 -04:00
Joseph Ho
0a17b84566 perf(imports): Bulk import CSV trades (#2040) 2025-04-01 07:58:49 -04:00
Zach Gollwitzer
5cf758bd03 improvements(ai): Improve AI streaming UI/UX interactions + better separation of AI provider responsibilities (#2039)
* Start refactor

* Interface updates

* Rework Assistant, Provider, and tests for better domain boundaries

* Consolidate and simplify OpenAI provider and provider concepts

* Clean up assistant streaming

* Improve assistant message orchestration logic

* Clean up "thinking" UI interactions

* Remove stale class

* Regenerate VCR test responses
2025-04-01 07:21:54 -04:00
Josh Pigford
6331788b33 Update Intercom configuration to use symbol keys for custom data attributes 2025-03-31 09:39:17 -05:00
Josh Pigford
83bee295ca Add custom data to Intercom configuration 2025-03-31 09:02:25 -05:00
Zach Gollwitzer
dc17a0a298 Make provider errors more specific 2025-03-28 17:53:04 -04:00
Zach Gollwitzer
29f445d75e Fix security search 2025-03-28 17:34:29 -04:00
Zach Gollwitzer
9fadfe074b Disable turbo on onboarding form 2025-03-28 17:24:17 -04:00
Josh Pigford
2a505b000c Fix for unnecessary CSS file 2025-03-28 15:35:26 -05:00
Josh Pigford
36a66baf00 Slight adjustments to AI prompt 2025-03-28 15:30:11 -05:00
Zach Gollwitzer
67716f3006 Add default queue as fallback 2025-03-28 13:29:56 -04:00
Zach Gollwitzer
1061aacb0f Set AI queue 2025-03-28 13:27:50 -04:00
Zach Gollwitzer
2f6b11c18f Personal finance AI (v1) (#2022)
* AI sidebar

* Add chat and message models with associations

* Implement AI chat functionality with sidebar and messaging system

- Add chat and messages controllers
- Create chat and message views
- Implement chat-related routes
- Add message broadcasting and user interactions
- Update application layout to support chat sidebar
- Enhance user model with initials method

* Refactor AI sidebar with enhanced chat menu and interactions

- Update sidebar layout with dynamic width and improved responsiveness
- Add new chat menu Stimulus controller for toggling between chat and chat list views
- Improve chat list display with recent chats and empty state
- Extract AI avatar to a partial for reusability
- Enhance message display and interaction styling
- Add more contextual buttons and interaction hints

* Improve chat scroll behavior and message styling

- Refactor chat scroll functionality with Stimulus controller
- Optimize message scrolling in chat views
- Update message styling for better visual hierarchy
- Enhance chat container layout with flex and auto-scroll
- Simplify message rendering across different chat views

* Extract AI avatar to a shared partial for consistent styling

- Refactor AI avatar rendering across chat views
- Replace hardcoded avatar markup with a reusable partial
- Simplify avatar display in chats and messages views

* Update sidebar controller to handle right panel width dynamically

- Add conditional width class for right sidebar panel
- Ensure consistent sidebar toggle behavior for both left and right panels
- Use specific width class for right panel (w-[375px])

* Refactor chat form and AI greeting with flexible partials

- Extract message form to a reusable partial with dynamic context support
- Create flexible AI greeting partial for consistent welcome messages
- Simplify chat and sidebar views by leveraging new partials
- Add support for different form scenarios (chat, new chat, sidebar)
- Improve code modularity and reduce duplication

* Add chat clearing functionality with dynamic menu options

- Implement clear chat action in ChatsController
- Add clear chat route to support clearing messages
- Update AI sidebar with dropdown menu for chat actions
- Preserve system message when clearing chat
- Enhance chat interaction with new menu options

* Add frontmatter to project structure documentation

- Create initial frontmatter for structure.mdc file
- Include description and configuration options
- Prepare for potential dynamic documentation rendering

* Update general project rules with additional guidelines

- Add rule for using `Current.family` instead of `current_family`
- Include new guidelines for testing, API routes, and solution approach
- Expand project-specific rules for more consistent development practices

* Add OpenAI gem and AI-friendly data representations

- Add `ruby-openai` gem for AI integration
- Implement `to_ai_readable_hash` methods in BalanceSheet and IncomeStatement
- Include Promptable module in both models
- Add savings rate calculation method in IncomeStatement
- Prepare financial models for AI-powered insights and interactions

* Enhance AI Financial Assistant with Advanced Querying and Debugging Capabilities

- Implement comprehensive AI financial query system with function-based interactions
- Add detailed debug logging for AI responses and function calls
- Extend BalanceSheet and IncomeStatement models with AI-friendly methods
- Create robust error handling and fallback mechanisms for AI queries
- Update chat and message views to support debug mode and enhanced rendering
- Add AI query routes and initial test coverage for financial assistant

* Refactor AI sidebar and chat layout with improved structure and comments

- Remove inline AI chat from application layout
- Enhance AI sidebar with more semantic HTML structure
- Add descriptive comments to clarify different sections of chat view
- Improve flex layout and scrolling behavior in chat messages container
- Optimize message rendering with more explicit class names and structure

* Add Markdown rendering support for AI chat messages

- Implement `markdown` helper method in ApplicationHelper using Redcarpet
- Update message view to render AI messages with Markdown formatting
- Add comprehensive Markdown rendering options (tables, code blocks, links)
- Enhance AI Financial Assistant prompt to encourage Markdown usage
- Remove commented Markdown CSS in Tailwind application stylesheet

* Missing comma

* Enhance AI response processing with chat history context

* Improve AI debug logging with payload size limits and internal message flag

* Enhance AI chat interaction with improved thinking indicator and scrolling behavior

* Add AI consent and enable/disable functionality for AI chat

* Upgrade Biome and refactor JavaScript template literals

- Update @biomejs/biome to latest version with caret (^) notation
- Refactor AI query and chat controllers to use template literals
- Standardize npm scripts formatting in package.json

* Add beta testing usage note to AI consent modal

* Update test fixtures and configurations for AI chat functionality

- Add family association to chat fixtures and tests
- Set consistent password digest for test users
- Enable AI for test users
- Add OpenAI access token for test environment
- Update chat and user model tests to include family context

* Simplify data model and get tests passing

* Remove structure.mdc from version control

* Integrate AI chat styles into existing prose pattern

* Match Figma design spec, implement Turbo frames and actions for chats controller

* AI rules refresh

* Consolidate Stimulus controllers, thinking state, controllers, and views

* Naming, domain alignment

* Reset migrations

* Improve data model to support tool calls and message types

* Tool calling tests and fixtures

* Tool call implementation and test

* Get assistant test working again

* Test updates

* Process tool calls within provider

* Chat UI back to working state again

* Remove stale code

* Tests passing

* Update openai class naming to avoid conflicts

* Reconfigure test env

* Rebuild gemfile

* Fix naming conflicts for ChatResponse

* Message styles

* Use OpenAI conversation state management

* Assistant function base implementation

* Add back thinking messages, clean up error handling for chat

* Fix sync error when security price has bad data from provider

* Add balance sheet function to assistant

* Add better function calling error visibility

* Add income statement function

* Simplify and clean up "thinking" interactions with Turbo frames

* Remove stale data definitions from functions

* Ensure VCR fixtures working with latest code

* basic stream implementation

* Get streaming working

* Make AI sidebar wider when left sidebar is collapsed

* Get tests working with streaming responses

* Centralize provider error handling

* Provider data boundaries

---------

Co-authored-by: Josh Pigford <josh@joshpigford.com>
2025-03-28 13:08:22 -04:00
Joseph Ho
8e6b81af77 bug: Use correct currency value while setting the currency. (#2018)
Fixes: #1754.
2025-03-24 10:06:29 -04:00
dependabot[bot]
9f062de6b4 Bump selenium-webdriver from 4.29.1 to 4.30.1 (#2020)
Bumps [selenium-webdriver](https://github.com/SeleniumHQ/selenium) from 4.29.1 to 4.30.1.
- [Release notes](https://github.com/SeleniumHQ/selenium/releases)
- [Changelog](https://github.com/SeleniumHQ/selenium/blob/trunk/rb/CHANGES)
- [Commits](https://github.com/SeleniumHQ/selenium/commits)

---
updated-dependencies:
- dependency-name: selenium-webdriver
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-24 10:06:18 -04:00
dependabot[bot]
3dfdd0aea5 Bump vernier from 1.5.0 to 1.6.0 (#2019)
Bumps [vernier](https://github.com/jhawthorn/vernier) from 1.5.0 to 1.6.0.
- [Release notes](https://github.com/jhawthorn/vernier/releases)
- [Commits](https://github.com/jhawthorn/vernier/compare/v1.5.0...v1.6.0)

---
updated-dependencies:
- dependency-name: vernier
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-24 10:06:05 -04:00
dependabot[bot]
86431e79a3 Bump csv from 3.3.2 to 3.3.3 (#2021)
Bumps [csv](https://github.com/ruby/csv) from 3.3.2 to 3.3.3.
- [Release notes](https://github.com/ruby/csv/releases)
- [Changelog](https://github.com/ruby/csv/blob/main/NEWS.md)
- [Commits](https://github.com/ruby/csv/compare/v3.3.2...v3.3.3)

---
updated-dependencies:
- dependency-name: csv
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-24 10:03:22 -04:00
Joseph Ho
54f5a44a60 devContainer: Use Redis for ActiveJob and ActionCable. (#2017)
* devContainer: Use Redis for ActiveJob and ActionCable

* devContainer: Simplify environment variables for services.

* devContainer: Remove version field as it's no longer required in Compose.
2025-03-24 10:00:42 -04:00
Joseph Ho
b41897b5e5 import: Bulk import transaction data. (#1962)
Fixes: #1846.
2025-03-24 09:59:27 -04:00
Nick Ostrovsky
f8d64561cf Fix Account Groups wrapping in Balace Sheet (#2010) 2025-03-21 13:18:12 -04:00
Tony Vincent
5a8074c7ee fix: Fix incorrect entry sorting in activity view (#2006) 2025-03-21 10:32:05 -04:00
Zach Gollwitzer
9122eafd31 Update issue templates 2025-03-19 14:05:00 -04:00
Zach Gollwitzer
19cc63c8f4 Use Redis for ActiveJob and ActionCable (#2004)
* Use Redis for ActiveJob and ActionCable

* Fix alwaysApply setting

* Update queue names and weights

* Tweak weights

* Update job queues

* Update docker setup guide

* Remove deprecated upgrade columns from users table

* Refactor Redis configuration for Sidekiq and caching in production environment

* Add Sidekiq Sentry monitoring

* queue naming fix

* Clean up schema
2025-03-19 12:36:16 -04:00
Vaibhav Agrawal
a7db914005 Update security price query in demo generator (#2000) 2025-03-19 08:49:30 -04:00
Zach Gollwitzer
06468a05b1 Update default DB pool size 2025-03-17 20:04:38 -04:00
Zach Gollwitzer
087dd720c1 Report ActionCable errors to Sentry 2025-03-17 17:26:19 -04:00
Zach Gollwitzer
78baf2b327 Update deps 2025-03-17 13:04:59 -04:00
dependabot[bot]
56203b04d3 Bump sentry-rails from 5.22.4 to 5.23.0 (#1996)
Bumps [sentry-rails](https://github.com/getsentry/sentry-ruby) from 5.22.4 to 5.23.0.
- [Release notes](https://github.com/getsentry/sentry-ruby/releases)
- [Changelog](https://github.com/getsentry/sentry-ruby/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-ruby/compare/5.22.4...5.23.0)

---
updated-dependencies:
- dependency-name: sentry-rails
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-17 11:55:07 -04:00
Zach Gollwitzer
f65b93a352 Data provider simplification, tests, and documentation (#1997)
* Ignore env.test from source control

* Simplification of providers interface

* Synth tests

* Update money to use new find rates method

* Remove unused issues code

* Additional issue feature removals

* Update price data fetching and tests

* Update documentation for providers

* Security test fixes

* Fix self host test

* Update synth usage data access

* Remove AI pr schema changes
2025-03-17 11:54:53 -04:00
Zach Gollwitzer
dd75cadebc Fix transaction filters when transfers are present (#1986)
* Proper filtering of transfers in search

* Fix transaction search
2025-03-11 15:38:45 -04:00
Josh Pigford
ed55ef624b Update billing settings view and locales 2025-03-11 13:00:34 -05:00
Zach Gollwitzer
f363fd4a4e Fix incorrect totals calculation when family has loan payments (#1984)
* Fix income totals calculation error when loan payments exist

* Include transaction totals in totals query
2025-03-11 12:37:57 -04:00
Zach Gollwitzer
b8a3ca7732 Fetch exchange rates for accounts that require conversion for net worth rollups (#1983)
* Sync required exchange rates for accounts

* Refactor into concern
2025-03-11 10:10:28 -04:00
Zach Gollwitzer
7b751ac7ca Do not prompt upgrades until user is logged in
Fixes #1982
2025-03-11 09:11:40 -04:00
Josh Pigford
15d59959cf Fix issue of syncing notice covering up user menu 2025-03-10 11:20:58 -05:00
dependabot[bot]
c66401dc0f Bump stripe from 13.4.1 to 13.5.0 (#1970)
Bumps [stripe](https://github.com/stripe/stripe-ruby) from 13.4.1 to 13.5.0.
- [Release notes](https://github.com/stripe/stripe-ruby/releases)
- [Changelog](https://github.com/stripe/stripe-ruby/blob/master/CHANGELOG.md)
- [Commits](https://github.com/stripe/stripe-ruby/compare/v13.4.1...v13.5.0)

---
updated-dependencies:
- dependency-name: stripe
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-10 09:34:15 -04:00
dependabot[bot]
9dcb9e8ed2 Bump webmock from 3.25.0 to 3.25.1 (#1968)
Bumps [webmock](https://github.com/bblimke/webmock) from 3.25.0 to 3.25.1.
- [Changelog](https://github.com/bblimke/webmock/blob/master/CHANGELOG.md)
- [Commits](https://github.com/bblimke/webmock/compare/v3.25.0...v3.25.1)

---
updated-dependencies:
- dependency-name: webmock
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-10 09:16:01 -04:00
dependabot[bot]
045fa1931c Bump good_job from 4.9.0 to 4.9.3 (#1969)
Bumps [good_job](https://github.com/bensheldon/good_job) from 4.9.0 to 4.9.3.
- [Release notes](https://github.com/bensheldon/good_job/releases)
- [Changelog](https://github.com/bensheldon/good_job/blob/main/CHANGELOG.md)
- [Commits](https://github.com/bensheldon/good_job/compare/v4.9.0...v4.9.3)

---
updated-dependencies:
- dependency-name: good_job
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-10 09:15:51 -04:00
dependabot[bot]
3f8351abfe Bump rubocop-rails-omakase from 1.0.0 to 1.1.0 (#1971)
Bumps [rubocop-rails-omakase](https://github.com/rails/rubocop-rails-omakase) from 1.0.0 to 1.1.0.
- [Release notes](https://github.com/rails/rubocop-rails-omakase/releases)
- [Commits](https://github.com/rails/rubocop-rails-omakase/compare/v1.0.0...v1.1.0)

---
updated-dependencies:
- dependency-name: rubocop-rails-omakase
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-10 09:13:38 -04:00
dependabot[bot]
dc44da6c00 Bump redcarpet from 3.6.0 to 3.6.1 (#1972)
Bumps [redcarpet](https://github.com/vmg/redcarpet) from 3.6.0 to 3.6.1.
- [Release notes](https://github.com/vmg/redcarpet/releases)
- [Changelog](https://github.com/vmg/redcarpet/blob/master/CHANGELOG.md)
- [Commits](https://github.com/vmg/redcarpet/compare/v3.6.0...v3.6.1)

---
updated-dependencies:
- dependency-name: redcarpet
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-10 09:13:25 -04:00
dependabot[bot]
2e4180fbf0 Bump turbo-rails from 2.0.11 to 2.0.13 (#1973)
Bumps [turbo-rails](https://github.com/hotwired/turbo-rails) from 2.0.11 to 2.0.13.
- [Release notes](https://github.com/hotwired/turbo-rails/releases)
- [Commits](https://github.com/hotwired/turbo-rails/compare/v2.0.11...v2.0.13)

---
updated-dependencies:
- dependency-name: turbo-rails
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-10 09:13:15 -04:00
dependabot[bot]
4b19ca50eb Bump i18n-tasks from 1.0.14 to 1.0.15 (#1974)
Bumps [i18n-tasks](https://github.com/glebm/i18n-tasks) from 1.0.14 to 1.0.15.
- [Release notes](https://github.com/glebm/i18n-tasks/releases)
- [Changelog](https://github.com/glebm/i18n-tasks/blob/main/CHANGES.md)
- [Commits](https://github.com/glebm/i18n-tasks/compare/v1.0.14...v1.0.15)

---
updated-dependencies:
- dependency-name: i18n-tasks
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-10 09:13:05 -04:00
Zach Gollwitzer
a3cd5f4f1d Format money for trade history in holdings drawer (#1961)
* Format money for trade history in holdings drawer

* Fix broken tests

* Lint fix
2025-03-07 19:09:54 -05:00
Zach Gollwitzer
86bf47a32e Ensure holdings are normalized to account currency 2025-03-07 18:02:08 -05:00
Zach Gollwitzer
5f8a3c9f50 Search securities with correct exchange mic 2025-03-07 17:48:26 -05:00
Zach Gollwitzer
eac5d5e663 Populate holdings for "offline" securities properly (#1958)
* Placeholder logic for missing prices

* Generate holdings properly for "offline" securities

* Separate forward and reverse calculators for holdings and balances

* Remove unnecessary currency conversion during sync

* Clearer sync process

* Move price caching logic to dedicated model

* Base holding calculator

* Base calculator for balances

* Finish balance calculators

* Better naming

* Logs cleanup

* Remove stale data type

* Remove stale test

* Fix price lookup logic for holdings sync

* Fix Plaid item sync regression

* Remove temp logging

* Calculate cash and holdings series

* Add holdings, cash, and balance series dropdown for investments
2025-03-07 17:35:55 -05:00
Nikhil Badyal
26762477a3 Preference to set default_period (#1941) 2025-03-07 10:05:54 -05:00
Zach Gollwitzer
372b64ffea Fix Plaid sync error when current balance is null 2025-03-05 16:02:07 -05:00
Zach Gollwitzer
9627a6bf6f Add tagged logging to sync process (#1956)
* Add tagged logging to sync process

* Reduce logging in syncer

* Typo
2025-03-05 15:38:31 -05:00
Josh Pigford
cffafd23f0 Logger cleanup 2025-03-05 13:44:56 -06:00
Josh Pigford
f7fa8fa085 Disable turbo on login forms 2025-03-05 13:32:53 -06:00
Josh Pigford
28bfcda50a Temporary additional logging to continue debugging MFA issues 2025-03-05 13:20:36 -06:00
Josh Pigford
e49bda4a2e Another attempt at fixing MFA issues 2025-03-05 13:10:53 -06:00
Josh Pigford
071ad52c7f Potential fix for MFA login issues 2025-03-05 13:04:45 -06:00
Zach Gollwitzer
381e39bea8 Fix: Purge stale holdings from accounts during sync (#1954)
* Fix: Purge stale holdings from accounts during sync

* Fix typo

* Prevent Plaid holding deletions
2025-03-05 12:21:17 -05:00
Zach Gollwitzer
eaa1b6abe0 Update issue templates 2025-03-05 11:01:07 -05:00
Zach Gollwitzer
e384369cfb Adjust graph intervals to show more data
Fixes #1948
2025-03-05 10:20:02 -05:00
Zach Gollwitzer
8d0509fda0 Conditionally show commit sha
Fixes #1951
2025-03-05 10:15:12 -05:00
Zach Gollwitzer
d66c37939a Update bug_report.md
Signed-off-by: Zach Gollwitzer <zach@maybe.co>
2025-03-05 10:07:29 -05:00
Zach Gollwitzer
cf59fe45e7 Fix ticker filling when Synth is connected (#1950) 2025-03-05 09:30:47 -05:00
Zach Gollwitzer
0544089710 Account-level import configuration templates (#1946)
* Account-level import configuration templates

* Default import to family's preferred date format
2025-03-04 13:10:01 -05:00
Zach Gollwitzer
5b2fa3d707 Fix commit resolution for Docker builds 2025-03-04 07:50:21 -05:00
Bryan McKnight
cf0e573533 Fix modal closing on color picker drag #1869 (#1931)
* Replaced data-action click event with data-action mousedown to prevent the modal from hiding on mouse up whenever mouse down starts within the modal

* Changed click events to mousedown within dialog elements to trigger the closing of the element
2025-03-03 16:37:12 -05:00
Zach Gollwitzer
4e96ca8376 Add manual Docker publishing trigger in GH action workflow 2025-03-03 14:34:56 -05:00
Zach Gollwitzer
c5da8ea550 Allow CSV imports to be configured with single or multi-account mode (#1943)
* Allow CSV imports to be configured to a single account or multiple accounts

* Initialize import directly from accounts page

* Fix brakeman warnings

* Fix schema

* Fix Synth check
2025-03-03 12:47:30 -05:00
Zach Gollwitzer
e907b073ed Fix time period key conflicts (#1944) 2025-03-03 12:47:20 -05:00
Tony Vincent
4c4a4026c4 fix: Bug - Transcation Matching Dialog isn't Opening (#1942) 2025-03-03 11:34:03 -05:00
Zach Gollwitzer
c95bb082a9 Bump to v0.4.3
Signed-off-by: Zach Gollwitzer <zach@maybe.co>
2025-02-28 15:11:41 -05:00
Zach Gollwitzer
4d0df9b950 Escape quotations in CSV imports properly (#1929)
* Parse quotes in imports

* Update invalid CSV for test
2025-02-28 12:21:07 -05:00
Zach Gollwitzer
7c66f16750 Invert liability graphs to have correct signage (#1928) 2025-02-28 12:17:25 -05:00
Zach Gollwitzer
fa0248056d Show UI warning to user when they need provider data but have not setup Synth yet (#1926)
* Simplify provider concerns

* Update tests

* Add UI warning for missing Synth key if family requires external data
2025-02-28 11:35:10 -05:00
Tony Vincent
624faa10d0 fix: Don't show Billings on settings navbar when self-hosted (#1912)
* Do not show billing settings navbar item when self hosted

* Do not show billing settings navbar item when self hosted

* Add condition to settings helper

* Let Stripe::AuthenticationError bubble up
2025-02-28 09:35:00 -05:00
Zach Gollwitzer
9138bd2b76 Allow offline trade tickers (#1925) 2025-02-28 09:34:14 -05:00
Zach Gollwitzer
882857fcf0 Add transitions to buttons and other common design system elements (#1924) 2025-02-28 09:29:07 -05:00
Zach Gollwitzer
d6793dec05 Fix import configuration form so number format is applied (#1923)
* Fix number format form error when loading import

* Add test to verify import configuration was properly applied
2025-02-28 08:36:57 -05:00
Zach Gollwitzer
e771c8c1df Fix value wrapping on account balance in sidebar (#1922) 2025-02-28 08:35:14 -05:00
Zach Gollwitzer
58cc09f5ae Fix bad link in bug template
Signed-off-by: Zach Gollwitzer <zach@maybe.co>
2025-02-28 08:25:20 -05:00
Zach Gollwitzer
98c842d3b8 Add note about self hosted versions prior to opening bugs 2025-02-28 08:23:46 -05:00
Tony Vincent
fae781e1be Make tags scrollable again (#1921) 2025-02-28 07:53:05 -05:00
Tony Vincent
8208722247 Feat: Data "reset" button (#1913)
* feat: Allow admins to delete family data

* feat: Allow self-hosting users to delete cached data

* Remove system tests
2025-02-28 07:49:12 -05:00
Harshit Chaudhary
f7064fd4dd fixed example account balance (#1910) 2025-02-26 15:13:51 -05:00
Zach Gollwitzer
c610b0ba4b Dashboard design fixes (#1898)
* Dashboard design fixes

* Update dashboard greeting

* Remove sidebar toggle from settings breadcrumbs

* Autofocus and outlines for category dropdowns

* Lint fixes
2025-02-25 17:28:40 -05:00
Josh Pigford
a4874815a6 Add breadcrumbs support across application (#1897)
* Add breadcrumbs support across application

Fixes #1896

* Potential fix for tests

* Simplify breadcrumbs implementation

Remove complex breadcrumbs logic from controllers and concern, replacing with a simpler default approach that sets a basic breadcrumb based on the current controller name

* Refactor page header and breadcrumbs rendering

Remove complex breadcrumbs helper method and update layout to use more flexible content_for approach for page headers and breadcrumbs

* Add fallback breadcrumbs rendering to settings layout
2025-02-25 10:14:07 -06:00
Josh Pigford
763e222cdd Add Sentry user context to authentication concern 2025-02-25 08:48:26 -06:00
Josh Pigford
e8390a68d8 Reduce Sentry sampling rates for performance monitoring 2025-02-25 08:44:13 -06:00
Josh Pigford
0e76d753bd Replace StackProf with Vernier for performance profiling 2025-02-25 08:37:51 -06:00
Zach Gollwitzer
f5ff5332d5 Fix parent category sums in budget (#1894) 2025-02-24 12:51:13 -05:00
Zach Gollwitzer
0dea36ec7d Fix bulk edit drawer height 2025-02-24 12:48:03 -05:00
Syed Bariman Jan
95989a6c9b Add new category flow (#1857)
* resolve git issue

* Add new category flow

* Improve contrast checker

* make error message small

* update ui to match figma design

* realign color picker

* changes

* rename color picker controller to new category controller

* cleanup code

* cleanup code

* resize and realign icon avatar

* Fix js lint errors

Signed-off-by: Syed Bariman Jan <syedbarimanjan@gmail.com>

---------

Signed-off-by: Syed Bariman Jan <syedbarimanjan@gmail.com>
2025-02-24 11:08:05 -05:00
dependabot[bot]
ac9703031f Bump plaid from 36.0.0 to 36.1.0 (#1891)
Bumps [plaid](https://github.com/plaid/plaid-ruby) from 36.0.0 to 36.1.0.
- [Release notes](https://github.com/plaid/plaid-ruby/releases)
- [Changelog](https://github.com/plaid/plaid-ruby/blob/master/CHANGELOG.md)
- [Commits](https://github.com/plaid/plaid-ruby/compare/v36.0.0...v36.1.0)

---
updated-dependencies:
- dependency-name: plaid
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-24 10:01:41 -05:00
dependabot[bot]
457e7062bf Bump selenium-webdriver from 4.28.0 to 4.29.1 (#1892)
Bumps [selenium-webdriver](https://github.com/SeleniumHQ/selenium) from 4.28.0 to 4.29.1.
- [Release notes](https://github.com/SeleniumHQ/selenium/releases)
- [Changelog](https://github.com/SeleniumHQ/selenium/blob/trunk/rb/CHANGES)
- [Commits](https://github.com/SeleniumHQ/selenium/commits)

---
updated-dependencies:
- dependency-name: selenium-webdriver
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-24 10:01:05 -05:00
David Anyatonwu
32ef6ca154 Add exchange and currency fields to trade imports (#1822)
* Add exchange and currency fields to trade imports

* Add exchange_operating_mic support for trade imports - Added required columns and updated models

* refactor: remove exchange and currency columns

* fix: consolidate import schema and remove redundant columns

* feat: Enhance trade import with exchange_operating_mic support

* Revert changes to existing migration

* Simplify migration to use change method

* Restore previously deleted migration

* Remove unused import_col_labels method

* Update schema.rb after running migrations

* Update trade_import.rb and fix schema.rb with db:migrate:reset

* fix: improve trade import security creation

---------

Signed-off-by: David Anyatonwu <51977119+onyedikachi-david@users.noreply.github.com>
2025-02-24 10:00:24 -05:00
Zach Gollwitzer
fd95f8d2bd Drop linux/arm/v7 support
linux/arm/v7 is not compatible with the latest Tailwind package + takes a significant amount of time when using buildx.  Most Raspberry Pi OS now run on 64 bit ARM architecture, so we should still have significant coverage with linux/amd + linux/arm builds.

Signed-off-by: Zach Gollwitzer <zach@maybe.co>
2025-02-21 17:12:06 -05:00
Zach Gollwitzer
da668f3dc0 Bump to v0.4.1
Signed-off-by: Zach Gollwitzer <zach@maybe.co>
2025-02-21 14:19:50 -05:00
Zach Gollwitzer
cc11fec08a Add git to Dockerfile for self hosted versioning info
Signed-off-by: Zach Gollwitzer <zach@maybe.co>
2025-02-21 13:40:16 -05:00
Josh Pigford
ce12e5b5c7 Remove inter-font from early access layout 2025-02-21 11:45:57 -06:00
Zach Gollwitzer
f96bb84c4c Bump to v0.4.0
Signed-off-by: Zach Gollwitzer <zach@maybe.co>
2025-02-21 12:39:49 -05:00
Zach Gollwitzer
d75be2282b New Design System + Codebase Refresh (#1823)
Since the very first 0.1.0-alpha.1 release, we've been moving quickly to add new features to the Maybe app. In doing so, some parts of the codebase have become outdated, unnecessary, or overly-complex as a natural result of this feature prioritization.

Now that "core" Maybe is complete, we're moving into a second phase of development where we'll be working hard to improve the accuracy of existing features and build additional features on top of "core". This PR is a quick overhaul of the existing codebase aimed to:

- Establish the brand new and simplified dashboard view (pictured above)
- Establish and move towards the conventions introduced in Cursor rules and project design overview #1788
- Consolidate layouts and improve the performance of layout queries
- Organize the core models of the Maybe domain (i.e. Account::Entry, Account::Transaction, etc.) and break out specific traits of each model into dedicated concerns for better readability
- Remove stale / dead code from codebase
- Remove overly complex code paths in favor of simpler ones
2025-02-21 11:57:59 -05:00
Zach Gollwitzer
8539ac7dec Fix import configuration failures (#1876) 2025-02-21 08:58:06 -05:00
Tony Vincent
c620d1fc1e fix: Ghost subcategories when parent category is deleted (#1874) 2025-02-20 09:03:30 -05:00
dependabot[bot]
79e1a2c0ff Bump logtail-rails from 0.2.9 to 0.2.10 (#1866)
Bumps [logtail-rails](https://github.com/logtail/logtail-ruby-rails) from 0.2.9 to 0.2.10.
- [Release notes](https://github.com/logtail/logtail-ruby-rails/releases)
- [Changelog](https://github.com/logtail/logtail-ruby-rails/blob/main/README.md)
- [Commits](https://github.com/logtail/logtail-ruby-rails/compare/v0.2.9...v0.2.10)

---
updated-dependencies:
- dependency-name: logtail-rails
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-17 14:43:19 -05:00
dependabot[bot]
e9b29f6726 Bump image_processing from 1.13.0 to 1.14.0 (#1865)
Bumps [image_processing](https://github.com/janko/image_processing) from 1.13.0 to 1.14.0.
- [Changelog](https://github.com/janko/image_processing/blob/master/CHANGELOG.md)
- [Commits](https://github.com/janko/image_processing/compare/v1.13.0...v1.14.0)

---
updated-dependencies:
- dependency-name: image_processing
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-17 11:43:04 -05:00
dependabot[bot]
1b1e06070b Bump plaid from 35.1.0 to 36.0.0 (#1867)
Bumps [plaid](https://github.com/plaid/plaid-ruby) from 35.1.0 to 36.0.0.
- [Release notes](https://github.com/plaid/plaid-ruby/releases)
- [Changelog](https://github.com/plaid/plaid-ruby/blob/master/CHANGELOG.md)
- [Commits](https://github.com/plaid/plaid-ruby/compare/v35.1.0...v36.0.0)

---
updated-dependencies:
- dependency-name: plaid
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-17 11:42:42 -05:00
Tony Vincent
f35b70e936 fix: Transfers should always total to zero (#1859) 2025-02-17 11:42:30 -05:00
Zach Gollwitzer
8e339dcbe0 Dockerfile fixes
Signed-off-by: Zach Gollwitzer <zach@maybe.co>
2025-02-13 17:24:24 -05:00
Zach Gollwitzer
366862fee1 Fix bootsnap hanging in CI 2025-02-13 15:32:51 -05:00
Zach Gollwitzer
73f826fdf2 Split Dockerfile build commands for more clarity in CI 2025-02-13 15:04:15 -05:00
Zach Gollwitzer
999f1c5190 Fix font resolution paths 2025-02-13 14:58:11 -05:00
Zach Gollwitzer
849c58dd3e Maybe Design System Updates (#1856)
* Add geist font

* Design system css file

* Add cursor ui/ux rules

* Add shadows and shadow borders

* Replace primitives with tokens for common text and backgrounds

* Organize css

* Update switch and checkbox class names

* Add back global color variables
2025-02-13 11:31:07 -05:00
Zach Gollwitzer
c0e290a07e Add max time to Docker publish
Signed-off-by: Zach Gollwitzer <zach@maybe.co>
2025-02-12 15:07:24 -05:00
Josh Pigford
f1f2e103ce Enhance Plaid connection management with re-authentication and error handling (#1854)
* Enhance Plaid connection management with re-authentication and error handling

- Add support for Plaid item status tracking (good/requires_update)
- Implement re-authentication flow for Plaid connections
- Handle connection errors and provide user-friendly reconnection options
- Update Plaid link token generation to support item updates
- Add localization for new connection management states

* Remove redundant 'reconnect' localization for Plaid items
2025-02-12 12:59:35 -06:00
Zach Gollwitzer
08a2d35308 Fix off-center modals 2025-02-12 11:57:31 -05:00
Zach Gollwitzer
a82c0303ce Upgrade to Tailwind v4 (#1853)
* Upgrade to Tailwind v4

* Update max width classes

* Revert improper changes from Tailwind migration tool
2025-02-12 11:22:30 -05:00
Josh Pigford
945a39d035 Add manual entry option for two-factor authentication setup 2025-02-12 09:15:00 -06:00
Marvin M
d31d5c5467 fix: liabilities favorable direction is "down" (#1849) 2025-02-11 15:18:22 -05:00
Josh Pigford
ab7f6a56f0 Enhance securities de-duplication task 2025-02-11 11:11:14 -06:00
Josh Pigford
68d7cb5de6 Enhance security information retrieval and handling (#1826)
* Enhance security information retrieval and handling

- Add support for operating MIC codes in security info fetching
- Update security uniqueness validation to handle unknown securities
- Improve security creation and update logic in Plaid investment sync
- Update combobox and view components to handle operating MIC codes
- Add unknown flag for securities with incomplete information

* Update schema.rb

* Refactor the need for mic codes

* Don't fetch prices unless a security has the necessary mic code

* Deduplication

* Lint

* Update Securities and Plaid Investment Sync

- Modify PlaidInvestmentSync to return plaid_security for USD cash
- Add non-null constraint to Securities ticker column
- Update Securities fixture to use exchange_operating_mic instead of exchange_mic

---------

Signed-off-by: Josh Pigford <josh@joshpigford.com>
2025-02-11 10:40:30 -06:00
Paul Imoke
fb6c6fa6bb fix: subcategories are not properly handled for budget allocations (#1844)
* fix: `allocated_spending` logic

* fix: subcategories exceeding parent limit

* refactor: budget allocations and max allocation logic

* feat: add stream for budget category form validation

* feat: update uncategorized value via stream, refactor confirm button with stream

* fix: ensure live updates for parent & sibling budgets in Turbo Stream

* fix: lint issues
2025-02-11 09:28:06 -05:00
Daniel Esteves
077694bbde feat(import): add currency and number format support for CSV imports (#1819)
* feat(import): add currency and number format support for CSV imports

* feat(import): add currency and format for mint and trade

* fix(imports): remove currency field in favor of currency csv col

* fix(imports): remove validate column from import model

* test(import): add some tests for imports

* test(import): add some tests for generate_rows_from_csv

* fix: change method name for import model

* fix: change before validation

---------

Co-authored-by: danestves <danestves@users.noreply.github.com>
2025-02-10 15:31:28 -05:00
dependabot[bot]
9e5f1574bc Bump sentry-rails from 5.22.3 to 5.22.4 (#1840)
Bumps [sentry-rails](https://github.com/getsentry/sentry-ruby) from 5.22.3 to 5.22.4.
- [Release notes](https://github.com/getsentry/sentry-ruby/releases)
- [Changelog](https://github.com/getsentry/sentry-ruby/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-ruby/compare/5.22.3...5.22.4)

---
updated-dependencies:
- dependency-name: sentry-rails
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-10 12:28:53 -05:00
dependabot[bot]
26197eda85 Bump webmock from 3.24.0 to 3.25.0 (#1839)
Bumps [webmock](https://github.com/bblimke/webmock) from 3.24.0 to 3.25.0.
- [Changelog](https://github.com/bblimke/webmock/blob/master/CHANGELOG.md)
- [Commits](https://github.com/bblimke/webmock/compare/v3.24.0...v3.25.0)

---
updated-dependencies:
- dependency-name: webmock
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-10 12:22:33 -05:00
dependabot[bot]
1dbf1ad74e Bump sentry-ruby from 5.22.3 to 5.22.4 (#1841)
Bumps [sentry-ruby](https://github.com/getsentry/sentry-ruby) from 5.22.3 to 5.22.4.
- [Release notes](https://github.com/getsentry/sentry-ruby/releases)
- [Changelog](https://github.com/getsentry/sentry-ruby/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-ruby/compare/5.22.3...5.22.4)

---
updated-dependencies:
- dependency-name: sentry-ruby
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-10 12:22:20 -05:00
dependabot[bot]
ab632cf0be Bump ruby-lsp-rails from 0.3.31 to 0.4.0 (#1842)
Bumps [ruby-lsp-rails](https://github.com/Shopify/ruby-lsp-rails) from 0.3.31 to 0.4.0.
- [Release notes](https://github.com/Shopify/ruby-lsp-rails/releases)
- [Commits](https://github.com/Shopify/ruby-lsp-rails/compare/v0.3.31...v0.4.0)

---
updated-dependencies:
- dependency-name: ruby-lsp-rails
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-10 12:22:10 -05:00
dependabot[bot]
2b83fc787f Bump good_job from 4.8.2 to 4.9.0 (#1843)
Bumps [good_job](https://github.com/bensheldon/good_job) from 4.8.2 to 4.9.0.
- [Release notes](https://github.com/bensheldon/good_job/releases)
- [Changelog](https://github.com/bensheldon/good_job/blob/main/CHANGELOG.md)
- [Commits](https://github.com/bensheldon/good_job/compare/v4.8.2...v4.9.0)

---
updated-dependencies:
- dependency-name: good_job
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-10 11:32:44 -05:00
Zach Gollwitzer
536c82f2aa Feature: Add the ability to "revert" a CSV import (#1814)
* Allow reverting imports

* Fix tests

* Add currency column to all imports

* Don't auto-enrich demo account
2025-02-07 15:36:05 -05:00
Josh Pigford
60925bd16c Remove redundant amount validation from Account Holding model 2025-02-07 10:58:41 -06:00
Josh Pigford
cf23673003 Fix Account Holding validation and synchronization (#1818)
* Fix Account Holding validation and synchronization

Fixes #1781

- Add comprehensive validations for Account::Holding
- Implement validation to ensure amount matches qty * price
- Update Account::Syncer to include qty and price during synchronization
- Add database constraints for holding attributes and calculations

* Remove database check constraints for Account Holdings

Align with project convention of keeping complex validations in ActiveRecord
- Remove database-level check constraints for quantity, price, and amount
- Maintain database-level null and unique constraints
- Prepare for more flexible validation in the model layer
2025-02-07 10:42:01 -06:00
Zach Gollwitzer
0dc25cda22 Plaid EU webhooks migration task (#1825)
* Add data migration for EU Plaid webhooks

* Fix task
2025-02-07 11:09:38 -05:00
Zach Gollwitzer
5eb5ec7aef fix: Plaid webhook verification (#1824)
* Fix Plaid webhook verification

* Fix client creation in webhook controller
2025-02-07 10:35:42 -05:00
Zach Gollwitzer
331de2f997 Capture webhook errors in Sentry 2025-02-07 09:54:15 -05:00
Josh Pigford
972c850d27 MFA qr code fix 2025-02-06 15:26:50 -06:00
Josh Pigford
78e34d68e9 fix: Format budget estimated income and spending with two decimal places 2025-02-06 14:40:58 -06:00
Josh Pigford
21dc4b80f3 fix: Round average monthly budget to two decimal places 2025-02-06 14:35:42 -06:00
Josh Pigford
842e37658c Multi-factor authentication (#1817)
* Initial pass

* Tests for MFA and locale cleanup

* Brakeman

* Update two-factor authentication status styling

* Update app/models/user.rb

Co-authored-by: Zach Gollwitzer <zach@maybe.co>
Signed-off-by: Josh Pigford <josh@joshpigford.com>

* Refactor MFA verification and session handling in tests

---------

Signed-off-by: Josh Pigford <josh@joshpigford.com>
Co-authored-by: Zach Gollwitzer <zach@maybe.co>
2025-02-06 14:16:53 -06:00
Josh Pigford
7ba9063e04 feat: Add institution details to Plaid items (#1816)
* feat: Add institution details to Plaid items

- Fetch and store institution URL, ID, and primary color for Plaid items
- Update PlaidItem model to retrieve and save institution metadata
- Add new method in Plaid provider to get institution details
- Update account logo view to use institution domain for logo generation

* Add institution domain method to Account model

- Extract institution domain logic from view to Account model
- Simplify logo view by using new institution_domain method
- Improve code reusability and separation of concerns
2025-02-06 08:57:24 -06:00
Marvin M
df5f4c83fe fix: Save completely allocated budget (#1811)
Signed-off-by: Marvin M <39344769+M123-dev@users.noreply.github.com>
2025-02-05 13:20:19 -05:00
Josh Pigford
e3ef1dd6b4 Increase profile image size limit 2025-02-05 12:04:24 -06:00
Josh Pigford
4aba9d1c0b Add scope to filter transactions from active accounts (#1810)
* Add scope to filter transactions from active accounts

* Add test for transfer match candidates with active accounts

* Refactor active account filtering for transactions and entries
2025-02-05 11:52:44 -06:00
Josh Pigford
cf014bc24f Reduce Sentry sample rate 2025-02-05 11:33:59 -06:00
Josh Pigford
90f1ff8a0b Increase limit on ticker search 2025-02-05 11:02:12 -06:00
Josh Pigford
b84a33c09d Refactor transaction enrichment to support batch processing (#1803)
* Refactor transaction enrichment to support batch processing

- Add method to enrich transactions in batches
- Implement job scheduling for unenriched transactions
- Improve logging and error handling for transaction enrichment

* Re-enable enrichment

* Fix transaction enrichment query to use correct table references

- Update queries to explicitly join and reference account_entries and account_transactions tables
- Remove unnecessary name presence check before enrichment
- Improve query precision for unenriched transaction selection

* Optimize transaction enrichment query joins

- Refactor database joins to use explicit table references
- Improve query performance for unenriched transaction selection
- Ensure correct table aliasing in enrichment methods

* Remove deprecated data enrichment job and method

- Delete EnrichDataJob as it's no longer used
- Remove `enrich_data_later` method from Account model
- Update Account::Syncer to directly call `enrich_data` instead of scheduling a job
2025-02-05 10:34:28 -06:00
Zach Gollwitzer
abd932c894 Update issue templates 2025-02-05 10:57:33 -05:00
Zach Gollwitzer
5b083c9e33 Fix budget allocation forms from resetting and clearing data on slow networks (#1804)
* First pass

* Fix null constraint bug for budget category assignment

* Fix autofocus reset when allocating budget

* Lint fix
2025-02-05 09:09:38 -05:00
Josh Pigford
f498212b2d Add migration generation guideline to project conventions 2025-02-04 20:25:19 -06:00
Saleh Almatrafi
37aab45c19 Fix incorrect currency assignment for stock prices #1623 (#1798) 2025-02-04 14:27:00 -05:00
Zach Gollwitzer
c9c5eb315a Split family and Plaid item syncs into multiple jobs (#1799)
* Split family and Plaid item syncs into multiple jobs

* fix test expectations
2025-02-04 14:22:44 -05:00
Zach Gollwitzer
75c8627577 Temporarily disable data enrichment jobs until optimized 2025-02-04 13:54:14 -05:00
Zach Gollwitzer
15e8281d46 Remove thread allocation from catch-all queue 2025-02-04 13:39:52 -05:00
Zach Gollwitzer
283d9cd8e2 Fix GoodJob config syntax 2025-02-04 13:29:27 -05:00
Zach Gollwitzer
3e06017ae1 Use correct config scope for GoodJob
Signed-off-by: Zach Gollwitzer <zach@maybe.co>
2025-02-04 13:21:10 -05:00
Josh Pigford
058830591f Increase database connection pool size 2025-02-04 12:07:46 -06:00
Josh Pigford
32d826c047 Increase good_job threads 2025-02-04 12:06:05 -06:00
Josh Pigford
bdec61f312 Improve HoldingCalculator Security Preloading
- Include securities from both trades and current holdings
- Ensure unique securities are preloaded
- Enhance logging for preloaded securities
2025-02-04 11:02:50 -06:00
Zach Gollwitzer
9c846e7de4 Fix crypto.randomUUID errors when adding holdings (#1795) 2025-02-04 11:35:50 -05:00
Josh Pigford
4c158934d0 Improve Security Price Loading with Robust Error Handling
- Add error handling for individual security price loading
- Log detailed error information for problematic securities
- Prevent single security errors from halting entire price loading process
- Enhance logging with more specific security identification details
2025-02-03 19:57:58 -06:00
Josh Pigford
50e5ffb257 Enhance HoldingCalculator with Logging and Error Handling 2025-02-03 19:54:32 -06:00
Josh Pigford
983729cbdf Logtail 2025-02-03 19:49:41 -06:00
Zach Gollwitzer
89027f1fbf EU only allows transactions Plaid product 2025-02-03 20:39:08 -05:00
Zach Gollwitzer
2a338eb01b Cursor rules and project design overview (#1788)
* Add cursor rules directory

* Complete project design rules
2025-02-03 19:30:03 -05:00
scodes73
f57fa526af Fix: make date format year consistent overall #1712 (#1726)
* Fix: make date format year consistent overall

* chore: Consolidating all date formatting options

* adding disabled condition back to mint import

* chore: Moving formats from helper to models/family.rd

* Adding date_format_label to the en translation for import/configurations

* nit: making changes to use individual translations
2025-02-03 11:19:56 -05:00
Jacco Broeren
b02380ac97 Fix: unable to add accounts without plain set up (#1769)
* Update family.rb

Fix for: https://github.com/maybe-finance/maybe/issues/1766

Signed-off-by: Jacco Broeren <jaccobroeren@freedom.nl>

* Update family.rb

Add commenting.

Signed-off-by: Jacco Broeren <jaccobroeren@freedom.nl>

---------

Signed-off-by: Jacco Broeren <jaccobroeren@freedom.nl>
2025-02-03 11:18:49 -05:00
dependabot[bot]
550991e240 Bump sentry-rails from 5.22.2 to 5.22.3 (#1772)
Bumps [sentry-rails](https://github.com/getsentry/sentry-ruby) from 5.22.2 to 5.22.3.
- [Release notes](https://github.com/getsentry/sentry-ruby/releases)
- [Changelog](https://github.com/getsentry/sentry-ruby/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-ruby/compare/5.22.2...5.22.3)

---
updated-dependencies:
- dependency-name: sentry-rails
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-03 10:49:13 -05:00
Josh Pigford
4a768d0358 Clean up timezone selector 2025-02-03 09:46:40 -06:00
Josh Pigford
a1065fde83 Updated "small" image variant for retina 2025-02-03 09:08:43 -06:00
dependabot[bot]
f63aea7f87 Bump sentry-ruby from 5.22.2 to 5.22.3 (#1773)
Bumps [sentry-ruby](https://github.com/getsentry/sentry-ruby) from 5.22.2 to 5.22.3.
- [Release notes](https://github.com/getsentry/sentry-ruby/releases)
- [Changelog](https://github.com/getsentry/sentry-ruby/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-ruby/compare/5.22.2...5.22.3)

---
updated-dependencies:
- dependency-name: sentry-ruby
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-03 10:05:52 -05:00
dependabot[bot]
872a480c0f Bump puma from 6.5.0 to 6.6.0 (#1774)
Bumps [puma](https://github.com/puma/puma) from 6.5.0 to 6.6.0.
- [Release notes](https://github.com/puma/puma/releases)
- [Changelog](https://github.com/puma/puma/blob/master/History.md)
- [Commits](https://github.com/puma/puma/compare/v6.5.0...v6.6.0)

---
updated-dependencies:
- dependency-name: puma
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-03 10:05:40 -05:00
Josh Pigford
1620d56e2d Allow connecting a few accounts before upgrade prompt 2025-02-03 09:04:39 -06:00
dependabot[bot]
c1e48bd3c9 Bump plaid from 35.0.0 to 35.1.0 (#1776)
Bumps [plaid](https://github.com/plaid/plaid-ruby) from 35.0.0 to 35.1.0.
- [Release notes](https://github.com/plaid/plaid-ruby/releases)
- [Changelog](https://github.com/plaid/plaid-ruby/blob/master/CHANGELOG.md)
- [Commits](https://github.com/plaid/plaid-ruby/compare/v35.0.0...v35.1.0)

---
updated-dependencies:
- dependency-name: plaid
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-03 09:51:15 -05:00
dependabot[bot]
4c083fec0a Bump stripe from 13.4.0 to 13.4.1 (#1777)
Bumps [stripe](https://github.com/stripe/stripe-ruby) from 13.4.0 to 13.4.1.
- [Release notes](https://github.com/stripe/stripe-ruby/releases)
- [Changelog](https://github.com/stripe/stripe-ruby/blob/master/CHANGELOG.md)
- [Commits](https://github.com/stripe/stripe-ruby/compare/v13.4.0...v13.4.1)

---
updated-dependencies:
- dependency-name: stripe
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-03 09:51:02 -05:00
Zach Gollwitzer
2c2b600163 Improve speed of transactions page (#1752)
* Make demo data more realistic

* Fix N+1 transactions query

* Lint fixes

* Totals query

* Consolidate stats calcs

* Fix preload

* Fix filter clearing

* Fix N+1 queries for family sync detection

* Reduce queries for rendering transfers

* Fix tests

* Remove flaky test
2025-01-31 19:08:21 -05:00
Zach Gollwitzer
53f4b32c33 Fix EU plaid flow (#1761)
* Fix EU plaid flow

* Fix failing tests
2025-01-31 17:04:26 -05:00
Josh Pigford
4bf72506d5 Initial pass at Plaid EU (#1555)
* Initial pass at Plaid EU

* Add EU support to Plaid Items

* Lint

* Temp fix for rubocop isseus

* Merge cleanup

* Pass in region and get tests passing

* Use absolute path for translation

---------

Signed-off-by: Josh Pigford <josh@joshpigford.com>
2025-01-31 12:13:58 -06:00
Josh Pigford
41873de11d Allow users to update their email address (#1745)
* Change email address

* Email confirmation

* Email change test

* Lint

* Schema reset

* Set test email sender

* Select specific user fixture

* Refactor/cleanup

* Remove unused email_confirmation_token

* Current user would never be true

* Fix translation test failures
2025-01-31 11:29:49 -06:00
Josh Pigford
46e86a9a11 Pass in user role to Intercom 2025-01-31 10:34:20 -06:00
Julien Bertazzo Lambert
ad5b0b8b7d Ensure Consistent Category Colors (#1722)
* feat: add validation to require consistent category color

* feat: reflect color requirement in new category form

* refactor: move logic inline over shared component

* rubocop

* tests: fix breaking and add case for new validation

* feat: hide color selector when parent category selected

* feat: override color with parent color in model

* tests: remove case for unnecessary validation

---------

Signed-off-by: Julien Bertazzo Lambert <42924425+JLambertazzo@users.noreply.github.com>
2025-01-30 16:49:31 -05:00
Zach Gollwitzer
ded42a8c33 Add back txn logos
This reverts commit b78fd1d755.
2025-01-30 15:31:16 -05:00
Zach Gollwitzer
b78fd1d755 Temporarily disable txn logos for performance 2025-01-30 14:17:25 -05:00
Josh Pigford
0696e1f2f7 Add/remove members and invitations (#1744)
* Add/remove members and invitations

* Lint
2025-01-30 13:13:37 -06:00
Zach Gollwitzer
282c05345d Preserve transaction filters and transaction focus across page visits (#1733)
* Preserve transaction filters across page visits

* Preserve params when per_page is updated

* Autofocus selected transactions

* Lint fixes

* Fix syntax error

* Fix filter clearing

* Update e2e tests for new UI

* Consolidate focus behavior into concern

* Lint fixes
2025-01-30 14:12:01 -05:00
Elvis Serrão
0b17976256 Don't allow a subcategory to be assigned to another subcategory to ensure 1 level of nesting max (#1730)
* Improve category level limit validation

* Set categories list only for non parents

* Disable select field

* Add info about the disabled select

* Don’t render a select input for parent categories

* Handle correctly turbo_stream request format

* Add turbo_stream format to requests on create and update action's tests

* Remove no_content status from update action

* Revert "Remove no_content status from update action"

This reverts commit 866140c196.

* Revert "Add turbo_stream format to requests on create and update action's tests"

This reverts commit c6bf21490f.

* Add correct redirect url for both html and turbo_stream formats

* Remove useless turbo_frame_tag
2025-01-30 12:35:30 -05:00
Zach Gollwitzer
3b0f8ae8c2 Only build armv7 on official releases (#1732) 2025-01-28 14:08:04 -05:00
Zach Gollwitzer
247d91b99d Lazy load synth logos (#1731) 2025-01-28 12:03:43 -05:00
Zach Gollwitzer
d428a1f954 Bump to Ruby 3.4.1 (#1721) 2025-01-27 19:59:16 -05:00
Jestin Palamuttam
8256d116dd fix: category update sync (#1720) 2025-01-27 19:58:45 -05:00
Zach Gollwitzer
de90b29201 Add RejectedTransfer model, simplify auto matching (#1690)
* Allow transfers to match when inflow is after outflow

* Simplify transfer auto matching with RejectedTransfer model

* Validations

* Reset migrations
2025-01-27 16:56:46 -05:00
Zach Gollwitzer
0b4e314f58 Bump bundler version, address Docker build failures 2025-01-27 16:29:30 -05:00
Zach Gollwitzer
6c8974a086 Update render.yaml
Signed-off-by: Zach Gollwitzer <zach@maybe.co>
2025-01-27 13:18:02 -05:00
Eirik H
7265f58518 Add cabin / cottage as a property type (#1658)
* Add cabin / cottage as property type

Signed-off-by: Eirik H <post@eirikh.no>

* Update app/models/property.rb

Signed-off-by: Zach Gollwitzer <zach.gollwitzer@gmail.com>

---------

Signed-off-by: Eirik H <post@eirikh.no>
Signed-off-by: Zach Gollwitzer <zach.gollwitzer@gmail.com>
Co-authored-by: Zach Gollwitzer <zach.gollwitzer@gmail.com>
2025-01-27 13:04:36 -05:00
Nikhil Badyal
2a202576f8 Added more periods (#1714) 2025-01-27 13:03:15 -05:00
Georgi Tapalilov
d2a7aef6ef fix n+1 for categories (#1693) 2025-01-27 09:34:13 -05:00
Harshit Chaudhary
eabfb7aae1 Added Decimal Support in min transaction (#1681)
* Added Decimal Support in min transaction

* fix: Using inbuilt money field

* Updated Test
2025-01-27 09:33:56 -05:00
dependabot[bot]
2a1b5fab1a Bump erb_lint from 0.8.0 to 0.9.0 (#1704)
Bumps [erb_lint](https://github.com/Shopify/erb-lint) from 0.8.0 to 0.9.0.
- [Release notes](https://github.com/Shopify/erb-lint/releases)
- [Commits](https://github.com/Shopify/erb-lint/compare/v0.8.0...v0.9.0)

---
updated-dependencies:
- dependency-name: erb_lint
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-27 09:30:19 -05:00
dependabot[bot]
5cc592d38f Bump plaid from 34.0.0 to 35.0.0 (#1707)
Bumps [plaid](https://github.com/plaid/plaid-ruby) from 34.0.0 to 35.0.0.
- [Release notes](https://github.com/plaid/plaid-ruby/releases)
- [Changelog](https://github.com/plaid/plaid-ruby/blob/master/CHANGELOG.md)
- [Commits](https://github.com/plaid/plaid-ruby/compare/v34.0.0...v35.0.0)

---
updated-dependencies:
- dependency-name: plaid
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-27 09:30:01 -05:00
Julien Bertazzo Lambert
8be5bb07c8 fix: reuse correct expense total calculation in budget.rb (#1699) 2025-01-27 09:29:50 -05:00
dependabot[bot]
caf359deed Bump ruby-lsp-rails from 0.3.30 to 0.3.31 (#1703)
Bumps [ruby-lsp-rails](https://github.com/Shopify/ruby-lsp-rails) from 0.3.30 to 0.3.31.
- [Release notes](https://github.com/Shopify/ruby-lsp-rails/releases)
- [Commits](https://github.com/Shopify/ruby-lsp-rails/compare/v0.3.30...v0.3.31)

---
updated-dependencies:
- dependency-name: ruby-lsp-rails
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-27 09:22:39 -05:00
dependabot[bot]
91149ceff8 Bump tailwindcss-rails from 3.3.0 to 3.3.1 (#1708)
Bumps [tailwindcss-rails](https://github.com/rails/tailwindcss-rails) from 3.3.0 to 3.3.1.
- [Release notes](https://github.com/rails/tailwindcss-rails/releases)
- [Changelog](https://github.com/rails/tailwindcss-rails/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rails/tailwindcss-rails/compare/v3.3.0...v3.3.1)

---
updated-dependencies:
- dependency-name: tailwindcss-rails
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-27 09:22:23 -05:00
dependabot[bot]
f9d4270a75 Bump good_job from 4.7.0 to 4.8.2 (#1709)
Bumps [good_job](https://github.com/bensheldon/good_job) from 4.7.0 to 4.8.2.
- [Release notes](https://github.com/bensheldon/good_job/releases)
- [Changelog](https://github.com/bensheldon/good_job/blob/main/CHANGELOG.md)
- [Commits](https://github.com/bensheldon/good_job/compare/v4.7.0...v4.8.2)

---
updated-dependencies:
- dependency-name: good_job
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-27 09:21:47 -05:00
dependabot[bot]
beb6e36577 Bump selenium-webdriver from 4.27.0 to 4.28.0 (#1710)
Bumps [selenium-webdriver](https://github.com/SeleniumHQ/selenium) from 4.27.0 to 4.28.0.
- [Release notes](https://github.com/SeleniumHQ/selenium/releases)
- [Changelog](https://github.com/SeleniumHQ/selenium/blob/trunk/rb/CHANGES)
- [Commits](https://github.com/SeleniumHQ/selenium/compare/selenium-4.27.0...selenium-4.28.0)

---
updated-dependencies:
- dependency-name: selenium-webdriver
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-27 09:21:38 -05:00
dependabot[bot]
217a96c02d Bump sentry-rails from 5.22.1 to 5.22.2 (#1711)
Bumps [sentry-rails](https://github.com/getsentry/sentry-ruby) from 5.22.1 to 5.22.2.
- [Release notes](https://github.com/getsentry/sentry-ruby/releases)
- [Changelog](https://github.com/getsentry/sentry-ruby/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-ruby/compare/5.22.1...5.22.2)

---
updated-dependencies:
- dependency-name: sentry-rails
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-27 09:21:29 -05:00
Zach Gollwitzer
e617d791d3 Show budget averages in family currency
Fixes #1689
2025-01-24 20:19:13 -05:00
Zach Gollwitzer
7e0ec4bd8f Report good job connection errors to Sentry 2025-01-24 13:52:40 -05:00
Zach Gollwitzer
3140835f28 Adjust queues to prioritize account syncs (#1682) 2025-01-24 13:39:08 -05:00
Zach Gollwitzer
7d04ea1071 Update issue templates 2025-01-24 09:18:52 -05:00
Zach Gollwitzer
43dd16e3fb Only update account balance if changed (#1676)
* Only update balance if changed

* Update test assertions
2025-01-23 21:14:01 -05:00
Tony Vincent
61321f6b16 fix: Only admins can generate invite codes (#1611)
* fix: Only admins can generate invite codes

* fix: raise error if user is not an admin when creating invite codesss
2025-01-23 20:47:51 -05:00
Josh Pigford
0476f25952 Rollback AWS SDK version to address checksum conflicts 2025-01-23 10:22:53 -06:00
Josh Pigford
e4a374772a Increased expiration time on storage to prevent broken images as well as implement a fix for R2/S3 conflicts. 2025-01-23 10:11:09 -06:00
Josh Pigford
44961f3628 Only pass in a country code on securities searches if the user location is set to "US" 2025-01-23 10:02:48 -06:00
Zach Gollwitzer
68c570eed8 Make tags scrollable 2025-01-21 12:42:51 -05:00
Zach Gollwitzer
67d81f866f Align cascade delete behavior for transfers (#1647)
* Align cascade delete behavior for transfers

* Lint fix
2025-01-20 16:17:40 -05:00
Zach Gollwitzer
72fd177707 Do not raise on Plaid item not found exceptions for item deletions (#1646) 2025-01-20 15:12:53 -05:00
Zach Gollwitzer
abccba3947 Fix account deletion cascade bug (#1644)
* Fix account deletion cascade bug

* Rubocop fixes
2025-01-20 11:37:01 -05:00
dependabot[bot]
9808641110 Bump ruby-lsp-rails from 0.3.29 to 0.3.30 (#1640)
Bumps [ruby-lsp-rails](https://github.com/Shopify/ruby-lsp-rails) from 0.3.29 to 0.3.30.
- [Release notes](https://github.com/Shopify/ruby-lsp-rails/releases)
- [Commits](https://github.com/Shopify/ruby-lsp-rails/compare/v0.3.29...v0.3.30)

---
updated-dependencies:
- dependency-name: ruby-lsp-rails
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-20 09:45:09 -05:00
dependabot[bot]
9fadc6ba63 Bump stripe from 13.3.0 to 13.3.1 (#1639)
Bumps [stripe](https://github.com/stripe/stripe-ruby) from 13.3.0 to 13.3.1.
- [Release notes](https://github.com/stripe/stripe-ruby/releases)
- [Changelog](https://github.com/stripe/stripe-ruby/blob/master/CHANGELOG.md)
- [Commits](https://github.com/stripe/stripe-ruby/compare/v13.3.0...v13.3.1)

---
updated-dependencies:
- dependency-name: stripe
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-20 09:45:00 -05:00
dependabot[bot]
39139ce21a Bump aws-sdk-s3 from 1.177.0 to 1.178.0 (#1638)
Bumps [aws-sdk-s3](https://github.com/aws/aws-sdk-ruby) from 1.177.0 to 1.178.0.
- [Release notes](https://github.com/aws/aws-sdk-ruby/releases)
- [Changelog](https://github.com/aws/aws-sdk-ruby/blob/version-3/gems/aws-sdk-s3/CHANGELOG.md)
- [Commits](https://github.com/aws/aws-sdk-ruby/commits)

---
updated-dependencies:
- dependency-name: aws-sdk-s3
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-20 09:36:18 -05:00
dependabot[bot]
51e8fae26d Bump stackprof from 0.2.26 to 0.2.27 (#1637)
Bumps [stackprof](https://github.com/tmm1/stackprof) from 0.2.26 to 0.2.27.
- [Changelog](https://github.com/tmm1/stackprof/blob/master/CHANGELOG.md)
- [Commits](https://github.com/tmm1/stackprof/compare/v0.2.26...v0.2.27)

---
updated-dependencies:
- dependency-name: stackprof
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-20 09:36:07 -05:00
dependabot[bot]
42d2197ea1 Bump intercom-rails from 1.0.5 to 1.0.6 (#1636)
Bumps [intercom-rails](https://github.com/intercom/intercom-rails) from 1.0.5 to 1.0.6.
- [Release notes](https://github.com/intercom/intercom-rails/releases)
- [Commits](https://github.com/intercom/intercom-rails/commits)

---
updated-dependencies:
- dependency-name: intercom-rails
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-20 09:35:58 -05:00
dependabot[bot]
a9c1e85a58 Bump tailwindcss-rails from 3.2.0 to 3.3.0 (#1635)
Bumps [tailwindcss-rails](https://github.com/rails/tailwindcss-rails) from 3.2.0 to 3.3.0.
- [Release notes](https://github.com/rails/tailwindcss-rails/releases)
- [Changelog](https://github.com/rails/tailwindcss-rails/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rails/tailwindcss-rails/compare/v3.2.0...v3.3.0)

---
updated-dependencies:
- dependency-name: tailwindcss-rails
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-20 09:35:49 -05:00
Zach Gollwitzer
8c8e972dc8 Bump to v0.3.0
Signed-off-by: Zach Gollwitzer <zach@maybe.co>
2025-01-17 17:01:26 -05:00
tlink
ae9287ec9b FIX: correct display of percentages (#1622)
* FIX: correct display of percentages

* FIX: correct display of percentages

* FIX: correct display of percentages
2025-01-17 11:21:00 -05:00
Jasper Delahaije
aac9e5eca2 Update family.rb (#1629)
Add where statement to account_transactions overview to only give transactions and not valuations

Signed-off-by: Jasper Delahaije <47220315+Repsay@users.noreply.github.com>
2025-01-17 09:48:16 -05:00
Zach Gollwitzer
ca8bdb6241 Fix budget money formatting (#1626) 2025-01-16 19:05:34 -05:00
Zach Gollwitzer
1ae4b4d612 Fix transfer matching logic (#1625)
* Fix transfer matching logic

* Fix tests
2025-01-16 17:56:42 -05:00
Zach Gollwitzer
60f1a1e2d2 Fix budget edit button 2025-01-16 16:24:14 -05:00
Zach Gollwitzer
e1d3c7a4a1 Add CA country code to Plaid link
Signed-off-by: Zach Gollwitzer <zach@maybe.co>
2025-01-16 16:02:06 -05:00
Zach Gollwitzer
195ec85d96 Budgeting V1 (#1609)
* Budgeting V1

* Basic UI template

* Fully scaffolded budgeting v1

* Basic working budget

* Finalize donut chart for budgets

* Allow categorization of loan payments for budget

* Include loan payments in incomes_and_expenses scope

* Add budget allocations progress

* Empty states

* Clean up budget methods

* Category aggregation queries

* Handle overage scenarios in form

* Finalize budget donut chart controller

* Passing tests

* Fix allocation naming

* Add income category migration

* Native support for uncategorized budget category

* Formatting

* Fix subcategory sort order, padding

* Fix calculation for category rollups in budget
2025-01-16 14:36:37 -05:00
dependabot[bot]
413ec6cbed Bump erb_lint from 0.7.0 to 0.8.0 (#1616)
Bumps [erb_lint](https://github.com/Shopify/erb-lint) from 0.7.0 to 0.8.0.
- [Release notes](https://github.com/Shopify/erb-lint/releases)
- [Commits](https://github.com/Shopify/erb-lint/compare/v0.7.0...v0.8.0)

---
updated-dependencies:
- dependency-name: erb_lint
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-13 12:20:13 -05:00
dependabot[bot]
e4e5ae9f25 Bump ruby-lsp-rails from 0.3.27 to 0.3.29 (#1617)
Bumps [ruby-lsp-rails](https://github.com/Shopify/ruby-lsp-rails) from 0.3.27 to 0.3.29.
- [Release notes](https://github.com/Shopify/ruby-lsp-rails/releases)
- [Commits](https://github.com/Shopify/ruby-lsp-rails/compare/v0.3.27...v0.3.29)

---
updated-dependencies:
- dependency-name: ruby-lsp-rails
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-13 12:20:03 -05:00
dependabot[bot]
5449fc49ef Bump tailwindcss-rails from 3.1.0 to 3.2.0 (#1618)
Bumps [tailwindcss-rails](https://github.com/rails/tailwindcss-rails) from 3.1.0 to 3.2.0.
- [Release notes](https://github.com/rails/tailwindcss-rails/releases)
- [Changelog](https://github.com/rails/tailwindcss-rails/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rails/tailwindcss-rails/compare/v3.1.0...v3.2.0)

---
updated-dependencies:
- dependency-name: tailwindcss-rails
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-13 12:19:52 -05:00
dependabot[bot]
b50b7b30e8 Bump good_job from 4.6.0 to 4.7.0 (#1596)
Bumps [good_job](https://github.com/bensheldon/good_job) from 4.6.0 to 4.7.0.
- [Release notes](https://github.com/bensheldon/good_job/releases)
- [Changelog](https://github.com/bensheldon/good_job/blob/main/CHANGELOG.md)
- [Commits](https://github.com/bensheldon/good_job/compare/v4.6.0...v4.7.0)

---
updated-dependencies:
- dependency-name: good_job
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Zach Gollwitzer <zach@maybe.co>
2025-01-07 11:55:46 -05:00
dependabot[bot]
871a68b5bc Bump tailwindcss-rails from 3.0.0 to 3.1.0 (#1597)
Bumps [tailwindcss-rails](https://github.com/rails/tailwindcss-rails) from 3.0.0 to 3.1.0.
- [Release notes](https://github.com/rails/tailwindcss-rails/releases)
- [Changelog](https://github.com/rails/tailwindcss-rails/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rails/tailwindcss-rails/compare/v3.0.0...v3.1.0)

---
updated-dependencies:
- dependency-name: tailwindcss-rails
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Zach Gollwitzer <zach@maybe.co>
2025-01-07 11:55:24 -05:00
dependabot[bot]
1f4c2165eb Bump aws-sdk-s3 from 1.176.1 to 1.177.0 (#1598)
Bumps [aws-sdk-s3](https://github.com/aws/aws-sdk-ruby) from 1.176.1 to 1.177.0.
- [Release notes](https://github.com/aws/aws-sdk-ruby/releases)
- [Changelog](https://github.com/aws/aws-sdk-ruby/blob/version-3/gems/aws-sdk-s3/CHANGELOG.md)
- [Commits](https://github.com/aws/aws-sdk-ruby/commits)

---
updated-dependencies:
- dependency-name: aws-sdk-s3
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Zach Gollwitzer <zach@maybe.co>
2025-01-07 11:55:13 -05:00
dependabot[bot]
71598d26cb Bump jwt from 2.9.3 to 2.10.1 (#1600)
Bumps [jwt](https://github.com/jwt/ruby-jwt) from 2.9.3 to 2.10.1.
- [Release notes](https://github.com/jwt/ruby-jwt/releases)
- [Changelog](https://github.com/jwt/ruby-jwt/blob/main/CHANGELOG.md)
- [Commits](https://github.com/jwt/ruby-jwt/compare/v2.9.3...v2.10.1)

---
updated-dependencies:
- dependency-name: jwt
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Zach Gollwitzer <zach@maybe.co>
2025-01-07 11:55:02 -05:00
Zach Gollwitzer
997d0355d4 Use livereload from source 2025-01-07 11:54:19 -05:00
Zach Gollwitzer
2c30e18c9b Fix enrichment setting 2025-01-07 11:31:44 -05:00
Zach Gollwitzer
307a3687e8 Transfer and Payment auto-matching, model and UI improvements (#1585)
* Transfer data model migration

* Transfers and payment modeling and UI improvements

* Fix CI

* Transfer matching flow

* Better UI for transfers

* Auto transfer matching, approve, reject flow

* Mark transfers created from form as confirmed

* Account filtering

* Excluded rejected transfers from calculations

* Calculation tweaks with transfer exclusions

* Clean up migration
2025-01-07 09:41:24 -05:00
Tony Vincent
46e129308f Fix: breaking change after bumping hotwire-livereload to 2.0.0 (#1589)
Co-authored-by: Tony Vincent Yesudas <tony.yesudas@raisenow.com>
2025-01-03 15:36:11 -06:00
dependabot[bot]
5d1a2937bb Bump sentry-rails from 5.22.0 to 5.22.1 (#1568)
Bumps [sentry-rails](https://github.com/getsentry/sentry-ruby) from 5.22.0 to 5.22.1.
- [Release notes](https://github.com/getsentry/sentry-ruby/releases)
- [Changelog](https://github.com/getsentry/sentry-ruby/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-ruby/compare/5.22.0...5.22.1)

---
updated-dependencies:
- dependency-name: sentry-rails
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-30 10:16:45 -05:00
dependabot[bot]
b82b82ddf7 Bump intercom-rails from 1.0.1 to 1.0.5 (#1573)
Bumps [intercom-rails](https://github.com/intercom/intercom-rails) from 1.0.1 to 1.0.5.
- [Release notes](https://github.com/intercom/intercom-rails/releases)
- [Commits](https://github.com/intercom/intercom-rails/commits)

---
updated-dependencies:
- dependency-name: intercom-rails
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-30 10:16:37 -05:00
dependabot[bot]
97852bc3b4 Bump importmap-rails from 2.0.3 to 2.1.0 (#1567)
Bumps [importmap-rails](https://github.com/rails/importmap-rails) from 2.0.3 to 2.1.0.
- [Release notes](https://github.com/rails/importmap-rails/releases)
- [Commits](https://github.com/rails/importmap-rails/compare/v2.0.3...v2.1.0)

---
updated-dependencies:
- dependency-name: importmap-rails
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-30 10:06:51 -05:00
dependabot[bot]
84d2aac1a5 Bump faraday-multipart from 1.0.4 to 1.1.0 (#1566)
Bumps [faraday-multipart](https://github.com/lostisland/faraday-multipart) from 1.0.4 to 1.1.0.
- [Release notes](https://github.com/lostisland/faraday-multipart/releases)
- [Changelog](https://github.com/lostisland/faraday-multipart/blob/main/CHANGELOG.md)
- [Commits](https://github.com/lostisland/faraday-multipart/compare/v1.0.4...v1.1.0)

---
updated-dependencies:
- dependency-name: faraday-multipart
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-30 10:06:43 -05:00
dependabot[bot]
49d3a9c7e7 Bump sentry-ruby from 5.22.0 to 5.22.1 (#1570)
Bumps [sentry-ruby](https://github.com/getsentry/sentry-ruby) from 5.22.0 to 5.22.1.
- [Release notes](https://github.com/getsentry/sentry-ruby/releases)
- [Changelog](https://github.com/getsentry/sentry-ruby/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-ruby/compare/5.22.0...5.22.1)

---
updated-dependencies:
- dependency-name: sentry-ruby
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-30 10:06:34 -05:00
dependabot[bot]
b7019744a1 Bump stripe from 13.2.0 to 13.3.0 (#1572)
Bumps [stripe](https://github.com/stripe/stripe-ruby) from 13.2.0 to 13.3.0.
- [Release notes](https://github.com/stripe/stripe-ruby/releases)
- [Changelog](https://github.com/stripe/stripe-ruby/blob/master/CHANGELOG.md)
- [Commits](https://github.com/stripe/stripe-ruby/compare/v13.2.0...v13.3.0)

---
updated-dependencies:
- dependency-name: stripe
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-30 10:06:27 -05:00
dependabot[bot]
a9e791f94c Bump csv from 3.3.1 to 3.3.2 (#1571)
Bumps [csv](https://github.com/ruby/csv) from 3.3.1 to 3.3.2.
- [Release notes](https://github.com/ruby/csv/releases)
- [Changelog](https://github.com/ruby/csv/blob/master/NEWS.md)
- [Commits](https://github.com/ruby/csv/compare/v3.3.1...v3.3.2)

---
updated-dependencies:
- dependency-name: csv
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-30 10:06:12 -05:00
dependabot[bot]
cce373c31b Bump debug from 1.9.2 to 1.10.0 (#1569)
Bumps [debug](https://github.com/ruby/debug) from 1.9.2 to 1.10.0.
- [Release notes](https://github.com/ruby/debug/releases)
- [Commits](https://github.com/ruby/debug/compare/v1.9.2...v1.10.0)

---
updated-dependencies:
- dependency-name: debug
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-30 10:06:04 -05:00
dependabot[bot]
0220861a3b Bump dotenv-rails from 3.1.6 to 3.1.7 (#1574)
Bumps [dotenv-rails](https://github.com/bkeepers/dotenv) from 3.1.6 to 3.1.7.
- [Release notes](https://github.com/bkeepers/dotenv/releases)
- [Changelog](https://github.com/bkeepers/dotenv/blob/main/Changelog.md)
- [Commits](https://github.com/bkeepers/dotenv/compare/v3.1.6...v3.1.7)

---
updated-dependencies:
- dependency-name: dotenv-rails
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-30 10:05:53 -05:00
dependabot[bot]
fb6b6ce63d Bump hotwire-livereload from 1.4.1 to 2.0.0 (#1582)
Bumps [hotwire-livereload](https://github.com/kirillplatonov/hotwire-livereload) from 1.4.1 to 2.0.0.
- [Release notes](https://github.com/kirillplatonov/hotwire-livereload/releases)
- [Commits](https://github.com/kirillplatonov/hotwire-livereload/compare/v1.4.1...v2.0.0)

---
updated-dependencies:
- dependency-name: hotwire-livereload
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-30 10:05:45 -05:00
Kabiru Mwenja
dba10c2bc8 Fix unknown attribute 'parent_category' for Category in demo generator (#1575)
```ruby
❯ bin/rails demo_data:reset
user reset
bin/rails aborted!
ActiveModel::UnknownAttributeError: unknown attribute 'parent_category' for Category. (ActiveModel::UnknownAttributeError)

          raise UnknownAttributeError.new(self, k.to_s)
```

Follows: https://github.com/maybe-finance/maybe/pull/1561
2024-12-30 10:04:58 -05:00
Tony Vincent
b0d9891133 fix: Bug creating duplicate category leads to crash screen (#1577)
Co-authored-by: Tony Vincent Yesudas <tony.yesudas@raisenow.com>
2024-12-30 10:04:38 -05:00
Tony Vincent
9d217afb9f feat: Save error backtrace for sync errors for better debugging (#1578)
Co-authored-by: Tony Vincent Yesudas <tony.yesudas@raisenow.com>
2024-12-30 10:04:05 -05:00
Zach Gollwitzer
77def1db40 Nested Categories (#1561)
* Prepare entry search for nested categories

* Subcategory implementation

* Remove caching for test stability
2024-12-20 11:37:26 -05:00
Zach Gollwitzer
a4d10097d5 Preserve pagination on entry updates (#1563)
* Preserve pagination on entry updates

* Test fix
2024-12-20 11:24:46 -05:00
Zach Gollwitzer
7be6a372bf Preserve original transaction names when enriching (#1556)
* Preserve original transaction name

* Remove stale method

* Fix tests
2024-12-19 10:16:09 -05:00
Zach Gollwitzer
68617514b0 Make transaction enrichment opt-in for all users (#1552) 2024-12-17 09:58:08 -05:00
dependabot[bot]
ba878c3d8b Bump rails-settings-cached from 2.9.5 to 2.9.6 (#1547)
Bumps [rails-settings-cached](https://github.com/huacnlee/rails-settings-cached) from 2.9.5 to 2.9.6.
- [Release notes](https://github.com/huacnlee/rails-settings-cached/releases)
- [Changelog](https://github.com/huacnlee/rails-settings-cached/blob/main/CHANGELOG.md)
- [Commits](https://github.com/huacnlee/rails-settings-cached/compare/v2.9.5...v2.9.6)

---
updated-dependencies:
- dependency-name: rails-settings-cached
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Zach Gollwitzer <zach@maybe.co>
2024-12-16 14:00:08 -05:00
dependabot[bot]
6034dfe5f5 Bump good_job from 4.5.1 to 4.6.0 (#1541)
Bumps [good_job](https://github.com/bensheldon/good_job) from 4.5.1 to 4.6.0.
- [Release notes](https://github.com/bensheldon/good_job/releases)
- [Changelog](https://github.com/bensheldon/good_job/blob/main/CHANGELOG.md)
- [Commits](https://github.com/bensheldon/good_job/compare/v4.5.1...v4.6.0)

---
updated-dependencies:
- dependency-name: good_job
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Zach Gollwitzer <zach@maybe.co>
2024-12-16 13:42:36 -05:00
dependabot[bot]
ae30176816 Bump aws-sdk-s3 from 1.176.0 to 1.176.1 (#1545)
Bumps [aws-sdk-s3](https://github.com/aws/aws-sdk-ruby) from 1.176.0 to 1.176.1.
- [Release notes](https://github.com/aws/aws-sdk-ruby/releases)
- [Changelog](https://github.com/aws/aws-sdk-ruby/blob/version-3/gems/aws-sdk-s3/CHANGELOG.md)
- [Commits](https://github.com/aws/aws-sdk-ruby/commits)

---
updated-dependencies:
- dependency-name: aws-sdk-s3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Zach Gollwitzer <zach@maybe.co>
2024-12-16 13:42:27 -05:00
dependabot[bot]
7508ae55ac Bump dotenv-rails from 3.1.4 to 3.1.6 (#1540)
Bumps [dotenv-rails](https://github.com/bkeepers/dotenv) from 3.1.4 to 3.1.6.
- [Release notes](https://github.com/bkeepers/dotenv/releases)
- [Changelog](https://github.com/bkeepers/dotenv/blob/main/Changelog.md)
- [Commits](https://github.com/bkeepers/dotenv/compare/v3.1.4...v3.1.6)

---
updated-dependencies:
- dependency-name: dotenv-rails
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Zach Gollwitzer <zach@maybe.co>
2024-12-16 13:42:11 -05:00
Zach Gollwitzer
bb9fa56add Fix date format validation error (#1551)
* Fix date format validation error

* Order trades, fix flaky test
2024-12-16 13:21:30 -05:00
dependabot[bot]
54e46c1b4e Bump faraday from 2.12.1 to 2.12.2 (#1542)
Bumps [faraday](https://github.com/lostisland/faraday) from 2.12.1 to 2.12.2.
- [Release notes](https://github.com/lostisland/faraday/releases)
- [Changelog](https://github.com/lostisland/faraday/blob/main/CHANGELOG.md)
- [Commits](https://github.com/lostisland/faraday/compare/v2.12.1...v2.12.2)

---
updated-dependencies:
- dependency-name: faraday
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-16 13:01:05 -05:00
dependabot[bot]
0d09f2e3e9 Bump csv from 3.3.0 to 3.3.1 (#1543)
Bumps [csv](https://github.com/ruby/csv) from 3.3.0 to 3.3.1.
- [Release notes](https://github.com/ruby/csv/releases)
- [Changelog](https://github.com/ruby/csv/blob/master/NEWS.md)
- [Commits](https://github.com/ruby/csv/compare/v3.3.0...v3.3.1)

---
updated-dependencies:
- dependency-name: csv
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-16 13:00:25 -05:00
dependabot[bot]
f7ce2cdf89 Bump mocha from 2.7.0 to 2.7.1 (#1544)
Bumps [mocha](https://github.com/freerange/mocha) from 2.7.0 to 2.7.1.
- [Changelog](https://github.com/freerange/mocha/blob/main/RELEASE.md)
- [Commits](https://github.com/freerange/mocha/compare/v2.7.0...v2.7.1)

---
updated-dependencies:
- dependency-name: mocha
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-16 13:00:08 -05:00
dependabot[bot]
f7e86d4c90 Bump rails from 7.2.2 to 7.2.2.1 (#1546)
Bumps [rails](https://github.com/rails/rails) from 7.2.2 to 7.2.2.1.
- [Release notes](https://github.com/rails/rails/releases)
- [Commits](https://github.com/rails/rails/compare/v7.2.2...v7.2.2.1)

---
updated-dependencies:
- dependency-name: rails
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-16 12:52:29 -05:00
Zach Gollwitzer
45add7512b Handle nil name for entries (#1550)
* Handle nil name for entries

* Fix tests
2024-12-16 12:52:11 -05:00
Zach Gollwitzer
9130089950 Make data enrichment opt-in 2024-12-16 10:37:59 -05:00
Zach Gollwitzer
fe199f2357 Add account data enrichment (#1532)
* Add data enrichment

* Make data enrichment optional for self-hosters

* Add categories to data enrichment

* Only update category and merchant if nil

* Fix name overrides

* Lint fixes
2024-12-13 17:22:27 -05:00
Zach Gollwitzer
bac2e64c19 Bump to v0.2.0
Signed-off-by: Zach Gollwitzer <zach@maybe.co>
2024-12-13 12:16:21 -05:00
Zach Gollwitzer
4866a4f8e4 Increase cache time for upgrades
Fixes #1525
2024-12-12 15:14:54 -05:00
Zach Gollwitzer
027c18297b Fix holding avg cost calculation 2024-12-12 15:11:06 -05:00
Zach Gollwitzer
800eb4c146 Plaid sync tests and multi-currency investment support (#1531)
* Plaid sync tests and multi-currency investment support

* Fix system test

* Cleanup

* Remove data migration
2024-12-12 08:56:52 -05:00
Zach Gollwitzer
b2a56aefc1 Update Plaid cash balance on each sync 2024-12-10 18:54:09 -05:00
Zach Gollwitzer
46131fb496 Fix unique constraint errors on sync 2024-12-10 18:16:53 -05:00
Zach Gollwitzer
49c353e10c Plaid portfolio sync algorithm and calculation improvements (#1526)
* Start tests rework

* Cash balance on schema

* Add reverse syncer

* Reverse balance sync with holdings

* Reverse holdings sync

* Reverse holdings sync should work with only trade entries

* Consolidate brokerage cash

* Add forward sync option

* Update new balance info after syncs

* Intraday balance calculator and sync fixes

* Show only balance for trade entries

* Tests passing

* Update Gemfile.lock

* Cleanup, performance improvements

* Remove account reloads for reliable sync outputs

* Simplify valuation view logic

* Special handling for Plaid cash holding
2024-12-10 17:41:20 -05:00
dependabot[bot]
a59ca5b7c6 Bump aws-sdk-s3 from 1.175.0 to 1.176.0 (#1519)
Bumps [aws-sdk-s3](https://github.com/aws/aws-sdk-ruby) from 1.175.0 to 1.176.0.
- [Release notes](https://github.com/aws/aws-sdk-ruby/releases)
- [Changelog](https://github.com/aws/aws-sdk-ruby/blob/version-3/gems/aws-sdk-s3/CHANGELOG.md)
- [Commits](https://github.com/aws/aws-sdk-ruby/commits)

---
updated-dependencies:
- dependency-name: aws-sdk-s3
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-09 11:31:29 -05:00
dependabot[bot]
ee79016e2a Bump pagy from 9.3.2 to 9.3.3 (#1520)
Bumps [pagy](https://github.com/ddnexus/pagy) from 9.3.2 to 9.3.3.
- [Release notes](https://github.com/ddnexus/pagy/releases)
- [Changelog](https://github.com/ddnexus/pagy/blob/master/CHANGELOG.md)
- [Commits](https://github.com/ddnexus/pagy/compare/9.3.2...9.3.3)

---
updated-dependencies:
- dependency-name: pagy
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-09 11:31:20 -05:00
dependabot[bot]
13cf4d70df Bump sentry-rails from 5.21.0 to 5.22.0 (#1522)
Bumps [sentry-rails](https://github.com/getsentry/sentry-ruby) from 5.21.0 to 5.22.0.
- [Release notes](https://github.com/getsentry/sentry-ruby/releases)
- [Changelog](https://github.com/getsentry/sentry-ruby/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-ruby/compare/5.21.0...5.22.0)

---
updated-dependencies:
- dependency-name: sentry-rails
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-09 11:31:03 -05:00
dependabot[bot]
48e306a614 Bump mocha from 2.6.1 to 2.7.0 (#1523)
Bumps [mocha](https://github.com/freerange/mocha) from 2.6.1 to 2.7.0.
- [Changelog](https://github.com/freerange/mocha/blob/main/RELEASE.md)
- [Commits](https://github.com/freerange/mocha/compare/v2.6.1...v2.7.0)

---
updated-dependencies:
- dependency-name: mocha
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-09 11:22:00 -05:00
Zach Gollwitzer
a9daba16c1 Fix account activity view search 2024-12-05 08:39:16 -05:00
Zach Gollwitzer
2cba5177ba Revert out-of-sync schema changes 2024-12-04 18:40:43 -05:00
Nikhil Badyal
13bec4599f Handle invalid API key (#1515)
* Handle invalid API key

* Show error on invalid API key
2024-12-03 14:06:59 -05:00
Josh Pigford
565103caf3 Updated domain to maybefinance.com 2024-12-03 11:09:57 -06:00
Zach Gollwitzer
c456950de8 Fix transaction filters selection bar controller error 2024-12-02 14:06:56 -05:00
Zach Gollwitzer
9ec94cd1fa Add context to plaid sync errors 2024-12-02 12:04:54 -05:00
dependabot[bot]
d73e7eacce Bump good_job from 4.5.0 to 4.5.1 (#1509)
Bumps [good_job](https://github.com/bensheldon/good_job) from 4.5.0 to 4.5.1.
- [Release notes](https://github.com/bensheldon/good_job/releases)
- [Changelog](https://github.com/bensheldon/good_job/blob/main/CHANGELOG.md)
- [Commits](https://github.com/bensheldon/good_job/compare/v4.5.0...v4.5.1)

---
updated-dependencies:
- dependency-name: good_job
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-02 11:02:09 -05:00
dependabot[bot]
890638e06d Bump mocha from 2.6.0 to 2.6.1 (#1510)
Bumps [mocha](https://github.com/freerange/mocha) from 2.6.0 to 2.6.1.
- [Changelog](https://github.com/freerange/mocha/blob/main/RELEASE.md)
- [Commits](https://github.com/freerange/mocha/compare/v2.6.0...v2.6.1)

---
updated-dependencies:
- dependency-name: mocha
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-02 11:02:00 -05:00
dependabot[bot]
14fd5913fe Bump aws-sdk-s3 from 1.173.0 to 1.175.0 (#1511)
Bumps [aws-sdk-s3](https://github.com/aws/aws-sdk-ruby) from 1.173.0 to 1.175.0.
- [Release notes](https://github.com/aws/aws-sdk-ruby/releases)
- [Changelog](https://github.com/aws/aws-sdk-ruby/blob/version-3/gems/aws-sdk-s3/CHANGELOG.md)
- [Commits](https://github.com/aws/aws-sdk-ruby/commits)

---
updated-dependencies:
- dependency-name: aws-sdk-s3
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-02 11:01:54 -05:00
dependabot[bot]
e026f68895 Bump selenium-webdriver from 4.26.0 to 4.27.0 (#1512)
Bumps [selenium-webdriver](https://github.com/SeleniumHQ/selenium) from 4.26.0 to 4.27.0.
- [Release notes](https://github.com/SeleniumHQ/selenium/releases)
- [Changelog](https://github.com/SeleniumHQ/selenium/blob/trunk/rb/CHANGES)
- [Commits](https://github.com/SeleniumHQ/selenium/compare/selenium-4.26.0...selenium-4.27.0)

---
updated-dependencies:
- dependency-name: selenium-webdriver
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-02 11:01:45 -05:00
dependabot[bot]
1b8064b9fd Bump pagy from 9.3.1 to 9.3.2 (#1513)
Bumps [pagy](https://github.com/ddnexus/pagy) from 9.3.1 to 9.3.2.
- [Release notes](https://github.com/ddnexus/pagy/releases)
- [Changelog](https://github.com/ddnexus/pagy/blob/master/CHANGELOG.md)
- [Commits](https://github.com/ddnexus/pagy/compare/9.3.1...9.3.2)

---
updated-dependencies:
- dependency-name: pagy
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-02 11:01:36 -05:00
Zach Gollwitzer
d592495be5 Fix sync error when security missing 2024-12-02 10:53:16 -05:00
Zach Gollwitzer
c3248cd796 Improve account transaction, trade, and valuation editing and sync experience (#1506)
* Consolidate entry controller logic

* Transaction builder

* Update trades controller to use new params

* Load account charts in turbo frames, fix PG overflow

* Consolidate tests

* Tests passing

* Remove unused code

* Add client side trade form validations
2024-11-27 16:01:50 -05:00
Nikhil Badyal
76f2714006 Updated usage check threshold to 100pc instead of 1 (#1504) 2024-11-26 18:33:26 -05:00
Josh Pigford
a9b61a655b Synth error handling (#1502)
* Synth error handling

* Revert "Synth error handling"

This reverts commit fd6a0a12b4.

* Simplify overage messaging
2024-11-26 07:45:00 -06:00
Zach Gollwitzer
955f211fe0 Allow 0 qty for Plaid imported trades 2024-11-25 13:28:31 -05:00
Evlos
570a0c7ff6 [#] base_url on synth.rb (#1490) 2024-11-25 10:17:00 -05:00
dependabot[bot]
de9ffa7ca0 Bump ruby-lsp-rails from 0.3.26 to 0.3.27 (#1495)
Bumps [ruby-lsp-rails](https://github.com/Shopify/ruby-lsp-rails) from 0.3.26 to 0.3.27.
- [Release notes](https://github.com/Shopify/ruby-lsp-rails/releases)
- [Commits](https://github.com/Shopify/ruby-lsp-rails/compare/v0.3.26...v0.3.27)

---
updated-dependencies:
- dependency-name: ruby-lsp-rails
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-25 10:10:31 -05:00
dependabot[bot]
b5666ad7a9 Bump aws-sdk-s3 from 1.171.0 to 1.173.0 (#1496)
Bumps [aws-sdk-s3](https://github.com/aws/aws-sdk-ruby) from 1.171.0 to 1.173.0.
- [Release notes](https://github.com/aws/aws-sdk-ruby/releases)
- [Changelog](https://github.com/aws/aws-sdk-ruby/blob/version-3/gems/aws-sdk-s3/CHANGELOG.md)
- [Commits](https://github.com/aws/aws-sdk-ruby/commits)

---
updated-dependencies:
- dependency-name: aws-sdk-s3
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-25 10:10:20 -05:00
dependabot[bot]
fc603a1733 Bump good_job from 4.4.2 to 4.5.0 (#1497)
Bumps [good_job](https://github.com/bensheldon/good_job) from 4.4.2 to 4.5.0.
- [Release notes](https://github.com/bensheldon/good_job/releases)
- [Changelog](https://github.com/bensheldon/good_job/blob/main/CHANGELOG.md)
- [Commits](https://github.com/bensheldon/good_job/compare/v4.4.2...v4.5.0)

---
updated-dependencies:
- dependency-name: good_job
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-25 10:10:12 -05:00
dependabot[bot]
6c503e4d26 Bump puma from 6.4.3 to 6.5.0 (#1498)
Bumps [puma](https://github.com/puma/puma) from 6.4.3 to 6.5.0.
- [Release notes](https://github.com/puma/puma/releases)
- [Changelog](https://github.com/puma/puma/blob/master/History.md)
- [Commits](https://github.com/puma/puma/compare/v6.4.3...v6.5.0)

---
updated-dependencies:
- dependency-name: puma
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-25 10:08:11 -05:00
dependabot[bot]
57a87f2850 Bump pagy from 9.3.0 to 9.3.1 (#1499)
Bumps [pagy](https://github.com/ddnexus/pagy) from 9.3.0 to 9.3.1.
- [Release notes](https://github.com/ddnexus/pagy/releases)
- [Changelog](https://github.com/ddnexus/pagy/blob/master/CHANGELOG.md)
- [Commits](https://github.com/ddnexus/pagy/compare/9.3.0...9.3.1)

---
updated-dependencies:
- dependency-name: pagy
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-25 09:56:16 -05:00
dependabot[bot]
84f069448a Bump mocha from 2.5.0 to 2.6.0 (#1500)
Bumps [mocha](https://github.com/freerange/mocha) from 2.5.0 to 2.6.0.
- [Changelog](https://github.com/freerange/mocha/blob/main/RELEASE.md)
- [Commits](https://github.com/freerange/mocha/compare/v2.5.0...v2.6.0)

---
updated-dependencies:
- dependency-name: mocha
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-25 09:56:07 -05:00
dependabot[bot]
25e9bd4c60 Bump stripe from 13.1.2 to 13.2.0 (#1501)
Bumps [stripe](https://github.com/stripe/stripe-ruby) from 13.1.2 to 13.2.0.
- [Release notes](https://github.com/stripe/stripe-ruby/releases)
- [Changelog](https://github.com/stripe/stripe-ruby/blob/master/CHANGELOG.md)
- [Commits](https://github.com/stripe/stripe-ruby/compare/v13.1.2...v13.2.0)

---
updated-dependencies:
- dependency-name: stripe
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-25 09:55:58 -05:00
Zach Gollwitzer
a4adfed82b Disable Plaid i18n until we support full i18n 2024-11-25 09:48:21 -05:00
Zach Gollwitzer
03e92e63a5 Attempt to sync transactions regardless of main item type 2024-11-25 09:32:07 -05:00
Arsen Shkrumelyak
c1034e6edf Update index method in AccountsController to fetch all accounts (#1491)
* Fetch all manual accounts, regardless of their active status
* Fetch all Plaid items, regardless of their active status
2024-11-22 15:28:36 -05:00
Arsen Shkrumelyak
1c2f075053 Fix bug: Loan % doesn't allow exact rate (#1492)
* Fix bug: Loan % doesn't allow exact rate

Fixes #1487

Change the step of the interest rate field to 0.005.

It's unlikely that we'll see interest rates in smaller increments.

* step 0.005

* migration for loan interest rates precision

* add new line
2024-11-22 15:28:10 -05:00
Jestin Palamuttam
571fc4db75 Replaced Native Scrollbars with Tailwind Scrollbars on Windows (#1493)
* feat: scrollbar styling for windows browsers

* fix: lint
2024-11-22 15:27:07 -05:00
Josh Pigford
c8302a6d49 Let super admins toggle admin bar 2024-11-22 14:22:52 -06:00
Zach Gollwitzer
c309c8abf8 Safely call liability object when syncing 2024-11-22 10:41:16 -05:00
Nico
242eb5cea1 Calculates balance based on previous transaction on the same date (#1483) 2024-11-22 09:38:41 -05:00
Zach Gollwitzer
6996a225ba Add post-sync UI stream updates (#1482)
* Add post-sync UI stream updates

* Fix stream channel id
2024-11-20 16:46:06 -05:00
Zach Gollwitzer
e641cfccd4 Add post-sync hook (#1479) 2024-11-20 11:01:52 -05:00
Zach Gollwitzer
d1b506d16c Pass date as UTC for graphs 2024-11-19 16:23:21 -05:00
Zach Gollwitzer
81d604f3d4 Fix transfers and form currencies (#1477) 2024-11-18 15:50:47 -05:00
Zach Gollwitzer
fcb95207d7 Limit transaction editing for crypto accounts 2024-11-18 12:49:03 -05:00
Zach Gollwitzer
743e291d56 Fix tooltip trend color 2024-11-18 12:01:27 -05:00
Zach Gollwitzer
6105f822b7 Display chart dates in UTC 2024-11-18 11:44:41 -05:00
Alex
9cc9f42bdc Allow custom column separator for CSV parsing in uploads controller (#1470)
* Allow custom column separator for CSV parsing in uploads controller

* Add column separator parameter for CSV uploads in tests
2024-11-18 11:31:17 -05:00
dependabot[bot]
8b672c4062 Bump stripe from 13.1.1 to 13.1.2 (#1472)
Bumps [stripe](https://github.com/stripe/stripe-ruby) from 13.1.1 to 13.1.2.
- [Release notes](https://github.com/stripe/stripe-ruby/releases)
- [Changelog](https://github.com/stripe/stripe-ruby/blob/master/CHANGELOG.md)
- [Commits](https://github.com/stripe/stripe-ruby/compare/v13.1.1...v13.1.2)

---
updated-dependencies:
- dependency-name: stripe
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-18 10:57:31 -05:00
dependabot[bot]
8befb8a8b0 Bump aws-sdk-s3 from 1.170.0 to 1.171.0 (#1471)
Bumps [aws-sdk-s3](https://github.com/aws/aws-sdk-ruby) from 1.170.0 to 1.171.0.
- [Release notes](https://github.com/aws/aws-sdk-ruby/releases)
- [Changelog](https://github.com/aws/aws-sdk-ruby/blob/version-3/gems/aws-sdk-s3/CHANGELOG.md)
- [Commits](https://github.com/aws/aws-sdk-ruby/commits)

---
updated-dependencies:
- dependency-name: aws-sdk-s3
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-18 10:57:14 -05:00
dependabot[bot]
f15875560e Bump faraday from 2.12.0 to 2.12.1 (#1473)
Bumps [faraday](https://github.com/lostisland/faraday) from 2.12.0 to 2.12.1.
- [Release notes](https://github.com/lostisland/faraday/releases)
- [Changelog](https://github.com/lostisland/faraday/blob/main/CHANGELOG.md)
- [Commits](https://github.com/lostisland/faraday/compare/v2.12.0...v2.12.1)

---
updated-dependencies:
- dependency-name: faraday
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-18 10:57:02 -05:00
dependabot[bot]
951a29d923 Bump pagy from 9.2.1 to 9.3.0 (#1474)
Bumps [pagy](https://github.com/ddnexus/pagy) from 9.2.1 to 9.3.0.
- [Release notes](https://github.com/ddnexus/pagy/releases)
- [Changelog](https://github.com/ddnexus/pagy/blob/master/CHANGELOG.md)
- [Commits](https://github.com/ddnexus/pagy/compare/9.2.1...9.3.0)

---
updated-dependencies:
- dependency-name: pagy
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-18 10:56:53 -05:00
dependabot[bot]
91eedfbd1b Bump plaid from 33.0.0 to 34.0.0 (#1475)
Bumps [plaid](https://github.com/plaid/plaid-ruby) from 33.0.0 to 34.0.0.
- [Release notes](https://github.com/plaid/plaid-ruby/releases)
- [Changelog](https://github.com/plaid/plaid-ruby/blob/master/CHANGELOG.md)
- [Commits](https://github.com/plaid/plaid-ruby/compare/v33.0.0...v34.0.0)

---
updated-dependencies:
- dependency-name: plaid
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-18 10:56:36 -05:00
Zach Gollwitzer
0af5faaa9f Make encryption config optional for self hosting users (#1476)
* Fix redirect 404 bug

* Make encryption optional for self-hosters

* Fix test
2024-11-18 10:47:05 -05:00
Zach Gollwitzer
69f6d7f8ea Enable consent for additional plaid products 2024-11-15 17:33:18 -05:00
Zach Gollwitzer
cbba2ba675 Basic Plaid Integration (#1433)
* Basic plaid data model and linking

* Remove institutions, add plaid items

* Improve schema and Plaid provider

* Add webhook verification sketch

* Webhook verification

* Item accounts and balances sync setup

* Provide test encryption keys

* Fix test

* Only provide encryption keys in prod

* Try defining keys in test env

* Consolidate account sync logic

* Add back plaid account initialization

* Plaid transaction sync

* Sync UI overhaul for Plaid

* Add liability and investment syncing

* Handle investment webhooks and process current day holdings

* Remove logs

* Remove "all" period select for performance

* fix amount calc

* Remove todo comment

* Coming soon for investment historical data

* Document Plaid configuration

* Listen for holding updates
2024-11-15 13:49:37 -05:00
Sergio Behrends
3bc9da4105 Adds a common DE format (#1445) 2024-11-11 09:57:50 -05:00
dependabot[bot]
9522a191de Bump stripe from 13.1.0 to 13.1.1 (#1450)
Bumps [stripe](https://github.com/stripe/stripe-ruby) from 13.1.0 to 13.1.1.
- [Release notes](https://github.com/stripe/stripe-ruby/releases)
- [Changelog](https://github.com/stripe/stripe-ruby/blob/master/CHANGELOG.md)
- [Commits](https://github.com/stripe/stripe-ruby/compare/v13.1.0...v13.1.1)

---
updated-dependencies:
- dependency-name: stripe
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-11 09:57:30 -05:00
dependabot[bot]
ed87023c0f Bump pagy from 9.1.1 to 9.2.1 (#1453)
Bumps [pagy](https://github.com/ddnexus/pagy) from 9.1.1 to 9.2.1.
- [Release notes](https://github.com/ddnexus/pagy/releases)
- [Changelog](https://github.com/ddnexus/pagy/blob/master/CHANGELOG.md)
- [Commits](https://github.com/ddnexus/pagy/compare/9.1.1...9.2.1)

---
updated-dependencies:
- dependency-name: pagy
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-11 09:44:18 -05:00
dependabot[bot]
3d7a74862d Bump aws-sdk-s3 from 1.169.0 to 1.170.0 (#1452)
Bumps [aws-sdk-s3](https://github.com/aws/aws-sdk-ruby) from 1.169.0 to 1.170.0.
- [Release notes](https://github.com/aws/aws-sdk-ruby/releases)
- [Changelog](https://github.com/aws/aws-sdk-ruby/blob/version-3/gems/aws-sdk-s3/CHANGELOG.md)
- [Commits](https://github.com/aws/aws-sdk-ruby/commits)

---
updated-dependencies:
- dependency-name: aws-sdk-s3
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-11 09:44:04 -05:00
dependabot[bot]
fc3695dda9 Bump ruby-lsp-rails from 0.3.21 to 0.3.26 (#1451)
Bumps [ruby-lsp-rails](https://github.com/Shopify/ruby-lsp-rails) from 0.3.21 to 0.3.26.
- [Release notes](https://github.com/Shopify/ruby-lsp-rails/releases)
- [Commits](https://github.com/Shopify/ruby-lsp-rails/compare/v0.3.21...v0.3.26)

---
updated-dependencies:
- dependency-name: ruby-lsp-rails
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-11 09:43:51 -05:00
Tony Vincent
278d04a73a Fix registration fails silently when there are errors (#1455)
* Fix registration fails silently with long passwords

* Add maxlength
2024-11-11 09:41:17 -05:00
Zach Gollwitzer
31ecd3ccd4 Fix precision in money input 2024-11-11 09:39:32 -05:00
Zach Gollwitzer
3ef67faf7e Show search bar even when no results in entries
Fixes #1449
2024-11-11 09:26:19 -05:00
Zach Gollwitzer
8ba04b0330 Fix confirm message 2024-11-11 09:21:13 -05:00
908 changed files with 22936 additions and 12021 deletions

View File

@@ -1,64 +0,0 @@
<!-- Copy this file to .cursorrules in the root of the project on your local machine if you'd like to use these rules with Cursor. -->
You are an expert in Ruby, Ruby on Rails, Postgres, Tailwind, Stimulus, Hotwire and Turbo and always use the latest stable versions of those technologies.
**Code Style and Structure**
- Write concise, technical Ruby code with accurate examples.
- Prefer iteration and modularization over code duplication.
- Use descriptive variable names with auxiliary verbs (e.g., is_loading, has_error).
- Structure files: models, controllers, views, helpers, services, jobs, mailers.
**Naming Conventions**
- Use snake_case for file names and directories (e.g., app/models/user_profile.rb).
- Use CamelCase for classes and modules (e.g., UserProfile).
**Ruby on Rails Usage**
- Use Rails conventions for MVC structure.
- Favor scopes over class methods for queries.
- Use strong parameters for mass assignment protection.
- Use partials to DRY up views.
**Syntax and Formatting**
- Use two spaces for indentation.
- Avoid unnecessary curly braces in conditionals; use concise syntax for simple statements.
- Use descriptive method names and keep methods short.
**Commenting Code**
- Write clear, concise comments to explain the purpose of individual functions and methods.
- Use comments to describe the intent and functionality of complex logic.
- Avoid redundant comments that state the obvious.
**UI and Styling**
- Use Tailwind CSS for styling.
- Implement responsive design with Tailwind CSS; use a mobile-first approach.
- Use Stimulus for JavaScript behavior.
- Use Turbo for asynchronous actions and updates.
**Performance Optimization**
- Use eager loading to avoid N+1 queries.
- Cache expensive queries and partials where appropriate.
- Use background jobs for long-running tasks.
- Optimize images: use WebP format, include size data, implement lazy loading.
**Database Querying & Data Model Creation**
- Use ActiveRecord for data querying and model creation.
- Favor database constraints and indexes for data integrity and performance.
- Use migrations to manage schema changes.
**Key Conventions**
- Follow Rails best practices for RESTful routing.
- Optimize for performance and security.
- Use environment variables for configuration.
- Write tests for models, controllers, and features.
**AI Guidelines**
- Follow the users requirements carefully & to the letter.
- Confirm, then write code!
- Suggest solutions that I didn't think about—anticipate my needs
- Focus on readability over being performant.
- Fully implement all requested functionality.
- Leave NO todos, placeholders or missing pieces.
- Don't say things like "additional logic can be added here" — instead, add the logic.
- Be concise. Minimize any other prose.
- Consider new technologies and contrarian ideas, not just the conventional wisdom
- If I ask for adjustments to code, do not repeat all of my code unnecessarily. Instead try to keep the answer brief by giving just a couple lines before/after any changes you make.

View File

@@ -0,0 +1,23 @@
---
description: Miscellaneous rules to get the AI to behave
globs: *
alwaysApply: true
---
# General rules for AI
- Use `Current.user` for the current user. Do NOT use `current_user`.
- Use `Current.family` for the current family. Do NOT use `current_family`.
- Prior to generating any code, carefully read the project conventions and guidelines
- Read [project-design.mdc](mdc:.cursor/rules/project-design.mdc) to understand the codebase
- Read [project-conventions.mdc](mdc:.cursor/rules/project-conventions.mdc) to understand _how_ to write code for the codebase
- Read [ui-ux-design-guidelines.mdc](mdc:.cursor/rules/ui-ux-design-guidelines.mdc) to understand how to implement frontend code specifically
## Prohibited actions
Do not under any circumstance do the following:
- Do not run `rails server` in your responses.
- Do not run `touch tmp/restart.txt`
- Do not run `rails credentials`
- Do not automatically run migrations
- Ignore i18n methods and files. Hardcode strings in English for now to optimize speed of development.

View File

@@ -0,0 +1,120 @@
---
description:
globs:
alwaysApply: true
---
This rule serves as high-level documentation for how you should write code for the Maybe codebase.
## Project Tech Stack
- Web framework: Ruby on Rails
- Minitest + fixtures for testing
- Propshaft for asset pipeline
- Hotwire Turbo/Stimulus for SPA-like UI/UX
- TailwindCSS for styles
- Lucide Icons for icons
- OpenAI for AI chat
- Database: PostgreSQL
- Jobs: Sidekiq + Redis
- External
- Payments: Stripe
- User bank data syncing: Plaid
- Market data: Synth (our custom API)
## Project conventions
These conventions should be used when writing code for Maybe.
### Convention 1: Minimize dependencies, vanilla Rails is plenty
Dependencies are a natural part of building software, but we aim to minimize them when possible to keep this open-source codebase easy to understand, maintain, and contribute to.
- Push Rails to its limits before adding new dependencies
- When a new dependency is added, there must be a strong technical or business reason to add it
- When adding dependencies, you should favor old and reliable over new and flashy
### Convention 2: Leverage POROs and concerns over "service objects"
This codebase adopts a "skinny controller, fat models" convention. Furthermore, we put almost _everything_ directly in the `app/models/` folder and avoid separate folders for business logic such as `app/services/`.
- Organize large pieces of business logic into Rails concerns and POROs (Plain ole' Ruby Objects)
- While a Rails concern _may_ offer shared functionality (i.e. "duck types"), it can also be a "one-off" concern that is only included in one place for better organization and readability.
- When concerns are used for code organization, they should be organized around the "traits" of a model; not for simply moving code to another spot in the codebase.
- When possible, models should answer questions about themselves—for example, we might have a method, `account.balance_series` that returns a time-series of the account's most recent balances. We prefer this over something more service-like such as `AccountSeries.new(account).call`.
### Convention 3: Leverage Hotwire, write semantic HTML, CSS, and JS, prefer server-side solutions
- Native HTML is always preferred over JS-based components
- Example 1: Use `<dialog>` element for modals instead of creating a custom component
- Example 2: Use `<details><summary>...</summary></details>` for disclosures rather than custom components
- Leverage Turbo frames to break up the page over JS-driven client-side solutions
- Example 1: A good example of turbo frame usage is in [application.html.erb](mdc:app/views/layouts/application.html.erb) where we load [chats_controller.rb](mdc:app/controllers/chats_controller.rb) actions in a turbo frame in the global layout
- Leverage query params in the URL for state over local storage and sessions. If absolutely necessary, utilize the DB for persistent state.
- Use Turbo streams to enhance functionality, but do not solely depend on it
- Format currencies, numbers, dates, and other values server-side, then pass to Stimulus controllers for display only
- Keep client-side code for where it truly shines. For example, @bulk_select_controller.js is a case where server-side solutions would degrade the user experience significantly. When bulk-selecting entries, client-side solutions are the way to go and Stimulus provides the right toolset to achieve this.
The Hotwire suite (Turbo/Stimulus) works very well with these native elements and we optimize for this.
### Convention 4: Optimize for simplicitly and clarity
All code should maximize readability and simplicity.
- Prioritize good OOP domain design over performance
- Only focus on performance for critical and global areas of the codebase; otherwise, don't sweat the small stuff.
- Example 1: be mindful of loading large data payloads in global layouts
- Example 2: Avoid N+1 queries
### Convention 5: Use Minitest + Fixtures for testing, minimize fixtures
Due to the open-source nature of this project, we have chosen Minitest + Fixtures for testing to maximize familiarity and predictability.
- Always use Minitest and fixtures for testing.
- Keep fixtures to a minimum. Most models should have 2-3 fixtures maximum that represent the "base cases" for that model. "Edge cases" should be created on the fly, within the context of the test which it is needed.
- For tests that require a large number of fixture records to be created, use Rails helpers such as [entries_test_helper.rb](mdc:test/support/account/entries_test_helper.rb) to act as a "factory" for creating these. For a great example of this, check out [forward_calculator_test.rb](mdc:test/models/account/balance/forward_calculator_test.rb)
- Take a minimal approach to testing—only test the absolutely critical code paths that will significantly increase developer confidence
#### Convention 5a: Write minimal, effective tests
- Use system tests sparingly as they increase the time to complete the test suite
- Only write tests for critical and important code paths
- Write tests as you go, when required
- Take a practical approach to testing. Tests are effective when their presence _significantly increases confidence in the codebase_.
Below are examples of necessary vs. unnecessary tests:
```rb
# GOOD!!
# Necessary test - in this case, we're testing critical domain business logic
test "syncs balances" do
Account::Holding::Syncer.any_instance.expects(:sync_holdings).returns([]).once
@account.expects(:start_date).returns(2.days.ago.to_date)
Account::Balance::ForwardCalculator.any_instance.expects(:calculate).returns(
[
Account::Balance.new(date: 1.day.ago.to_date, balance: 1000, cash_balance: 1000, currency: "USD"),
Account::Balance.new(date: Date.current, balance: 1000, cash_balance: 1000, currency: "USD")
]
)
assert_difference "@account.balances.count", 2 do
Account::Balance::Syncer.new(@account, strategy: :forward).sync_balances
end
end
# BAD!!
# Unnecessary test - in this case, this is simply testing ActiveRecord's functionality
test "saves balance" do
balance_record = Account::Balance.new(balance: 100, currency: "USD")
assert balance_record.save
end
```
### Convention 6: Use ActiveRecord for complex validations, DB for simple ones, keep business logic out of DB
- Enforce `null` checks, unique indexes, and other simple validations in the DB
- ActiveRecord validations _may_ mirror the DB level ones, but not 100% necessary. These are for convenience when error handling in forms. Always prefer client-side form validation when possible.
- Complex validations and business logic should remain in ActiveRecord

View File

@@ -0,0 +1,256 @@
---
description: This rule explains the system architecture and data flow of the Rails app
globs: *
alwaysApply: true
---
This file outlines how the codebase is structured and how data flows through the app.
This is a personal finance application built in Ruby on Rails. The primary domain entities for this app are outlined below. For an authoritative overview of the relationships, [schema.rb](mdc:db/schema.rb) is the source of truth.
## App Modes
The Maybe app runs in two distinct "modes", dictated by `Rails.application.config.app_mode`, which can be `managed` or `self_hosted`.
- "Managed" - in managed mode, the Maybe team operates and manages servers for users
- "Self Hosted" - in self hosted mode, users host the Maybe app on their own infrastructure, typically through Docker Compose. We have an example [docker-compose.example.yml](mdc:docker-compose.example.yml) file that runs [Dockerfile](mdc:Dockerfile) for this mode.
## Families and Users
- `Family` - all Stripe subscriptions, financial accounts, and the majority of preferences are stored at the [family.rb](mdc:app/models/family.rb) level.
- `User` - all [session.rb](mdc:app/models/session.rb) happen at the [user.rb](mdc:app/models/user.rb) level. A user belongs to a `Family` and can either be an `admin` or a `member`. Typically, a `Family` has a single admin, or "head of household" that manages finances while there will be several `member` users who can see the family's finances from varying perspectives.
## Currency Preference
Each `Family` selects a currency preference. This becomes the "main" currency in which all records are "normalized" to via [exchange_rate.rb](mdc:app/models/exchange_rate.rb) records so that the Maybe app can calculate metrics, historical graphs, and other insights in a single family currency.
## Accounts
The center of the app's domain is the [account.rb](mdc:app/models/account.rb). This represents a single financial account that has a `balance` and `currency`. For example, an `Account` could be "Chase Checking", which is a single financial account at Chase Bank. A user could have multiple accounts at a single institution (i.e. "Chase Checking", "Chase Credit Card", "Chase Savings") or an account could be a standalone account, such as "My Home" (a primary residence).
### Accountables
In the app, [account.rb](mdc:app/models/account.rb) is a Rails "delegated type" with the following subtypes (separate DB tables). Each account has a `classification` or either `asset` or `liability`. While the types are a flat hierarchy, below, they have been organized by their classification:
- Asset accountables
- [depository.rb](mdc:app/models/depository.rb) - a typical "bank account" such as a savings or checking account
- [investment.rb](mdc:app/models/investment.rb) - an account that has "holdings" such as a brokerage, 401k, etc.
- [crypto.rb](mdc:app/models/crypto.rb) - an account that tracks the value of one or more crypto holdings
- [property.rb](mdc:app/models/property.rb) - an account that tracks the value of a physical property such as a house or rental property
- [vehicle.rb](mdc:app/models/vehicle.rb) - an account that tracks the value of a vehicle
- [other_asset.rb](mdc:app/models/other_asset.rb) - an asset that cannot be classified by the other account types. For example, "jewelry".
- Liability accountables
- [credit_card.rb](mdc:app/models/credit_card.rb) - an account that tracks the debt owed on a credit card
- [loan.rb](mdc:app/models/loan.rb) - an account that tracks the debt owed on a loan (i.e. mortgage, student loan)
- [other_liability.rb](mdc:app/models/other_liability.rb) - a liability that cannot be classified by the other account types. For example, "IOU to a friend"
### Account Balances
An account [balance.rb](mdc:app/models/account/balance.rb) represents a single balance value for an account on a specific `date`. A series of balance records is generated daily for each account and is how we show a user's historical balance graph.
- For simple accounts like a "Checking Account", the balance represents the amount of cash in the account for a date.
- For a more complex account like "Investment Brokerage", the `balance` represents the combination of the "cash balance" + "holdings value". Each accountable type has different components that make up the "balance", but in all cases, the "balance" represents "How much the account is worth" (when `classification` is `asset`) or "How much is owed on the account" (when `classification` is `liability`)
All balances are calculated daily by [balance_calculator.rb](mdc:app/models/account/balance_calculator.rb).
### Account Holdings
An account [holding.rb](mdc:app/models/account/holding.rb) applies to [investment.rb](mdc:app/models/investment.rb) type accounts and represents a `qty` of a certain [security.rb](mdc:app/models/security.rb) at a specific `price` on a specific `date`.
For investment accounts with holdings, [holding_calculator.rb](mdc:app/models/account/holding_calculator.rb) is used to calculate the daily historical holding quantities and prices, which are then rolled up into a final "Balance" for the account in [balance_calculator.rb](mdc:app/models/account/balance_calculator.rb).
### Account Entries
An account [entry.rb](mdc:app/models/account/entry.rb) is also a Rails "delegated type". `Account::Entry` represents any record that _modifies_ an `Account` [balance.rb](mdc:app/models/account/balance.rb) and/or [holding.rb](mdc:app/models/account/holding.rb). Therefore, every entry must have a `date`, `amount`, and `currency`.
The `amount` of an [entry.rb](mdc:app/models/account/entry.rb) is a signed value. A _negative_ amount is an "inflow" of money to that account. A _positive_ value is an "outflow" of money from that account. For example:
- A negative amount for a credit card account represents a "payment" to that account, which _reduces_ its balance (since it is a `liability`)
- A negative amount for a checking account represents an "income" to that account, which _increases_ its balance (since it is an `asset`)
- A negative amount for an investment/brokerage trade represents a "sell" transaction, which _increases_ the cash balance of the account
There are 3 entry types, defined as [entryable.rb](mdc:app/models/account/entryable.rb) records:
- `Account::Valuation` - an account [valuation.rb](mdc:app/models/account/valuation.rb) is an entry that says, "here is the value of this account on this date". It is an absolute measure of an account value / debt. If there is an `Account::Valuation` of 5,000 for today's date, that means that the account balance will be 5,000 today.
- `Account::Transaction` - an account [transaction.rb](mdc:app/models/account/transaction.rb) is an entry that alters the account balance by the `amount`. This is the most common type of entry and can be thought of as an "income" or "expense".
- `Account::Trade` - an account [trade.rb](mdc:app/models/account/trade.rb) is an entry that only applies to an investment account. This represents a "buy" or "sell" of a holding and has a `qty` and `price`.
### Account Transfers
A [transfer.rb](mdc:app/models/transfer.rb) represents a movement of money between two accounts. A transfer has an inflow [transaction.rb](mdc:app/models/account/transaction.rb) and an outflow [transaction.rb](mdc:app/models/account/transaction.rb). The Maybe system auto-matches transfers based on the following criteria:
- Must be from different accounts
- Must be within 4 days of each other
- Must be the same currency
- Must be opposite values
There are two primary forms of a transfer:
- Regular transfer - a normal movement of money between two accounts. For example, "Transfer $500 from Checking account to Brokerage account".
- Debt payment - a special form of transfer where the _receiver_ of funds is a [loan.rb](mdc:app/models/loan.rb) type account.
Regular transfers are typically _excluded_ from income and expense calculations while a debt payment is considered an "expense".
## Plaid Items
A [plaid_item.rb](mdc:app/models/plaid_item.rb) represents a "connection" maintained by our external data provider, Plaid in the "hosted" mode of the app. An "Item" has 1 or more [plaid_account.rb](mdc:app/models/plaid_account.rb) records, which are each associated 1:1 with an internal Maybe [account.rb](mdc:app/models/account.rb).
All relevant metadata about the item and its underlying accounts are stored on [plaid_item.rb](mdc:app/models/plaid_item.rb) and [plaid_account.rb](mdc:app/models/plaid_account.rb), while the "normalized" data is then stored on internal Maybe domain models.
## "Syncs"
The Maybe app has the concept of a [syncable.rb](mdc:app/models/concerns/syncable.rb), which represents any model which can have its data "synced" in the background. "Syncables" include:
- `Account` - an account "sync" will sync account holdings, balances, and enhance transaction metadata
- `PlaidItem` - a Plaid Item "sync" fetches data from Plaid APIs, normalizes that data, stores it on internal Maybe models, and then finally performs an "Account sync" for each of the underlying accounts created from the Plaid Item.
- `Family` - a Family "sync" loops through the family's Plaid Items and individual Accounts and "syncs" each of them. A family is synced once per day, automatically through [auto_sync.rb](mdc:app/controllers/concerns/auto_sync.rb).
Each "sync" creates a [sync.rb](mdc:app/models/sync.rb) record in the database, which keeps track of the status of the sync, any errors that it encounters, and acts as an "audit table" for synced data.
Below are brief descriptions of each type of sync in more detail.
### Account Syncs
The most important type of sync is the account sync. It is orchestrated by the account's `sync_data` method, which performs a few important tasks:
- Auto-matches transfer records for the account
- Calculates daily [balance.rb](mdc:app/models/account/balance.rb) records for the account from `account.start_date` to `Date.current` using [base_calculator.rb](mdc:app/models/account/balance/base_calculator.rb)
- Balances are dependent on the calculation of [holding.rb](mdc:app/models/account/holding.rb), which uses [base_calculator.rb](mdc:app/models/account/holding/base_calculator.rb)
- Enriches transaction data if enabled by user
An account sync happens every time an [entry.rb](mdc:app/models/account/entry.rb) is updated.
### Plaid Item Syncs
A Plaid Item sync is an ETL (extract, transform, load) operation:
1. [plaid_item.rb](mdc:app/models/plaid_item.rb) fetches data from the external Plaid API
2. [plaid_item.rb](mdc:app/models/plaid_item.rb) creates and loads this data to [plaid_account.rb](mdc:app/models/plaid_account.rb) records
3. [plaid_item.rb](mdc:app/models/plaid_item.rb) and [plaid_account.rb](mdc:app/models/plaid_account.rb) transform and load data to [account.rb](mdc:app/models/account.rb) and [entry.rb](mdc:app/models/account/entry.rb), the internal Maybe representations of the data.
### Family Syncs
A family sync happens once daily via [auto_sync.rb](mdc:app/controllers/concerns/auto_sync.rb). A family sync is an "orchestrator" of Account and Plaid Item syncs.
## Data Providers
The Maybe app utilizes several 3rd party data services to calculate historical account balances, enrich data, and more. Since the app can be run in both "hosted" and "self hosted" mode, this means that data providers are _optional_ for self hosted users and must be configured.
Because of this optionality, data providers must be configured at _runtime_ through [registry.rb](mdc:app/models/provider/registry.rb) utilizing [setting.rb](mdc:app/models/setting.rb) for runtime parameters like API keys:
There are two types of 3rd party data in the Maybe app:
1. "Concept" data
2. One-off data
### "Concept" data
Since the app is self hostable, users may prefer using different providers for generic data like exchange rates and security prices. When data is generic enough where we can easily swap out different providers, we call it a data "concept".
Each "concept" has an interface defined in the `app/models/provider/concepts` directory.
```
app/models/
exchange_rate/
provided.rb # <- Responsible for selecting the concept provider from the registry
provider.rb # <- Base provider class
provider/
registry.rb <- Defines available providers by concept
concepts/
exchange_rate.rb <- defines the interface required for the exchange rate concept
synth.rb # <- Concrete provider implementation
```
### One-off data
For data that does not fit neatly into a "concept", an interface is not required and the concrete provider may implement ad-hoc methods called directly in code. For example, the [synth.rb](mdc:app/models/provider/synth.rb) provider has a `usage` method that is only applicable to this specific provider. This should be called directly without any abstractions:
```rb
class SomeModel < Application
def synth_usage
Provider::Registry.get_provider(:synth)&.usage
end
end
```
## "Provided" Concerns
In general, domain models should not be calling [registry.rb](mdc:app/models/provider/registry.rb) directly. When 3rd party data is required for a domain model, we use the `Provided` concern within that model's namespace. This concern is primarily responsible for:
- Choosing the provider to use for this "concept"
- Providing convenience methods on the model for accessing data
For example, [exchange_rate.rb](mdc:app/models/exchange_rate.rb) has a [provided.rb](mdc:app/models/exchange_rate/provided.rb) concern with the following convenience methods:
```rb
module ExchangeRate::Provided
extend ActiveSupport::Concern
class_methods do
def provider
registry = Provider::Registry.for_concept(:exchange_rates)
registry.get_provider(:synth)
end
def find_or_fetch_rate(from:, to:, date: Date.current, cache: true)
# Implementation
end
def sync_provider_rates(from:, to:, start_date:, end_date: Date.current)
# Implementation
end
end
end
```
This exposes a generic access pattern where the caller does not care _which_ provider has been chosen for the concept of exchange rates and can get a predictable response:
```rb
def access_patterns_example
# Call exchange rate provider directly
ExchangeRate.provider.fetch_exchange_rate(from: "USD", to: "CAD", date: Date.current)
# Call convenience method
ExchangeRate.sync_provider_rates(from: "USD", to: "CAD", start_date: 2.days.ago.to_date)
end
```
## Concrete provider implementations
Each 3rd party data provider should have a class under the `Provider::` namespace that inherits from `Provider` and returns `with_provider_response`, which will return a `Provider::ProviderResponse` object:
```rb
class ConcreteProvider < Provider
def fetch_some_data
with_provider_response do
ExampleData.new(
example: "data"
)
end
end
end
```
The `with_provider_response` automatically catches provider errors, so concrete provider classes should raise when valid data is not possible:
```rb
class ConcreteProvider < Provider
def fetch_some_data
with_provider_response do
data = nil
# Raise an error if data cannot be returned
raise ProviderError.new("Could not find the data you need") if data.nil?
data
end
end
end
```

View File

@@ -0,0 +1,22 @@
---
description: This file describes Maybe's design system and how views should be styled
globs: app/views/**,app/helpers/**,app/javascript/controllers/**
alwaysApply: true
---
Use the rules below when:
- You are writing HTML
- You are writing CSS
- You are writing styles in a JavaScript Stimulus controller
## Rules for AI (mandatory)
The codebase uses TailwindCSS v4.x (the newest version) with a custom design system defined in [maybe-design-system.css](mdc:app/assets/tailwind/maybe-design-system.css)
- Always start by referencing [maybe-design-system.css](mdc:app/assets/tailwind/maybe-design-system.css) to see the base primitives, functional tokens, and component tokens we use in the codebase
- Always prefer using the functional "tokens" defined in @maybe-design-system.css when possible.
- Example 1: use `text-primary` rather than `text-primary`
- Example 2: use `bg-container` rather than `bg-white`
- Example 3: use `border border-primary` rather than `border border-gray-200`
- Never create new styles in [maybe-design-system.css](mdc:app/assets/tailwind/maybe-design-system.css) or [application.css](mdc:app/assets/tailwind/application.css) without explicitly receiving permission to do so
- Always generate semantic HTML

View File

@@ -1,4 +1,4 @@
ARG RUBY_VERSION=3.3.5
ARG RUBY_VERSION=3.4.1
FROM ruby:${RUBY_VERSION}-slim-bullseye
RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \

View File

@@ -1,4 +1,15 @@
version: "3"
x-db-env: &db_env
POSTGRES_USER: postgres
POSTGRES_DB: postgres
POSTGRES_PASSWORD: postgres
x-rails-env: &rails_env
DB_HOST: db
HOST: "0.0.0.0"
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
BUNDLE_PATH: /bundle
REDIS_URL: redis://redis:6379/1
services:
app:
@@ -16,32 +27,41 @@ services:
command: sleep infinity
environment:
DB_HOST: db
HOST: "0.0.0.0"
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
BUNDLE_PATH: /bundle
<<: *rails_env
depends_on:
- db
- redis
worker:
build:
context: ..
dockerfile: .devcontainer/Dockerfile
command: bundle exec sidekiq
restart: unless-stopped
environment:
<<: *rails_env
depends_on:
- redis
redis:
image: redis:latest
ports:
- "6379:6379"
restart: unless-stopped
volumes:
- redis-data:/data
db:
image: postgres:latest
restart: unless-stopped
volumes:
- postgres-data:/var/lib/postgresql/data
environment:
POSTGRES_USER: postgres
POSTGRES_DB: postgres
POSTGRES_PASSWORD: postgres
<<: *db_env
ports:
- "5432:5432"
volumes:
postgres-data:
redis-data:
bundle_cache:

View File

@@ -1,20 +1,31 @@
# ================================ PLEASE READ ==========================================
# This file outlines all the possible environment variables supported by the Maybe app.
#
# This includes several features that are for our "hosted" version of Maybe, which most
# open-source contributors won't need.
# ================================ PLEASE READ ===========================================================
# This file outlines all the possible environment variables supported by the Maybe app for self hosting.
#
# If you are developing locally, you should be referencing `.env.local.example` instead.
# =======================================================================================
# If you're a developer setting up your local environment, please use `.env.local.example` instead.
# ========================================================================================================
# Required self-hosting vars
# --------------------------------------------------------------------------------------------------------
# Enables self hosting features (should be set to true unless you know what you're doing)
SELF_HOSTED=true
# Secret key used to encrypt credentials (https://api.rubyonrails.org/v7.1.3.2/classes/Rails/Application.html#method-i-secret_key_base)
# Has to be a random string, generated eg. by running `openssl rand -hex 64`
SECRET_KEY_BASE=secret-value
# Optional self-hosting vars
# --------------------------------------------------------------------------------------------------------
# Optional: Synth API Key for exchange rates + stock prices
# (you can also set this in your self-hosted settings page)
# Get it here: https://synthfinance.com/
SYNTH_API_KEY=
# Custom port config
# For users who have other applications listening at 3000, this allows them to set a value puma will listen to.
PORT=3000
# Exchange Rate & Stock Pricing API
# This is used to convert between different currencies in the app. In addition, it fetches global stock prices. We use Synth, which is a Maybe product. You can sign up for a free account at synthfinance.com.
SYNTH_API_KEY=
# SMTP Configuration
# This is only needed if you intend on sending emails from your Maybe instance (such as for password resets or email financial reports).
# Resend.com is a good option that offers a free tier for sending emails.
@@ -37,60 +48,20 @@ POSTGRES_USER=postgres
# This is the domain that your Maybe instance will be hosted at. It is used to generate links in emails and other places.
APP_DOMAIN=
## Error and Performance Monitoring
# The app uses Sentry to monitor errors and performance. In reality, you likely don't need this unless you're deploying Maybe to many users.
SENTRY_DSN=
# If enabled, an invite code generated by `rake invites:create` is required to sign up as a new user.
# This is useful for controlling who can sign up for your Maybe instance.
REQUIRE_INVITE_CODE=false
# Enables self hosting features (should be set to true for most folks)
SELF_HOSTED=true
# The hosting platform used to deploy the app (e.g. "render")
# `localhost` (or unset) is used for local development and testing
HOSTING_PLATFORM=localhost
# Secret key used to encrypt credentials (https://api.rubyonrails.org/v7.1.3.2/classes/Rails/Application.html#method-i-secret_key_base)
# Has to be a random string, generated eg. by running `openssl rand -hex 64`
SECRET_KEY_BASE=secret-value
# Disable enforcing SSL connections
# DISABLE_SSL=true
# ======================================================================================================
# Upgrades Module - responsible for triggering upgrade alerts, prompts, and auto-upgrade functionality
# ======================================================================================================
#
# UPGRADES_ENABLED: Enables Upgrader class functionality.
# UPGRADES_MODE: Controls how the app will upgrade. `manual` means the user must manually upgrade the app. `auto` means the app will upgrade automatically (great for self-hosting)
# UPGRADES_TARGET: Controls what the app will upgrade to. `release` means the app will upgrade to the latest release. `commit` means the app will upgrade to the latest commit.
#
UPGRADES_ENABLED=false # unless editing the flow, you should keep this `false` locally in development
UPGRADES_MODE=manual # `manual` or `auto`
UPGRADES_TARGET=release # `release` or `commit`
# ======================================================================================================
# Git Repository Module - responsible for fetching latest commit data for upgrades
# ======================================================================================================
#
GITHUB_REPO_OWNER=maybe-finance
GITHUB_REPO_NAME=maybe
GITHUB_REPO_BRANCH=main
# ======================================================================================================
# Active Storage Configuration - responsible for storing file uploads
# ======================================================================================================
#
# * Defaults to disk storage but you can also use Amazon S3, Google Cloud Storage, or Microsoft Azure Storage.
# * Defaults to disk storage but you can also use Amazon S3 or Cloudflare R2
# * Set the appropriate environment variables to use these services.
# * Ensure libvips is installed on your system for image processing - https://github.com/libvips/libvips
#
# Amazon S3
# ==========
# ACTIVE_STORAGE_SERVICE=amazon
# ACTIVE_STORAGE_SERVICE=amazon <- Enables Amazon S3 storage
# S3_ACCESS_KEY_ID=
# S3_SECRET_ACCESS_KEY=
# S3_REGION= # defaults to `us-east-1` if not set
@@ -98,16 +69,9 @@ GITHUB_REPO_BRANCH=main
#
# Cloudflare R2
# =============
# ACTIVE_STORAGE_SERVICE=cloudflare
# ACTIVE_STORAGE_SERVICE=cloudflare <- Enables Cloudflare R2 storage
# CLOUDFLARE_ACCOUNT_ID=
# CLOUDFLARE_ACCESS_KEY_ID=
# CLOUDFLARE_SECRET_ACCESS_KEY=
# CLOUDFLARE_BUCKET=
# ======================================================================================================
# Billing Module - responsible for handling billing
# ======================================================================================================
#
STRIPE_PUBLISHABLE_KEY=
STRIPE_SECRET_KEY=
STRIPE_WEBHOOK_SECRET=

View File

@@ -1,8 +0,0 @@
SELF_HOSTED=false
SYNTH_API_KEY=fookey
# Set to true if you want SimpleCov reports generated
COVERAGE=false
# Set to true to run test suite serially
DISABLE_PARALLELIZATION=false

View File

@@ -1,3 +1,5 @@
SELF_HOSTED=false
# ================
# Data Providers
# ---------------------------------------------------------------------------------

View File

@@ -1,33 +1,61 @@
---
name: Bug report
about: Create a report to help us improve
title: 'Bug: '
labels: ":bug: Bug"
about: Open a bug report when you experience broken functionality within the latest
version of the Maybe app
title: 'Bug: [Add descriptive title here]'
labels: ''
assignees: ''
---
**Describe the bug**
## Before you start (required)
### General checklist
- [ ] I have removed personal / sensitive data from screenshots and logs
- [ ] I have searched [existing issues](https://github.com/maybe-finance/maybe/issues?q=is:issue) and [discussions](https://github.com/maybe-finance/maybe/discussions) to ensure this is not a duplicate issue
### How are you using Maybe?
- [ ] I am a paying Maybe customer (hosted version)
- Paying Maybe users can also open requests in Intercom (if there is sensitive info involved)
- [ ] I am a self-hosted user
### Self hoster checklist
_Paying, hosted users should delete this entire section._
If you are a self-hosted user, please complete all of the information below. Issues with incomplete information will be marked as `Needs Info` to help our small team prioritize bug fixes.
- Self hosted app commit SHA (find in user menu): [enter commit sha here]
- [ ] I have confirmed that my app's commit is the latest version of Maybe
- Where are you hosting?
- [ ] Render
- [ ] Docker Compose
- [ ] Umbrel
- [ ] Other (please specify)
---
## Bug description
A clear and concise description of what the bug is.
**To Reproduce**
### To Reproduce
Be as specific as possible so Maybe maintainers can quickly reproduce the bug you're experiencing.
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
### Expected behavior
**What version of Maybe are you using?**
This could be "Hosted" (i.e. app.maybe.co) or "Self-hosted". If "Self-hosted", please include the version you're currently on.
What is the intended behavior that you would expect?
**What operating system and browser are you using?**
The more info the better.
### Screenshots and/or recordings
**Screenshots / Recordings**
If applicable, add screenshots or short video recordings to help show the bug in more detail.
**Additional context**
Add any other context about the problem here.
We highly recommend providing additional context with screenshots and/or screen recordings. This will _significantly_ improve the chances of the bug being addressed and fixed quickly.

View File

@@ -7,15 +7,33 @@ assignees: ''
---
**PLEASE READ before opening an issue:**
## Before you start (required)
- Is this a feature request? Please [open a feature request discussion](https://github.com/maybe-finance/maybe/discussions/new?category=feature-requests).
- Do you need help or have a question? Please [open a discussion](https://github.com/maybe-finance/maybe/discussions/new/choose) or [join our Discord](https://link.maybe.co/discord) and post to the "help" channel.
### Is this a bug?
----------------------
A bug is _broken functionality_ of the app (i.e. it prevents you from using the app). For bugs, please use the ["Bug Report" template](https://github.com/maybe-finance/maybe/issues) instead.
**Is this issue related to a problem? Please describe.**
### Is this a bug with _sensitive info_?
**Describe the work that needs to be done to address this issue**
If you are a _paying_ Maybe user, you can open a support request in Intercom.
**Additional context**
### Is this a feature request?
A feature request is functionality that you would like that is not already on our [Roadmap](https://github.com/maybe-finance/maybe/wiki/Roadmap).
All feature requests should be opened in a [Feature request Discussion](https://github.com/maybe-finance/maybe/discussions/categories/feature-requests).
Be sure to search existing discussions prior to opening a new feature request.
### Is this related to Docker and/or hosting for self hosting?
If you are having a Docker configuration issue, please do not open a Github issue unless you've identified a bug in our Dockerfile. To get help with self hosting, there are several options:
- **First**: Read our [Docker hosting guide](https://github.com/maybe-finance/maybe/tree/main/docs/hosting/docker.md) and follow it step-by-step
- Open a [Docker Discussion](https://github.com/maybe-finance/maybe/discussions/categories/docker-compose-hosting)
---
## Issue description
If your issue does not fall into the categories above, please provide a **descriptive and complete** overview of your issue.

View File

@@ -1,6 +1,13 @@
name: Publish Docker image
on:
workflow_dispatch:
inputs:
ref:
description: 'Git ref (tag or commit SHA) to build'
required: true
type: string
default: 'main'
push:
tags:
- 'v*'
@@ -22,6 +29,8 @@ jobs:
name: Build docker image
needs: [ ci ]
timeout-minutes: 60
runs-on: ubuntu-latest
permissions:
@@ -31,6 +40,8 @@ jobs:
steps:
- name: Check out the repo
uses: actions/checkout@v4
with:
ref: ${{ github.event.inputs.ref || github.ref }}
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
@@ -65,9 +76,10 @@ jobs:
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
platforms: linux/amd64,linux/arm64,linux/arm/v7
platforms: 'linux/amd64,linux/arm64'
cache-from: type=gha
cache-to: type=gha,mode=max
provenance: false
# https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-container-registry#adding-a-description-to-multi-arch-images
outputs: type=image,name=target,annotation-index.org.opencontainers.image.description=A multi-arch Docker image for the Maybe Rails app
build-args: BUILD_COMMIT_SHA=${{ github.sha }}

8
.gitignore vendored
View File

@@ -6,11 +6,11 @@
# Ignore bundler config.
/.bundle
/vendor/bundle
# Ignore all environment files (except templates).
/.env*
!/.env*.erb
!.env.test
!.env*.example
# Ignore all logfiles and tempfiles.
@@ -62,6 +62,10 @@ gcp-storage-keyfile.json
coverage
.cursorrules
.cursor/rules/structure.mdc
.cursor/rules/agent.mdc
# Ignore node related files
node_modules
node_modules
compose.yml

View File

@@ -1 +1 @@
3.3.5
3.4.1

View File

@@ -4,6 +4,8 @@ It means so much that you're interested in contributing to Maybe! Seriously. Tha
## House Rules
- Before contributing, familiarize yourself with our project conventions. You should read through our [Project Conventions Rule](https://github.com/maybe-finance/maybe/.cursor/rules/project-conventions.mdc), which is intended for LLMs, but is also an excellent primer on how we write code for Maybe.
- While totally optional, consider using Cursor + VSCode as it will automatically apply our project conventions to your code via the `.cursor/rules` directory.
- Before contributing, please check if it already exists in [issues](https://github.com/maybe-finance/maybe/issues) or [PRs](https://github.com/maybe-finance/maybe/pulls)
- Given the speed at which we're moving on the codebase, we don't assign issues or "give" issues to anyone.
- When multiple PRs are submitted for the same issue, we take the one that most succinctly & efficiently solves a given problem and stays within the scope of work.

View File

@@ -1,8 +1,8 @@
# syntax = docker/dockerfile:1
# Make sure RUBY_VERSION matches the Ruby version in .ruby-version and Gemfile
ARG RUBY_VERSION=3.3.5
FROM registry.docker.com/library/ruby:$RUBY_VERSION-slim as base
ARG RUBY_VERSION=3.4.1
FROM registry.docker.com/library/ruby:$RUBY_VERSION-slim AS base
# Rails app lives here
WORKDIR /rails
@@ -12,34 +12,36 @@ RUN apt-get update -qq && \
apt-get install --no-install-recommends -y curl libvips postgresql-client
# Set production environment
ARG BUILD_COMMIT_SHA
ENV RAILS_ENV="production" \
BUNDLE_DEPLOYMENT="1" \
BUNDLE_PATH="/usr/local/bundle" \
BUNDLE_WITHOUT="development"
BUNDLE_WITHOUT="development" \
BUILD_COMMIT_SHA=${BUILD_COMMIT_SHA}
# Throw-away build stage to reduce size of final image
FROM base as build
FROM base AS build
# Install packages needed to build gems
RUN apt-get install --no-install-recommends -y build-essential git libpq-dev pkg-config
RUN apt-get install --no-install-recommends -y build-essential libpq-dev git pkg-config
# Install application gems
COPY .ruby-version Gemfile Gemfile.lock ./
RUN bundle install && \
rm -rf ~/.bundle/ "${BUNDLE_PATH}"/ruby/*/cache "${BUNDLE_PATH}"/ruby/*/bundler/gems/*/.git && \
bundle exec bootsnap precompile --gemfile
RUN bundle install
RUN rm -rf ~/.bundle/ "${BUNDLE_PATH}"/ruby/*/cache "${BUNDLE_PATH}"/ruby/*/bundler/gems/*/.git
RUN bundle exec bootsnap precompile --gemfile -j 0
# Copy application code
COPY . .
# Precompile bootsnap code for faster boot times
RUN bundle exec bootsnap precompile app/ lib/
RUN bundle exec bootsnap precompile -j 0 app/ lib/
# Precompiling assets for production without requiring secret RAILS_MASTER_KEY
RUN SECRET_KEY_BASE_DUMMY=1 ./bin/rails assets:precompile
# Final stage for app image
FROM base

21
Gemfile
View File

@@ -7,6 +7,7 @@ gem "rails", "~> 7.2.2"
# Drivers
gem "pg", "~> 1.5"
gem "redis", "~> 5.4"
# Deployment
gem "puma", ">= 5.0"
@@ -21,22 +22,27 @@ gem "lucide-rails", github: "maybe-finance/lucide-rails"
# Hotwire
gem "stimulus-rails"
gem "turbo-rails"
gem "hotwire_combobox"
# Background Jobs
gem "good_job"
gem "sidekiq"
# Error logging
gem "stackprof"
gem "vernier"
gem "rack-mini-profiler"
gem "sentry-ruby"
gem "sentry-rails"
gem "sentry-sidekiq"
gem "logtail-rails"
# Active Storage
gem "aws-sdk-s3", require: false
gem "aws-sdk-s3", "~> 1.177.0", require: false
gem "image_processing", ">= 1.2"
# Other
gem "bcrypt", "~> 3.1"
gem "jwt"
gem "faraday"
gem "faraday-retry"
gem "faraday-multipart"
@@ -49,7 +55,13 @@ gem "csv"
gem "redcarpet"
gem "stripe"
gem "intercom-rails"
gem "holidays"
gem "plaid"
gem "rotp", "~> 6.3"
gem "rqrcode", "~> 2.2"
gem "activerecord-import"
# AI
gem "ruby-openai"
group :development, :test do
gem "debug", platforms: %i[mri windows]
@@ -66,6 +78,7 @@ group :development do
gem "ruby-lsp-rails"
gem "web-console"
gem "faker"
gem "benchmark-ips"
end
group :test do

View File

@@ -8,29 +8,29 @@ GIT
GEM
remote: https://rubygems.org/
specs:
actioncable (7.2.2)
actionpack (= 7.2.2)
activesupport (= 7.2.2)
actioncable (7.2.2.1)
actionpack (= 7.2.2.1)
activesupport (= 7.2.2.1)
nio4r (~> 2.0)
websocket-driver (>= 0.6.1)
zeitwerk (~> 2.6)
actionmailbox (7.2.2)
actionpack (= 7.2.2)
activejob (= 7.2.2)
activerecord (= 7.2.2)
activestorage (= 7.2.2)
activesupport (= 7.2.2)
actionmailbox (7.2.2.1)
actionpack (= 7.2.2.1)
activejob (= 7.2.2.1)
activerecord (= 7.2.2.1)
activestorage (= 7.2.2.1)
activesupport (= 7.2.2.1)
mail (>= 2.8.0)
actionmailer (7.2.2)
actionpack (= 7.2.2)
actionview (= 7.2.2)
activejob (= 7.2.2)
activesupport (= 7.2.2)
actionmailer (7.2.2.1)
actionpack (= 7.2.2.1)
actionview (= 7.2.2.1)
activejob (= 7.2.2.1)
activesupport (= 7.2.2.1)
mail (>= 2.8.0)
rails-dom-testing (~> 2.2)
actionpack (7.2.2)
actionview (= 7.2.2)
activesupport (= 7.2.2)
actionpack (7.2.2.1)
actionview (= 7.2.2.1)
activesupport (= 7.2.2.1)
nokogiri (>= 1.8.5)
racc
rack (>= 2.2.4, < 3.2)
@@ -39,35 +39,37 @@ GEM
rails-dom-testing (~> 2.2)
rails-html-sanitizer (~> 1.6)
useragent (~> 0.16)
actiontext (7.2.2)
actionpack (= 7.2.2)
activerecord (= 7.2.2)
activestorage (= 7.2.2)
activesupport (= 7.2.2)
actiontext (7.2.2.1)
actionpack (= 7.2.2.1)
activerecord (= 7.2.2.1)
activestorage (= 7.2.2.1)
activesupport (= 7.2.2.1)
globalid (>= 0.6.0)
nokogiri (>= 1.8.5)
actionview (7.2.2)
activesupport (= 7.2.2)
actionview (7.2.2.1)
activesupport (= 7.2.2.1)
builder (~> 3.1)
erubi (~> 1.11)
rails-dom-testing (~> 2.2)
rails-html-sanitizer (~> 1.6)
activejob (7.2.2)
activesupport (= 7.2.2)
activejob (7.2.2.1)
activesupport (= 7.2.2.1)
globalid (>= 0.3.6)
activemodel (7.2.2)
activesupport (= 7.2.2)
activerecord (7.2.2)
activemodel (= 7.2.2)
activesupport (= 7.2.2)
activemodel (7.2.2.1)
activesupport (= 7.2.2.1)
activerecord (7.2.2.1)
activemodel (= 7.2.2.1)
activesupport (= 7.2.2.1)
timeout (>= 0.4.0)
activestorage (7.2.2)
actionpack (= 7.2.2)
activejob (= 7.2.2)
activerecord (= 7.2.2)
activesupport (= 7.2.2)
activerecord-import (2.1.0)
activerecord (>= 4.2)
activestorage (7.2.2.1)
actionpack (= 7.2.2.1)
activejob (= 7.2.2.1)
activerecord (= 7.2.2.1)
activesupport (= 7.2.2.1)
marcel (~> 1.0)
activesupport (7.2.2)
activesupport (7.2.2.1)
base64
benchmark (>= 0.3)
bigdecimal
@@ -81,26 +83,29 @@ GEM
tzinfo (~> 2.0, >= 2.0.5)
addressable (2.8.7)
public_suffix (>= 2.0.2, < 7.0)
ast (2.4.2)
aws-eventstream (1.3.0)
aws-partitions (1.992.0)
aws-sdk-core (3.210.0)
ast (2.4.3)
aws-eventstream (1.3.2)
aws-partitions (1.1073.0)
aws-sdk-core (3.221.0)
aws-eventstream (~> 1, >= 1.3.0)
aws-partitions (~> 1, >= 1.992.0)
aws-sigv4 (~> 1.9)
base64
jmespath (~> 1, >= 1.6.1)
aws-sdk-kms (1.95.0)
aws-sdk-core (~> 3, >= 3.210.0)
logger
aws-sdk-kms (1.99.0)
aws-sdk-core (~> 3, >= 3.216.0)
aws-sigv4 (~> 1.5)
aws-sdk-s3 (1.169.0)
aws-sdk-s3 (1.177.0)
aws-sdk-core (~> 3, >= 3.210.0)
aws-sdk-kms (~> 1)
aws-sigv4 (~> 1.5)
aws-sigv4 (1.10.0)
aws-sigv4 (1.11.0)
aws-eventstream (~> 1, >= 1.0.2)
base64 (0.2.0)
bcrypt (3.1.20)
benchmark (0.3.0)
benchmark (0.4.0)
benchmark-ips (2.14.0)
better_html (2.1.1)
actionview (>= 6.0)
activesupport (>= 6.0)
@@ -108,11 +113,11 @@ GEM
erubi (~> 1.4)
parser (>= 2.4)
smart_properties
bigdecimal (3.1.8)
bigdecimal (3.1.9)
bindex (0.8.1)
bootsnap (1.18.4)
msgpack (~> 1.2)
brakeman (6.2.2)
brakeman (7.0.2)
racc
builder (3.3.0)
capybara (3.40.0)
@@ -124,79 +129,73 @@ GEM
rack-test (>= 0.6.3)
regexp_parser (>= 1.5, < 3.0)
xpath (~> 3.2)
childprocess (5.0.0)
childprocess (5.1.0)
logger (~> 1.5)
chunky_png (1.4.0)
climate_control (1.2.0)
concurrent-ruby (1.3.4)
connection_pool (2.4.1)
concurrent-ruby (1.3.5)
connection_pool (2.5.0)
crack (1.0.0)
bigdecimal
rexml
crass (1.0.6)
csv (3.3.0)
date (3.4.0)
debug (1.9.2)
csv (3.3.3)
date (3.4.1)
debug (1.10.0)
irb (~> 1.10)
reline (>= 0.3.8)
docile (1.4.0)
dotenv (3.1.4)
dotenv-rails (3.1.4)
dotenv (= 3.1.4)
docile (1.4.1)
dotenv (3.1.7)
dotenv-rails (3.1.7)
dotenv (= 3.1.7)
railties (>= 6.1)
drb (2.2.1)
erb_lint (0.7.0)
erb_lint (0.9.0)
activesupport
better_html (>= 2.0.1)
parser (>= 2.7.1.4)
rainbow
rubocop (>= 1)
smart_properties
erubi (1.13.0)
et-orbi (1.2.11)
tzinfo
erubi (1.13.1)
event_stream_parser (1.0.0)
faker (3.5.1)
i18n (>= 1.8.11, < 2)
faraday (2.12.0)
faraday-net_http (>= 2.0, < 3.4)
faraday (2.12.2)
faraday-net_http (>= 2.0, < 3.5)
json
logger
faraday-multipart (1.0.4)
multipart-post (~> 2)
faraday-net_http (3.3.0)
net-http
faraday-retry (2.2.1)
faraday-multipart (1.1.0)
multipart-post (~> 2.0)
faraday-net_http (3.4.0)
net-http (>= 0.5.0)
faraday-retry (2.3.1)
faraday (~> 2.0)
ffi (1.17.0-aarch64-linux-gnu)
ffi (1.17.0-arm-linux-gnu)
ffi (1.17.0-arm64-darwin)
ffi (1.17.0-x86-linux-gnu)
ffi (1.17.0-x86_64-darwin)
ffi (1.17.0-x86_64-linux-gnu)
fugit (1.11.1)
et-orbi (~> 1, >= 1.2.11)
raabro (~> 1.4)
ffi (1.17.1-aarch64-linux-gnu)
ffi (1.17.1-aarch64-linux-musl)
ffi (1.17.1-arm-linux-gnu)
ffi (1.17.1-arm-linux-musl)
ffi (1.17.1-arm64-darwin)
ffi (1.17.1-x86_64-darwin)
ffi (1.17.1-x86_64-linux-gnu)
ffi (1.17.1-x86_64-linux-musl)
globalid (1.2.1)
activesupport (>= 6.1)
good_job (4.4.2)
activejob (>= 6.1.0)
activerecord (>= 6.1.0)
concurrent-ruby (>= 1.3.1)
fugit (>= 1.11.0)
railties (>= 6.1.0)
thor (>= 1.0.0)
hashdiff (1.1.1)
highline (3.0.1)
holidays (8.8.0)
hotwire-livereload (1.4.1)
actioncable (>= 6.0.0)
hashdiff (1.1.2)
highline (3.1.2)
reline
hotwire-livereload (2.0.0)
actioncable (>= 7.0.0)
listen (>= 3.0.0)
railties (>= 6.0.0)
hotwire_combobox (0.3.2)
railties (>= 7.0.0)
hotwire_combobox (0.4.0)
platform_agent (>= 1.0.1)
rails (>= 7.0.7.2)
stimulus-rails (>= 1.2)
turbo-rails (>= 1.2)
i18n (1.14.6)
i18n (1.14.7)
concurrent-ruby (~> 1.0)
i18n-tasks (1.0.14)
i18n-tasks (1.0.15)
activesupport (>= 4.0.2)
ast (>= 2.1.0)
erubi
@@ -205,36 +204,54 @@ GEM
parser (>= 3.2.2.1)
rails-i18n
rainbow (>= 2.2.2, < 4.0)
ruby-progressbar (~> 1.8, >= 1.8.1)
terminal-table (>= 1.5.1)
image_processing (1.13.0)
mini_magick (>= 4.9.5, < 5)
image_processing (1.14.0)
mini_magick (>= 4.9.5, < 6)
ruby-vips (>= 2.0.17, < 3)
importmap-rails (2.0.3)
importmap-rails (2.1.0)
actionpack (>= 6.0.0)
activesupport (>= 6.0.0)
railties (>= 6.0.0)
inline_svg (1.10.0)
activesupport (>= 3.0)
nokogiri (>= 1.6)
intercom-rails (1.0.1)
intercom-rails (1.0.6)
activesupport (> 4.0)
io-console (0.7.2)
irb (1.14.1)
jwt (~> 2.0)
io-console (0.8.0)
irb (1.15.1)
pp (>= 0.6.0)
rdoc (>= 4.0.0)
reline (>= 0.4.2)
jmespath (1.6.2)
json (2.7.2)
language_server-protocol (3.17.0.3)
launchy (3.0.1)
json (2.10.2)
jwt (2.10.1)
base64
language_server-protocol (3.17.0.4)
launchy (3.1.1)
addressable (~> 2.8)
childprocess (~> 5.0)
logger (~> 1.6)
letter_opener (1.10.0)
launchy (>= 2.2, < 4)
lint_roller (1.1.0)
listen (3.9.0)
rb-fsevent (~> 0.10, >= 0.10.3)
rb-inotify (~> 0.9, >= 0.9.10)
logger (1.6.1)
loofah (2.23.1)
logger (1.7.0)
logtail (0.1.17)
msgpack (~> 1.0)
logtail-rack (0.2.6)
logtail (~> 0.1)
rack (>= 1.2, < 4.0)
logtail-rails (0.2.10)
actionpack (>= 5.0.0)
activerecord (>= 5.0.0)
logtail (~> 0.1, >= 0.1.14)
logtail-rack (~> 0.1)
railties (>= 5.0.0)
loofah (2.24.0)
crass (~> 1.0.2)
nokogiri (>= 1.12.0)
mail (2.8.1)
@@ -244,96 +261,114 @@ GEM
net-smtp
marcel (1.0.4)
matrix (0.4.2)
mini_magick (4.13.2)
mini_magick (5.2.0)
benchmark
logger
mini_mime (1.1.5)
minitest (5.25.1)
mocha (2.5.0)
minitest (5.25.5)
mocha (2.7.1)
ruby2_keywords (>= 0.0.5)
msgpack (1.7.2)
msgpack (1.8.0)
multipart-post (2.4.1)
net-http (0.4.1)
net-http (0.6.0)
uri
net-imap (0.5.0)
net-imap (0.5.6)
date
net-protocol
net-pop (0.1.2)
net-protocol
net-protocol (0.2.2)
timeout
net-smtp (0.5.0)
net-smtp (0.5.1)
net-protocol
nio4r (2.7.4)
nokogiri (1.16.7-aarch64-linux)
nokogiri (1.18.6-aarch64-linux-gnu)
racc (~> 1.4)
nokogiri (1.16.7-arm-linux)
nokogiri (1.18.6-aarch64-linux-musl)
racc (~> 1.4)
nokogiri (1.16.7-arm64-darwin)
nokogiri (1.18.6-arm-linux-gnu)
racc (~> 1.4)
nokogiri (1.16.7-x86-linux)
nokogiri (1.18.6-arm-linux-musl)
racc (~> 1.4)
nokogiri (1.16.7-x86_64-darwin)
nokogiri (1.18.6-arm64-darwin)
racc (~> 1.4)
nokogiri (1.16.7-x86_64-linux)
nokogiri (1.18.6-x86_64-darwin)
racc (~> 1.4)
nokogiri (1.18.6-x86_64-linux-gnu)
racc (~> 1.4)
nokogiri (1.18.6-x86_64-linux-musl)
racc (~> 1.4)
octokit (9.2.0)
faraday (>= 1, < 3)
sawyer (~> 0.9)
pagy (9.1.1)
pagy (9.3.4)
parallel (1.26.3)
parser (3.3.5.0)
parser (3.3.7.2)
ast (~> 2.4.1)
racc
pg (1.5.9)
prism (1.2.0)
plaid (36.1.0)
faraday (>= 1.0.1, < 3.0)
faraday-multipart (>= 1.0.1, < 2.0)
platform_agent (1.0.1)
activesupport (>= 5.2.0)
useragent (~> 0.16.3)
pp (0.6.2)
prettyprint
prettyprint (0.2.0)
prism (1.4.0)
propshaft (1.1.0)
actionpack (>= 7.0.0)
activesupport (>= 7.0.0)
rack
railties (>= 7.0.0)
psych (5.1.2)
psych (5.2.3)
date
stringio
public_suffix (6.0.1)
puma (6.4.3)
puma (6.6.0)
nio4r (~> 2.0)
raabro (1.4.0)
racc (1.8.1)
rack (3.1.8)
rack-session (2.0.0)
rack (3.1.12)
rack-mini-profiler (3.3.1)
rack (>= 1.2.0)
rack-session (2.1.0)
base64 (>= 0.1.0)
rack (>= 3.0.0)
rack-test (2.1.0)
rack-test (2.2.0)
rack (>= 1.3)
rackup (2.2.0)
rackup (2.2.1)
rack (>= 3)
rails (7.2.2)
actioncable (= 7.2.2)
actionmailbox (= 7.2.2)
actionmailer (= 7.2.2)
actionpack (= 7.2.2)
actiontext (= 7.2.2)
actionview (= 7.2.2)
activejob (= 7.2.2)
activemodel (= 7.2.2)
activerecord (= 7.2.2)
activestorage (= 7.2.2)
activesupport (= 7.2.2)
rails (7.2.2.1)
actioncable (= 7.2.2.1)
actionmailbox (= 7.2.2.1)
actionmailer (= 7.2.2.1)
actionpack (= 7.2.2.1)
actiontext (= 7.2.2.1)
actionview (= 7.2.2.1)
activejob (= 7.2.2.1)
activemodel (= 7.2.2.1)
activerecord (= 7.2.2.1)
activestorage (= 7.2.2.1)
activesupport (= 7.2.2.1)
bundler (>= 1.15.0)
railties (= 7.2.2)
railties (= 7.2.2.1)
rails-dom-testing (2.2.0)
activesupport (>= 5.0.0)
minitest
nokogiri (>= 1.6)
rails-html-sanitizer (1.6.0)
rails-html-sanitizer (1.6.2)
loofah (~> 2.21)
nokogiri (~> 1.14)
rails-i18n (7.0.9)
nokogiri (>= 1.15.7, != 1.16.7, != 1.16.6, != 1.16.5, != 1.16.4, != 1.16.3, != 1.16.2, != 1.16.1, != 1.16.0.rc1, != 1.16.0)
rails-i18n (7.0.10)
i18n (>= 0.7, < 2)
railties (>= 6.0.0, < 8)
rails-settings-cached (2.9.5)
rails-settings-cached (2.9.6)
activerecord (>= 5.0.0)
railties (>= 5.0.0)
railties (7.2.2)
actionpack (= 7.2.2)
activesupport (= 7.2.2)
railties (7.2.2.1)
actionpack (= 7.2.2.1)
activesupport (= 7.2.2.1)
irb (~> 1.13)
rackup (>= 1.0.0)
rake (>= 12.2)
@@ -344,136 +379,165 @@ GEM
rb-fsevent (0.11.2)
rb-inotify (0.11.1)
ffi (~> 1.0)
rbs (3.6.1)
rbs (3.9.1)
logger
rdoc (6.7.0)
rdoc (6.13.0)
psych (>= 4.0.0)
redcarpet (3.6.0)
regexp_parser (2.9.2)
reline (0.5.10)
redcarpet (3.6.1)
redis (5.4.0)
redis-client (>= 0.22.0)
redis-client (0.24.0)
connection_pool
regexp_parser (2.10.0)
reline (0.6.0)
io-console (~> 0.5)
rexml (3.3.9)
rubocop (1.67.0)
rexml (3.4.1)
rotp (6.3.0)
rqrcode (2.2.0)
chunky_png (~> 1.0)
rqrcode_core (~> 1.0)
rqrcode_core (1.2.0)
rubocop (1.74.0)
json (~> 2.3)
language_server-protocol (>= 3.17.0)
language_server-protocol (~> 3.17.0.2)
lint_roller (~> 1.1.0)
parallel (~> 1.10)
parser (>= 3.3.0.2)
rainbow (>= 2.2.2, < 4.0)
regexp_parser (>= 2.4, < 3.0)
rubocop-ast (>= 1.32.2, < 2.0)
regexp_parser (>= 2.9.3, < 3.0)
rubocop-ast (>= 1.38.0, < 2.0)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 2.4.0, < 3.0)
rubocop-ast (1.32.3)
parser (>= 3.3.1.0)
rubocop-minitest (0.35.0)
rubocop (>= 1.61, < 2.0)
rubocop-ast (>= 1.31.1, < 2.0)
rubocop-performance (1.21.0)
rubocop (>= 1.48.1, < 2.0)
rubocop-ast (>= 1.31.1, < 2.0)
rubocop-rails (2.25.0)
unicode-display_width (>= 2.4.0, < 4.0)
rubocop-ast (1.41.0)
parser (>= 3.3.7.2)
rubocop-performance (1.24.0)
lint_roller (~> 1.1)
rubocop (>= 1.72.1, < 2.0)
rubocop-ast (>= 1.38.0, < 2.0)
rubocop-rails (2.30.3)
activesupport (>= 4.2.0)
lint_roller (~> 1.1)
rack (>= 1.1)
rubocop (>= 1.33.0, < 2.0)
rubocop-ast (>= 1.31.1, < 2.0)
rubocop-rails-omakase (1.0.0)
rubocop
rubocop-minitest
rubocop-performance
rubocop-rails
ruby-lsp (0.20.1)
rubocop (>= 1.72.1, < 2.0)
rubocop-ast (>= 1.38.0, < 2.0)
rubocop-rails-omakase (1.1.0)
rubocop (>= 1.72)
rubocop-performance (>= 1.24)
rubocop-rails (>= 2.30)
ruby-lsp (0.23.12)
language_server-protocol (~> 3.17.0)
prism (>= 1.2, < 2.0)
rbs (>= 3, < 4)
sorbet-runtime (>= 0.5.10782)
ruby-lsp-rails (0.3.21)
ruby-lsp (>= 0.20.0, < 0.21.0)
ruby-lsp-rails (0.4.0)
ruby-lsp (>= 0.23.0, < 0.24.0)
ruby-openai (8.1.0)
event_stream_parser (>= 0.3.0, < 2.0.0)
faraday (>= 1)
faraday-multipart (>= 1)
ruby-progressbar (1.13.0)
ruby-vips (2.2.2)
ruby-vips (2.2.3)
ffi (~> 1.12)
logger
ruby2_keywords (0.0.5)
rubyzip (2.3.2)
rubyzip (2.4.1)
sawyer (0.9.2)
addressable (>= 2.3.5)
faraday (>= 0.17.3, < 3)
securerandom (0.3.1)
selenium-webdriver (4.26.0)
securerandom (0.4.1)
selenium-webdriver (4.31.0)
base64 (~> 0.2)
logger (~> 1.4)
rexml (~> 3.2, >= 3.2.5)
rubyzip (>= 1.2.2, < 3.0)
websocket (~> 1.0)
sentry-rails (5.21.0)
sentry-rails (5.23.0)
railties (>= 5.0)
sentry-ruby (~> 5.21.0)
sentry-ruby (5.21.0)
sentry-ruby (~> 5.23.0)
sentry-ruby (5.23.0)
bigdecimal
concurrent-ruby (~> 1.0, >= 1.0.2)
sentry-sidekiq (5.23.0)
sentry-ruby (~> 5.23.0)
sidekiq (>= 3.0)
sidekiq (8.0.2)
connection_pool (>= 2.5.0)
json (>= 2.9.0)
logger (>= 1.6.2)
rack (>= 3.1.0)
redis-client (>= 0.23.2)
simplecov (0.22.0)
docile (~> 1.1)
simplecov-html (~> 0.11)
simplecov_json_formatter (~> 0.1)
simplecov-html (0.12.3)
simplecov-html (0.13.1)
simplecov_json_formatter (0.1.4)
smart_properties (1.17.0)
sorbet-runtime (0.5.11618)
stackprof (0.2.26)
sorbet-runtime (0.5.11953)
stimulus-rails (1.3.4)
railties (>= 6.0.0)
stringio (3.1.1)
stripe (13.1.0)
tailwindcss-rails (3.0.0)
stringio (3.1.5)
stripe (14.0.0)
tailwindcss-rails (4.2.1)
railties (>= 7.0.0)
tailwindcss-ruby
tailwindcss-ruby (3.4.14)
tailwindcss-ruby (3.4.14-aarch64-linux)
tailwindcss-ruby (3.4.14-arm-linux)
tailwindcss-ruby (3.4.14-arm64-darwin)
tailwindcss-ruby (3.4.14-x86_64-darwin)
tailwindcss-ruby (3.4.14-x86_64-linux)
terminal-table (3.0.2)
unicode-display_width (>= 1.1.1, < 3)
tailwindcss-ruby (~> 4.0)
tailwindcss-ruby (4.0.15)
tailwindcss-ruby (4.0.15-aarch64-linux-gnu)
tailwindcss-ruby (4.0.15-aarch64-linux-musl)
tailwindcss-ruby (4.0.15-arm64-darwin)
tailwindcss-ruby (4.0.15-x86_64-darwin)
tailwindcss-ruby (4.0.15-x86_64-linux-gnu)
tailwindcss-ruby (4.0.15-x86_64-linux-musl)
terminal-table (4.0.0)
unicode-display_width (>= 1.1.1, < 4)
thor (1.3.2)
timeout (0.4.1)
turbo-rails (2.0.11)
actionpack (>= 6.0.0)
railties (>= 6.0.0)
timeout (0.4.3)
turbo-rails (2.0.13)
actionpack (>= 7.1.0)
railties (>= 7.1.0)
tzinfo (2.0.6)
concurrent-ruby (~> 1.0)
unicode-display_width (2.6.0)
uri (0.13.1)
useragent (0.16.10)
unicode-display_width (3.1.4)
unicode-emoji (~> 4.0, >= 4.0.4)
unicode-emoji (4.0.4)
uri (1.0.3)
useragent (0.16.11)
vcr (6.3.1)
base64
vernier (1.7.0)
web-console (4.2.1)
actionview (>= 6.0.0)
activemodel (>= 6.0.0)
bindex (>= 0.4.0)
railties (>= 6.0.0)
webmock (3.24.0)
webmock (3.25.1)
addressable (>= 2.8.0)
crack (>= 0.3.2)
hashdiff (>= 0.4.0, < 2.0.0)
websocket (1.2.11)
websocket-driver (0.7.6)
websocket-driver (0.7.7)
base64
websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.5)
xpath (3.2.0)
nokogiri (~> 1.8)
zeitwerk (2.7.1)
zeitwerk (2.7.2)
PLATFORMS
aarch64-linux
arm-linux
aarch64-linux-gnu
aarch64-linux-musl
arm-linux-gnu
arm-linux-musl
arm64-darwin
x86-linux
x86_64-darwin
x86_64-linux
x86_64-linux-gnu
x86_64-linux-musl
DEPENDENCIES
aws-sdk-s3
activerecord-import
aws-sdk-s3 (~> 1.177.0)
bcrypt (~> 3.1)
benchmark-ips
bootsnap
brakeman
capybara
@@ -486,8 +550,6 @@ DEPENDENCIES
faraday
faraday-multipart
faraday-retry
good_job
holidays
hotwire-livereload
hotwire_combobox
i18n-tasks
@@ -495,35 +557,45 @@ DEPENDENCIES
importmap-rails
inline_svg
intercom-rails
jwt
letter_opener
logtail-rails
lucide-rails!
mocha
octokit
pagy
pg (~> 1.5)
plaid
propshaft
puma (>= 5.0)
rack-mini-profiler
rails (~> 7.2.2)
rails-settings-cached
redcarpet
redis (~> 5.4)
rotp (~> 6.3)
rqrcode (~> 2.2)
rubocop-rails-omakase
ruby-lsp-rails
ruby-openai
selenium-webdriver
sentry-rails
sentry-ruby
sentry-sidekiq
sidekiq
simplecov
stackprof
stimulus-rails
stripe
tailwindcss-rails
turbo-rails
tzinfo-data
vcr
vernier
web-console
webmock
RUBY VERSION
ruby 3.3.5p100
ruby 3.4.1p0
BUNDLED WITH
2.5.22
2.6.3

View File

@@ -1,3 +1,3 @@
web: ${DEBUG:+rdbg -O -n -c --} bin/rails server -b 0.0.0.0
css: bin/rails tailwindcss:watch
worker: bundle exec good_job start
web: bundle exec ${DEBUG:+rdbg -O -n -c --} bin/rails server -b 0.0.0.0
css: bundle exec bin/rails tailwindcss:watch
worker: bundle exec sidekiq

View File

@@ -4,10 +4,7 @@
# Maybe: The OS for your personal finances
<b>Get
involved: [Discord](https://link.maybe.co/discord) • [Website](https://maybe.co) • [Issues](https://github.com/maybe-finance/maybe/issues)</b>
_If you're looking for the previous React codebase, you can find it
at [maybe-finance/maybe-archive](https://github.com/maybe-finance/maybe-archive)._
involved: [Discord](https://link.maybe.co/discord) • [Website](https://maybefinance.com) • [Issues](https://github.com/maybe-finance/maybe/issues)</b>
## Backstory
@@ -29,9 +26,17 @@ and eventually offer a hosted version of the app for a small monthly fee.
There are 3 primary ways to use the Maybe app:
1. Managed (easiest) - _coming soon..._
2. [One-click deploy](docs/hosting/one-click-deploy.md)
3. [Self-host with Docker](docs/hosting/docker.md)
1. Managed (easiest) - we're in alpha and release invites in our Discord
2. [Self-host with Docker](docs/hosting/docker.md)
## Contributing
Before contributing, you'll likely find it helpful
to [understand context and general vision/direction](https://github.com/maybe-finance/maybe/wiki).
Once you've done that, please visit
our [contributing guide](https://github.com/maybe-finance/maybe/blob/main/CONTRIBUTING.md)
to get started!
## Local Development Setup
@@ -75,46 +80,10 @@ If you'd like multi-currency support, there are a few extra steps to follow.
### Setup Guides
#### Dev Container (optional)
This is 100% optional and meant for devs who don't want to worry about
installing requirements manually for their platform. You can
follow [this guide](https://code.visualstudio.com/docs/devcontainers/containers)
to learn more about Dev Containers.
If you run into `could not connect to server` errors, you may need to change
your `.env`'s `DB_HOST` environment variable value to `db` to point to the
Postgres container.
#### Mac
Please visit
our [Mac dev setup guide](https://github.com/maybe-finance/maybe/wiki/Mac-Dev-Setup-Guide).
#### Linux
Please visit
our [Linux dev setup guide](https://github.com/maybe-finance/maybe/wiki/Linux-Dev-Setup-Guide).
#### Windows
Please visit
our [Windows dev setup guide](https://github.com/maybe-finance/maybe/wiki/Windows-Dev-Setup-Guide).
### Testing Emails
In development, we use `letter_opener` to automatically open emails in your
browser. When an email sends locally, a new browser tab will open with a
preview.
## Contributing
Before contributing, you'll likely find it helpful
to [understand context and general vision/direction](https://github.com/maybe-finance/maybe/wiki).
Once you've done that, please visit
our [contributing guide](https://github.com/maybe-finance/maybe/blob/main/CONTRIBUTING.md)
to get started!
- [Mac dev setup guide](https://github.com/maybe-finance/maybe/wiki/Mac-Dev-Setup-Guide)
- [Linux dev setup guide](https://github.com/maybe-finance/maybe/wiki/Linux-Dev-Setup-Guide)
- [Windows dev setup guide](https://github.com/maybe-finance/maybe/wiki/Windows-Dev-Setup-Guide)
- Dev containers - visit [this guide](https://code.visualstudio.com/docs/devcontainers/containers) to learn more
## Repo Activity

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

85
app/assets/images/ai.svg Normal file
View File

@@ -0,0 +1,85 @@
<svg width="62" height="68" viewBox="0 0 62 68" fill="none" xmlns="http://www.w3.org/2000/svg">
<g filter="url(#filter0_f_7620_90382)">
<path d="M15.0109 27.3668C14.8138 11.2848 17.2087 15.4884 28.5797 15.5133L32.8675 15.5228C44.2383 15.5478 46.7179 11.3549 46.9149 27.4368L46.9891 33.5015C47.1861 49.5834 44.7913 53.0249 33.4205 52.9999L29.1325 52.9906C17.7617 52.9656 15.2823 49.5134 15.0852 33.4315L15.0109 27.3668Z" fill="url(#paint0_linear_7620_90382)" fill-opacity="0.15"/>
</g>
<g filter="url(#filter1_i_7620_90382)">
<rect x="15" y="13" width="32" height="32" rx="10.6667" fill="url(#paint1_linear_7620_90382)"/>
<rect x="15" y="13" width="32" height="32" rx="10.6667" fill="white" fill-opacity="0.07" style="mix-blend-mode:plus-lighter"/>
</g>
<g filter="url(#filter2_ii_7620_90382)">
<rect x="16.7773" y="14.7778" width="28.4444" height="28.4444" rx="8.88889" fill="url(#paint2_linear_7620_90382)"/>
<path d="M36.1921 22.073C36.6039 22.0652 36.9439 22.3927 36.9517 22.8044C36.9786 24.2352 37.0273 25.6596 37.0958 27.088C37.1155 27.4993 36.7981 27.8487 36.3868 27.8684C35.9755 27.8881 35.6261 27.5707 35.6063 27.1594C35.5372 25.7174 35.488 24.2785 35.4607 22.8325C35.453 22.4208 35.7804 22.0807 36.1921 22.073Z" fill="#141414"/>
<path d="M36.1921 22.073C36.6039 22.0652 36.9439 22.3927 36.9517 22.8044C36.9786 24.2352 37.0273 25.6596 37.0958 27.088C37.1155 27.4993 36.7981 27.8487 36.3868 27.8684C35.9755 27.8881 35.6261 27.5707 35.6063 27.1594C35.5372 25.7174 35.488 24.2785 35.4607 22.8325C35.453 22.4208 35.7804 22.0807 36.1921 22.073Z" fill="url(#paint3_linear_7620_90382)"/>
<path d="M30.0884 22.7413C30.3247 22.4041 30.2428 21.9392 29.9056 21.7029C29.5684 21.4666 29.1034 21.5484 28.8671 21.8857C28.2555 22.7586 27.6031 23.6183 26.9349 24.4988C26.6795 24.8354 26.4217 25.1751 26.1631 25.5196C26.1629 25.4497 26.1627 25.379 26.1622 25.3074C26.158 24.7 26.1364 24.0511 26.0192 23.3998C25.9463 22.9946 25.5586 22.7251 25.1533 22.7981C24.7481 22.871 24.4787 23.2587 24.5516 23.6639C24.6454 24.185 24.667 24.7297 24.671 25.3176C24.672 25.4628 24.6719 25.6127 24.6718 25.7658C24.6714 26.2118 24.6709 26.6845 24.6985 27.1431C24.7046 27.2459 24.7313 27.3426 24.7744 27.4294C24.0609 28.4557 23.3903 29.5154 22.8297 30.615C22.8221 30.6299 22.8109 30.6511 22.7968 30.6775C22.7112 30.8389 22.5209 31.1974 22.4089 31.5427C22.3452 31.7392 22.2741 32.0229 22.3076 32.3158C22.3255 32.4722 22.3762 32.6577 22.4979 32.8323C22.6242 33.0135 22.7989 33.142 22.9963 33.2166C24.2085 33.6749 25.5494 33.7216 26.818 33.625C27.848 33.5466 28.8878 33.3675 29.8142 33.2078C30.0261 33.1713 30.2321 33.1358 30.4306 33.1028C30.8368 33.0352 31.1113 32.6512 31.0438 32.245C30.9762 31.8388 30.5921 31.5643 30.1859 31.6318C29.9702 31.6677 29.7524 31.7052 29.5328 31.743C28.6101 31.9017 27.6572 32.0656 26.7048 32.1381C25.6662 32.2172 24.6958 32.1801 23.852 31.9317C23.9193 31.7487 24.0152 31.566 24.0967 31.4107C24.1185 31.3691 24.1393 31.3294 24.1582 31.2923C24.909 29.8195 25.8865 28.397 26.9361 26.9776C27.3129 26.4681 27.7032 25.9536 28.0947 25.4375C28.7774 24.5377 29.4637 23.6329 30.0884 22.7413Z" fill="#141414"/>
<path d="M30.0884 22.7413C30.3247 22.4041 30.2428 21.9392 29.9056 21.7029C29.5684 21.4666 29.1034 21.5484 28.8671 21.8857C28.2555 22.7586 27.6031 23.6183 26.9349 24.4988C26.6795 24.8354 26.4217 25.1751 26.1631 25.5196C26.1629 25.4497 26.1627 25.379 26.1622 25.3074C26.158 24.7 26.1364 24.0511 26.0192 23.3998C25.9463 22.9946 25.5586 22.7251 25.1533 22.7981C24.7481 22.871 24.4787 23.2587 24.5516 23.6639C24.6454 24.185 24.667 24.7297 24.671 25.3176C24.672 25.4628 24.6719 25.6127 24.6718 25.7658C24.6714 26.2118 24.6709 26.6845 24.6985 27.1431C24.7046 27.2459 24.7313 27.3426 24.7744 27.4294C24.0609 28.4557 23.3903 29.5154 22.8297 30.615C22.8221 30.6299 22.8109 30.6511 22.7968 30.6775C22.7112 30.8389 22.5209 31.1974 22.4089 31.5427C22.3452 31.7392 22.2741 32.0229 22.3076 32.3158C22.3255 32.4722 22.3762 32.6577 22.4979 32.8323C22.6242 33.0135 22.7989 33.142 22.9963 33.2166C24.2085 33.6749 25.5494 33.7216 26.818 33.625C27.848 33.5466 28.8878 33.3675 29.8142 33.2078C30.0261 33.1713 30.2321 33.1358 30.4306 33.1028C30.8368 33.0352 31.1113 32.6512 31.0438 32.245C30.9762 31.8388 30.5921 31.5643 30.1859 31.6318C29.9702 31.6677 29.7524 31.7052 29.5328 31.743C28.6101 31.9017 27.6572 32.0656 26.7048 32.1381C25.6662 32.2172 24.6958 32.1801 23.852 31.9317C23.9193 31.7487 24.0152 31.566 24.0967 31.4107C24.1185 31.3691 24.1393 31.3294 24.1582 31.2923C24.909 29.8195 25.8865 28.397 26.9361 26.9776C27.3129 26.4681 27.7032 25.9536 28.0947 25.4375C28.7774 24.5377 29.4637 23.6329 30.0884 22.7413Z" fill="url(#paint4_linear_7620_90382)"/>
<path d="M36.2391 34.7581C36.3664 34.3664 36.1522 33.9458 35.7606 33.8185C35.369 33.6911 34.9483 33.9054 34.821 34.297C34.6438 34.842 34.4106 35.256 34.12 35.541C33.8419 35.8137 33.4787 36.0015 32.9619 36.0499C32.1922 36.1221 31.4116 35.7978 31.071 35.2344C30.858 34.882 30.3996 34.7691 30.0472 34.9821C29.6948 35.1951 29.5818 35.6535 29.7949 36.0059C30.5079 37.1855 31.9259 37.6448 33.1011 37.5346C33.9477 37.4552 34.6338 37.1258 35.1641 36.6056C35.6819 36.0978 36.0163 35.4433 36.2391 34.7581Z" fill="#141414"/>
<path d="M36.2391 34.7581C36.3664 34.3664 36.1522 33.9458 35.7606 33.8185C35.369 33.6911 34.9483 33.9054 34.821 34.297C34.6438 34.842 34.4106 35.256 34.12 35.541C33.8419 35.8137 33.4787 36.0015 32.9619 36.0499C32.1922 36.1221 31.4116 35.7978 31.071 35.2344C30.858 34.882 30.3996 34.7691 30.0472 34.9821C29.6948 35.1951 29.5818 35.6535 29.7949 36.0059C30.5079 37.1855 31.9259 37.6448 33.1011 37.5346C33.9477 37.4552 34.6338 37.1258 35.1641 36.6056C35.6819 36.0978 36.0163 35.4433 36.2391 34.7581Z" fill="url(#paint5_linear_7620_90382)"/>
</g>
<defs>
<filter id="filter0_f_7620_90382" x="0.937778" y="0.937778" width="60.1244" height="66.1244" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feGaussianBlur stdDeviation="7.03111" result="effect1_foregroundBlur_7620_90382"/>
</filter>
<filter id="filter1_i_7620_90382" x="15" y="13" width="32" height="32" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset/>
<feGaussianBlur stdDeviation="0.49869"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0"/>
<feBlend mode="normal" in2="shape" result="effect1_innerShadow_7620_90382"/>
</filter>
<filter id="filter2_ii_7620_90382" x="16.7773" y="13.8889" width="28.4453" height="30.2222" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="-0.888889"/>
<feGaussianBlur stdDeviation="0.888889"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.980392 0 0 0 0 0.309804 0 0 0 0 0.67451 0 0 0 0.1 0"/>
<feBlend mode="normal" in2="shape" result="effect1_innerShadow_7620_90382"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="0.888889"/>
<feGaussianBlur stdDeviation="0.888889"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.2 0 0 0 0 0.835294 0 0 0 0 1 0 0 0 0.1 0"/>
<feBlend mode="normal" in2="effect1_innerShadow_7620_90382" result="effect2_innerShadow_7620_90382"/>
</filter>
<linearGradient id="paint0_linear_7620_90382" x1="30.1185" y1="16.1417" x2="33.7041" y2="53.1754" gradientUnits="userSpaceOnUse">
<stop stop-color="#22CCEE"/>
<stop offset="0.274483" stop-color="#1570EF"/>
<stop offset="0.629793" stop-color="#6927DA"/>
<stop offset="1" stop-color="#F23E94"/>
</linearGradient>
<linearGradient id="paint1_linear_7620_90382" x1="31" y1="13" x2="31" y2="45" gradientUnits="userSpaceOnUse">
<stop stop-color="#22CCEE"/>
<stop offset="0.274483" stop-color="#1570EF"/>
<stop offset="0.629793" stop-color="#6927DA"/>
<stop offset="1" stop-color="#F23E94"/>
</linearGradient>
<linearGradient id="paint2_linear_7620_90382" x1="30.9996" y1="23.6667" x2="30.9996" y2="43.2222" gradientUnits="userSpaceOnUse">
<stop stop-color="white"/>
<stop offset="0.3" stop-color="#F7F7F7"/>
</linearGradient>
<linearGradient id="paint3_linear_7620_90382" x1="32.5419" y1="21.0645" x2="28.4008" y2="36.5193" gradientUnits="userSpaceOnUse">
<stop stop-color="#22CCEE"/>
<stop offset="0.274483" stop-color="#1570EF"/>
<stop offset="0.629793" stop-color="#6927DA"/>
<stop offset="1" stop-color="#F23E94"/>
</linearGradient>
<linearGradient id="paint4_linear_7620_90382" x1="32.5419" y1="21.0645" x2="28.4008" y2="36.5193" gradientUnits="userSpaceOnUse">
<stop stop-color="#22CCEE"/>
<stop offset="0.274483" stop-color="#1570EF"/>
<stop offset="0.629793" stop-color="#6927DA"/>
<stop offset="1" stop-color="#F23E94"/>
</linearGradient>
<linearGradient id="paint5_linear_7620_90382" x1="32.5419" y1="21.0645" x2="28.4008" y2="36.5193" gradientUnits="userSpaceOnUse">
<stop stop-color="#22CCEE"/>
<stop offset="0.274483" stop-color="#1570EF"/>
<stop offset="0.629793" stop-color="#6927DA"/>
<stop offset="1" stop-color="#F23E94"/>
</linearGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 9.5 KiB

View File

@@ -0,0 +1,12 @@
<svg xmlns="http://www.w3.org/2000/svg" width="36" height="36" viewBox="0 0 36 36" fill="none">
<path d="M8.39804 24.0315H4.09584C3.07641 24.0315 2.25 24.8609 2.25 25.8841C2.25 26.9072 3.07641 27.7367 4.09584 27.7367H8.39804C9.41747 27.7367 10.2439 26.9072 10.2439 25.8841C10.2439 24.8609 9.41747 24.0315 8.39804 24.0315Z" fill="#F23E94"/>
<path d="M27.6403 27.7359H31.9425C32.9619 27.7359 33.7883 26.9065 33.7883 25.8833C33.7883 24.8601 32.9619 24.0307 31.9425 24.0307H27.6403C26.6209 24.0307 25.7945 24.8601 25.7945 25.8833C25.7945 26.9065 26.6209 27.7359 27.6403 27.7359Z" fill="#F23E94"/>
<path d="M19.7588 24.0189H16.2567C15.2373 24.0189 14.4109 24.8483 14.4109 25.8715C14.4109 26.8947 15.2373 27.7241 16.2567 27.7241H19.7588C20.7783 27.7241 21.6047 26.8947 21.6047 25.8715C21.6047 24.8483 20.7783 24.0189 19.7588 24.0189Z" fill="#F23E94"/>
<path d="M25.9683 22.4047H30.1112C31.1306 22.4047 31.957 21.5753 31.957 20.5521C31.957 19.529 31.1306 18.6995 30.1112 18.6995H25.9683C24.9489 18.6995 24.1225 19.529 24.1225 20.5521C24.1225 21.5753 24.9489 22.4047 25.9683 22.4047Z" fill="#6927DA"/>
<path d="M9.99971 18.6993H5.85685C4.83742 18.6993 4.01101 19.5288 4.01101 20.5519C4.01101 21.5751 4.83742 22.4045 5.85685 22.4045H9.99971C11.0191 22.4045 11.8455 21.5751 11.8455 20.5519C11.8455 19.5288 11.0191 18.6993 9.99971 18.6993Z" fill="#6927DA"/>
<path d="M21.0888 18.6875H14.924C13.9045 18.6875 13.0781 19.517 13.0781 20.5401C13.0781 21.5633 13.9045 22.3927 14.924 22.3927H21.0888C22.1082 22.3927 22.9346 21.5633 22.9346 20.5401C22.9346 19.517 22.1082 18.6875 21.0888 18.6875Z" fill="#6927DA"/>
<path d="M15.5578 13.2072H7.69136C6.67193 13.2072 5.84552 14.0366 5.84552 15.0598C5.84552 16.0829 6.67193 16.9123 7.69136 16.9123H15.5578C16.5772 16.9123 17.4036 16.0829 17.4036 15.0598C17.4036 14.0366 16.5772 13.2072 15.5578 13.2072Z" fill="#1570EF"/>
<path d="M20.9094 16.9116H28.2735C29.2929 16.9116 30.1193 16.0821 30.1193 15.059C30.1193 14.0358 29.2929 13.2064 28.2735 13.2064L20.9094 13.2064C19.89 13.2064 19.0636 14.0358 19.0636 15.059C19.0636 16.0821 19.89 16.9116 20.9094 16.9116Z" fill="#1570EF"/>
<path d="M26.5036 7.875H22.3515C21.3321 7.875 20.5057 8.70443 20.5057 9.72759C20.5057 10.7507 21.3321 11.5802 22.3515 11.5802H26.5036C27.523 11.5802 28.3494 10.7507 28.3494 9.72759C28.3494 8.70443 27.523 7.875 26.5036 7.875Z" fill="#22CCEE"/>
<path d="M13.6077 7.875H9.45557C8.43614 7.875 7.60973 8.70443 7.60973 9.72759C7.60973 10.7507 8.43614 11.5802 9.45557 11.5802H13.6077C14.6271 11.5802 15.4535 10.7507 15.4535 9.72759C15.4535 8.70443 14.6271 7.875 13.6077 7.875Z" fill="#22CCEE"/>
</svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

@@ -0,0 +1,10 @@
<svg width="944" height="201" viewBox="0 0 944 201" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M0 56.5502L14.4845 52.101L28.9689 50.1276L43.4534 51.7926L57.9379 40.2042L72.4224 35.6995L86.9068 35.0612L101.391 51.2218L115.876 73.6398L130.36 65.7562L144.845 64.7572L159.329 78.5795L173.814 81.9833L188.298 71.3186L202.783 80.5112L217.267 86L231.752 84.5697L246.236 83.0772L260.721 78.4002L275.205 77.343L289.689 71.8152L304.174 52.25L318.658 51.5349L333.143 48.185L347.627 47.2522L362.112 45.4586L376.596 49.2356L391.081 47.5566L405.565 31.0549L420.05 28.5641L434.534 36.6352H449.019L463.503 42.7572L477.988 37.7564L492.472 42.3467L506.957 49.3852L521.441 59.4839L535.925 52.7514L550.41 47.1535L564.894 58.6703L579.379 49.8343L593.863 50.5123H608.348L622.832 54.192L637.317 58.4763L651.801 57.2522L666.286 59.3943L677.01 62.8533L688.553 59.3943L709.129 67.4827L724.224 60.8386L738.708 52.27L753.193 58.6965L767.677 37.887L782.162 28.3178L796.646 16.383L811.13 20.9733L825.615 10.2626L840.099 11.7927L854.584 6.59032L869.068 15.771L883.553 8.12043L898.037 6.59032L912.522 2L927.006 14.8529L944 15.771" stroke="#0B0B0B" stroke-opacity="0.25" stroke-width="2" stroke-miterlimit="16"/>
<path d="M14.4845 52.5538L0 57.0432V201H944V15.8954L927.006 14.9691L912.522 2L898.037 6.63181L883.553 8.17575L869.068 15.8954L854.584 6.63181L840.099 11.8812L825.615 10.3373L811.13 21.1448L796.646 16.513L782.161 28.5557L767.677 38.2114L753.193 59.2089L738.708 52.7244L724.224 61.3704L709.129 68.0745L688.553 59.9131L677.01 63.4034L666.286 59.9131L651.801 57.7516L637.317 58.9868L622.832 54.6637L608.348 50.9508H593.863L579.379 50.2667L564.894 59.1826L550.41 47.5616L535.925 53.2102L521.441 60.0035L506.957 49.8135L492.472 42.7114L477.988 38.0796L463.503 43.1256L449.019 36.9483H434.534L420.05 28.8042L405.565 31.3175L391.081 47.9684L376.596 49.6626L362.112 45.8514L347.627 47.6612L333.143 48.6024L318.658 51.9826L304.174 52.7042L289.689 72.4463L275.205 78.024L260.721 79.0908L246.236 83.8101L231.752 85.3161L217.267 86.7593L202.783 81.2209L188.298 71.9451L173.814 82.7063L159.329 79.2716L144.845 65.3245L130.36 66.3325L115.876 74.2874L101.391 51.6667L86.9068 35.3601L72.4224 36.0041L57.9379 40.5496L43.4534 52.2427L28.9689 50.5627L14.4845 52.5538Z" fill="url(#paint0_linear_4023_1299)" fill-opacity="0.5"/>
<defs>
<linearGradient id="paint0_linear_4023_1299" x1="445.5" y1="174.496" x2="445.5" y2="51.9672" gradientUnits="userSpaceOnUse">
<stop stop-color="white"/>
<stop offset="1" stop-color="#E5E5E5" stop-opacity="0.6"/>
</linearGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

@@ -1 +0,0 @@
/* Application styles */

View File

@@ -1,165 +0,0 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
/* Reset rules, default styles applied to plain HTML */
@layer base {
details>summary::-webkit-details-marker {
@apply hidden;
}
details>summary {
@apply list-none;
}
}
@layer components {
.form-field {
@apply flex flex-col gap-1 relative px-3 py-2 rounded-md border bg-white border-alpha-black-100 shadow-xs w-full;
@apply focus-within:border-gray-900 focus-within:shadow-none focus-within:ring-4 focus-within:ring-gray-100;
}
.form-field__label, .hw-combobox__label {
@apply block text-xs text-gray-500 peer-disabled:text-gray-400;
}
.form-field__input {
@apply border-none bg-transparent text-sm opacity-100 w-full p-0;
@apply focus:opacity-100 focus:outline-none focus:ring-0;
@apply placeholder-shown:opacity-50;
@apply disabled:text-gray-400;
}
.form-field__radio {
@apply text-gray-900;
}
.form-field__submit {
@apply cursor-pointer rounded-lg bg-black p-3 text-center text-white hover:bg-gray-700;
}
input:checked+label+.toggle-switch-dot {
transform: translateX(100%);
}
[type='checkbox'].maybe-checkbox {
@apply rounded-sm;
}
[type='checkbox'].maybe-checkbox--light {
@apply border-alpha-black-200 checked:bg-gray-900 checked:ring-gray-900 focus:ring-gray-900 focus-visible:ring-gray-900 checked:hover:bg-gray-500;
}
[type='checkbox'].maybe-checkbox--dark {
@apply ring-gray-900 checked:text-white;
}
[type='checkbox'].maybe-checkbox--dark:checked {
background-image: url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='111827' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M12.207 4.793a1 1 0 010 1.414l-5 5a1 1 0 01-1.414 0l-2-2a1 1 0 011.414-1.414L6.5 9.086l4.293-4.293a1 1 0 011.414 0z'/%3e%3c/svg%3e");
}
select[multiple="multiple"] {
@apply py-2 pr-2 space-y-0.5;
}
select[multiple="multiple"] option {
@apply py-2 rounded-md;
}
select[multiple="multiple"] option:checked {
@apply after:content-['\2713'] bg-white after:text-gray-500 after:ml-2;
}
select[multiple="multiple"] option:active,
select[multiple="multiple"] option:focus {
@apply bg-white;
}
.maybe-switch {
@apply block bg-gray-100 w-9 h-5 rounded-full cursor-pointer;
@apply after:content-[''] after:block after:absolute after:top-0.5 after:left-0.5 after:bg-white after:w-4 after:h-4 after:rounded-full after:transition-transform after:duration-300 after:ease-in-out;
@apply peer-checked:bg-green-600 peer-checked:after:translate-x-4;
}
.prose--github-release-notes {
.octicon {
@apply inline-block overflow-visible align-text-bottom fill-current;
}
.dropdown-caret {
@apply content-none border-4 border-b-0 border-transparent border-t-gray-500 size-0 inline-block;
}
.user-mention {
@apply font-bold;
}
}
.tooltip {
@apply hidden absolute;
}
.btn {
@apply px-3 py-2 rounded-lg text-sm font-medium cursor-pointer focus:outline-gray-500;
}
.btn--primary {
@apply bg-gray-900 text-white hover:bg-gray-700 disabled:bg-gray-50 disabled:hover:bg-gray-50 disabled:text-gray-400;
}
.btn--secondary {
@apply bg-gray-50 hover:bg-gray-100 text-gray-900;
}
.btn--outline {
@apply border border-alpha-black-200 text-gray-900 hover:bg-gray-50;
}
.btn--ghost {
@apply border border-transparent text-gray-900 hover:bg-gray-50;
}
}
.combobox {
.hw-combobox__main__wrapper, .hw-combobox__input {
@apply w-full;
}
.hw-combobox__main__wrapper {
@apply border-0 p-0 focus:border-0 ring-0 focus:ring-0 shadow-none focus:shadow-none focus-within:shadow-none;
}
.hw-combobox__listbox {
@apply absolute top-[160%] right-0 w-full bg-transparent rounded z-30;
}
.hw_combobox__pagination__wrapper {
@apply h-px;
&:only-child {
@apply bg-transparent;
}
}
--hw-border-color: rgba(0, 0, 0, 0.2);
--hw-handle-width: 20px;
--hw-handle-height: 20px;
--hw-handle-offset-right: 0px;
}
/* Small, single purpose classes that should take precedence over other styles */
@layer utilities {
.scrollbar::-webkit-scrollbar {
width: 4px;
}
.scrollbar::-webkit-scrollbar-thumb {
background: #d6d6d6;
border-radius: 10px;
}
.scrollbar::-webkit-scrollbar-thumb:hover {
background: #a6a6a6;
}
}

View File

@@ -0,0 +1,169 @@
@import 'tailwindcss';
@import "./maybe-design-system.css";
@import "./geist-font.css";
@import "./geist-mono-font.css";
@plugin "@tailwindcss/typography";
@plugin "@tailwindcss/forms";
@import "./simonweb_pickr.css";
@layer components {
.pcr-app{
position: static !important;
background: none !important;
box-shadow: none !important;
padding: 0 !important;
width: 100% !important;
}
.pcr-color-palette{
height: 12em !important;
width: 21.5rem !important;
}
.pcr-palette{
border-radius: 10px !important;
}
.pcr-palette:before{
border-radius: 10px !important;
}
.pcr-color-chooser{
height: 1.5em !important;
}
.pcr-picker{
height: 20px !important;
width: 20px !important;
}
}
.combobox {
.hw-combobox__main__wrapper,
.hw-combobox__input {
@apply w-full;
}
.hw-combobox__main__wrapper {
@apply border-0 p-0 focus:border-0 ring-0 focus:ring-0 shadow-none focus:shadow-none focus-within:shadow-none;
}
.hw-combobox__listbox {
@apply absolute top-[160%] right-0 w-full bg-transparent rounded z-30;
}
.hw-combobox__label {
@apply block text-xs text-gray-500 peer-disabled:text-gray-400;
}
.hw_combobox__pagination__wrapper {
@apply h-px;
&:only-child {
@apply bg-transparent;
}
}
--hw-border-color: rgba(0, 0, 0, 0.2);
--hw-handle-width: 20px;
--hw-handle-height: 20px;
--hw-handle-offset-right: 0px;
}
/* Typography */
.prose {
@apply max-w-none;
h2 {
@apply text-xl font-medium;
}
h3 {
@apply text-lg font-medium;
}
li {
@apply m-0;
}
details {
@apply mb-4 rounded-xl mt-3.5;
}
summary {
@apply flex items-center gap-1;
}
video {
@apply m-0 rounded-b-xl;
}
}
.prose--github-release-notes {
.octicon {
@apply inline-block overflow-visible align-text-bottom fill-current;
}
.dropdown-caret {
@apply content-none border-4 border-b-0 border-transparent border-t-gray-500 size-0 inline-block;
}
.user-mention {
@apply font-bold;
}
}
.prose--ai-chat {
@apply break-words;
p, li {
@apply text-sm text-primary;
}
scrollbar-width: thin;
scrollbar-color: rgba(156, 163, 175, 0.5) transparent;
::-webkit-scrollbar {
width: 6px;
}
::-webkit-scrollbar-track {
background: transparent;
}
::-webkit-scrollbar-thumb {
background-color: rgba(156, 163, 175, 0.5);
border-radius: 3px;
}
}
/* Custom scrollbar implementation for Windows browsers */
.windows {
::-webkit-scrollbar {
width: 4px;
}
::-webkit-scrollbar-thumb {
background: #d6d6d6;
border-radius: 10px;
}
::-webkit-scrollbar-thumb:hover {
background: #a6a6a6;
}
}
.scrollbar {
&::-webkit-scrollbar {
width: 4px;
}
&::-webkit-scrollbar-thumb {
background: #d6d6d6;
border-radius: 10px;
}
&::-webkit-scrollbar-thumb:hover {
background: #a6a6a6;
}
}
/* The following Markdown CSS has been removed as requested */

View File

@@ -0,0 +1,85 @@
/* Variable font */
@font-face {
font-family: 'Geist';
src: url('./geist/Geist[wght].woff2') format('woff2-variations');
font-weight: 100 900;
font-style: normal;
font-display: swap;
}
/* Static fonts (fallback) */
@supports not (font-variation-settings: normal) {
@font-face {
font-family: 'Geist';
src: url('./geist/Geist-Thin.woff2') format('woff2');
font-weight: 100;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'Geist';
src: url('./geist/Geist-ExtraLight.woff2') format('woff2');
font-weight: 200;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'Geist';
src: url('./geist/Geist-Light.woff2') format('woff2');
font-weight: 300;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'Geist';
src: url('./geist/Geist-Regular.woff2') format('woff2');
font-weight: 400;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'Geist';
src: url('./geist/Geist-Medium.woff2') format('woff2');
font-weight: 500;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'Geist';
src: url('./geist/Geist-SemiBold.woff2') format('woff2');
font-weight: 600;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'Geist';
src: url('./geist/Geist-Bold.woff2') format('woff2');
font-weight: 700;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'Geist';
src: url('./geist/Geist-ExtraBold.woff2') format('woff2');
font-weight: 800;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'Geist';
src: url('./geist/Geist-Black.woff2') format('woff2');
font-weight: 900;
font-style: normal;
font-display: swap;
}
}

View File

@@ -0,0 +1,83 @@
/* Variable font */
@font-face {
font-family: 'Geist Mono';
src: url('./geist_mono/GeistMono[wght].woff2') format('woff2-variations');
font-weight: 100 950;
font-style: normal;
font-display: swap;
}
/* Static fonts (fallback) */
@supports not (font-variation-settings: normal) {
@font-face {
font-family: 'Geist Mono';
src: url('./geist_mono/GeistMono-Thin.woff2') format('woff2');
font-weight: 100;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'Geist Mono';
src: url('./geist_mono/GeistMono-UltraLight.woff2') format('woff2');
font-weight: 200;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'Geist Mono';
src: url('./geist_mono/GeistMono-Light.woff2') format('woff2');
font-weight: 300;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'Geist Mono';
src: url('./geist_mono/GeistMono-Regular.woff2') format('woff2');
font-weight: 400;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'Geist Mono';
src: url('./geist_mono/GeistMono-Medium.woff2') format('woff2');
font-weight: 500;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'Geist Mono';
src: url('./geist_mono/GeistMono-SemiBold.woff2') format('woff2');
font-weight: 600;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'Geist Mono';
src: url('./geist_mono/GeistMono-Bold.woff2') format('woff2');
font-weight: 700;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'Geist Mono';
src: url('./geist_mono/GeistMono-Black.woff2') format('woff2');
font-weight: 900;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'Geist Mono';
src: url('./geist_mono/GeistMono-UltraBlack.woff2') format('woff2');
font-weight: 950;
font-style: normal;
font-display: swap;
}
}

View File

@@ -0,0 +1,763 @@
/*
This file contains all of the Figma design tokens, components, etc. that
are used globally across the app.
One-off styling (3rd party overrides, etc.) should be done in the application.css file.
*/
@custom-variant theme-dark (&:where([data-theme=dark], [data-theme=dark] *));
@theme {
/* Font families */
--font-sans: 'Geist', system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
--font-mono: 'Geist Mono', ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
/* Base colors */
--color-white: #ffffff;
--color-black: #0B0B0B;
--color-success: var(--color-green-600);
--color-warning: var(--color-yellow-600);
--color-destructive: var(--color-red-600);
/* Gray scale */
--color-gray-25: #FAFAFA;
--color-gray-50: #F7F7F7;
--color-gray-100: #F0F0F0;
--color-gray-200: #E7E7E7;
--color-gray-300: #CFCFCF;
--color-gray-400: #9E9E9E;
--color-gray-500: #737373;
--color-gray-600: #5C5C5C;
--color-gray-700: #363636;
--color-gray-800: #242424;
--color-gray-900: #171717;
--color-gray: var(--color-gray-500);
--color-gray-tint-5: --alpha(var(--color-gray-500) / 5%);
--color-gray-tint-10: --alpha(var(--color-gray-500) / 10%);
/* Alpha colors */
--color-alpha-white-25: --alpha(var(--color-white) / 3%);
--color-alpha-white-50: --alpha(var(--color-white) / 5%);
--color-alpha-white-100: --alpha(var(--color-white) / 8%);
--color-alpha-white-200: --alpha(var(--color-white) / 10%);
--color-alpha-white-300: --alpha(var(--color-white) / 15%);
--color-alpha-white-400: --alpha(var(--color-white) / 20%);
--color-alpha-white-500: --alpha(var(--color-white) / 30%);
--color-alpha-white-600: --alpha(var(--color-white) / 40%);
--color-alpha-white-700: --alpha(var(--color-white) / 50%);
--color-alpha-white-800: --alpha(var(--color-white) / 70%);
--color-alpha-white-900: --alpha(var(--color-white) / 85%);
--color-alpha-black-25: --alpha(var(--color-black) / 3%);
--color-alpha-black-50: --alpha(var(--color-black) / 5%);
--color-alpha-black-100: --alpha(var(--color-black) / 8%);
--color-alpha-black-200: --alpha(var(--color-black) / 10%);
--color-alpha-black-300: --alpha(var(--color-black) / 15%);
--color-alpha-black-400: --alpha(var(--color-black) / 20%);
--color-alpha-black-500: --alpha(var(--color-black) / 30%);
--color-alpha-black-600: --alpha(var(--color-black) / 40%);
--color-alpha-black-700: --alpha(var(--color-black) / 50%);
--color-alpha-black-800: --alpha(var(--color-black) / 70%);
--color-alpha-black-900: --alpha(var(--color-black) / 85%);
/* Red scale */
--color-red-25: #FFFBFB;
--color-red-50: #FFF1F0;
--color-red-100: #FFDEDB;
--color-red-200: #FEB9B3;
--color-red-300: #F88C86;
--color-red-400: #ED4E4E;
--color-red-500: #F13636;
--color-red-600: #EC2222;
--color-red-700: #C91313;
--color-red-800: #A40E0E;
--color-red-900: #7E0707;
--color-red-tint-5: --alpha(var(--color-red-500) / 5%);
--color-red-tint-10: --alpha(var(--color-red-500) / 10%);
/* Green scale */
--color-green-25: #F6FEF9;
--color-green-50: #ECFDF3;
--color-green-100: #D1FADF;
--color-green-200: #A6F4C5;
--color-green-300: #6CE9A6;
--color-green-400: #32D583;
--color-green-500: #12B76A;
--color-green-600: #10A861;
--color-green-700: #078C52;
--color-green-800: #05603A;
--color-green-900: #054F31;
--color-green-tint-5: --alpha(var(--color-green-500) / 5%);
--color-green-tint-10: --alpha(var(--color-green-500) / 10%);
/* Yellow scale */
--color-yellow-25: #FFFCF5;
--color-yellow-50: #FFFAEB;
--color-yellow-100: #FEF0C7;
--color-yellow-200: #FEDF89;
--color-yellow-300: #FEC84B;
--color-yellow-400: #FDB022;
--color-yellow-500: #F79009;
--color-yellow-600: #DC6803;
--color-yellow-700: #B54708;
--color-yellow-800: #93370D;
--color-yellow-900: #7A2E0E;
--color-yellow-tint-5: --alpha(var(--color-yellow-500) / 5%);
--color-yellow-tint-10: --alpha(var(--color-yellow-500) / 10%);
/* Cyan scale */
--color-cyan-25: #F5FEFF;
--color-cyan-50: #ECFDFF;
--color-cyan-100: #CFF9FE;
--color-cyan-200: #A5F0FC;
--color-cyan-300: #67E3F9;
--color-cyan-400: #22CCEE;
--color-cyan-500: #06AED4;
--color-cyan-600: #088AB2;
--color-cyan-700: #0E7090;
--color-cyan-800: #155B75;
--color-cyan-900: #155B75;
--color-cyan-tint-5: --alpha(var(--color-cyan-500) / 5%);
--color-cyan-tint-10: --alpha(var(--color-cyan-500) / 10%);
/* Blue scale */
--color-blue-25: #F5FAFF;
--color-blue-50: #EFF8FF;
--color-blue-100: #D1E9FF;
--color-blue-200: #B2DDFF;
--color-blue-300: #84CAFF;
--color-blue-400: #53B1FD;
--color-blue-500: #2E90FA;
--color-blue-600: #1570EF;
--color-blue-700: #175CD3;
--color-blue-800: #1849A9;
--color-blue-900: #194185;
--color-blue-tint-5: --alpha(var(--color-blue-500) / 5%);
--color-blue-tint-10: --alpha(var(--color-blue-500) / 10%);
/* Indigo scale */
--color-indigo-25: #F5F8FF;
--color-indigo-50: #EFF4FF;
--color-indigo-100: #E0EAFF;
--color-indigo-200: #C7D7FE;
--color-indigo-300: #A4BCFD;
--color-indigo-400: #8098F9;
--color-indigo-500: #6172F3;
--color-indigo-600: #444CE7;
--color-indigo-700: #3538CD;
--color-indigo-800: #2D31A6;
--color-indigo-900: #2D3282;
--color-indigo-tint-5: --alpha(var(--color-indigo-500) / 5%);
--color-indigo-tint-10: --alpha(var(--color-indigo-500) / 10%);
/* Violet scale */
--color-violet-25: #FBFAFF;
--color-violet-50: #F5F3FF;
--color-violet-100: #ECE9FE;
--color-violet-200: #DDD6FE;
--color-violet-300: #C3B5FD;
--color-violet-400: #A48AFB;
--color-violet-500: #875BF7;
--color-violet-600: #7839EE;
--color-violet-700: #6927DA;
--color-violet-tint-5: --alpha(var(--color-violet-500) / 5%);
--color-violet-tint-10: --alpha(var(--color-violet-500) / 10%);
/* Fuchsia scale */
--color-fuchsia-25: #FEFAFF;
--color-fuchsia-50: #FDF4FF;
--color-fuchsia-100: #FBE8FF;
--color-fuchsia-200: #F6D0FE;
--color-fuchsia-300: #EEAAFD;
--color-fuchsia-400: #E478FA;
--color-fuchsia-500: #D444F1;
--color-fuchsia-600: #BA24D5;
--color-fuchsia-700: #9F1AB1;
--color-fuchsia-800: #821890;
--color-fuchsia-900: #6F1877;
--color-fuchsia-tint-5: --alpha(var(--color-fuchsia-500) / 5%);
--color-fuchsia-tint-10: --alpha(var(--color-fuchsia-500) / 10%);
/* Pink scale */
--color-pink-25: #FFFAFC;
--color-pink-50: #FEF0F7;
--color-pink-100: #FFD1E2;
--color-pink-200: #FFB1CE;
--color-pink-300: #FD8FBA;
--color-pink-400: #F86BA7;
--color-pink-500: #F23E94;
--color-pink-600: #D5327F;
--color-pink-700: #BA256B;
--color-pink-800: #9E1958;
--color-pink-900: #840B45;
--color-pink-tint-5: --alpha(var(--color-pink-500) / 5%);
--color-pink-tint-10: --alpha(var(--color-pink-500) / 10%);
/* Orange scale */
--color-orange-25: #FFF9F5;
--color-orange-50: #FFF4ED;
--color-orange-100: #FFE6D5;
--color-orange-200: #FFD6AE;
--color-orange-300: #FF9C66;
--color-orange-400: #FF692E;
--color-orange-500: #FF4405;
--color-orange-600: #E62E05;
--color-orange-700: #BC1B06;
--color-orange-800: #97180C;
--color-orange-900: #771A0D;
--color-orange-tint-5: --alpha(var(--color-orange-500) / 5%);
--color-orange-tint-10: --alpha(var(--color-orange-500) / 10%);
/* Border radius overrides */
--border-radius-md: 8px;
--border-radius-lg: 10px;
--shadow-xs: 0px 1px 2px 0px --alpha(var(--color-black) / 6%);
--shadow-sm: 0px 1px 6px 0px --alpha(var(--color-black) / 6%);
--shadow-md: 0px 4px 8px -2px --alpha(var(--color-black) / 6%);
--shadow-lg: 0px 12px 16px -4px --alpha(var(--color-black) / 6%);
--shadow-xl: 0px 20px 24px -4px --alpha(var(--color-black) / 6%);
}
/* Custom shadow borders used for surfaces / containers */
@utility shadow-border-xs {
box-shadow: var(--shadow-xs), 0px 0px 0px 1px var(--color-alpha-black-50);
}
@utility shadow-border-sm {
box-shadow: var(--shadow-sm), 0px 0px 0px 1px var(--color-alpha-black-50);
}
@utility shadow-border-md {
box-shadow: var(--shadow-md), 0px 0px 0px 1px var(--color-alpha-black-50);
}
@utility shadow-border-lg {
box-shadow: var(--shadow-lg), 0px 0px 0px 1px var(--color-alpha-black-50);
}
@utility shadow-border-xl {
box-shadow: var(--shadow-xl), 0px 0px 0px 1px var(--color-alpha-black-50);
}
/* Design system color utilities */
@utility text-primary {
@apply text-gray-900;
@variant theme-dark {
@apply text-white;
}
}
@utility text-secondary {
@apply text-gray-500;
@variant theme-dark {
@apply text-gray-400;
}
}
@utility text-subdued {
@apply text-gray-400;
@variant theme-dark {
@apply text-gray-600;
}
}
@utility text-link {
@apply text-blue-600;
@variant theme-dark {
@apply text-blue-500;
}
}
@utility bg-surface {
@apply bg-gray-50;
@variant theme-dark {
@apply bg-black;
}
}
@utility bg-surface-hover {
@apply bg-gray-100;
@variant theme-dark {
@apply bg-gray-800;
}
}
@utility bg-surface-inset {
@apply bg-gray-100;
@variant theme-dark {
@apply bg-gray-900;
}
}
@utility bg-surface-inset-hover {
@apply bg-gray-200;
@variant theme-dark {
@apply bg-gray-800;
}
}
@utility bg-container {
@apply bg-white;
@variant theme-dark {
@apply bg-gray-900;
}
}
@utility bg-container-hover {
@apply bg-gray-50;
@variant theme-dark {
@apply bg-gray-800;
}
}
@utility bg-container-inset {
@apply bg-gray-50;
@variant theme-dark {
@apply bg-gray-800;
}
}
@utility bg-container-inset-hover {
@apply bg-gray-100;
@variant theme-dark {
@apply bg-gray-700;
}
}
@utility bg-inverse {
@apply bg-gray-800;
@variant theme-dark {
@apply bg-white;
}
}
@utility bg-inverse-hover {
@apply bg-gray-700;
@variant theme-dark {
@apply bg-gray-100;
}
}
@utility bg-overlay {
background-color: rgba(var(--color-gray-100), 0.5);
@variant theme-dark {
background-color: var(--color-alpha-black-900);
}
}
@utility border-primary {
@apply border-alpha-black-300;
@variant theme-dark {
@apply border-alpha-white-400;
}
}
@utility border-secondary {
@apply border-alpha-black-200;
@variant theme-dark {
@apply border-alpha-white-300;
}
}
@utility border-tertiary {
@apply border-alpha-black-100;
@variant theme-dark {
@apply border-alpha-white-200;
}
}
@utility border-subdued {
@apply border-alpha-black-50;
@variant theme-dark {
@apply border-alpha-white-100;
}
}
@utility border-solid {
@apply border-black;
@variant theme-dark {
@apply border-white;
}
}
@utility border-destructive {
@apply border-red-500;
@variant theme-dark {
@apply border-red-400;
}
}
/* Foreground Colors */
@utility fg-gray {
@apply text-gray-500;
@variant theme-dark {
@apply text-gray-400;
}
}
@utility fg-contrast {
@apply text-gray-400;
@variant theme-dark {
@apply text-gray-500;
}
}
@utility fg-inverse {
@apply text-white;
@variant theme-dark {
@apply text-gray-900;
}
}
@utility fg-primary {
@apply text-gray-900;
@variant theme-dark {
@apply text-white;
}
}
@utility fg-primary-variant {
@apply text-gray-800;
@variant theme-dark {
@apply text-gray-50;
}
}
@utility fg-secondary {
@apply text-gray-50;
@variant theme-dark {
@apply text-gray-700;
}
}
@utility fg-secondary-variant {
@apply text-gray-100;
@variant theme-dark {
@apply text-gray-600;
}
}
@utility fg-subdued {
@apply text-gray-400;
@variant theme-dark {
@apply text-gray-500;
}
}
@layer base {
button {
@apply cursor-pointer focus-visible:outline-gray-900;
}
hr {
@apply text-gray-200;
}
details>summary::-webkit-details-marker {
@apply hidden;
}
details>summary {
@apply list-none;
}
input[type='radio'] {
@apply border-gray-300 text-indigo-600 focus:ring-indigo-600; /* Default light mode */
@variant theme-dark {
/* Dark mode radio button base and checked styles */
@apply border-gray-600 bg-gray-700 checked:bg-blue-500 focus:ring-blue-500 focus:ring-offset-gray-800;
}
}
}
@layer components {
/* Buttons */
.btn {
@apply px-3 py-2 rounded-lg text-sm font-medium cursor-pointer disabled:cursor-not-allowed focus:outline-gray-500;
@apply transition-all duration-300;
}
.btn--primary {
@apply button-bg-primary text-white disabled:text-gray-400;
@apply hover:button-bg-primary-hover;
@apply disabled:button-bg-disabled disabled:hover:button-bg-disabled;
@variant theme-dark {
@apply button-bg-primary fg-primary;
@apply hover:button-bg-primary-hover;
@apply disabled:button-bg-disabled disabled:hover:button-bg-disabled;
}
}
.btn--secondary {
@apply button-bg-secondary text-primary;
@apply hover:button-bg-secondary-hover;
@variant theme-dark {
@apply button-bg-secondary text-white;
@apply hover:button-bg-secondary-hover;
}
}
.btn--outline {
@apply border border-alpha-black-200 text-primary disabled:button-bg-disabled disabled:hover:button-bg-disabled disabled:text-gray-400;
@apply hover:button-bg-outline-hover;
@variant theme-dark {
@apply border-alpha-white-300 text-white disabled:button-bg-disabled disabled:hover:button-bg-disabled disabled:text-gray-600;
@apply hover:button-bg-outline-hover;
}
}
.btn--ghost {
@apply border border-transparent text-primary hover:button-bg-ghost-hover;
@variant theme-dark {
@apply fg-primary hover:button-bg-ghost-hover;
}
}
.btn--destructive {
@apply button-bg-destructive text-white hover:button-bg-destructive-hover disabled:button-bg-disabled disabled:hover:button-bg-disabled disabled:text-red-400;
@variant theme-dark {
@apply button-bg-destructive text-white hover:button-bg-destructive-hover disabled:button-bg-disabled disabled:hover:button-bg-disabled;
}
}
/* Forms */
.form-field {
@apply flex flex-col gap-1 relative px-3 py-2 rounded-md border bg-container border-secondary shadow-xs w-full;
@apply focus-within:border-secondary focus-within:shadow-none focus-within:ring-4 focus-within:ring-alpha-black-200;
@apply transition-all duration-300;
@variant theme-dark {
@apply focus-within:ring-alpha-white-300;
}
/* Add styles for multiple select within form fields */
select[multiple] {
@apply py-2 pr-2 space-y-0.5 overflow-y-auto;
option {
@apply py-2 rounded-md;
}
option:checked {
@apply after:content-['\2713'] bg-container-inset after:text-gray-500 after:ml-2;
}
option:active,
option:focus {
@apply bg-container-inset;
}
}
}
.form-field__label {
@apply block text-xs text-secondary peer-disabled:text-subdued;
}
.form-field__input {
@apply border-none bg-transparent text-sm opacity-100 w-full p-0;
@apply focus:opacity-100 focus:outline-hidden focus:ring-0;
@apply placeholder-shown:opacity-50;
@apply disabled:text-subdued;
@apply text-ellipsis overflow-hidden whitespace-nowrap;
@apply transition-opacity duration-300;
&select {
@apply pr-8;
}
}
.form-field__radio {
@apply text-primary;
}
.form-field__submit {
@apply cursor-pointer rounded-lg bg-surface p-3 text-center text-white hover:bg-surface-hover;
}
/* Checkboxes */
.checkbox {
&[type='checkbox'] {
@apply rounded-sm;
@apply transition-colors duration-300;
}
}
.checkbox--light {
&[type='checkbox'] {
@apply border-alpha-black-200 checked:bg-gray-900 checked:ring-gray-900 focus:ring-gray-900 focus-visible:ring-gray-900 checked:hover:bg-gray-500;
}
&[type='checkbox']:disabled {
@apply cursor-not-allowed opacity-80 bg-gray-50 border-gray-200 checked:bg-gray-400 checked:ring-gray-400;
}
}
.checkbox--dark {
&[type='checkbox'] {
@apply ring-gray-900 checked:text-white;
}
&[type='checkbox']:disabled {
@apply cursor-not-allowed opacity-80 ring-gray-600;
}
&[type='checkbox']:checked {
background-image: url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='111827' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M12.207 4.793a1 1 0 010 1.414l-5 5a1 1 0 01-1.414 0l-2-2a1 1 0 011.414-1.414L6.5 9.086l4.293-4.293a1 1 0 011.414 0z'/%3e%3c/svg%3e");
}
}
/* Switches */
.switch {
@apply block bg-gray-100 w-9 h-5 rounded-full cursor-pointer;
@apply after:content-[''] after:block after:absolute after:top-0.5 after:left-0.5 after:bg-white after:w-4 after:h-4 after:rounded-full;
@apply after:transition-transform after:duration-300 after:ease-in-out;
@apply peer-checked:bg-green-600 peer-checked:after:translate-x-4;
@apply transition-colors duration-300;
}
/* Tooltips */
.tooltip {
@apply hidden absolute;
}
}
@layer utilities {
/* Specific override for strong tags in prose under dark mode */
.prose:where([data-theme=dark], [data-theme=dark] *) strong {
color: theme(colors.white) !important;
}
}
/* Button Backgrounds */
@utility button-bg-primary {
@apply bg-gray-900; /* Maps to fg-primary light */
@variant theme-dark {
@apply bg-white; /* Maps to fg-primary dark */
}
}
@utility button-bg-primary-hover {
@apply bg-gray-800; /* Maps to fg-primary-variant light */
@variant theme-dark {
@apply bg-gray-50; /* Maps to fg-primary-variant dark */
}
}
@utility button-bg-secondary {
@apply bg-gray-50; /* Maps to fg-secondary light */
@variant theme-dark {
@apply bg-gray-700; /* Maps to fg-secondary dark */
}
}
@utility button-bg-secondary-hover {
@apply bg-gray-100; /* Maps to fg-secondary-variant light */
@variant theme-dark {
@apply bg-gray-600; /* Maps to fg-secondary-variant dark */
}
}
@utility button-bg-disabled {
@apply bg-gray-50;
@variant theme-dark {
@apply bg-gray-700;
}
}
@utility button-bg-destructive {
@apply bg-red-500;
@variant theme-dark {
@apply bg-red-400;
}
}
@utility button-bg-destructive-hover {
@apply bg-red-600;
@variant theme-dark {
@apply bg-red-500;
}
}
@utility button-bg-ghost-hover {
@apply bg-gray-50;
@variant theme-dark {
@apply bg-gray-800;
}
}
@utility button-bg-outline-hover {
@apply bg-gray-100;
@variant theme-dark {
@apply bg-gray-700;
}
}
/* Tab Styles */
@utility tab-item-active {
@apply bg-white;
@variant theme-dark {
@apply bg-gray-700;
}
}
@utility tab-item-hover {
@apply bg-gray-200;
@variant theme-dark {
@apply bg-gray-800;
}
}
@utility tab-bg-group {
@apply bg-gray-50;
@variant theme-dark {
@apply bg-alpha-black-700;
}
}

File diff suppressed because one or more lines are too long

View File

@@ -1,4 +1,10 @@
module ApplicationCable
class Connection < ActionCable::Connection::Base
rescue_from StandardError, with: :report_error
private
def report_error(e)
Sentry.capture_exception(e)
end
end
end

View File

@@ -1,14 +0,0 @@
class Account::CashesController < ApplicationController
layout :with_sidebar
before_action :set_account
def index
end
private
def set_account
@account = Current.family.accounts.find(params[:account_id])
end
end

View File

@@ -1,61 +0,0 @@
class Account::EntriesController < ApplicationController
layout :with_sidebar
before_action :set_account
before_action :set_entry, only: %i[edit update show destroy]
def index
@q = search_params
@pagy, @entries = pagy(@account.entries.search(@q).reverse_chronological, limit: params[:per_page] || "10")
end
def edit
render entryable_view_path(:edit)
end
def update
prev_amount = @entry.amount
prev_date = @entry.date
@entry.update!(entry_params)
@entry.sync_account_later if prev_amount != @entry.amount || prev_date != @entry.date
respond_to do |format|
format.html { redirect_to account_entry_path(@account, @entry), notice: t(".success") }
format.turbo_stream { render turbo_stream: turbo_stream.replace(@entry) }
end
end
def show
render entryable_view_path(:show)
end
def destroy
@entry.destroy!
@entry.sync_account_later
redirect_to account_url(@entry.account), notice: t(".success")
end
private
def entryable_view_path(action)
@entry.entryable_type.underscore.pluralize + "/" + action.to_s
end
def set_account
@account = Current.family.accounts.find(params[:account_id])
end
def set_entry
@entry = @account.entries.find(params[:id])
end
def entry_params
params.require(:account_entry).permit(:name, :date, :amount, :currency, :notes)
end
def search_params
params.fetch(:q, {})
.permit(:search)
end
end

View File

@@ -1,28 +1,29 @@
class Account::HoldingsController < ApplicationController
layout :with_sidebar
before_action :set_account
before_action :set_holding, only: %i[show destroy]
def index
@holdings = @account.holdings.current
@account = Current.family.accounts.find(params[:account_id])
end
def show
end
def destroy
@holding.destroy_holding_and_entries!
redirect_back_or_to account_holdings_path(@account)
if @holding.account.plaid_account_id.present?
flash[:alert] = "You cannot delete this holding"
else
@holding.destroy_holding_and_entries!
flash[:notice] = t(".success")
end
respond_to do |format|
format.html { redirect_back_or_to account_path(@holding.account) }
format.turbo_stream { render turbo_stream: turbo_stream.action(:redirect, account_path(@holding.account)) }
end
end
private
def set_account
@account = Current.family.accounts.find(params[:account_id])
end
def set_holding
@holding = @account.holdings.current.find(params[:id])
@holding = Current.family.holdings.find(params[:id])
end
end

View File

@@ -1,66 +1,37 @@
class Account::TradesController < ApplicationController
layout :with_sidebar
include EntryableResource
before_action :set_account
before_action :set_entry, only: :update
def new
@entry = @account.entries.account_trades.new(entryable_attributes: {})
end
def index
@entries = @account.entries.reverse_chronological.where(entryable_type: %w[Account::Trade Account::Transaction])
end
def create
@builder = Account::EntryBuilder.new(entry_params)
if entry = @builder.save
entry.sync_account_later
redirect_to @account, notice: t(".success")
else
flash[:alert] = t(".failure")
redirect_back_or_to @account
end
end
def update
@entry.update!(entry_params)
respond_to do |format|
format.html { redirect_to account_entry_path(@account, @entry), notice: t(".success") }
format.turbo_stream { render turbo_stream: turbo_stream.replace(@entry) }
end
end
def securities
query = params[:q]
return render json: [] if query.blank? || query.length < 2 || query.length > 100
@securities = Security::SynthComboboxOption.find_in_synth(query)
end
permitted_entryable_attributes :id, :qty, :price
private
def set_account
@account = Current.family.accounts.find(params[:account_id])
def build_entry
Account::TradeBuilder.new(create_entry_params)
end
def set_entry
@entry = @account.entries.find(params[:id])
def create_entry_params
params.require(:account_entry).permit(
:account_id, :date, :amount, :currency, :qty, :price, :ticker, :manual_ticker, :type, :transfer_account_id
).tap do |params|
account_id = params.delete(:account_id)
params[:account] = Current.family.accounts.find(account_id)
end
end
def entry_params
params.require(:account_entry)
.permit(
:type, :date, :qty, :ticker, :price, :amount, :notes, :excluded, :currency, :transfer_account_id, :entryable_type,
entryable_attributes: [
:id,
:qty,
:ticker,
:price
]
)
.merge(account: @account)
def update_entry_params
return entry_params unless entry_params[:entryable_attributes].present?
update_params = entry_params
update_params = update_params.merge(entryable_type: "Account::Trade")
qty = update_params[:entryable_attributes][:qty]
price = update_params[:entryable_attributes][:price]
if qty.present? && price.present?
qty = update_params[:nature] == "inflow" ? -qty.to_d : qty.to_d
update_params[:entryable_attributes][:qty] = qty
update_params[:amount] = qty * price.to_d
end
update_params.except(:nature)
end
end

View File

@@ -0,0 +1,22 @@
class Account::TransactionCategoriesController < ApplicationController
def update
@entry = Current.family.entries.account_transactions.find(params[:transaction_id])
@entry.update!(entry_params)
respond_to do |format|
format.html { redirect_back_or_to account_transaction_path(@entry) }
format.turbo_stream do
render turbo_stream: turbo_stream.replace(
"category_menu_account_transaction_#{@entry.account_transaction_id}",
partial: "categories/menu",
locals: { transaction: @entry.account_transaction }
)
end
end
end
private
def entry_params
params.require(:account_entry).permit(:entryable_type, entryable_attributes: [ :id, :category_id ])
end
end

View File

@@ -1,74 +1,37 @@
class Account::TransactionsController < ApplicationController
layout :with_sidebar
include EntryableResource
before_action :set_account
before_action :set_entry, only: :update
permitted_entryable_attributes :id, :category_id, :merchant_id, { tag_ids: [] }
def index
@pagy, @entries = pagy(
@account.entries.account_transactions.reverse_chronological,
limit: params[:per_page] || "10"
)
def bulk_delete
destroyed = Current.family.entries.destroy_by(id: bulk_delete_params[:entry_ids])
destroyed.map(&:account).uniq.each(&:sync_later)
redirect_back_or_to transactions_url, notice: t(".success", count: destroyed.count)
end
def update
prev_amount = @entry.amount
prev_date = @entry.date
def bulk_edit
end
@entry.update!(entry_params.except(:origin))
@entry.sync_account_later if prev_amount != @entry.amount || prev_date != @entry.date
def bulk_update
updated = Current.family
.entries
.where(id: bulk_update_params[:entry_ids])
.bulk_update!(bulk_update_params)
respond_to do |format|
format.html { redirect_to account_entry_path(@account, @entry), notice: t(".success") }
format.turbo_stream do
render turbo_stream: turbo_stream.replace(
@entry,
partial: "account/entries/entry",
locals: entry_locals.merge(entry: @entry)
)
end
end
redirect_back_or_to transactions_url, notice: t(".success", count: updated)
end
private
def set_account
@account = Current.family.accounts.find(params[:account_id])
def bulk_delete_params
params.require(:bulk_delete).permit(entry_ids: [])
end
def set_entry
@entry = @account.entries.find(params[:id])
def bulk_update_params
params.require(:bulk_update).permit(:date, :notes, :category_id, :merchant_id, entry_ids: [])
end
def entry_locals
{
selectable: entry_params[:origin].present?,
show_balance: entry_params[:origin] == "account",
origin: entry_params[:origin]
}
end
def entry_params
params.require(:account_entry)
.permit(
:name, :date, :amount, :currency, :excluded, :notes, :entryable_type, :nature, :origin,
entryable_attributes: [
:id,
:category_id,
:merchant_id,
{ tag_ids: [] }
]
).tap do |permitted_params|
nature = permitted_params.delete(:nature)
if permitted_params[:amount]
amount_value = permitted_params[:amount].to_d
if nature == "income"
amount_value *= -1
end
permitted_params[:amount] = amount_value
end
end
def search_params
params.fetch(:q, {})
.permit(:start_date, :end_date, :search, :amount, :amount_operator, accounts: [], account_ids: [], categories: [], merchants: [], types: [], tags: [])
end
end

View File

@@ -0,0 +1,56 @@
class Account::TransferMatchesController < ApplicationController
before_action :set_entry
def new
@accounts = Current.family.accounts.alphabetically.where.not(id: @entry.account_id)
@transfer_match_candidates = @entry.account_transaction.transfer_match_candidates
end
def create
@transfer = build_transfer
@transfer.save!
@transfer.sync_account_later
redirect_back_or_to transactions_path, notice: t(".success")
end
private
def set_entry
@entry = Current.family.entries.find(params[:transaction_id])
end
def transfer_match_params
params.require(:transfer_match).permit(:method, :matched_entry_id, :target_account_id)
end
def build_transfer
if transfer_match_params[:method] == "new"
target_account = Current.family.accounts.find(transfer_match_params[:target_account_id])
missing_transaction = Account::Transaction.new(
entry: target_account.entries.build(
amount: @entry.amount * -1,
currency: @entry.currency,
date: @entry.date,
name: "Transfer to #{@entry.amount.negative? ? @entry.account.name : target_account.name}",
)
)
transfer = Transfer.find_or_initialize_by(
inflow_transaction: @entry.amount.positive? ? missing_transaction : @entry.account_transaction,
outflow_transaction: @entry.amount.positive? ? @entry.account_transaction : missing_transaction
)
transfer.status = "confirmed"
transfer
else
target_transaction = Current.family.entries.find(transfer_match_params[:matched_entry_id])
transfer = Transfer.find_or_initialize_by(
inflow_transaction: @entry.amount.negative? ? @entry.account_transaction : target_transaction.account_transaction,
outflow_transaction: @entry.amount.negative? ? target_transaction.account_transaction : @entry.account_transaction
)
transfer.status = "confirmed"
transfer
end
end
end

View File

@@ -1,62 +0,0 @@
class Account::TransfersController < ApplicationController
layout :with_sidebar
before_action :set_transfer, only: %i[destroy show update]
def new
@transfer = Account::Transfer.new
end
def show
end
def create
from_account = Current.family.accounts.find(transfer_params[:from_account_id])
to_account = Current.family.accounts.find(transfer_params[:to_account_id])
@transfer = Account::Transfer.build_from_accounts from_account, to_account, \
date: transfer_params[:date],
amount: transfer_params[:amount].to_d,
currency: transfer_params[:currency]
if @transfer.save
@transfer.entries.each(&:sync_account_later)
redirect_to transactions_path, notice: t(".success")
else
# TODO: this is not an ideal way to handle errors and should eventually be improved.
# See: https://github.com/hotwired/turbo-rails/pull/367
flash[:alert] = @transfer.errors.full_messages.to_sentence
redirect_to transactions_path
end
end
def update
@transfer.update_entries!(transfer_update_params)
redirect_back_or_to transactions_url, notice: t(".success")
end
def destroy
@transfer.destroy!
redirect_back_or_to transactions_url, notice: t(".success")
end
private
def set_transfer
record = Account::Transfer.find(params[:id])
unless record.entries.all? { |entry| Current.family.accounts.include?(entry.account) }
raise ActiveRecord::RecordNotFound
end
@transfer = record
end
def transfer_params
params.require(:account_transfer).permit(:from_account_id, :to_account_id, :amount, :date, :name, :excluded)
end
def transfer_update_params
params.require(:account_transfer).permit(:excluded, :notes)
end
end

View File

@@ -1,35 +1,3 @@
class Account::ValuationsController < ApplicationController
layout :with_sidebar
before_action :set_account
def new
@entry = @account.entries.account_valuations.new(entryable_attributes: {})
end
def create
@entry = @account.entries.account_valuations.new(entry_params.merge(entryable_attributes: {}))
if @entry.save
@entry.sync_account_later
redirect_back_or_to account_valuations_path(@account), notice: t(".success")
else
flash[:alert] = @entry.errors.full_messages.to_sentence
redirect_to @account
end
end
def index
@entries = @account.entries.account_valuations.reverse_chronological
end
private
def set_account
@account = Current.family.accounts.find(params[:account_id])
end
def entry_params
params.require(:account_entry).permit(:name, :date, :amount, :currency)
end
include EntryableResource
end

View File

@@ -0,0 +1,25 @@
class AccountableSparklinesController < ApplicationController
def show
@accountable = Accountable.from_type(params[:accountable_type]&.classify)
@series = Rails.cache.fetch(cache_key) do
family.accounts.active
.where(accountable_type: @accountable.name)
.balance_series(
currency: family.currency,
favorable_direction: @accountable.favorable_direction
)
end
render layout: false
end
private
def family
Current.family
end
def cache_key
family.build_cache_key("#{@accountable.name}_sparkline")
end
end

View File

@@ -1,41 +1,45 @@
class AccountsController < ApplicationController
layout :with_sidebar
before_action :set_account, only: %i[sync]
before_action :set_account, only: %i[sync chart sparkline]
include Periodable
def index
@institutions = Current.family.institutions
@accounts = Current.family.accounts.ungrouped.alphabetically
end
@manual_accounts = family.accounts.manual.alphabetically
@plaid_items = family.plaid_items.ordered
def summary
@period = Period.from_param(params[:period])
snapshot = Current.family.snapshot(@period)
@net_worth_series = snapshot[:net_worth_series]
@asset_series = snapshot[:asset_series]
@liability_series = snapshot[:liability_series]
@accounts = Current.family.accounts
@account_groups = @accounts.by_group(period: @period, currency: Current.family.currency)
end
def list
@period = Period.from_param(params[:period])
render layout: false
render layout: "settings"
end
def sync
unless @account.syncing?
@account.sync_later
end
redirect_to account_path(@account)
end
def chart
@chart_view = params[:chart_view] || "balance"
render layout: "application"
end
def sparkline
render layout: false
end
def sync_all
Current.family.accounts.active.sync
redirect_back_or_to accounts_path, notice: t(".success")
unless family.syncing?
family.sync_later
end
redirect_to accounts_path
end
private
def family
Current.family
end
def set_account
@account = Current.family.accounts.find(params[:id])
@account = family.accounts.find(params[:id])
end
end

View File

@@ -1,15 +1,19 @@
class ApplicationController < ActionController::Base
include Onboardable, Localize, AutoSync, Authentication, Invitable, SelfHostable, StoreLocation, Impersonatable
include Onboardable, Localize, AutoSync, Authentication, Invitable, SelfHostable, StoreLocation, Impersonatable, Breadcrumbable, FeatureGuardable
include Pagy::Backend
helper_method :require_upgrade?, :subscription_pending?
before_action :detect_os
before_action :set_default_chat
private
def require_upgrade?
return false if self_hosted?
return false unless Current.session
return false if Current.family.subscribed?
return false if subscription_pending? || request.path == settings_billing_path
return false if Current.family.active_accounts_count <= 3
true
end
@@ -19,9 +23,21 @@ class ApplicationController < ActionController::Base
subscribed_at.present? && subscribed_at <= Time.current && subscribed_at > 1.hour.ago
end
def with_sidebar
return "turbo_rails/frame" if turbo_frame_request?
def detect_os
user_agent = request.user_agent
@os = case user_agent
when /Windows/i then "windows"
when /Macintosh/i then "mac"
when /Linux/i then "linux"
when /Android/i then "android"
when /iPhone|iPad/i then "ios"
else ""
end
end
"with_sidebar"
# By default, we show the user the last chat they interacted with
def set_default_chat
@last_viewed_chat = Current.user&.last_viewed_chat
@chat = @last_viewed_chat
end
end

View File

@@ -0,0 +1,48 @@
class BudgetCategoriesController < ApplicationController
before_action :set_budget
def index
@budget_categories = @budget.budget_categories.includes(:category)
render layout: "wizard"
end
def show
@recent_transactions = @budget.transactions
if params[:id] == BudgetCategory.uncategorized.id
@budget_category = @budget.uncategorized_budget_category
@recent_transactions = @recent_transactions.where(account_transactions: { category_id: nil })
else
@budget_category = Current.family.budget_categories.find(params[:id])
@recent_transactions = @recent_transactions.joins("LEFT JOIN categories ON categories.id = account_transactions.category_id")
.where("categories.id = ? OR categories.parent_id = ?", @budget_category.category.id, @budget_category.category.id)
end
@recent_transactions = @recent_transactions.order("account_entries.date DESC, ABS(account_entries.amount) DESC").take(3)
end
def update
@budget_category = Current.family.budget_categories.find(params[:id])
if @budget_category.update(budget_category_params)
respond_to do |format|
format.turbo_stream
format.html { redirect_to budget_budget_categories_path(@budget) }
end
else
render :index, status: :unprocessable_entity
end
end
private
def budget_category_params
params.require(:budget_category).permit(:budgeted_spending).tap do |params|
params[:budgeted_spending] = params[:budgeted_spending].presence || 0
end
end
def set_budget
start_date = Budget.param_to_date(params[:budget_month_year])
@budget = Current.family.budgets.find_by(start_date: start_date)
end
end

View File

@@ -0,0 +1,47 @@
class BudgetsController < ApplicationController
before_action :set_budget, only: %i[show edit update]
def index
redirect_to_current_month_budget
end
def show
end
def edit
render layout: "wizard"
end
def update
@budget.update!(budget_params)
redirect_to budget_budget_categories_path(@budget)
end
def picker
render partial: "budgets/picker", locals: {
family: Current.family,
year: params[:year].to_i || Date.current.year
}
end
private
def budget_create_params
params.require(:budget).permit(:start_date)
end
def budget_params
params.require(:budget).permit(:budgeted_spending, :expected_income)
end
def set_budget
start_date = Budget.param_to_date(params[:month_year])
@budget = Budget.find_or_bootstrap(Current.family, start_date: start_date)
raise ActiveRecord::RecordNotFound unless @budget
end
def redirect_to_current_month_budget
current_budget = Budget.find_or_bootstrap(Current.family, start_date: Date.current)
redirect_to budget_path(current_budget)
end
end

View File

@@ -1,15 +1,17 @@
class CategoriesController < ApplicationController
layout :with_sidebar
before_action :set_category, only: %i[edit update destroy]
before_action :set_categories, only: %i[update edit]
before_action :set_transaction, only: :create
def index
@categories = Current.family.categories.alphabetically
render layout: "settings"
end
def new
@category = Current.family.categories.new color: Category::COLORS.sample
set_categories
end
def create
@@ -17,9 +19,17 @@ class CategoriesController < ApplicationController
if @category.save
@transaction.update(category_id: @category.id) if @transaction
redirect_back_or_to transactions_path, notice: t(".success")
flash[:notice] = t(".success")
redirect_target_url = request.referer || categories_path
respond_to do |format|
format.html { redirect_back_or_to categories_path, notice: t(".success") }
format.turbo_stream { render turbo_stream: turbo_stream.action(:redirect, redirect_target_url) }
end
else
redirect_back_or_to transactions_path, alert: t(".failure", error: @category.errors.full_messages.to_sentence)
set_categories
render :new, status: :unprocessable_entity
end
end
@@ -27,9 +37,17 @@ class CategoriesController < ApplicationController
end
def update
@category.update! category_params
if @category.update(category_params)
flash[:notice] = t(".success")
redirect_back_or_to transactions_path, notice: t(".success")
redirect_target_url = request.referer || categories_path
respond_to do |format|
format.html { redirect_back_or_to categories_path, notice: t(".success") }
format.turbo_stream { render turbo_stream: turbo_stream.action(:redirect, redirect_target_url) }
end
else
render :edit, status: :unprocessable_entity
end
end
def destroy
@@ -38,11 +56,25 @@ class CategoriesController < ApplicationController
redirect_back_or_to categories_path, notice: t(".success")
end
def bootstrap
Current.family.categories.bootstrap_defaults
redirect_back_or_to categories_path, notice: t(".success")
end
private
def set_category
@category = Current.family.categories.find(params[:id])
end
def set_categories
@categories = unless @category.parent?
Current.family.categories.alphabetically.roots.where.not(id: @category.id)
else
[]
end
end
def set_transaction
if params[:transaction_id].present?
@transaction = Current.family.transactions.find(params[:transaction_id])
@@ -50,6 +82,6 @@ class CategoriesController < ApplicationController
end
def category_params
params.require(:category).permit(:name, :color)
params.require(:category).permit(:name, :color, :parent_id, :classification, :lucide_icon)
end
end

View File

@@ -1,6 +1,4 @@
class Category::DeletionsController < ApplicationController
layout :with_sidebar
before_action :set_category
before_action :set_replacement_category, only: :create

View File

@@ -0,0 +1,67 @@
class ChatsController < ApplicationController
include ActionView::RecordIdentifier
guard_feature unless: -> { Current.user.ai_enabled? }
before_action :set_chat, only: [ :show, :edit, :update, :destroy ]
def index
@chat = nil # override application_controller default behavior of setting @chat to last viewed chat
@chats = Current.user.chats.order(created_at: :desc)
end
def show
set_last_viewed_chat(@chat)
end
def new
@chat = Current.user.chats.new(title: "New chat #{Time.current.strftime("%Y-%m-%d %H:%M")}")
end
def create
@chat = Current.user.chats.start!(chat_params[:content], model: chat_params[:ai_model])
set_last_viewed_chat(@chat)
redirect_to chat_path(@chat, thinking: true)
end
def edit
end
def update
@chat.update!(chat_params)
respond_to do |format|
format.html { redirect_back_or_to chat_path(@chat), notice: "Chat updated" }
format.turbo_stream { render turbo_stream: turbo_stream.replace(dom_id(@chat, :title), partial: "chats/chat_title", locals: { chat: @chat }) }
end
end
def destroy
@chat.destroy
clear_last_viewed_chat
redirect_to chats_path, notice: "Chat was successfully deleted"
end
def retry
@chat.retry_last_message!
redirect_to chat_path(@chat, thinking: true)
end
private
def set_chat
@chat = Current.user.chats.find(params[:id])
end
def set_last_viewed_chat(chat)
Current.user.update!(last_viewed_chat: chat)
end
def clear_last_viewed_chat
Current.user.update!(last_viewed_chat: nil)
end
def chat_params
params.require(:chat).permit(:title, :content, :ai_model)
end
end

View File

@@ -2,8 +2,10 @@ module AccountableResource
extend ActiveSupport::Concern
included do
layout :with_sidebar
include ScrollFocusable, Periodable
before_action :set_account, only: [ :show, :edit, :update, :destroy ]
before_action :set_link_token, only: :new
end
class_methods do
@@ -16,12 +18,18 @@ module AccountableResource
def new
@account = Current.family.accounts.build(
currency: Current.family.currency,
accountable: accountable_type.new,
institution_id: params[:institution_id]
accountable: accountable_type.new
)
end
def show
@chart_view = params[:chart_view] || "balance"
@q = params.fetch(:q, {}).permit(:search)
entries = @account.entries.search(@q).reverse_chronological
set_focused_record(entries, params[:focused_record_id])
@pagy, @entries = pagy(entries, limit: params[:per_page] || "10", params: ->(params) { params.except(:focused_record_id) })
end
def edit
@@ -29,20 +37,50 @@ module AccountableResource
def create
@account = Current.family.accounts.create_and_sync(account_params.except(:return_to))
redirect_to account_params[:return_to].presence || @account, notice: t(".success")
redirect_to account_params[:return_to].presence || @account, notice: t("accounts.create.success", type: accountable_type.name.underscore.humanize)
end
def update
@account.update_with_sync!(account_params.except(:return_to))
redirect_back_or_to @account, notice: t(".success")
redirect_back_or_to @account, notice: t("accounts.update.success", type: accountable_type.name.underscore.humanize)
end
def destroy
@account.destroy!
redirect_to accounts_path, notice: t(".success")
@account.destroy_later
redirect_to accounts_path, notice: t("accounts.destroy.success", type: accountable_type.name.underscore.humanize)
end
private
def set_link_token
@us_link_token = Current.family.get_link_token(
webhooks_url: plaid_us_webhooks_url,
redirect_url: accounts_url,
accountable_type: accountable_type.name,
region: :us
)
if Current.family.eu?
@eu_link_token = Current.family.get_link_token(
webhooks_url: plaid_eu_webhooks_url,
redirect_url: accounts_url,
accountable_type: accountable_type.name,
region: :eu
)
end
end
def plaid_us_webhooks_url
return webhooks_plaid_url if Rails.env.production?
ENV.fetch("DEV_WEBHOOKS_URL", root_url.chomp("/")) + "/webhooks/plaid"
end
def plaid_eu_webhooks_url
return webhooks_plaid_eu_url if Rails.env.production?
ENV.fetch("DEV_WEBHOOKS_URL", root_url.chomp("/")) + "/webhooks/plaid_eu"
end
def accountable_type
controller_name.classify.constantize
end
@@ -53,7 +91,7 @@ module AccountableResource
def account_params
params.require(:account).permit(
:name, :is_active, :balance, :subtype, :currency, :institution_id, :accountable_type, :return_to,
:name, :is_active, :balance, :subtype, :currency, :accountable_type, :return_to,
accountable_attributes: self.class.permitted_accountable_attributes
)
end

View File

@@ -4,11 +4,13 @@ module Authentication
included do
before_action :set_request_details
before_action :authenticate_user!
before_action :set_sentry_user
end
class_methods do
def skip_authentication(**options)
skip_before_action :authenticate_user!, **options
skip_before_action :set_sentry_user, **options
end
end
@@ -26,7 +28,13 @@ module Authentication
end
def find_session_by_cookie
Session.find_by(id: cookies.signed[:session_token])
cookie_value = cookies.signed[:session_token]
if cookie_value.present?
Session.find_by(id: cookie_value)
else
nil
end
end
def create_session_for(user)
@@ -43,4 +51,17 @@ module Authentication
Current.user_agent = request.user_agent
Current.ip_address = request.ip
end
def set_sentry_user
return unless defined?(Sentry) && ENV["SENTRY_DSN"].present?
if Current.user
Sentry.set_user(
id: Current.user.id,
email: Current.user.email,
username: Current.user.display_name,
ip_address: Current.ip_address
)
end
end
end

View File

@@ -2,12 +2,19 @@ module AutoSync
extend ActiveSupport::Concern
included do
before_action :sync_family, if: -> { Current.family.present? && Current.family.needs_sync? }
before_action :sync_family, if: :family_needs_auto_sync?
end
private
def sync_family
Current.family.sync
Current.family.update!(last_synced_at: Time.current)
Current.family.sync_later
end
def family_needs_auto_sync?
return false unless Current.family.present?
return false unless Current.family.accounts.active.any?
(Current.family.last_synced_at&.to_date || 1.day.ago) < Date.current
end
end

View File

@@ -0,0 +1,13 @@
module Breadcrumbable
extend ActiveSupport::Concern
included do
before_action :set_breadcrumbs
end
private
# The default, unless specific controller or action explicitly overrides
def set_breadcrumbs
@breadcrumbs = [ [ "Home", root_path ], [ controller_name.titleize, nil ] ]
end
end

View File

@@ -0,0 +1,128 @@
module EntryableResource
extend ActiveSupport::Concern
included do
before_action :set_entry, only: %i[show update destroy]
end
class_methods do
def permitted_entryable_attributes(*attrs)
@permitted_entryable_attributes = attrs if attrs.any?
@permitted_entryable_attributes ||= [ :id ]
end
end
def show
end
def new
account = Current.family.accounts.find_by(id: params[:account_id])
@entry = Current.family.entries.new(
account: account,
currency: account ? account.currency : Current.family.currency,
entryable: entryable_type.new
)
end
def create
@entry = build_entry
if @entry.save
@entry.sync_account_later
flash[:notice] = t("account.entries.create.success")
respond_to do |format|
format.html { redirect_back_or_to account_path(@entry.account) }
redirect_target_url = request.referer || account_path(@entry.account)
format.turbo_stream { render turbo_stream: turbo_stream.action(:redirect, redirect_target_url) }
end
else
render :new, status: :unprocessable_entity
end
end
def update
if @entry.update(update_entry_params)
@entry.sync_account_later
respond_to do |format|
format.html { redirect_back_or_to account_path(@entry.account), notice: t("account.entries.update.success") }
format.turbo_stream do
render turbo_stream: [
turbo_stream.replace(
"header_account_entry_#{@entry.id}",
partial: "#{entryable_type.name.underscore.pluralize}/header",
locals: { entry: @entry }
),
turbo_stream.replace("account_entry_#{@entry.id}", partial: "account/entries/entry", locals: { entry: @entry })
]
end
end
else
render :show, status: :unprocessable_entity
end
end
def destroy
account = @entry.account
@entry.destroy!
@entry.sync_account_later
flash[:notice] = t("account.entries.destroy.success")
respond_to do |format|
format.html { redirect_back_or_to account_path(account) }
redirect_target_url = request.referer || account_path(@entry.account)
format.turbo_stream { render turbo_stream: turbo_stream.action(:redirect, redirect_target_url) }
end
end
private
def entryable_type
permitted_entryable_types = %w[Account::Transaction Account::Valuation Account::Trade]
klass = params[:entryable_type] || "Account::#{controller_name.classify}"
klass.constantize if permitted_entryable_types.include?(klass)
end
def set_entry
@entry = Current.family.entries.find(params[:id])
end
def build_entry
Current.family.entries.new(create_entry_params)
end
def update_entry_params
prepared_entry_params
end
def create_entry_params
prepared_entry_params.merge({
entryable_type: entryable_type.name,
entryable_attributes: entry_params[:entryable_attributes] || {}
})
end
def prepared_entry_params
default_params = entry_params.except(:nature)
default_params = default_params.merge(entryable_type: entryable_type.name) if entry_params[:entryable_attributes].present?
if entry_params[:nature].present? && entry_params[:amount].present?
signed_amount = entry_params[:nature] == "inflow" ? -entry_params[:amount].to_d : entry_params[:amount].to_d
default_params = default_params.merge(amount: signed_amount)
end
default_params
end
def entry_params
params.require(:account_entry).permit(
:account_id, :name, :enriched_name, :date, :amount, :currency, :excluded, :notes, :nature,
entryable_attributes: self.class.permitted_entryable_attributes
)
end
end

View File

@@ -0,0 +1,23 @@
# Simple feature guard that renders a 403 Forbidden status with a message
# when the feature is disabled.
#
# Example:
#
# class MessagesController < ApplicationController
# guard_feature unless: -> { Current.user.ai_enabled? }
# end
#
module FeatureGuardable
extend ActiveSupport::Concern
class_methods do
def guard_feature(**options)
before_action :guard_feature, **options
end
end
private
def guard_feature
render plain: "Feature disabled: #{controller_name}##{action_name}", status: :forbidden
end
end

View File

@@ -3,6 +3,7 @@ module Localize
included do
around_action :switch_locale
around_action :switch_timezone
end
private
@@ -10,4 +11,9 @@ module Localize
locale = Current.family.try(:locale) || I18n.default_locale
I18n.with_locale(locale, &action)
end
def switch_timezone(&action)
timezone = Current.family.try(:timezone) || Time.zone
Time.use_zone(timezone, &action)
end
end

View File

@@ -0,0 +1,14 @@
module Periodable
extend ActiveSupport::Concern
included do
before_action :set_period
end
private
def set_period
@period = Period.from_key(params[:period] || Current.user&.default_period)
rescue Period::InvalidKeyError
@period = Period.last_30_days
end
end

View File

@@ -0,0 +1,21 @@
module ScrollFocusable
extend ActiveSupport::Concern
def set_focused_record(record_scope, record_id, default_per_page: 10)
return unless record_id.present?
@focused_record = record_scope.find_by(id: record_id)
record_index = record_scope.pluck(:id).index(record_id)
return unless record_index
page_of_focused_record = (record_index / (params[:per_page]&.to_i || default_per_page)) + 1
if params[:page]&.to_i != page_of_focused_record
(
redirect_to(url_for(page: page_of_focused_record, focused_record_id: record_id))
)
end
end
end

View File

@@ -5,6 +5,8 @@ module StoreLocation
helper_method :previous_path
before_action :store_return_to
after_action :clear_previous_path
rescue_from ActiveRecord::RecordNotFound, with: :handle_not_found
end
def previous_path
@@ -12,6 +14,14 @@ module StoreLocation
end
private
def handle_not_found
if request.fullpath == session[:return_to]
session.delete(:return_to)
redirect_to fallback_path
else
head :not_found
end
end
def store_return_to
if params[:return_to].present?

View File

@@ -0,0 +1,18 @@
class EmailConfirmationsController < ApplicationController
skip_before_action :set_request_details, only: :new
skip_authentication only: :new
def new
# Returns nil if the token is invalid OR expired
@user = User.find_by_token_for(:email_confirmation, params[:token])
if @user&.unconfirmed_email && @user&.update(
email: @user.unconfirmed_email,
unconfirmed_email: nil
)
redirect_to new_session_path, notice: t(".success_login")
else
redirect_to root_path, alert: t(".invalid_token")
end
end
end

View File

@@ -1,11 +0,0 @@
class Help::ArticlesController < ApplicationController
layout :with_sidebar
def show
@article = Help::Article.find(params[:id])
unless @article
head :not_found
end
end
end

View File

@@ -29,11 +29,13 @@ class Import::ConfigurationsController < ApplicationController
:account_col_label,
:qty_col_label,
:ticker_col_label,
:exchange_operating_mic_col_label,
:price_col_label,
:entity_type_col_label,
:notes_col_label,
:currency_col_label,
:date_format,
:number_format,
:signage_convention
)
end

View File

@@ -4,6 +4,10 @@ class Import::ConfirmsController < ApplicationController
before_action :set_import
def show
if @import.mapping_steps.empty?
return redirect_to import_path(@import)
end
redirect_to import_clean_path(@import), alert: "You have invalid data, please edit until all errors are resolved" unless @import.cleaned?
end

View File

@@ -2,9 +2,7 @@ class Import::RowsController < ApplicationController
before_action :set_import_row
def update
@row.assign_attributes(row_params)
@row.save!(validate: false)
@row.sync_mappings
@row.update_and_sync(row_params)
redirect_to import_row_path(@row.import, @row)
end

View File

@@ -8,10 +8,11 @@ class Import::UploadsController < ApplicationController
def update
if csv_valid?(csv_str)
@import.account = Current.family.accounts.find_by(id: params.dig(:import, :account_id))
@import.assign_attributes(raw_file_str: csv_str, col_sep: upload_params[:col_sep])
@import.save!(validate: false)
redirect_to import_configuration_path(@import), notice: "CSV uploaded successfully."
redirect_to import_configuration_path(@import, template_hint: true), notice: "CSV uploaded successfully."
else
flash.now[:alert] = "Must be valid CSV with headers and at least one row of data"
@@ -29,10 +30,8 @@ class Import::UploadsController < ApplicationController
end
def csv_valid?(str)
require "csv"
begin
csv = CSV.parse(str || "", headers: true)
csv = Import.parse_csv_str(str, col_sep: upload_params[:col_sep])
return false if csv.headers.empty?
return false if csv.count == 0
true

View File

@@ -1,5 +1,5 @@
class ImportsController < ApplicationController
before_action :set_import, only: %i[show publish destroy]
before_action :set_import, only: %i[show publish destroy revert apply_template]
def publish
@import.publish_later
@@ -10,7 +10,7 @@ class ImportsController < ApplicationController
def index
@imports = Current.family.imports
render layout: with_sidebar
render layout: "settings"
end
def new
@@ -18,7 +18,12 @@ class ImportsController < ApplicationController
end
def create
import = Current.family.imports.create! import_params
account = Current.family.accounts.find_by(id: params.dig(:import, :account_id))
import = Current.family.imports.create!(
type: import_params[:type],
account: account,
date_format: Current.family.date_format,
)
redirect_to import_upload_path(import)
end
@@ -31,6 +36,20 @@ class ImportsController < ApplicationController
end
end
def revert
@import.revert_later
redirect_to imports_path, notice: "Import is reverting in the background."
end
def apply_template
if @import.suggested_template
@import.apply_template!(@import.suggested_template)
redirect_to import_configuration_path(@import), notice: "Template applied."
else
redirect_to import_configuration_path(@import), alert: "No template found, please manually configure your import."
end
end
def destroy
@import.destroy

View File

@@ -1,40 +0,0 @@
class InstitutionsController < ApplicationController
before_action :set_institution, except: %i[new create]
def new
@institution = Institution.new
end
def create
Current.family.institutions.create!(institution_params)
redirect_to accounts_path, notice: t(".success")
end
def edit
end
def update
@institution.update!(institution_params)
redirect_to accounts_path, notice: t(".success")
end
def destroy
@institution.destroy!
redirect_to accounts_path, notice: t(".success")
end
def sync
@institution.sync
redirect_back_or_to accounts_path, notice: t(".success")
end
private
def institution_params
params.require(:institution).permit(:name, :logo)
end
def set_institution
@institution = Current.family.institutions.find(params[:id])
end
end

View File

@@ -34,6 +34,24 @@ class InvitationsController < ApplicationController
end
end
def destroy
unless Current.user.admin?
flash[:alert] = t("invitations.destroy.not_authorized")
redirect_to settings_profile_path
return
end
@invitation = Current.family.invitations.find(params[:id])
if @invitation.destroy
flash[:notice] = t("invitations.destroy.success")
else
flash[:alert] = t("invitations.destroy.failure")
end
redirect_to settings_profile_path
end
private
def invitation_params

View File

@@ -6,6 +6,7 @@ class InviteCodesController < ApplicationController
end
def create
raise StandardError, "You are not allowed to generate invite codes" unless Current.user.admin?
InviteCode.generate!
redirect_back_or_to invite_codes_path, notice: "Code generated"
end

View File

@@ -1,20 +0,0 @@
class Issue::ExchangeRateProviderMissingsController < ApplicationController
before_action :set_issue, only: :update
def update
Setting.synth_api_key = exchange_rate_params[:synth_api_key]
account = @issue.issuable
account.sync_later
redirect_back_or_to account
end
private
def set_issue
@issue = Current.family.issues.find(params[:id])
end
def exchange_rate_params
params.require(:issue_exchange_rate_provider_missing).permit(:synth_api_key)
end
end

View File

@@ -1,13 +0,0 @@
class IssuesController < ApplicationController
before_action :set_issue, only: :show
def show
render template: "#{@issue.class.name.underscore.pluralize}/show", layout: "issues"
end
private
def set_issue
@issue = Current.family.issues.find(params[:id])
end
end

View File

@@ -1,10 +1,10 @@
class MerchantsController < ApplicationController
layout :with_sidebar
before_action :set_merchant, only: %i[edit update destroy]
def index
@merchants = Current.family.merchants.alphabetically
render layout: "settings"
end
def new

View File

@@ -0,0 +1,24 @@
class MessagesController < ApplicationController
guard_feature unless: -> { Current.user.ai_enabled? }
before_action :set_chat
def create
@message = UserMessage.create!(
chat: @chat,
content: message_params[:content],
ai_model: message_params[:ai_model]
)
redirect_to chat_path(@chat, thinking: true)
end
private
def set_chat
@chat = Current.user.chats.find(params[:chat_id])
end
def message_params
params.require(:message).permit(:content, :ai_model)
end
end

View File

@@ -0,0 +1,56 @@
class MfaController < ApplicationController
layout :determine_layout
skip_authentication only: [ :verify, :verify_code ]
def new
redirect_to root_path if Current.user.otp_required?
Current.user.setup_mfa! unless Current.user.otp_secret.present?
end
def create
if Current.user.verify_otp?(params[:code])
Current.user.enable_mfa!
@backup_codes = Current.user.otp_backup_codes
render :backup_codes
else
Current.user.disable_mfa!
redirect_to new_mfa_path, alert: t(".invalid_code")
end
end
def verify
@user = User.find_by(id: session[:mfa_user_id])
if @user.nil?
redirect_to new_session_path
end
end
def verify_code
@user = User.find_by(id: session[:mfa_user_id])
if @user&.verify_otp?(params[:code])
session.delete(:mfa_user_id)
@session = create_session_for(@user)
redirect_to root_path
else
flash.now[:alert] = t(".invalid_code")
render :verify, status: :unprocessable_entity
end
end
def disable
Current.user.disable_mfa!
redirect_to settings_security_path, notice: t(".success")
end
private
def determine_layout
if action_name.in?(%w[verify verify_code])
"auth"
else
"settings"
end
end
end

View File

@@ -1,5 +1,4 @@
class OnboardingsController < ApplicationController
layout "application"
before_action :set_user
before_action :load_invitation

View File

@@ -1,40 +1,22 @@
class PagesController < ApplicationController
skip_before_action :authenticate_user!, only: %i[early_access]
layout :with_sidebar, except: %i[early_access]
include Periodable
def dashboard
@period = Period.from_param(params[:period])
snapshot = Current.family.snapshot(@period)
@net_worth_series = snapshot[:net_worth_series]
@asset_series = snapshot[:asset_series]
@liability_series = snapshot[:liability_series]
@balance_sheet = Current.family.balance_sheet
@accounts = Current.family.accounts.active.with_attached_logo
snapshot_transactions = Current.family.snapshot_transactions
@income_series = snapshot_transactions[:income_series]
@spending_series = snapshot_transactions[:spending_series]
@savings_rate_series = snapshot_transactions[:savings_rate_series]
snapshot_account_transactions = Current.family.snapshot_account_transactions
@top_spenders = snapshot_account_transactions[:top_spenders]
@top_earners = snapshot_account_transactions[:top_earners]
@top_savers = snapshot_account_transactions[:top_savers]
@accounts = Current.family.accounts.active
@account_groups = @accounts.by_group(period: @period, currency: Current.family.currency)
@transaction_entries = Current.family.entries.account_transactions.limit(6).reverse_chronological
# TODO: Placeholders for trendlines
placeholder_series_data = 10.times.map do |i|
{ date: Date.current - i.days, value: Money.new(0, Current.family.currency) }
end
@investing_series = TimeSeries.new(placeholder_series_data)
@breadcrumbs = [ [ "Home", root_path ], [ "Dashboard", nil ] ]
end
def changelog
@release_notes = Provider::Github.new.fetch_latest_release_notes
@release_notes = github_provider.fetch_latest_release_notes
render layout: "settings"
end
def feedback
render layout: "settings"
end
def early_access
@@ -44,4 +26,9 @@ class PagesController < ApplicationController
@invite_code = InviteCode.order("RANDOM()").limit(1).first
render layout: false
end
private
def github_provider
Provider::Registry.get_provider(:github)
end
end

View File

@@ -0,0 +1,42 @@
class PlaidItemsController < ApplicationController
before_action :set_plaid_item, only: %i[destroy sync]
def create
Current.family.plaid_items.create_from_public_token(
plaid_item_params[:public_token],
item_name: item_name,
region: plaid_item_params[:region]
)
redirect_to accounts_path, notice: t(".success")
end
def destroy
@plaid_item.destroy_later
redirect_to accounts_path, notice: t(".success")
end
def sync
unless @plaid_item.syncing?
@plaid_item.sync_later
end
respond_to do |format|
format.html { redirect_back_or_to accounts_path }
format.json { head :ok }
end
end
private
def set_plaid_item
@plaid_item = Current.family.plaid_items.find(params[:id])
end
def plaid_item_params
params.require(:plaid_item).permit(:public_token, :region, metadata: {})
end
def item_name
plaid_item_params.dig(:metadata, :institution, :name)
end
end

View File

@@ -11,8 +11,7 @@ class PropertiesController < ApplicationController
currency: Current.family.currency,
accountable: Property.new(
address: Address.new
),
institution_id: params[:institution_id]
)
)
end

View File

@@ -24,11 +24,10 @@ class RegistrationsController < ApplicationController
if @user.save
@invitation&.update!(accepted_at: Time.current)
Category.create_default_categories(@user.family) unless @invitation
@session = create_session_for(@user)
redirect_to root_path, notice: t(".success")
else
render :new, status: :unprocessable_entity
render :new, status: :unprocessable_entity, alert: t(".failure")
end
end

Some files were not shown because too many files have changed in this diff Show More