Skip to content

Commit

Permalink
Implement rejection of new club applications
Browse files Browse the repository at this point in the history
  • Loading branch information
zachlatta committed Jan 31, 2018
1 parent 0a89c1f commit 100f6e2
Show file tree
Hide file tree
Showing 7 changed files with 166 additions and 5 deletions.
5 changes: 4 additions & 1 deletion api/app/controllers/v1/new_club_applications_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,10 @@ def club_application_params
:point_of_contact_id,
:interviewed_at,
:interview_duration,
:interview_notes
:interview_notes,
:rejected_at,
:rejected_reason,
:rejected_notes
)
end
end
Expand Down
13 changes: 13 additions & 0 deletions api/app/models/new_club_application.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ class NewClubApplication < ApplicationRecord
private_school charter_school
]

enum rejected_reason: %i[
other
]

with_options if: -> { submitted_at.present? } do |application|
application.validates :high_school_name,
:high_school_type,
Expand Down Expand Up @@ -63,6 +67,15 @@ class NewClubApplication < ApplicationRecord
interview_notes.present?
}

# submitted_at must be set for rejected_at to be set
validates :submitted_at, presence: true, if: -> { rejected_at.present? }
validates :rejected_at, :rejected_reason, :rejected_notes,
presence: true, if: lambda {
rejected_at.present? ||
rejected_reason.present? ||
rejected_notes.present?
}

def submit!
self.submitted_at = Time.current

Expand Down
5 changes: 4 additions & 1 deletion api/app/serializers/new_club_application_serializer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,12 @@ class NewClubApplicationSerializer < ActiveModel::Serializer
:point_of_contact_id,
:submitted_at,
:interviewed_at,
:interview_duration
:interview_duration,
:rejected_at

attribute :interview_notes, if: :admin?
attribute :rejected_reason, if: :admin?
attribute :rejected_notes, if: :admin?

has_many :leader_profiles

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# frozen_string_literal: true

class AddRejectionToNewClubApplications < ActiveRecord::Migration[5.1]
def change
add_column :new_club_applications, :rejected_at, :datetime
add_column :new_club_applications, :rejected_reason, :integer
add_column :new_club_applications, :rejected_notes, :text
end
end
5 changes: 4 additions & 1 deletion api/db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.

ActiveRecord::Schema.define(version: 20180130224937) do
ActiveRecord::Schema.define(version: 20180131005432) do

# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
Expand Down Expand Up @@ -278,6 +278,9 @@
t.datetime "interviewed_at"
t.text "interview_notes"
t.integer "interview_duration"
t.datetime "rejected_at"
t.integer "rejected_reason"
t.text "rejected_notes"
t.index ["point_of_contact_id"], name: "index_new_club_applications_on_point_of_contact_id"
end

Expand Down
55 changes: 55 additions & 0 deletions api/spec/models/new_club_application_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,14 @@
it { should have_db_column :interview_duration }
it { should have_db_column :interview_notes }

it { should have_db_column :rejected_at }
it { should have_db_column :rejected_reason }
it { should have_db_column :rejected_notes }

## enums ##

it { should define_enum_for :high_school_type }
it { should define_enum_for :rejected_reason }

## validations ##

Expand Down Expand Up @@ -129,6 +134,56 @@
end
end

describe 'rejected fields' do
subject { create(:completed_new_club_application) }
before { subject.submit! }

it 'does not allow rejected_at to be set unless submitted_at is' do
subject.submitted_at = nil
subject.rejected_at = Time.current

subject.validate
expect(subject.errors).to include('submitted_at')
end

it 'should require other fields to be set if rejected_at is' do
expect(subject.valid?).to be(true)

subject.rejected_at = Time.current

subject.validate
expect(subject.errors).to include('rejected_reason')
expect(subject.errors).to include('rejected_notes')
end

it 'should require other fields to be set if rejected_reason is' do
expect(subject.valid?).to be(true)

subject.rejected_reason = :other

subject.validate
expect(subject.errors).to include('rejected_at')
expect(subject.errors).to include('rejected_notes')
end

it 'should require other fields to be set if rejected_notes is' do
expect(subject.valid?).to be(true)

subject.rejected_notes = "Didn't have faith in leadship skills."

subject.validate
expect(subject.errors).to include('rejected_at')
expect(subject.errors).to include('rejected_reason')
end

it 'should be valid if all rejected fields are set' do
subject.rejected_at = Time.current
subject.rejected_reason = :other
subject.rejected_notes = 'Example rejection reason.'
expect(subject.valid?).to eq(true)
end
end

describe ':submit!' do
subject { create(:completed_new_club_application, profile_count: 3) }
let(:user) { subject.point_of_contact }
Expand Down
79 changes: 77 additions & 2 deletions api/spec/requests/v1/new_club_applications_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -136,17 +136,29 @@
expect(json).to include('interviewed_at')
expect(json).to include('interview_duration')
expect(json).to_not include('interview_notes')

# includes rejected_at, but not rejected_reason or rejected_notes
expect(json).to include('rejected_at')
expect(json).to_not include('rejected_reason')
expect(json).to_not include('rejected_notes')
end

it 'includes interview_notes when authed as an admin' do
it 'includes private fields when authed as an admin' do
user.make_admin!
user.save

get "/v1/new_club_applications/#{club_application.id}",
headers: auth_headers

expect(response.status).to eq(200)

expect(json).to include('interviewed_at')
expect(json).to include('interview_duration')
expect(json).to include('interview_notes')

expect(json).to include('rejected_at')
expect(json).to include('rejected_reason')
expect(json).to include('rejected_notes')
end

it '404s when application does not exist' do
Expand Down Expand Up @@ -309,6 +321,28 @@
expect(response.status).to eq(422)
end

it 'fails to update rejection fields' do
application = create(:completed_new_club_application)
create(:completed_leader_profile, new_club_application: application,
user: user)
application.update_attributes(point_of_contact: user)

# application must be submitted for any modification (even by admins) to
# be allowed
post "/v1/new_club_applications/#{application.id}/submit",
headers: auth_headers

patch "/v1/new_club_applications/#{application.id}",
headers: auth_headers,
params: {
rejected_at: Time.current,
rejected_reason: :other,
rejected_notes: 'Example reason'
}

expect(response.status).to eq(422)
end

context 'when admin' do
let(:club_application) do
app = create(:completed_new_club_application)
Expand Down Expand Up @@ -352,7 +386,7 @@
expect(json['errors']).to include('interview_notes')
end

it 'fails if application is not submitted' do
it 'fails to update interview fields if application is not submitted' do
club_application = create(:new_club_application)

patch "/v1/new_club_applications/#{club_application.id}",
Expand All @@ -364,6 +398,47 @@
expect(response.status).to eq(422)
expect(json['errors']['submitted_at']).to include("can't be blank")
end

it 'allows updating rejected fields' do
patch "/v1/new_club_applications/#{club_application.id}",
headers: auth_headers,
params: {
rejected_at: Time.current,
rejected_reason: :other,
rejected_notes: 'Example reason'
}

expect(response.status).to eq(200)
expect(
Time.zone.parse(json['rejected_at'])
).to be_within(3.seconds).of(Time.current)
expect(json).to include('rejected_reason' => 'other')
expect(json).to include('rejected_notes' => 'Example reason')
end

it 'fails if not all rejected fields are set' do
patch "/v1/new_club_applications/#{club_application.id}",
headers: auth_headers,
params: {
rejected_at: Time.current
}

expect(response.status).to eq(422)
expect(json['errors']).to include('rejected_reason', 'rejected_notes')
end

it 'fails to update rejected fields if application is not submitted' do
club_application = create(:new_club_application)

patch "/v1/new_club_applications/#{club_application.id}",
headers: auth_headers,
params: {
rejected_at: Time.current
}

expect(response.status).to eq(422)
expect(json['errors']['submitted_at']).to include("can't be blank")
end
end
end

Expand Down

0 comments on commit 100f6e2

Please sign in to comment.