From 5be8b31a393484a8b2313d3d35439ecdd97c9e04 Mon Sep 17 00:00:00 2001 From: jonkaplan Date: Fri, 31 May 2024 11:38:16 -0400 Subject: [PATCH 1/9] Spacing --- app/models/student.rb | 6 +++--- test/fixtures/portfolios.yml | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/app/models/student.rb b/app/models/student.rb index 71dfb88..7f04f5f 100644 --- a/app/models/student.rb +++ b/app/models/student.rb @@ -1,4 +1,4 @@ class Student < User - belongs_to :classroom - has_one :portfolio, foreign_key: 'user_id' -end \ No newline at end of file + belongs_to :classroom + has_one :portfolio, foreign_key: 'user_id' +end diff --git a/test/fixtures/portfolios.yml b/test/fixtures/portfolios.yml index 156f883..0faf4ad 100644 --- a/test/fixtures/portfolios.yml +++ b/test/fixtures/portfolios.yml @@ -4,10 +4,10 @@ one: user: one cash_balance: 1.5 current_position: 1.5 - transactions: + transactions: two: user: two cash_balance: 1.5 current_position: 1.5 - transactions: + transactions: From 4df5a3e5a4a2cf51d3794aa7bbad8b32481a9756 Mon Sep 17 00:00:00 2001 From: jonkaplan Date: Fri, 31 May 2024 11:42:16 -0400 Subject: [PATCH 2/9] Moving cash_balance to calculated value - PortfolioTransaction now has an amount, the cash_value on the Portfolio will be derived from the sum of those transactions --- app/models/portfolio.rb | 4 ++++ ...0531145714_add_amount_to_portfolio_transactions.rb | 5 +++++ ...40531151002_remove_cash_balance_from_portfolios.rb | 5 +++++ db/schema.rb | 2 +- test/fixtures/portfolio_transactions.yml | 4 +++- test/fixtures/portfolios.yml | 2 -- test/models/portfolio_test.rb | 11 ++++++----- 7 files changed, 24 insertions(+), 9 deletions(-) create mode 100644 db/migrate/20240531145714_add_amount_to_portfolio_transactions.rb create mode 100644 db/migrate/20240531151002_remove_cash_balance_from_portfolios.rb diff --git a/app/models/portfolio.rb b/app/models/portfolio.rb index da52130..198a859 100644 --- a/app/models/portfolio.rb +++ b/app/models/portfolio.rb @@ -3,6 +3,10 @@ class Portfolio < ApplicationRecord has_many :portfolio_transactions has_many :portfolio_stocks + def cash_balance + portfolio_transactions.sum(:amount) + end + # a User (specifically student) can buy a certain amount of stock def buy_stock(ticker, shares) stock = Stock.find_by(ticker:) diff --git a/db/migrate/20240531145714_add_amount_to_portfolio_transactions.rb b/db/migrate/20240531145714_add_amount_to_portfolio_transactions.rb new file mode 100644 index 0000000..508d88d --- /dev/null +++ b/db/migrate/20240531145714_add_amount_to_portfolio_transactions.rb @@ -0,0 +1,5 @@ +class AddAmountToPortfolioTransactions < ActiveRecord::Migration[7.1] + def change + add_column :portfolio_transactions, :amount, :decimal, precision: 8, scale: 2, null: false + end +end diff --git a/db/migrate/20240531151002_remove_cash_balance_from_portfolios.rb b/db/migrate/20240531151002_remove_cash_balance_from_portfolios.rb new file mode 100644 index 0000000..67cffd3 --- /dev/null +++ b/db/migrate/20240531151002_remove_cash_balance_from_portfolios.rb @@ -0,0 +1,5 @@ +class RemoveCashBalanceFromPortfolios < ActiveRecord::Migration[7.1] + def change + remove_column :portfolios, :cash_balance + end +end diff --git a/db/schema.rb b/db/schema.rb index b3274e4..8b3f071 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -53,12 +53,12 @@ t.integer "transaction_type" t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.decimal "amount", precision: 8, scale: 2, null: false t.index ["portfolio_id"], name: "index_portfolio_transactions_on_portfolio_id" end create_table "portfolios", force: :cascade do |t| t.bigint "user_id", null: false - t.float "cash_balance" t.float "current_position" t.json "transactions" t.datetime "created_at", null: false diff --git a/test/fixtures/portfolio_transactions.yml b/test/fixtures/portfolio_transactions.yml index 8e51926..8dc242f 100644 --- a/test/fixtures/portfolio_transactions.yml +++ b/test/fixtures/portfolio_transactions.yml @@ -2,8 +2,10 @@ one: portfolio: one + amount: 10.00 transaction_type: 1 two: - portfolio: two + portfolio: one + amount: 15.50 transaction_type: 1 diff --git a/test/fixtures/portfolios.yml b/test/fixtures/portfolios.yml index 0faf4ad..f1c9c49 100644 --- a/test/fixtures/portfolios.yml +++ b/test/fixtures/portfolios.yml @@ -2,12 +2,10 @@ one: user: one - cash_balance: 1.5 current_position: 1.5 transactions: two: user: two - cash_balance: 1.5 current_position: 1.5 transactions: diff --git a/test/models/portfolio_test.rb b/test/models/portfolio_test.rb index 1c329a7..692d1f2 100644 --- a/test/models/portfolio_test.rb +++ b/test/models/portfolio_test.rb @@ -1,8 +1,9 @@ -require "test_helper" +require 'test_helper' class PortfolioTest < ActiveSupport::TestCase - # test "the truth" do - # assert true - # end - #TODO: Add tests for the Portfolio model + fixtures :portfolios + test '#cash_balance' do + portfolio = portfolios(:one) + assert_equal BigDecimal('25.50'), portfolio.cash_balance + end end From 30701c97c7715f2fec5c8bfa233b54757d3b0a1c Mon Sep 17 00:00:00 2001 From: jonkaplan Date: Fri, 31 May 2024 11:42:40 -0400 Subject: [PATCH 3/9] Fixture fixes - Have unique values where unique constraints are set in the db --- test/fixtures/users.yml | 6 +++--- test/fixtures/years.yml | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/test/fixtures/users.yml b/test/fixtures/users.yml index 82fa2a2..60a3904 100644 --- a/test/fixtures/users.yml +++ b/test/fixtures/users.yml @@ -4,10 +4,10 @@ # model remove the "{}" from the fixture names and add the columns immediately # below each fixture, per the syntax in the comments below # -one: - username: "lkfjd" +one: + username: abc123 # column: value # two: - username: "dglk" + username: def123 # column: value diff --git a/test/fixtures/years.yml b/test/fixtures/years.yml index 338db83..e066652 100644 --- a/test/fixtures/years.yml +++ b/test/fixtures/years.yml @@ -1,7 +1,7 @@ # Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html one: - year: 1 + year: 2023 two: - year: 2 + year: 2024 From 8a1b33102ec64a20786199c02b476a72dca252d4 Mon Sep 17 00:00:00 2001 From: jonkaplan Date: Fri, 31 May 2024 13:21:40 -0400 Subject: [PATCH 4/9] Fix the profile transaction dashboard --- app/dashboards/portfolio_transaction_dashboard.rb | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/app/dashboards/portfolio_transaction_dashboard.rb b/app/dashboards/portfolio_transaction_dashboard.rb index 0f943da..edefdf2 100644 --- a/app/dashboards/portfolio_transaction_dashboard.rb +++ b/app/dashboards/portfolio_transaction_dashboard.rb @@ -1,4 +1,4 @@ -require "administrate/base_dashboard" +require 'administrate/base_dashboard' class PortfolioTransactionDashboard < Administrate::BaseDashboard # ATTRIBUTE_TYPES @@ -9,11 +9,12 @@ class PortfolioTransactionDashboard < Administrate::BaseDashboard # on pages throughout the dashboard. ATTRIBUTE_TYPES = { id: Field::Number, - actor: Field::BelongsTo, portfolio: Field::BelongsTo, - transaction_type: Field::Select.with_options(searchable: false, collection: ->(field) { field.resource.class.send(field.attribute.to_s.pluralize).keys }), + transaction_type: Field::Select.with_options(searchable: false, collection: lambda { |field| + field.resource.class.send(field.attribute.to_s.pluralize).keys + }), created_at: Field::DateTime, - updated_at: Field::DateTime, + updated_at: Field::DateTime }.freeze # COLLECTION_ATTRIBUTES @@ -23,7 +24,6 @@ class PortfolioTransactionDashboard < Administrate::BaseDashboard # Feel free to add, remove, or rearrange items. COLLECTION_ATTRIBUTES = %i[ id - actor portfolio transaction_type ].freeze @@ -32,7 +32,6 @@ class PortfolioTransactionDashboard < Administrate::BaseDashboard # an array of attributes that will be displayed on the model's show page. SHOW_PAGE_ATTRIBUTES = %i[ id - actor portfolio transaction_type created_at @@ -43,7 +42,6 @@ class PortfolioTransactionDashboard < Administrate::BaseDashboard # an array of attributes that will be displayed # on the model's form (`new` and `edit`) pages. FORM_ATTRIBUTES = %i[ - actor portfolio transaction_type ].freeze From 89316f0472f07f320e1d9c8af25c6151089ba3c8 Mon Sep 17 00:00:00 2001 From: jonkaplan Date: Fri, 31 May 2024 13:45:11 -0400 Subject: [PATCH 5/9] Copy administrate form partial --- app/views/admin/students/_form.html.erb | 60 +++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 app/views/admin/students/_form.html.erb diff --git a/app/views/admin/students/_form.html.erb b/app/views/admin/students/_form.html.erb new file mode 100644 index 0000000..8186ebf --- /dev/null +++ b/app/views/admin/students/_form.html.erb @@ -0,0 +1,60 @@ +<%# +# Form Partial + +This partial is rendered on a resource's `new` and `edit` pages, +and renders all form fields for a resource's editable attributes. + +## Local variables: + +- `page`: + An instance of [Administrate::Page::Form][1]. + Contains helper methods to display a form, + and knows which attributes should be displayed in the resource's form. + +[1]: http://www.rubydoc.info/gems/administrate/Administrate/Page/Form +%> + +<%= form_for([namespace, page.resource], html: { class: "form" }) do |f| %> + <% if page.resource.errors.any? %> +
+

+ <%= t( + "administrate.form.errors", + pluralized_errors: pluralize(page.resource.errors.count, t("administrate.form.error")), + resource_name: display_resource_name(page.resource_name, singular: true) + ) %> +

+ +
    + <% page.resource.errors.full_messages.each do |message| %> +
  • <%= message %>
  • + <% end %> +
+
+ <% end %> + + <% page.attributes(controller.action_name).each do |title, attributes| -%> +
"> + <% if title.present? %> + <%= t "helpers.label.#{f.object_name}.#{title}", default: title %> + <% end %> + + <% attributes.each do |attribute| %> +
+ <%= render_field attribute, f: f %> + + <% hint_key = "administrate.field_hints.#{page.resource_name}.#{attribute.name}" %> + <% if I18n.exists?(hint_key) -%> +
+ <%= I18n.t(hint_key) %> +
+ <% end -%> +
+ <% end %> +
+ <% end -%> + +
+ <%= f.submit %> +
+<% end %> From 226df3df0697475c7afc9a2647865e999bcc3188 Mon Sep 17 00:00:00 2001 From: jonkaplan Date: Fri, 31 May 2024 14:49:07 -0400 Subject: [PATCH 6/9] Basic adminisrate update test - Working test without any customization --- app/controllers/admin/students_controller.rb | 10 +++++----- app/models/student.rb | 2 -- app/models/user.rb | 1 + .../admin/students_controller_test.rb | 16 ++++++++++++++++ test/fixtures/users.yml | 2 ++ 5 files changed, 24 insertions(+), 7 deletions(-) create mode 100644 test/controllers/admin/students_controller_test.rb diff --git a/app/controllers/admin/students_controller.rb b/app/controllers/admin/students_controller.rb index 6d6caa9..4e256e9 100644 --- a/app/controllers/admin/students_controller.rb +++ b/app/controllers/admin/students_controller.rb @@ -2,11 +2,11 @@ module Admin class StudentsController < Admin::ApplicationController # Overwrite any of the RESTful controller actions to implement custom behavior # For example, you may want to send an email after a foo is updated. - # - # def update - # super - # send_foo_updated_email(requested_resource) - # end + + def update + super + # send_foo_updated_email(requested_resource) + end # Override this method to specify custom lookup behavior. # This will be used to set the resource for the `show`, `edit`, and `update` diff --git a/app/models/student.rb b/app/models/student.rb index 7f04f5f..43e6df0 100644 --- a/app/models/student.rb +++ b/app/models/student.rb @@ -1,4 +1,2 @@ class Student < User - belongs_to :classroom - has_one :portfolio, foreign_key: 'user_id' end diff --git a/app/models/user.rb b/app/models/user.rb index 16a0cc1..0afdf52 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -1,6 +1,7 @@ class User < ApplicationRecord has_one :portfolio has_many :orders + belongs_to :classroom # Include default devise modules. Others available are: # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable diff --git a/test/controllers/admin/students_controller_test.rb b/test/controllers/admin/students_controller_test.rb new file mode 100644 index 0000000..7320cc2 --- /dev/null +++ b/test/controllers/admin/students_controller_test.rb @@ -0,0 +1,16 @@ +require 'test_helper' + +class Admin::StudentsControllerTest < ActionDispatch::IntegrationTest + setup do + @student = users(:one) + end + + test 'should update student' do + @student.update_attribute(:email, 'nottest@nottest.com') + + patch admin_student_url(@student), params: { student: { email: 'test@test.com' } } + @student.reload + assert_equal 'test@test.com', @student.email + assert_redirected_to admin_student_url(@student) + end +end diff --git a/test/fixtures/users.yml b/test/fixtures/users.yml index 60a3904..dc3b46e 100644 --- a/test/fixtures/users.yml +++ b/test/fixtures/users.yml @@ -6,8 +6,10 @@ # one: username: abc123 + classroom: one # column: value # two: username: def123 + classroom: two # column: value From 045588fc0c5a712a836dbb455afe13733514d185 Mon Sep 17 00:00:00 2001 From: jonkaplan Date: Fri, 31 May 2024 15:14:15 -0400 Subject: [PATCH 7/9] Customize student dashboard form to allow adding funds - Add custom form partial with cash balance + add_fund_amount - Process add_fund_amount and test --- app/controllers/admin/students_controller.rb | 15 ++++++++++++++- app/dashboards/portfolio_transaction_dashboard.rb | 2 ++ app/views/admin/students/_form.html.erb | 12 ++++++++++++ config/routes.rb | 2 +- .../controllers/admin/students_controller_test.rb | 15 ++++++++++++++- 5 files changed, 43 insertions(+), 3 deletions(-) diff --git a/app/controllers/admin/students_controller.rb b/app/controllers/admin/students_controller.rb index 4e256e9..42c3d28 100644 --- a/app/controllers/admin/students_controller.rb +++ b/app/controllers/admin/students_controller.rb @@ -5,7 +5,8 @@ class StudentsController < Admin::ApplicationController def update super - # send_foo_updated_email(requested_resource) + + create_portfolio_transaction! end # Override this method to specify custom lookup behavior. @@ -42,5 +43,17 @@ def update # See https://administrate-demo.herokuapp.com/customizing_controller_actions # for more information + # + private + + def create_portfolio_transaction! + return unless fund_amount + + PortfolioTransaction.create!(portfolio: requested_resource.portfolio, amount: fund_amount) if fund_amount + end + + def fund_amount + @fund_amount ||= params['student']['add_fund_amount'] + end end end diff --git a/app/dashboards/portfolio_transaction_dashboard.rb b/app/dashboards/portfolio_transaction_dashboard.rb index edefdf2..8d67f86 100644 --- a/app/dashboards/portfolio_transaction_dashboard.rb +++ b/app/dashboards/portfolio_transaction_dashboard.rb @@ -13,6 +13,7 @@ class PortfolioTransactionDashboard < Administrate::BaseDashboard transaction_type: Field::Select.with_options(searchable: false, collection: lambda { |field| field.resource.class.send(field.attribute.to_s.pluralize).keys }), + amount: Field::Number.with_options(decimals: 2), created_at: Field::DateTime, updated_at: Field::DateTime }.freeze @@ -44,6 +45,7 @@ class PortfolioTransactionDashboard < Administrate::BaseDashboard FORM_ATTRIBUTES = %i[ portfolio transaction_type + amount ].freeze # COLLECTION_FILTERS diff --git a/app/views/admin/students/_form.html.erb b/app/views/admin/students/_form.html.erb index 8186ebf..6386cf5 100644 --- a/app/views/admin/students/_form.html.erb +++ b/app/views/admin/students/_form.html.erb @@ -52,6 +52,18 @@ and renders all form fields for a resource's editable attributes. <% end %> +
+
+
+ <%= sprintf('%.2f', page.resource&.portfolio&.cash_balance || 0)%> +
+
+
+
+
+ +
+
<% end -%>
diff --git a/config/routes.rb b/config/routes.rb index 577bea4..a836d68 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -7,7 +7,7 @@ # resources :portfolios # resources :portfolio_stocks - # resources :portfolio_transactions + resources :portfolio_transactions, except: [:index] resources :students resources :teachers resources :users diff --git a/test/controllers/admin/students_controller_test.rb b/test/controllers/admin/students_controller_test.rb index 7320cc2..759283f 100644 --- a/test/controllers/admin/students_controller_test.rb +++ b/test/controllers/admin/students_controller_test.rb @@ -5,7 +5,7 @@ class Admin::StudentsControllerTest < ActionDispatch::IntegrationTest @student = users(:one) end - test 'should update student' do + test 'should update student email' do @student.update_attribute(:email, 'nottest@nottest.com') patch admin_student_url(@student), params: { student: { email: 'test@test.com' } } @@ -13,4 +13,17 @@ class Admin::StudentsControllerTest < ActionDispatch::IntegrationTest assert_equal 'test@test.com', @student.email assert_redirected_to admin_student_url(@student) end + + test 'given a add_fund_amount, creates a transaction' do + assert_difference('PortfolioTransaction.count', 1) do + patch admin_student_url(@student), params: { student: { add_fund_amount: '10.50' } } + end + + transaction = PortfolioTransaction.last + + assert_equal 10.50, transaction.amount + assert_equal @student.reload.portfolio.portfolio_transactions.last, transaction + + assert_redirected_to admin_student_url(@student) + end end From 00a676f925fe90592cac91c200a06b59633a59c2 Mon Sep 17 00:00:00 2001 From: jonkaplan Date: Fri, 31 May 2024 15:14:47 -0400 Subject: [PATCH 8/9] Compress CSS for test environment Seems needed for tailwind-css to work? https://stackoverflow.com/questions/71805735/error-function-rgb-is-missing-argument-green-in-sass --- config/environments/test.rb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/config/environments/test.rb b/config/environments/test.rb index adbb4a6..b8825b2 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -61,4 +61,7 @@ # Raise error when a before_action's only/except options reference missing actions config.action_controller.raise_on_missing_callback_actions = true + + # TODO: revisit + config.assets.css_compressor = nil end From cc1649ba864c2967f0adfe9486460bedc404c525 Mon Sep 17 00:00:00 2001 From: jonkaplan Date: Fri, 31 May 2024 15:23:14 -0400 Subject: [PATCH 9/9] Hide action on create - Only show when updating a student --- app/views/admin/students/_form.html.erb | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/app/views/admin/students/_form.html.erb b/app/views/admin/students/_form.html.erb index 6386cf5..25fb1d1 100644 --- a/app/views/admin/students/_form.html.erb +++ b/app/views/admin/students/_form.html.erb @@ -52,18 +52,20 @@ and renders all form fields for a resource's editable attributes.
<% end %> -
-
-
- <%= sprintf('%.2f', page.resource&.portfolio&.cash_balance || 0)%> + <% if action_name == 'edit' %> +
+
+
+ <%= sprintf('%.2f', page.resource&.portfolio&.cash_balance || 0)%> +
-
-
-
-
- +
+
+
+ +
-
+ <% end %> <% end -%>