diff --git a/app/controllers/rule/actions_controller.rb b/app/controllers/rule/actions_controller.rb new file mode 100644 index 00000000..bb461996 --- /dev/null +++ b/app/controllers/rule/actions_controller.rb @@ -0,0 +1,27 @@ +class Rule::ActionsController < ApplicationController + before_action :set_rule + before_action :set_action, only: [ :update, :destroy ] + + def create + end + + def update + end + + def destroy + end + + private + + def set_rule + @rule = Current.family.rules.find(params[:rule_id]) + end + + def set_action + @action = @rule.actions.find(params[:id]) + end + + def action_params + params.require(:action).permit(:action_type) + end +end diff --git a/app/controllers/rule/triggers_controller.rb b/app/controllers/rule/triggers_controller.rb new file mode 100644 index 00000000..9c32cdfe --- /dev/null +++ b/app/controllers/rule/triggers_controller.rb @@ -0,0 +1,27 @@ +class Rule::TriggersController < ApplicationController + before_action :set_rule + before_action :set_trigger, only: [ :update, :destroy ] + + def create + end + + def update + end + + def destroy + end + + private + + def set_rule + @rule = Current.family.rules.find(params[:rule_id]) + end + + def set_trigger + @trigger = @rule.triggers.find(params[:id]) + end + + def trigger_params + params.require(:trigger).permit(:trigger_type) + end +end diff --git a/app/controllers/rules_controller.b b/app/controllers/rules_controller.b new file mode 100644 index 00000000..e69de29b diff --git a/app/controllers/rules_controller.rb b/app/controllers/rules_controller.rb new file mode 100644 index 00000000..93b85962 --- /dev/null +++ b/app/controllers/rules_controller.rb @@ -0,0 +1,36 @@ +class RulesController < ApplicationController + before_action :set_rule, only: [ :show, :edit, :update, :destroy ] + + def index + @rules = Current.family.rules + render layout: "settings" + end + + def show + end + + def new + end + + def create + end + + def edit + end + + def update + end + + def destroy + end + + private + + def set_rule + @rule = Current.family.rules.find(params[:id]) + end + + def rule_params + params.require(:rule).permit(:effective_date, :active) + end +end diff --git a/app/helpers/settings_helper.rb b/app/helpers/settings_helper.rb index e15414a5..b7cfbcb6 100644 --- a/app/helpers/settings_helper.rb +++ b/app/helpers/settings_helper.rb @@ -9,6 +9,7 @@ module SettingsHelper { name: I18n.t("settings.settings_nav.imports_label"), path: :imports_path }, { name: I18n.t("settings.settings_nav.tags_label"), path: :tags_path }, { name: I18n.t("settings.settings_nav.categories_label"), path: :categories_path }, + { name: "Rules", path: :rules_path }, { name: I18n.t("settings.settings_nav.merchants_label"), path: :merchants_path }, { name: I18n.t("settings.settings_nav.whats_new_label"), path: :changelog_path }, { name: I18n.t("settings.settings_nav.feedback_label"), path: :feedback_path } diff --git a/app/models/rule.rb b/app/models/rule.rb new file mode 100644 index 00000000..47d4611e --- /dev/null +++ b/app/models/rule.rb @@ -0,0 +1,7 @@ +class Rule < ApplicationRecord + belongs_to :family + has_many :triggers, dependent: :destroy + has_many :actions, dependent: :destroy + + validates :effective_date, presence: true +end diff --git a/app/models/rule/action.rb b/app/models/rule/action.rb new file mode 100644 index 00000000..ec2b56fb --- /dev/null +++ b/app/models/rule/action.rb @@ -0,0 +1,5 @@ +class Rule::Action < ApplicationRecord + belongs_to :rule + + validates :action_type, presence: true +end diff --git a/app/models/rule/trigger.rb b/app/models/rule/trigger.rb new file mode 100644 index 00000000..4beae4d2 --- /dev/null +++ b/app/models/rule/trigger.rb @@ -0,0 +1,7 @@ +class Rule::Trigger < ApplicationRecord + self.table_name = "rule_triggers" + + belongs_to :rule + + validates :trigger_type, presence: true +end diff --git a/app/views/rules/_form.html.erb b/app/views/rules/_form.html.erb new file mode 100644 index 00000000..4ac65aae --- /dev/null +++ b/app/views/rules/_form.html.erb @@ -0,0 +1,2 @@ +

Placeholder: rules/_form partial

+ \ No newline at end of file diff --git a/app/views/rules/edit.html.erb b/app/views/rules/edit.html.erb new file mode 100644 index 00000000..df7abe4c --- /dev/null +++ b/app/views/rules/edit.html.erb @@ -0,0 +1,2 @@ +

Placeholder: rules#edit

+ \ No newline at end of file diff --git a/app/views/rules/index.html.erb b/app/views/rules/index.html.erb new file mode 100644 index 00000000..4d581fc4 --- /dev/null +++ b/app/views/rules/index.html.erb @@ -0,0 +1,3 @@ +<% content_for :page_title, "Rules" %> + +

Placeholder: rules#index

\ No newline at end of file diff --git a/app/views/rules/new.html.erb b/app/views/rules/new.html.erb new file mode 100644 index 00000000..a72fe5c4 --- /dev/null +++ b/app/views/rules/new.html.erb @@ -0,0 +1,2 @@ +

Placeholder: rules#new

+ \ No newline at end of file diff --git a/app/views/rules/show.html.erb b/app/views/rules/show.html.erb new file mode 100644 index 00000000..661b881f --- /dev/null +++ b/app/views/rules/show.html.erb @@ -0,0 +1,2 @@ +

Placeholder: rules#show

+ \ No newline at end of file diff --git a/app/views/settings/_settings_nav.html.erb b/app/views/settings/_settings_nav.html.erb index 632e774c..683a0b68 100644 --- a/app/views/settings/_settings_nav.html.erb +++ b/app/views/settings/_settings_nav.html.erb @@ -60,6 +60,9 @@
  • <%= render "settings/settings_nav_item", name: t(".categories_label"), path: categories_path, icon: "shapes" %>
  • +
  • + <%= render "settings/settings_nav_item", name: "Rules", path: rules_path, icon: "git-branch" %> +
  • <%= render "settings/settings_nav_item", name: t(".merchants_label"), path: merchants_path, icon: "store" %>
  • diff --git a/config/routes.rb b/config/routes.rb index e8e072ae..1f75c197 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -143,6 +143,11 @@ Rails.application.routes.draw do end end + resources :rules do + resources :triggers, only: %i[create update destroy] + resources :actions, only: %i[create update destroy] + end + # Convenience routes for polymorphic paths # Example: account_path(Account.new(accountable: Depository.new)) => /depositories/123 direct :account do |model, options| diff --git a/db/schema.rb b/db/schema.rb index aedba1e9..04be6dc3 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -468,31 +468,6 @@ ActiveRecord::Schema[7.2].define(version: 2025_03_19_212839) do t.index ["outflow_transaction_id"], name: "index_rejected_transfers_on_outflow_transaction_id" end - create_table "rule_actions", force: :cascade do |t| - t.uuid "rule_id", null: false - t.string "action_type", null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.index ["rule_id"], name: "index_rule_actions_on_rule_id" - end - - create_table "rule_triggers", force: :cascade do |t| - t.uuid "rule_id", null: false - t.string "trigger_type", null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.index ["rule_id"], name: "index_rule_triggers_on_rule_id" - end - - create_table "rules", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| - t.uuid "family_id", null: false - t.date "effective_date", null: false - t.boolean "active", default: true, null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.index ["family_id"], name: "index_rules_on_family_id" - end - create_table "securities", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| t.string "ticker", null: false t.string "name" @@ -686,9 +661,6 @@ ActiveRecord::Schema[7.2].define(version: 2025_03_19_212839) do add_foreign_key "plaid_items", "families" add_foreign_key "rejected_transfers", "account_transactions", column: "inflow_transaction_id" add_foreign_key "rejected_transfers", "account_transactions", column: "outflow_transaction_id" - add_foreign_key "rule_actions", "rules" - add_foreign_key "rule_triggers", "rules" - add_foreign_key "rules", "families" add_foreign_key "security_prices", "securities" add_foreign_key "sessions", "impersonation_sessions", column: "active_impersonator_session_id" add_foreign_key "sessions", "users"