diff --git a/.env.example b/.env.example index 2622021b..fd3e93c4 100644 --- a/.env.example +++ b/.env.example @@ -1,3 +1,12 @@ +# ================================ 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. +# +# If you are developing locally, you should be referencing `.env.local.example` instead. +# ======================================================================================= + # 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 diff --git a/.env.local.example b/.env.local.example new file mode 100644 index 00000000..d393f623 --- /dev/null +++ b/.env.local.example @@ -0,0 +1,5 @@ +# To enable / disable self-hosting features. +SELF_HOSTED=false + +# Enable Synth market data (careful, this will use your API credits) +SYNTH_API_KEY=yourapikeyhere diff --git a/.env.test b/.env.test new file mode 100644 index 00000000..f47801f1 --- /dev/null +++ b/.env.test @@ -0,0 +1,8 @@ +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 \ No newline at end of file diff --git a/.gitignore b/.gitignore index 3e1cbccd..dc09d53e 100644 --- a/.gitignore +++ b/.gitignore @@ -10,8 +10,8 @@ # Ignore all environment files (except templates). /.env* !/.env*.erb -!.env.example -!.env.test.example +!.env.test +!.env*.example # Ignore all logfiles and tempfiles. /log/* diff --git a/README.md b/README.md index d6dd1082..0372c4bd 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ After cloning the repo, the basic setup commands are: ```sh cd maybe -cp .env.example .env +cp .env.local.example .env.local bin/setup bin/dev diff --git a/app/assets/images/maybe-plus-background.png b/app/assets/images/maybe-plus-background.png new file mode 100644 index 00000000..29d626d1 Binary files /dev/null and b/app/assets/images/maybe-plus-background.png differ diff --git a/app/assets/images/maybe-plus-logo.png b/app/assets/images/maybe-plus-logo.png new file mode 100644 index 00000000..3cede186 Binary files /dev/null and b/app/assets/images/maybe-plus-logo.png differ diff --git a/app/assets/images/stripe-logo.svg b/app/assets/images/stripe-logo.svg new file mode 100644 index 00000000..d95ded83 --- /dev/null +++ b/app/assets/images/stripe-logo.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 8fd5c552..e9788920 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -2,7 +2,22 @@ class ApplicationController < ActionController::Base include Onboardable, Localize, AutoSync, Authentication, Invitable, SelfHostable, StoreLocation, Impersonatable include Pagy::Backend + helper_method :require_upgrade?, :subscription_pending? + 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 + + true + end + + def subscription_pending? + subscribed_at = Current.session.subscribed_at + subscribed_at.present? && subscribed_at <= Time.current && subscribed_at > 1.hour.ago + end def with_sidebar return "turbo_rails/frame" if turbo_frame_request? diff --git a/app/controllers/categories_controller.rb b/app/controllers/categories_controller.rb index 443770fe..ddc1ecaa 100644 --- a/app/controllers/categories_controller.rb +++ b/app/controllers/categories_controller.rb @@ -1,7 +1,7 @@ class CategoriesController < ApplicationController layout :with_sidebar - before_action :set_category, only: %i[edit update] + before_action :set_category, only: %i[edit update destroy] before_action :set_transaction, only: :create def index @@ -13,12 +13,14 @@ class CategoriesController < ApplicationController end def create - Category.transaction do - category = Current.family.categories.create!(category_params) - @transaction.update!(category_id: category.id) if @transaction - end + @category = Current.family.categories.new(category_params) - redirect_back_or_to transactions_path, notice: t(".success") + if @category.save + @transaction.update(category_id: @category.id) if @transaction + redirect_back_or_to transactions_path, notice: t(".success") + else + redirect_back_or_to transactions_path, alert: t(".failure", error: @category.errors.full_messages.to_sentence) + end end def edit @@ -30,6 +32,12 @@ class CategoriesController < ApplicationController redirect_back_or_to transactions_path, notice: t(".success") end + def destroy + @category.destroy + + redirect_back_or_to categories_path, notice: t(".success") + end + private def set_category @category = Current.family.categories.find(params[:id]) diff --git a/app/controllers/merchants_controller.rb b/app/controllers/merchants_controller.rb index 33fe156c..252c5de6 100644 --- a/app/controllers/merchants_controller.rb +++ b/app/controllers/merchants_controller.rb @@ -12,8 +12,13 @@ class MerchantsController < ApplicationController end def create - Current.family.merchants.create!(merchant_params) - redirect_to merchants_path, notice: t(".success") + @merchant = Current.family.merchants.new(merchant_params) + + if @merchant.save + redirect_to merchants_path, notice: t(".success") + else + redirect_to merchants_path, alert: t(".error", error: @merchant.errors.full_messages.to_sentence) + end end def edit diff --git a/app/controllers/subscriptions_controller.rb b/app/controllers/subscriptions_controller.rb index ef634b83..e2c19535 100644 --- a/app/controllers/subscriptions_controller.rb +++ b/app/controllers/subscriptions_controller.rb @@ -1,16 +1,14 @@ class SubscriptionsController < ApplicationController def new - client = Stripe::StripeClient.new(ENV["STRIPE_SECRET_KEY"]) - if Current.family.stripe_customer_id.blank? - customer = client.v1.customers.create( + customer = stripe_client.v1.customers.create( email: Current.family.primary_user.email, metadata: { family_id: Current.family.id } ) Current.family.update(stripe_customer_id: customer.id) end - session = client.v1.checkout.sessions.create({ + session = stripe_client.v1.checkout.sessions.create({ customer: Current.family.stripe_customer_id, line_items: [ { price: ENV["STRIPE_PLAN_ID"], @@ -18,7 +16,7 @@ class SubscriptionsController < ApplicationController } ], mode: "subscription", allow_promotion_codes: true, - success_url: settings_billing_url, + success_url: success_subscription_url + "?session_id={CHECKOUT_SESSION_ID}", cancel_url: settings_billing_url }) @@ -26,12 +24,24 @@ class SubscriptionsController < ApplicationController end def show - client = Stripe::StripeClient.new(ENV["STRIPE_SECRET_KEY"]) - - portal_session = client.v1.billing_portal.sessions.create( + portal_session = stripe_client.v1.billing_portal.sessions.create( customer: Current.family.stripe_customer_id, return_url: settings_billing_url ) + redirect_to portal_session.url, allow_other_host: true, status: :see_other end + + def success + checkout_session = stripe_client.v1.checkout.sessions.retrieve(params[:session_id]) + Current.session.update(subscribed_at: Time.at(checkout_session.created)) + redirect_to root_path, notice: "You have successfully subscribed to Maybe+." + rescue Stripe::InvalidRequestError + redirect_to settings_billing_path, alert: "Something went wrong processing your subscription. Please contact us to get this fixed." + end + + private + def stripe_client + @stripe_client ||= Stripe::StripeClient.new(ENV["STRIPE_SECRET_KEY"]) + end end diff --git a/app/controllers/tags_controller.rb b/app/controllers/tags_controller.rb index c2feb537..2b81e7cd 100644 --- a/app/controllers/tags_controller.rb +++ b/app/controllers/tags_controller.rb @@ -1,7 +1,7 @@ class TagsController < ApplicationController layout :with_sidebar - before_action :set_tag, only: %i[edit update] + before_action :set_tag, only: %i[edit update destroy] def index @tags = Current.family.tags.alphabetically @@ -12,8 +12,13 @@ class TagsController < ApplicationController end def create - Current.family.tags.create!(tag_params) - redirect_to tags_path, notice: t(".created") + @tag = Current.family.tags.new(tag_params) + + if @tag.save + redirect_to tags_path, notice: t(".created") + else + redirect_to tags_path, alert: t(".error", error: @tag.errors.full_messages.to_sentence) + end end def edit @@ -24,6 +29,11 @@ class TagsController < ApplicationController redirect_to tags_path, notice: t(".updated") end + def destroy + @tag.destroy! + redirect_to tags_path, notice: t(".deleted") + end + private def set_tag diff --git a/app/helpers/settings_helper.rb b/app/helpers/settings_helper.rb index f127905d..4f4e0272 100644 --- a/app/helpers/settings_helper.rb +++ b/app/helpers/settings_helper.rb @@ -5,10 +5,10 @@ module SettingsHelper { name: I18n.t("settings.nav.self_hosting_label"), path: :settings_hosting_path, condition: :self_hosted? }, { name: I18n.t("settings.nav.billing_label"), path: :settings_billing_path }, { name: I18n.t("settings.nav.accounts_label"), path: :accounts_path }, + { name: I18n.t("settings.nav.imports_label"), path: :imports_path }, { name: I18n.t("settings.nav.tags_label"), path: :tags_path }, { name: I18n.t("settings.nav.categories_label"), path: :categories_path }, { name: I18n.t("settings.nav.merchants_label"), path: :merchants_path }, - { name: I18n.t("settings.nav.imports_label"), path: :imports_path }, { name: I18n.t("settings.nav.whats_new_label"), path: :changelog_path }, { name: I18n.t("settings.nav.feedback_label"), path: :feedback_path } ] diff --git a/app/helpers/styled_form_builder.rb b/app/helpers/styled_form_builder.rb index f9e060af..c7e27b0a 100644 --- a/app/helpers/styled_form_builder.rb +++ b/app/helpers/styled_form_builder.rb @@ -49,7 +49,12 @@ class StyledFormBuilder < ActionView::Helpers::FormBuilder end def submit(value = nil, options = {}) - merged_options = { class: "btn btn--primary w-full" }.merge(options) + default_options = { + data: { turbo_submits_with: "Submitting..." }, + class: "btn btn--primary w-full" + } + + merged_options = default_options.merge(options) value, options = nil, value if value.is_a?(Hash) super(value, merged_options) end diff --git a/app/models/account_import.rb b/app/models/account_import.rb index 3987a1ff..98e7e0d0 100644 --- a/app/models/account_import.rb +++ b/app/models/account_import.rb @@ -14,6 +14,14 @@ class AccountImport < Import ) account.save! + + account.entries.create!( + amount: row.amount, + currency: row.currency, + date: Date.current, + name: "Imported account value", + entryable: Account::Valuation.new + ) end end end diff --git a/app/models/category.rb b/app/models/category.rb index 3744295a..4a2d6361 100644 --- a/app/models/category.rb +++ b/app/models/category.rb @@ -4,6 +4,7 @@ class Category < ApplicationRecord belongs_to :family validates :name, :color, :family, presence: true + validates :name, uniqueness: { scope: :family_id } before_update :clear_internal_category, if: :name_changed? diff --git a/app/models/demo/generator.rb b/app/models/demo/generator.rb index 20e5c01c..ba210b2b 100644 --- a/app/models/demo/generator.rb +++ b/app/models/demo/generator.rb @@ -71,7 +71,8 @@ class Demo::Generator first_name: "Demo", last_name: "User", role: "admin", - password: "password" + password: "password", + onboarded_at: Time.current end def create_tags! diff --git a/app/models/family.rb b/app/models/family.rb index c4949a4d..ddfdab3e 100644 --- a/app/models/family.rb +++ b/app/models/family.rb @@ -132,7 +132,7 @@ class Family < ApplicationRecord end def subscribed? - stripe_subscription_status.present? && stripe_subscription_status == "active" + stripe_subscription_status == "active" end def primary_user diff --git a/app/models/merchant.rb b/app/models/merchant.rb index 3d1448e2..e363f6aa 100644 --- a/app/models/merchant.rb +++ b/app/models/merchant.rb @@ -3,6 +3,7 @@ class Merchant < ApplicationRecord belongs_to :family validates :name, :color, :family, presence: true + validates :name, uniqueness: { scope: :family } scope :alphabetically, -> { order(:name) } diff --git a/app/views/categories/_category.html.erb b/app/views/categories/_category.html.erb index f25e5c25..97f19775 100644 --- a/app/views/categories/_category.html.erb +++ b/app/views/categories/_category.html.erb @@ -9,11 +9,15 @@
<%= contextual_menu_modal_action_item t(".edit"), edit_category_path(category) %> - <%= link_to new_category_deletion_path(category), + <% if category.transactions.any? %> + <%= link_to new_category_deletion_path(category), class: "flex items-center w-full rounded-lg text-red-600 hover:bg-red-50 py-2 px-3 gap-2", data: { turbo_frame: :modal } do %> - <%= lucide_icon "trash-2", class: "shrink-0 w-5 h-5" %> - <%= t(".delete") %> + <%= lucide_icon "trash-2", class: "shrink-0 w-5 h-5" %> + <%= t(".delete") %> + <% end %> + <% else %> + <%= contextual_menu_destructive_item t(".delete"), category_path(category), turbo_confirm: nil %> <% end %>
<% end %> diff --git a/app/views/categories/_form.html.erb b/app/views/categories/_form.html.erb index 5f36f8d9..313e48ba 100644 --- a/app/views/categories/_form.html.erb +++ b/app/views/categories/_form.html.erb @@ -1,5 +1,5 @@
- <%= styled_form_with model: category, class: "space-y-4", data: { turbo: false } do |f| %> + <%= styled_form_with model: category, class: "space-y-4", data: { turbo_frame: :_top } do |f| %>
<%= render partial: "shared/color_avatar", locals: { name: category.name, color: category.color } %> @@ -13,7 +13,7 @@ <% end %>
- <%= f.text_field :name, placeholder: t(".placeholder"), class: "text-sm font-normal placeholder:text-gray-500 h-10 relative pl-3 w-full border-none rounded-lg", required: true, data: { color_avatar_target: "name" } %> + <%= f.text_field :name, placeholder: t(".placeholder"), required: true, autofocus: true, data: { color_avatar_target: "name" } %>
diff --git a/app/views/layouts/with_sidebar.html.erb b/app/views/layouts/with_sidebar.html.erb index ca824d45..6551526b 100644 --- a/app/views/layouts/with_sidebar.html.erb +++ b/app/views/layouts/with_sidebar.html.erb @@ -7,7 +7,12 @@ <%= render "layouts/sidebar" %> <% end %>
-
+ +
"> + <% if require_upgrade? %> + <%= render "shared/subscribe_modal" %> + <% end %> + <%= yield %>
diff --git a/app/views/merchants/_form.html.erb b/app/views/merchants/_form.html.erb index 4b748f67..93efecb9 100644 --- a/app/views/merchants/_form.html.erb +++ b/app/views/merchants/_form.html.erb @@ -1,5 +1,5 @@
- <%= styled_form_with model: @merchant, class: "space-y-4", data: { turbo: false } do |f| %> + <%= styled_form_with model: @merchant, class: "space-y-4", data: { turbo_frame: :_top } do |f| %>
<%= render partial: "shared/color_avatar", locals: { name: @merchant.name, color: @merchant.color } %> @@ -13,7 +13,7 @@ <% end %>
- <%= f.text_field :name, placeholder: t(".name_placeholder"), class: "text-sm font-normal placeholder:text-gray-500 h-10 relative pl-3 w-full border-none rounded-lg", required: true, data: { color_avatar_target: "name" } %> + <%= f.text_field :name, placeholder: t(".name_placeholder"), autofocus: true, required: true, data: { color_avatar_target: "name" } %>
diff --git a/app/views/merchants/_merchant.html.erb b/app/views/merchants/_merchant.html.erb index 33fba7ee..2b964140 100644 --- a/app/views/merchants/_merchant.html.erb +++ b/app/views/merchants/_merchant.html.erb @@ -15,11 +15,11 @@ <%= contextual_menu_destructive_item t(".delete"), merchant_path(merchant), turbo_frame: "_top", - turbo_confirm: { + turbo_confirm: merchant.transactions.any? ? { title: t(".confirm_title"), body: t(".confirm_body"), accept: t(".confirm_accept") - } %> + } : nil %>
<% end %> diff --git a/app/views/onboardings/preferences.html.erb b/app/views/onboardings/preferences.html.erb index 84712a3e..26b0ac1f 100644 --- a/app/views/onboardings/preferences.html.erb +++ b/app/views/onboardings/preferences.html.erb @@ -8,8 +8,8 @@

<%= t(".subtitle") %>

-
-
+
+
<%= tag.p t(".example"), class: "text-gray-500 text-sm" %> <%= tag.p "$2,323.25", class: "text-gray-900 font-medium text-2xl" %> diff --git a/app/views/pages/dashboard.html.erb b/app/views/pages/dashboard.html.erb index b25e8497..f3846a4a 100644 --- a/app/views/pages/dashboard.html.erb +++ b/app/views/pages/dashboard.html.erb @@ -24,9 +24,7 @@
- <% if !Current.family.subscribed? && !self_hosted? %> - <%= render "shared/subscribe_prompt" %> - <% elsif @accounts.empty? %> + <% if @accounts.empty? %> <%= render "shared/no_account_empty_state" %> <% else %>
diff --git a/app/views/settings/billings/show.html.erb b/app/views/settings/billings/show.html.erb index c3ed66bc..45b9c702 100644 --- a/app/views/settings/billings/show.html.erb +++ b/app/views/settings/billings/show.html.erb @@ -5,11 +5,42 @@

<%= t(".page_title") %>

<%= settings_section title: t(".subscription_title"), subtitle: t(".subscription_subtitle") do %> - <% if @user.family.stripe_plan_id.blank? %> - <%= link_to t(".subscribe_button"), new_subscription_path, class: "w-fit flex text-white text-sm font-medium items-center gap-1 bg-gray-900 rounded-lg p-2", data: { turbo: false } %> - <% else %> - <%= link_to t(".manage_subscription_button"), subscription_path, class: "w-fit flex text-white text-sm font-medium items-center gap-1 bg-gray-900 rounded-lg p-2", data: { turbo: false } %> - <% end %> +
+
+
+
+ <%= lucide_icon "gem", class: "w-5 h-5 text-gray-500" %> +
+ +
+ <% if @user.family.subscribed? || subscription_pending? %> +

You are currently subscribed to Maybe+

+

Manage your billing settings here.

+ <% else %> +

You are currently not subscribed

+

Once you subscribe to Maybe+, you’ll see your billing settings here.

+ <% end %> +
+
+ + <% if @user.family.subscribed? || subscription_pending? %> + <%= link_to subscription_path, class: "btn btn--secondary flex items-center gap-1" do %> + Manage + <%= lucide_icon "external-link", class: "w-5 h-5 shrink-0 text-gray-500" %> + <% end %> + <% else %> + <%= link_to new_subscription_path, class: "btn btn--secondary flex items-center gap-1" do %> + Subscribe + <%= lucide_icon "external-link", class: "w-5 h-5 shrink-0 text-gray-500" %> + <% end %> + <% end %> +
+ +
+ <%= image_tag "stripe-logo.svg", class: "w-5 h-5 shrink-0" %> +

Managed via Stripe

+
+
<% end %> <%= settings_nav_footer %> diff --git a/app/views/shared/_subscribe_modal.html.erb b/app/views/shared/_subscribe_modal.html.erb new file mode 100644 index 00000000..463c195a --- /dev/null +++ b/app/views/shared/_subscribe_modal.html.erb @@ -0,0 +1,25 @@ + diff --git a/app/views/shared/_subscribe_prompt.html.erb b/app/views/shared/_subscribe_prompt.html.erb deleted file mode 100644 index 35315af4..00000000 --- a/app/views/shared/_subscribe_prompt.html.erb +++ /dev/null @@ -1,16 +0,0 @@ -
-
- <%= lucide_icon "circle-fading-arrow-up", class: "w-8 h-8 text-green-500" %> - -
-

<%= t(".title") %>

-

<%= t(".subtitle") %>

-

<%= t(".guarantee") %>

-
- - <%= link_to new_subscription_path, class: "btn btn--primary flex items-center gap-1" do %> - <%= lucide_icon("credit-card", class: "w-5 h-5") %> - <%= t(".subscribe") %> - <% end %> -
-
diff --git a/app/views/tags/_form.html.erb b/app/views/tags/_form.html.erb index 99b1c706..395a1f03 100644 --- a/app/views/tags/_form.html.erb +++ b/app/views/tags/_form.html.erb @@ -1,5 +1,5 @@
- <%= styled_form_with model: tag, class: "space-y-4", data: { turbo: false } do |f| %> + <%= styled_form_with model: tag, class: "space-y-4", data: { turbo_frame: :_top } do |f| %>
<%= render partial: "shared/color_avatar", locals: { name: tag.name, color: tag.color } %> @@ -13,7 +13,7 @@ <% end %>
- <%= f.text_field :name, placeholder: t(".placeholder"), class: "text-sm font-normal placeholder:text-gray-500 h-10 relative pl-3 w-full border-none rounded-lg", required: true, data: { color_avatar_target: "name" } %> + <%= f.text_field :name, placeholder: t(".placeholder"), autofocus: true, required: true, data: { color_avatar_target: "name" } %>
diff --git a/app/views/tags/_tag.html.erb b/app/views/tags/_tag.html.erb index 5a65a341..ed325d74 100644 --- a/app/views/tags/_tag.html.erb +++ b/app/views/tags/_tag.html.erb @@ -12,11 +12,15 @@
<%= contextual_menu_modal_action_item t(".edit"), edit_tag_path(tag) %> - <%= link_to new_tag_deletion_path(tag), + <% if tag.transactions.any? %> + <%= link_to new_tag_deletion_path(tag), class: "block w-full py-2 px-3 space-x-2 text-red-600 hover:bg-red-50 flex items-center rounded-lg", data: { turbo_frame: :modal } do %> - <%= lucide_icon "trash-2", class: "w-5 h-5" %> - <%= t(".delete") %> + <%= lucide_icon "trash-2", class: "w-5 h-5" %> + <%= t(".delete") %> + <% end %> + <% else %> + <%= contextual_menu_destructive_item t(".delete"), tag_path(tag), turbo_confirm: nil %> <% end %>
<% end %> diff --git a/config/locales/views/categories/en.yml b/config/locales/views/categories/en.yml index 5ef738c0..6dd57a4c 100644 --- a/config/locales/views/categories/en.yml +++ b/config/locales/views/categories/en.yml @@ -5,7 +5,10 @@ en: delete: Delete category edit: Edit category create: + failure: 'Failed to create category: %{error}' success: New transaction category created successfully + destroy: + success: Category deleted successfully edit: edit: Edit category form: diff --git a/config/locales/views/merchants/en.yml b/config/locales/views/merchants/en.yml index b95aa729..3f31dd59 100644 --- a/config/locales/views/merchants/en.yml +++ b/config/locales/views/merchants/en.yml @@ -2,6 +2,7 @@ en: merchants: create: + error: 'Error creating merchant: %{error}' success: New merchant created successfully destroy: success: Merchant deleted successfully diff --git a/config/locales/views/settings/en.yml b/config/locales/views/settings/en.yml index 205be0f8..0e2fe635 100644 --- a/config/locales/views/settings/en.yml +++ b/config/locales/views/settings/en.yml @@ -3,9 +3,7 @@ en: settings: billings: show: - manage_subscription_button: Manage subscription page_title: Billing - subscribe_button: Subscribe subscription_subtitle: Manage your subscription and billing details subscription_title: Manage subscription nav: diff --git a/config/locales/views/shared/en.yml b/config/locales/views/shared/en.yml index 89ad83bc..80f4fc3d 100644 --- a/config/locales/views/shared/en.yml +++ b/config/locales/views/shared/en.yml @@ -13,12 +13,6 @@ en: no_account_subtitle: Since no accounts have been added, there's no data to display. Add your first accounts to start viewing dashboard data. no_account_title: No accounts yet - subscribe_prompt: - guarantee: We're reasonable people here. If you're not happy or something doesn't - work, we'll gladly refund you. - subscribe: Upgrade your account - subtitle: To continue using Maybe, please subscribe! - title: Upgrade upgrade_notification: app_upgraded: The app has been upgraded to %{version}. dismiss: Dismiss diff --git a/config/locales/views/tags/en.yml b/config/locales/views/tags/en.yml index 4a78e350..a1f2ba32 100644 --- a/config/locales/views/tags/en.yml +++ b/config/locales/views/tags/en.yml @@ -3,6 +3,9 @@ en: tags: create: created: Tag created + error: 'Error creating tag: %{error}' + destroy: + deleted: Tag deleted edit: edit: Edit tag form: diff --git a/config/routes.rb b/config/routes.rb index 94fcd02c..2d6fe452 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -26,9 +26,11 @@ Rails.application.routes.draw do resource :billing, only: :show end - resource :subscription, only: %i[new show] + resource :subscription, only: %i[new show] do + get :success, on: :collection + end - resources :tags, except: %i[show destroy] do + resources :tags, except: :show do resources :deletions, only: %i[new create], module: :tag end diff --git a/db/migrate/20241024142537_add_subscription_timestamp_to_session.rb b/db/migrate/20241024142537_add_subscription_timestamp_to_session.rb new file mode 100644 index 00000000..0f9677a2 --- /dev/null +++ b/db/migrate/20241024142537_add_subscription_timestamp_to_session.rb @@ -0,0 +1,5 @@ +class AddSubscriptionTimestampToSession < ActiveRecord::Migration[7.2] + def change + add_column :sessions, :subscribed_at, :datetime + end +end diff --git a/db/schema.rb b/db/schema.rb index d9fb2e48..7fe73452 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.2].define(version: 2024_10_22_221544) do +ActiveRecord::Schema[7.2].define(version: 2024_10_24_142537) do # These are extensions that must be enabled in order to support this database enable_extension "pgcrypto" enable_extension "plpgsql" @@ -496,6 +496,7 @@ ActiveRecord::Schema[7.2].define(version: 2024_10_22_221544) do t.datetime "created_at", null: false t.datetime "updated_at", null: false t.uuid "active_impersonator_session_id" + t.datetime "subscribed_at" t.index ["active_impersonator_session_id"], name: "index_sessions_on_active_impersonator_session_id" t.index ["user_id"], name: "index_sessions_on_user_id" end diff --git a/test/fixtures/families.yml b/test/fixtures/families.yml index c1b0831a..57697046 100644 --- a/test/fixtures/families.yml +++ b/test/fixtures/families.yml @@ -1,6 +1,8 @@ empty: name: Family + stripe_subscription_status: active dylan_family: name: The Dylan Family + stripe_subscription_status: active diff --git a/test/fixtures/files/imports/accounts.csv b/test/fixtures/files/imports/accounts.csv index fb3974f8..a24b1f81 100644 --- a/test/fixtures/files/imports/accounts.csv +++ b/test/fixtures/files/imports/accounts.csv @@ -1,5 +1,5 @@ type,name,amount,currency Checking,Main Checking Account,5000.00,USD Savings,Emergency Fund,10000.00,USD -Credit Card,Rewards Credit Card,-1500.00,USD +Credit Card,Rewards Credit Card,1500.00,USD Investment,Retirement Portfolio,75000.00,USD diff --git a/test/test_helper.rb b/test/test_helper.rb index b3bacfa8..6b386535 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -7,8 +7,6 @@ end require_relative "../config/environment" -ENV["SELF_HOSTED"] = "false" -ENV["UPGRADES_ENABLED"] = "false" ENV["RAILS_ENV"] ||= "test" # Fixes Segfaults on M1 Macs when running tests in parallel (temporary workaround)