Skip to content

Commit

Permalink
Merge pull request #157 from rubyforgood/add-student-funds_issue-142
Browse files Browse the repository at this point in the history
Add student funds to admin
  • Loading branch information
h-m-m authored May 31, 2024
2 parents d4f7864 + cc1649b commit 0598a8c
Show file tree
Hide file tree
Showing 17 changed files with 167 additions and 32 deletions.
23 changes: 18 additions & 5 deletions app/controllers/admin/students_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@ 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

create_portfolio_transaction!
end

# Override this method to specify custom lookup behavior.
# This will be used to set the resource for the `show`, `edit`, and `update`
Expand Down Expand Up @@ -42,5 +43,17 @@ class StudentsController < Admin::ApplicationController

# 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
14 changes: 7 additions & 7 deletions app/dashboards/portfolio_transaction_dashboard.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
require "administrate/base_dashboard"
require 'administrate/base_dashboard'

class PortfolioTransactionDashboard < Administrate::BaseDashboard
# ATTRIBUTE_TYPES
Expand All @@ -9,11 +9,13 @@ 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
}),
amount: Field::Number.with_options(decimals: 2),
created_at: Field::DateTime,
updated_at: Field::DateTime,
updated_at: Field::DateTime
}.freeze

# COLLECTION_ATTRIBUTES
Expand All @@ -23,7 +25,6 @@ class PortfolioTransactionDashboard < Administrate::BaseDashboard
# Feel free to add, remove, or rearrange items.
COLLECTION_ATTRIBUTES = %i[
id
actor
portfolio
transaction_type
].freeze
Expand All @@ -32,7 +33,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
Expand All @@ -43,9 +43,9 @@ 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
amount
].freeze

# COLLECTION_FILTERS
Expand Down
4 changes: 4 additions & 0 deletions app/models/portfolio.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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:)
Expand Down
4 changes: 1 addition & 3 deletions app/models/student.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,2 @@
class Student < User
belongs_to :classroom
has_one :portfolio, foreign_key: 'user_id'
end
end
1 change: 1 addition & 0 deletions app/models/user.rb
Original file line number Diff line number Diff line change
@@ -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
Expand Down
74 changes: 74 additions & 0 deletions app/views/admin/students/_form.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
<%#
# 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? %>
<div id="error_explanation">
<h2>
<%= 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)
) %>
</h2>

<ul>
<% page.resource.errors.full_messages.each do |message| %>
<li class="flash-error"><%= message %></li>
<% end %>
</ul>
</div>
<% end %>

<% page.attributes(controller.action_name).each do |title, attributes| -%>
<fieldset class="<%= "field-unit--nested" if title.present? %>">
<% if title.present? %>
<legend><%= t "helpers.label.#{f.object_name}.#{title}", default: title %></legend>
<% end %>

<% attributes.each do |attribute| %>
<div class="field-unit field-unit--<%= attribute.html_class %> field-unit--<%= requireness(attribute) %>">
<%= render_field attribute, f: f %>

<% hint_key = "administrate.field_hints.#{page.resource_name}.#{attribute.name}" %>
<% if I18n.exists?(hint_key) -%>
<div class="field-unit__hint">
<%= I18n.t(hint_key) %>
</div>
<% end -%>
</div>
<% end %>
</fieldset>
<% if action_name == 'edit' %>
<div class="field-unit">
<div class="field-unit__label"><label>Cash balance</label></div>
<div class="field-unit__field">
<%= sprintf('%.2f', page.resource&.portfolio&.cash_balance || 0)%>
</div>
</div>
<div class="field-unit">
<div class="field-unit__label"><label>Add funds</label></div>
<div class="field-unit__field">
<input step="any" type="number" name="student[add_fund_amount]" id="student_add_fund_amount">
</div>
</div>
<% end %>
<% end -%>

<div class="form-actions">
<%= f.submit %>
</div>
<% end %>
3 changes: 3 additions & 0 deletions config/environments/test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
2 changes: 1 addition & 1 deletion config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

# resources :portfolios
# resources :portfolio_stocks
# resources :portfolio_transactions
resources :portfolio_transactions, except: [:index]
resources :students
resources :teachers
resources :users
Expand Down
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class RemoveCashBalanceFromPortfolios < ActiveRecord::Migration[7.1]
def change
remove_column :portfolios, :cash_balance
end
end
2 changes: 1 addition & 1 deletion db/schema.rb

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

29 changes: 29 additions & 0 deletions test/controllers/admin/students_controller_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
require 'test_helper'

class Admin::StudentsControllerTest < ActionDispatch::IntegrationTest
setup do
@student = users(:one)
end

test 'should update student email' do
@student.update_attribute(:email, '[email protected]')

patch admin_student_url(@student), params: { student: { email: '[email protected]' } }
@student.reload
assert_equal '[email protected]', @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
4 changes: 3 additions & 1 deletion test/fixtures/portfolio_transactions.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@

one:
portfolio: one
amount: 10.00
transaction_type: 1

two:
portfolio: two
portfolio: one
amount: 15.50
transaction_type: 1
6 changes: 2 additions & 4 deletions test/fixtures/portfolios.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,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:
8 changes: 5 additions & 3 deletions test/fixtures/users.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@
# 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
classroom: one
# column: value
#
two:
username: "dglk"
username: def123
classroom: two
# column: value
4 changes: 2 additions & 2 deletions test/fixtures/years.yml
Original file line number Diff line number Diff line change
@@ -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
11 changes: 6 additions & 5 deletions test/models/portfolio_test.rb
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit 0598a8c

Please sign in to comment.