Adding payments

This commit is contained in:
Will Bradley 2013-02-12 01:58:17 -07:00
parent 3fb774d057
commit ed75ea0e90
29 changed files with 447 additions and 60 deletions

View File

@ -0,0 +1,3 @@
# Place all the behaviors and hooks related to the matching controller here.
# All this logic will automatically be available in application.js.
# You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/

View File

@ -0,0 +1,3 @@
// Place all the styles related to the Payments controller here.
// They will automatically be included in application.css.
// You can use Sass (SCSS) here: http://sass-lang.com/

View File

@ -0,0 +1,88 @@
class PaymentsController < ApplicationController
load_and_authorize_resource :payment
load_and_authorize_resource :user, :through => :payment
before_filter :authenticate_user!
# Load users and certs based on current ability
before_filter do
@users = User.accessible_by(current_ability).sort_by(&:name_with_payee_and_member_level)
end
before_filter :only => [:create, :update] do
@payment.created_by = current_user.id
end
# GET /payments
# GET /payments.json
def index
@payments = @payments.order("date DESC")
respond_to do |format|
format.html # index.html.erb
format.json { render :json => @payments }
end
end
# GET /payments/1
# GET /payments/1.json
def show
respond_to do |format|
format.html # show.html.erb
format.json { render :json => @payment }
end
end
# GET /payments/new
# GET /payments/new.json
def new
respond_to do |format|
format.html # new.html.erb
format.json { render :json => @payment }
end
end
# GET /payments/1/edit
def edit
end
# POST /payments
# POST /payments.json
def create
Rails.logger.warn "payment:"
Rails.logger.warn @payment.inspect
respond_to do |format|
if @payment.save
format.html { redirect_to payments_url, :notice => 'Payment was successfully created.' }
format.json { render :json => @payment, :status => :created, :location => @payment }
else
format.html { render :action => "new" }
format.json { render :json => @payment.errors, :status => :unprocessable_entity }
end
end
end
# PUT /payments/1
# PUT /payments/1.json
def update
respond_to do |format|
if @payment.update_attributes(params[:payment])
format.html { redirect_to payments_url, :notice => 'Payment was successfully updated.' }
format.json { head :no_content }
else
format.html { render :action => "edit" }
format.json { render :json => @payment.errors, :status => :unprocessable_entity }
end
end
end
# DELETE /payments/1
# DELETE /payments/1.json
def destroy
@payment.destroy
respond_to do |format|
format.html { redirect_to payments_url }
format.json { head :no_content }
end
end
end

View File

@ -15,7 +15,7 @@ class UsersController < ApplicationController
when "waiver" when "waiver"
@users = @users.sort_by{ |u| [-u.waiver.to_i,u.name] } @users = @users.sort_by{ |u| [-u.waiver.to_i,u.name] }
when "member" when "member"
@users = @users.sort_by{ |u| [-u.member.to_i,-u.member_level.to_i,u.name] } @users = @users.sort_by{ |u| [-u.member_status.to_i,u.name] }
when "card" when "card"
@users = @users.sort_by{ |u| [-u.cards.count,u.name] } @users = @users.sort_by{ |u| [-u.cards.count,u.name] }
when "instructor" when "instructor"

View File

@ -0,0 +1,2 @@
module PaymentsHelper
end

View File

@ -28,6 +28,11 @@ class Ability
can :read, UserCertification can :read, UserCertification
end end
# Accountants can manage all
if user.accountant?
can :manage, Payment
end
# Admins can manage all # Admins can manage all
if user.admin? if user.admin?
can :manage, :all can :manage, :all
@ -41,6 +46,7 @@ class Ability
cannot :destroy, MacLog cannot :destroy, MacLog
cannot :destroy, UserCertification cannot :destroy, UserCertification
cannot :destroy, DoorLog cannot :destroy, DoorLog
# no exception for destroying payments
end end
# Define abilities for the passed in user here. For example: # Define abilities for the passed in user here. For example:
# #

15
app/models/payment.rb Normal file
View File

@ -0,0 +1,15 @@
class Payment < ActiveRecord::Base
belongs_to :user
attr_accessible :date, :user_id, :created_by
validates_presence_of :user_id, :date, :created_by
validates_uniqueness_of :date, :scope => :user_id, :message => ' of payment already exists for this user.'
def human_date
if date.year < DateTime.now.year
date.strftime("%b %e, %y")
else
date.strftime("%b %e")
end
end
end

View File

@ -9,46 +9,103 @@ class User < ActiveRecord::Base
:recoverable, :rememberable, :trackable, :validatable :recoverable, :rememberable, :trackable, :validatable
# Setup accessible (or protected) attributes for your model # Setup accessible (or protected) attributes for your model
attr_accessible :email, :password, :password_confirmation, :remember_me, :name, :admin, :instructor, :member, :emergency_name, :emergency_phone, :current_skills, :desired_skills, :waiver, :emergency_email, :phone, :payment_method, :orientation, :member_level, :certifications, :hidden, :marketing_source #TODO: make admin/instructor/member/etc not accessible attr_accessible :email, :password, :password_confirmation, :remember_me, :name, :admin, :instructor, :member, :emergency_name, :emergency_phone, :current_skills, :desired_skills, :waiver, :emergency_email, :phone, :payment_method, :orientation, :member_level, :certifications, :hidden, :marketing_source, :payee, :accountant #TODO: make admin/instructor/member/etc not accessible
has_many :cards has_many :cards
has_many :user_certifications has_many :user_certifications
has_many :certifications, :through => :user_certifications has_many :certifications, :through => :user_certifications
has_many :payments
after_create :send_new_user_email after_create :send_new_user_email
def name_with_payee_and_member_level
def member_status if payee.blank? then
output = "" "#{name} - #{member_level_string}"
else
if self.member_level.to_i >= 1 then "#{payee} for #{name} - #{member_level_string}"
output = "<span class='hoverinfo' title='Inactive'>&#9676;</span>" end
end end
unless self.member.nil? then def member_level_string
# 1 = inactive, show an X case self.member_level.to_i
if self.member >= 10 then when 0
output = "<span class='hoverinfo' title='Volunteer'>&#9684;</span>" "None"
# 25 or higher is paying, show a check when 1
end "Unable"
if self.member >= 25 then when 10..24
output = "<span class='hoverinfo' title='25'>&#9681;</span>" "Volunteer"
end when 25..49
if self.member >= 50 then "Associate ($25)"
output = "<span class='hoverinfo' title='50'>&#9685;</span>" when 50..99
end "Basic ($50)"
if self.member >= 100 then when 100..999
output = "<span class='hoverinfo' title='100'>&#9679;</span>" "Plus ($100)"
end
if self.member < self.member_level.to_i then
output = "<span class='hoverinfo' title='Lapsed'>&#x2717;</span>"
end end
end end
return output def member_status
case self.member_level.to_i
when 0
if self.payments.count > 0 then
2
else
-1
end
when 1
1
when 10..24
10
when 25..999
if self.payments.count > 0 then
if self.payments.last.date < (DateTime.now - 1.month)
3
else
case self.member_level.to_i
when 25..49
25
when 50..99
50
when 100..999
100
end
end
else
return 0
end
end
end end
def member_status_symbol
case self.member_level.to_i
when 0
if self.payments.count > 0 then
"<span class='hoverinfo' title='Former Member'>:(</span>"
else
"<!-- Not a member -->"
end
when 1
"Unable"
when 10..24
"<span class='hoverinfo' title='Volunteer'>&#9684;</span>"
when 25..999
if self.payments.count > 0 then
if self.payments.last.date < (DateTime.now - 1.month)
"<span class='hoverinfo' title='Lapsed'>&#9676;</span>"
else
case self.member_level.to_i
when 25..49
"<span class='hoverinfo' title='#{member_level_string}'>&#9681;</span>"
when 50..99
"<span class='hoverinfo' title='#{member_level_string}'>&#9685;</span>"
when 100..999
"<span class='hoverinfo' title='#{member_level_string}'>&#9679;</span>"
end
end
else
"<span class='hoverinfo' title='No Payments'>?</span>"
end
end
end
private private

View File

@ -17,6 +17,7 @@
<% else %> <% else %>
<%= link_to 'Certifications', certifications_path if can? :read, Certification %> <%= link_to 'Certifications', certifications_path if can? :read, Certification %>
<% end %> <% end %>
<%= link_to 'Payments', payments_path if can? :read, Payment %>
<%= link_to 'Door Logs', door_logs_path if can? :read, DoorLog %> <%= link_to 'Door Logs', door_logs_path if can? :read, DoorLog %>
<%= link_to 'Computers', macs_path if user_signed_in? && (can? :read, Mac) %> <%= link_to 'Computers', macs_path if user_signed_in? && (can? :read, Mac) %>
<% if user_signed_in? then %><%= link_to 'Profile', edit_user_registration_path %><% end %> <% if user_signed_in? then %><%= link_to 'Profile', edit_user_registration_path %><% end %>

View File

@ -0,0 +1,25 @@
<%= form_for(@payment) do |f| %>
<% if @payment.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(@payment.errors.count, "error") %> prohibited this payment from being saved:</h2>
<ul>
<% @payment.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :user_id, "User" %><br />
<%= collection_select(:payment, :user_id, @users, :id, :name_with_payee_and_member_level) %>
</div>
<div class="field">
<%= f.label :date, "Paid for month beginning" %><br />
<%= f.date_select :date %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>

View File

@ -0,0 +1,6 @@
<h1>Editing payment</h1>
<%= render 'form' %>
<%= link_to 'Show', @payment %> |
<%= link_to 'Back', payments_path %>

View File

@ -0,0 +1,24 @@
<h1>Listing payments</h1>
<%= link_to 'New Payment', new_payment_path %>
<br />
<table>
<tr>
<th>User</th>
<th>Paid for month <br/>beginning</th>
<th></th>
<th></th>
<th></th>
</tr>
<% @payments.each do |payment| %>
<tr>
<td><%= link_to payment.user.name_with_payee_and_member_level, payment.user unless payment.user.blank? %></td>
<td><%= payment.human_date %></td>
<td><%= link_to 'Details', payment %></td>
<td><%= link_to 'Edit', edit_payment_path(payment) %></td>
</tr>
<% end %>
</table>

View File

@ -0,0 +1,5 @@
<h1>New payment</h1>
<%= render 'form' %>
<%= link_to 'Back', payments_path %>

View File

@ -0,0 +1,29 @@
<p>
<b>User:</b>
<%= @payment.user.name_with_payee_and_member_level unless @payment.user.blank? %>
</p>
<p>
<b>Paid for month beginning:</b>
<%= @payment.date %>
</p>
<p>
<b>Last Modified by:</b>
<%= user = @users.find{|u| u.id == @payment.created_by}; link_to user.name, user unless user.blank? %>
</p>
<p>
<b>Created date:</b>
<%= @payment.created_at %>
</p>
<p>
<b>Updated date:</b>
<%= @payment.updated_at %>
</p>
<%= link_to 'Edit', edit_payment_path(@payment) %> |
<%= link_to 'Destroy', @payment, :confirm => 'Are you sure you want to destroy this payment?', :method => :delete if can? :destroy, @payment %> |
<%= link_to 'Back', payments_path %>

View File

@ -12,6 +12,10 @@
<p> <p>
User Details: <%= link_to @url+user_path(@user), @url+user_path(@user) %> User Details: <%= link_to @url+user_path(@user), @url+user_path(@user) %>
</p> </p>
<p>
<b>Member Level:</b>
<%= simple_format @user.member_level_string %>
</p>
<p> <p>
<b>What skills, knowledge and experience do you bring to the community?</b> <b>What skills, knowledge and experience do you bring to the community?</b>
<%= simple_format @user.current_skills %> <%= simple_format @user.current_skills %>

View File

@ -4,6 +4,7 @@ Please contact them at <%= @user.email %><%= " or "+@user.phone.to_s unless @use
new user orientation, waiver, welcome, payment help, etc. new user orientation, waiver, welcome, payment help, etc.
User Details: <%= link_to @url+user_path(@user), @url+user_path(@user) %> User Details: <%= link_to @url+user_path(@user), @url+user_path(@user) %>
Member Level: <%= simple_format @user.member_level %>
What skills, knowledge and experience do you bring to the community? What skills, knowledge and experience do you bring to the community?
<%= simple_format @user.current_skills %> <%= simple_format @user.current_skills %>

View File

@ -65,6 +65,10 @@
<div class="field"> <div class="field">
<%= render :partial => "/users/payment_methods", :locals => { :g => f } %> <%= render :partial => "/users/payment_methods", :locals => { :g => f } %>
</div> </div>
<div class="field">
<%= f.label :payee %><br />
<%= f.text_field :payee%>
</div>
<div class="field"> <div class="field">
<%= f.label :phone %><br /> <%= f.label :phone %><br />
<%= f.text_field :phone %> <%= f.text_field :phone %>
@ -81,10 +85,6 @@
<%= f.label :marketing_source, "How'd you find out about HeatSync?" %><br /> <%= f.label :marketing_source, "How'd you find out about HeatSync?" %><br />
<%= f.text_area :marketing_source %> <%= f.text_area :marketing_source %>
</div> </div>
<div class="field">
<%= f.label :member, "Member?" %><br />
<%= f.select :member, [[nil],["No",0],["Inactive",1],["Volunteer",10],["Associate",25],["Basic",50],["Plus",100]] %>
</div>
<div class="field"> <div class="field">
<%= f.label :instructor, "Instructor?" %><br /> <%= f.label :instructor, "Instructor?" %><br />
<%= f.check_box :instructor %> <%= f.check_box :instructor %>
@ -93,6 +93,10 @@
<%= f.label :admin, "Admin?" %><br /> <%= f.label :admin, "Admin?" %><br />
<%= f.check_box :admin %> <%= f.check_box :admin %>
</div> </div>
<div class="field">
<%= f.label :accountant, "Accountant?" %><br />
<%= f.check_box :accountant %>
</div>
<div class="field"> <div class="field">
<%= f.label :hidden, "Hidden?" %><br /> <%= f.label :hidden, "Hidden?" %><br />
<%= f.check_box :hidden %> <%= f.check_box :hidden %>

View File

@ -8,8 +8,8 @@
<col /> <col />
<% if current_user.admin? then %><col /><% end %> <% if current_user.admin? then %><col /><% end %>
<col /> <col />
<% if current_user.admin? %><col /><% end %> <% if current_user.admin? %><col />
<col class="col_highlight" /> <col class="col_highlight" /><% end %>
<col /> <col />
<col class="col_highlight" /> <col class="col_highlight" />
<col /> <col />
@ -26,7 +26,7 @@
<th><a href="?sort=member">Member?</a></th> <th><a href="?sort=member">Member?</a></th>
<th><a href="?sort=card">Card?</a></th> <th><a href="?sort=card">Card?</a></th>
<th><a href="?sort=instructor">Instructor?</a></th> <th><a href="?sort=instructor">Instructor?</a></th>
<th><a href="?sort=admin">Admin?</a></th> <% if current_user.admin? then %><th><a href="?sort=admin">Admin?</a></th><% end %>
<th></th> <th></th>
<th></th> <th></th>
</tr> </tr>
@ -44,10 +44,10 @@
<%= unless user.orientation.blank? then raw("<span class='hoverinfo' title='"+user.orientation.strftime("%B %d %Y")+"'>&#x2713;</span>") end %> <%= unless user.orientation.blank? then raw("<span class='hoverinfo' title='"+user.orientation.strftime("%B %d %Y")+"'>&#x2713;</span>") end %>
</td><% end %> </td><% end %>
<td><%= unless user.waiver.blank? then raw("<span class='hoverinfo' title='"+user.waiver.strftime("%B %d %Y")+"'>&#x2713;</span>") end %></td> <td><%= unless user.waiver.blank? then raw("<span class='hoverinfo' title='"+user.waiver.strftime("%B %d %Y")+"'>&#x2713;</span>") end %></td>
<td><%= raw(user.member_status) %></td> <td><%= raw(user.member_status_symbol) %></td>
<td><%= unless user.cards.blank? then raw("<span class='iconinfo'>&#x2713;</span>") end %></td> <td><%= unless user.cards.blank? then raw("<span class='iconinfo'>&#x2713;</span>") end %></td>
<td><%= if user.instructor? then raw("<span class='iconinfo'>&#x2713;</a>") end %></td> <td><%= if user.instructor? then raw("<span class='iconinfo'>&#x2713;</a>") end %></td>
<td><%= if user.admin? then raw("<span class='iconinfo'>&#x2713;</a>") end %></td> <% if current_user.admin? then %><td><%= if user.admin? then raw("<span class='iconinfo'>&#x2713;</a>") end %></td><% end %>
<td><%= link_to 'Edit', edit_user_path(user) if can? :update, user %></td> <td><%= link_to 'Edit', edit_user_path(user) if can? :update, user %></td>
<td><%= link_to 'Destroy', user, :confirm => 'Are you sure? WARNING: THIS DOES NOT REMOVE THE USER FROM THE DOOR SYSTEM! DISABLE THEM FIRST.', :method => :delete if can? :destroy, user %></td> <td><%= link_to 'Destroy', user, :confirm => 'Are you sure? WARNING: THIS DOES NOT REMOVE THE USER FROM THE DOOR SYSTEM! DISABLE THEM FIRST.', :method => :delete if can? :destroy, user %></td>
</tr> </tr>

View File

@ -12,7 +12,7 @@
<p> <p>
<b>Current Member?</b> <b>Current Member?</b>
<%= raw(@user.member_status) %> <%= raw(@user.member_status_symbol) %>
</p> </p>
<p> <p>
@ -20,12 +20,6 @@
<%= @user.instructor? %> <%= @user.instructor? %>
</p> </p>
<p>
<b>Admin?</b>
<%= @user.admin? %>
</p>
<% if current_user.admin? then %> <% if current_user.admin? then %>
<p> <p>
<b>Email:</b> <b>Email:</b>
@ -56,6 +50,10 @@
<b>Payment Method:</b> <b>Payment Method:</b>
<%= @user.payment_method %> <%= @user.payment_method %>
</p> </p>
<p>
<b>Payee:</b>
<%= @user.payee %>
</p>
<p> <p>
<b>Phone:</b> <b>Phone:</b>
<%= @user.phone %> <%= @user.phone %>
@ -94,5 +92,12 @@
<% if @user.certifications.blank? %><li>n/a</li><% end %> <% if @user.certifications.blank? %><li>n/a</li><% end %>
</ul> </ul>
<% if current_user.admin? then %>
<p>
<b>Created:</b>
<%= @user.created_at %>
</p>
<% end %>
<% if can? :update, @user then %><%= link_to 'Edit', edit_user_path(@user) %> |<% end %> <% if can? :update, @user then %><%= link_to 'Edit', edit_user_path(@user) %> |<% end %>
<%= link_to 'Back', users_path %> <%= link_to 'Back', users_path %>

View File

@ -1,5 +1,7 @@
Dooraccess::Application.routes.draw do Dooraccess::Application.routes.draw do
resources :payments
resources :user_certifications resources :user_certifications
resources :certifications resources :certifications

View File

@ -0,0 +1,11 @@
class CreatePayments < ActiveRecord::Migration
def change
create_table :payments do |t|
t.references :user
t.date :date
t.timestamps
end
add_index :payments, :user_id
end
end

View File

@ -0,0 +1,5 @@
class AddCreatedByToPayments < ActiveRecord::Migration
def change
add_column :payments, :created_by, :integer
end
end

View File

@ -0,0 +1,5 @@
class AddPayeeToUsers < ActiveRecord::Migration
def change
add_column :users, :payee, :string
end
end

View File

@ -0,0 +1,5 @@
class AddAccountantToUsers < ActiveRecord::Migration
def change
add_column :users, :accountant, :boolean
end
end

View File

@ -10,7 +10,7 @@
# #
# It's strongly recommended to check this file into your version control system. # It's strongly recommended to check this file into your version control system.
ActiveRecord::Schema.define(:version => 20130209103457) do ActiveRecord::Schema.define(:version => 20130212083412) do
create_table "cards", :force => true do |t| create_table "cards", :force => true do |t|
t.string "card_number" t.string "card_number"
@ -58,6 +58,16 @@ ActiveRecord::Schema.define(:version => 20130209103457) do
add_index "macs", ["user_id"], :name => "index_macs_on_user_id" add_index "macs", ["user_id"], :name => "index_macs_on_user_id"
create_table "payments", :force => true do |t|
t.integer "user_id"
t.date "date"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.integer "created_by"
end
add_index "payments", ["user_id"], :name => "index_payments_on_user_id"
create_table "user_certifications", :force => true do |t| create_table "user_certifications", :force => true do |t|
t.integer "user_id" t.integer "user_id"
t.integer "certification_id" t.integer "certification_id"
@ -96,6 +106,8 @@ ActiveRecord::Schema.define(:version => 20130209103457) do
t.boolean "instructor" t.boolean "instructor"
t.boolean "hidden" t.boolean "hidden"
t.string "marketing_source" t.string "marketing_source"
t.string "payee"
t.boolean "accountant"
end end
add_index "users", ["email"], :name => "index_users_on_email", :unique => true add_index "users", ["email"], :name => "index_users_on_email", :unique => true

9
test/fixtures/payments.yml vendored Normal file
View File

@ -0,0 +1,9 @@
# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/Fixtures.html
one:
user:
date: 2013-02-11
two:
user:
date: 2013-02-11

View File

@ -0,0 +1,49 @@
require 'test_helper'
class PaymentsControllerTest < ActionController::TestCase
setup do
@payment = payments(:one)
end
test "should get index" do
get :index
assert_response :success
assert_not_nil assigns(:payments)
end
test "should get new" do
get :new
assert_response :success
end
test "should create payment" do
assert_difference('Payment.count') do
post :create, :payment => { :date => @payment.date }
end
assert_redirected_to payment_path(assigns(:payment))
end
test "should show payment" do
get :show, :id => @payment
assert_response :success
end
test "should get edit" do
get :edit, :id => @payment
assert_response :success
end
test "should update payment" do
put :update, :id => @payment, :payment => { :date => @payment.date }
assert_redirected_to payment_path(assigns(:payment))
end
test "should destroy payment" do
assert_difference('Payment.count', -1) do
delete :destroy, :id => @payment
end
assert_redirected_to payments_path
end
end

View File

@ -0,0 +1,4 @@
require 'test_helper'
class PaymentsHelperTest < ActionView::TestCase
end

View File

@ -0,0 +1,7 @@
require 'test_helper'
class PaymentTest < ActiveSupport::TestCase
# test "the truth" do
# assert true
# end
end