Skip to content

Commit

Permalink
242 3.25 application canceled state refactoring (#508)
Browse files Browse the repository at this point in the history
* event model method for phase #233

* added tests for event model phase function

* Add Test for event model function after_deadline? #233

* Revert Whitespace change #233

* Create canceled+pre_accepted state plus refactor part 1 #242

* Make only designated radio buttons selectable - Refactoring part 2 #242

* Fix tests for new states - Refactoring Part 3 #242

* Make counter test more sensable - Refactoring Part 4 #242

* Rename Email Template statuses #242

* Outsource selectable statuses to class method #242

* Convert pre_accepted into accepted by sending mail #242

* Fix feature test for pre_accepted -> accepted #242

* added some more application status changing tests #242

* move accepting all pre_accepted participants on acceptance mail from controller to model #242

* 242 go back from pre_accepted

* fix some things to get rid of pre_accepted #242

* remove unneccessary var in test #242

* remove duplicated tests #242

* move 2 expect few lines higher #242

* use factory for no status_status_notification_sent #242

* some requested changes #242

* #242 add missing locales

* #242 remove code duplication in test

* update schema.rb #242
  • Loading branch information
aloeser committed Feb 4, 2017
1 parent af512a0 commit 8d9c84c
Show file tree
Hide file tree
Showing 19 changed files with 274 additions and 71 deletions.
14 changes: 8 additions & 6 deletions app/controllers/emails_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ def show

@templates = EmailTemplate.with_status(get_email_template_status)
application_letter_status = get_corresponding_application_letter_status
@addresses = @event.email_addresses_of_type(application_letter_status)
@addresses = @event.email_addresses_of_type_without_notification_sent(application_letter_status)

@email = Email.new(hide_recipients: true, reply_to: Rails.configuration.reply_to_address, recipients: @addresses.join(','),
subject: '', content: '')
Expand All @@ -29,24 +29,26 @@ def submit
def send_email
@email = Email.new(email_params)
@event = Event.find(params[:event_id])

status = get_email_template_status
if @email.valid?
if get_corresponding_application_letter_status == :accepted
application_letter_status = get_corresponding_application_letter_status
if application_letter_status == :accepted
@email.send_email_with_ical @event
else
@email.send_email
end

if get_email_template_status == :acceptance
@event.set_status_notification_flag_for_applications_with_status(application_letter_status)
if status == :acceptance
@event.acceptances_have_been_sent = true
elsif get_email_template_status == :rejection
elsif status == :rejection
@event.rejections_have_been_sent = true
end
@event.save

redirect_to @event, notice: t('.sending_successful')
else
@templates = EmailTemplate.with_status(get_email_template_status)
@templates = EmailTemplate.with_status(status)

flash.now[:alert] = t('.sending_failed')
render :email
Expand Down
43 changes: 38 additions & 5 deletions app/models/application_letter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,22 @@ class ApplicationLetter < ActiveRecord::Base
validates_inclusion_of :grade, in: (VALID_GRADES.to_a.push(0))
validates :vegetarian, :vegan, :allergic, inclusion: { in: [true, false] }
validates :vegetarian, :vegan, :allergic, exclusion: { in: [nil] }
validate :deadline_cannot_be_in_the_past, :if => Proc.new { |letter| !(letter.status_changed?) }
validate :status_cannot_be_changed, :if => Proc.new { |letter| letter.status_changed?}
validate :deadline_cannot_be_in_the_past, :if => Proc.new { |letter| !(letter.status_changed? || letter.status_notification_sent_changed?) }
validate :status_notification_sent_cannot_be_changed, :if => Proc.new { |letter| letter.status_notification_sent_changed? }
validate :status_cannot_be_changed, :if => Proc.new { |letter| letter.status_changed? }

enum status: {accepted: 1, rejected: 0, pending: 2, alternative: 3}
enum status: {accepted: 1, rejected: 0, pending: 2, alternative: 3, canceled: 4}
validates :status, inclusion: { in: statuses.keys }


# Returns an array of selectable statuses
#
# @param none
# @return [Array <String>] array of selectable statuses
def self.selectable_statuses
["accepted","rejected","pending","alternative"]
end

# Checks if the deadline is over
# additionally only return if event and event.application_deadline is present
#
Expand All @@ -46,7 +55,21 @@ def after_deadline?
# @param none
# @return [Boolean] true if status changes are allowed
def status_change_allowed?
!event.participant_selection_locked
if event.phase == :execution
(status_was == 'accepted' && status == 'canceled') || (status_was == 'alternative' && status == 'accepted')
elsif event.phase == :selection && event.participant_selection_locked
false
else
true
end
end

# Checks if it is allowed to set the status_notification_sent flag
#
# @param none
# @return [Boolean] true if it can be changed
def status_notification_sent_change_allowed?
event.phase == :selection || event.phase == :execution
end

# Validator for after_deadline?
Expand Down Expand Up @@ -85,6 +108,8 @@ def status_type
else
return I18n.t("application_status.pending_before_deadline")
end
when ApplicationLetter.statuses[:canceled]
return I18n.t("application_status.canceled")
else
return I18n.t("application_status.alternative")
end
Expand All @@ -94,7 +119,15 @@ def status_type
# Adds error
def status_cannot_be_changed
unless status_change_allowed?
errors.add(:event, "Die Bewerbungen wurden bereits bearbeitet, eine Statusänderung ist nicht mehr erlaubt.")
errors.add(:event, I18n.t('application_letters.validation.status_cannot_be_changed'))
end
end

# Validator for status_change_allowed?
# Adds error
def status_notification_sent_cannot_be_changed
unless status_notification_sent_change_allowed?
errors.add(:event, I18n.t('application_letters.validation.status_notification_sent_cannot_be_changed'))
end
end

Expand Down
19 changes: 14 additions & 5 deletions app/models/event.rb
Original file line number Diff line number Diff line change
Expand Up @@ -154,17 +154,26 @@ def send_mails_tooltip
# @param none
# @return none
def accept_all_application_letters
application_letters.each do |application_letter|
application_letter.update(status: :accepted)
application_letters.map { |application| application.update(status: :accepted) }
end

# Sets the status_notification_sent flag for all application letters of the given type
#
# @param status [Type] the desired application status the flag should be set for
# @return none
def set_status_notification_flag_for_applications_with_status(status)
applications = application_letters.select {|application| application.status == status.to_s}
applications.each do |application_letter|
application_letter.update(status_notification_sent: true)
end
end

# Returns an array of strings of all email addresses of applications with a given status type
#
# @param type [Type] the status type of the email addresses that will be returned
# @return [Array<String>] Array of all email addresses of applications with given type
def email_addresses_of_type(type)
applications = application_letters.where(status: ApplicationLetter.statuses[type])
# @return [Array<String>] Array of all email addresses of applications with given type, that don't have status_notification_sent set
def email_addresses_of_type_without_notification_sent(type)
applications = application_letters.where(status: ApplicationLetter.statuses[type], status_notification_sent: false)
applications.collect { |a| a.user.email }
end

Expand Down
9 changes: 5 additions & 4 deletions app/models/user.rb
Original file line number Diff line number Diff line change
Expand Up @@ -119,15 +119,16 @@ def older_than_required_age_at_start_date_of_event?(given_event, age)
# @param [Event] current event (which application status will be excluded)
# @return [Int] of number of currently accepted applications
def accepted_applications_count(event)
ApplicationLetter.where(user_id: id, status: true).where.not(event: event).count()
ApplicationLetter.where(user_id: id, status: ApplicationLetter.statuses[:accepted])
.where.not(event: event).count()
end

# Returns the number of accepted applications from the user without counting status of current event application
# Returns the number of rejected applications from the user without counting status of current event application
#
# @param current event (which application status will be excluded)
# @return [Int] of number of currently accepted applications
# @return [Int] of number of currently rejected applications
def rejected_applications_count(event)
ApplicationLetter.where(user_id: id, status: false).where.not(event: event).count()
ApplicationLetter.where(user_id: id, status: ApplicationLetter.statuses[:rejected]).where.not(event: event).count()
end

# Searches all users with last/first_name containing pattern
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<%= form_for :application_letter, url: update_application_letter_status_path(application_letter), html: {method: :put} do |f| %>
<div class="form-group">
<div class="btn-group" data-toggle="buttons">
<% ApplicationLetter.statuses.keys.each do |key| %>
<% ApplicationLetter.selectable_statuses.each do |key| %>
<label class="btn btn-xs btn-default <%= 'active' if application_letter.status == key %>">
<%= f.radio_button :status,
key,
Expand Down
1 change: 0 additions & 1 deletion app/views/events/_applicants_overview.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,5 @@
<%= link_to t('events.participants.show_participants'),
event_path(@event) + "/participants" , :class => 'btn btn-primary btn-sm pull-right' %>
<% end %>

</div>
</div>
4 changes: 4 additions & 0 deletions config/locales/de.application_letters.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ de:
submit:
create: "Anmelden"
update: "Anmeldung aktualisieren"
validation:
status_cannot_be_changed: "Die Bewerbungen wurden bereits bearbeitet, eine Statusänderung ist nicht mehr erlaubt."
status_notification_sent_cannot_be_changed: "Das Status-Benachrichtungsflag kann noch nicht gesetzt werden"

fields_filled_in: "Wir haben einige Felder bereits für dich ausgefüllt. Falls sich seit deiner letzten Bewerbung etwas geändert hat, kannst du es jetzt anpassen."

Expand Down Expand Up @@ -74,6 +77,7 @@ de:
pending: "Ausstehend"
pending_before_deadline: "Beworben"
pending_after_deadline: "In Bearbeitung"
canceled: "Abgesagt"
alternative: "Nachrücker"


Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class AddStatusNotificationSentToApplicationLetters < ActiveRecord::Migration
def change
add_column :application_letters, :status_notification_sent, :boolean, default: false, null: false
end
end
13 changes: 7 additions & 6 deletions db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
#
# It's strongly recommended that you check this file into your version control system.

ActiveRecord::Schema.define(version: 20170201201932) do
ActiveRecord::Schema.define(version: 20170203180638) do

create_table "agreement_letters", force: :cascade do |t|
t.integer "user_id", null: false
Expand All @@ -26,11 +26,11 @@

create_table "application_letters", force: :cascade do |t|
t.string "motivation"
t.integer "user_id", null: false
t.integer "event_id", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "status", default: 2, null: false
t.integer "user_id", null: false
t.integer "event_id", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "status", default: 2, null: false
t.integer "grade"
t.string "coding_skills"
t.string "emergency_number"
Expand All @@ -40,6 +40,7 @@
t.text "custom_application_fields"
t.text "annotation"
t.string "organisation"
t.boolean "status_notification_sent", default: false, null: false
end

add_index "application_letters", ["event_id"], name: "index_application_letters_on_event_id"
Expand Down
6 changes: 3 additions & 3 deletions spec/controllers/email_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
expect(assigns(:email).recipients).to eq(@application.user.email)
end

it "sets @template with template for accepted emails" do
it "sets @template with template for acceptance emails" do
get :show, event_id: @event.id, status: :acceptance
expect(assigns(:templates)).to eq([@template])
end
Expand All @@ -43,7 +43,7 @@
expect(assigns(:email).recipients).to eq(@application.user.email)
end

it "sets @template with template for rejected emails" do
it "sets @template with template for rejection emails" do
get :show, event_id: @event.id, status: :rejection
expect(assigns(:templates)).to eq([@template])
end
Expand Down Expand Up @@ -145,4 +145,4 @@
end
end
end
end
end
5 changes: 5 additions & 0 deletions spec/factories/application_letters.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
event
annotation "Some"
custom_application_fields ["Value 1", "Value 2", "Value 3"]
status_notification_sent false
end

factory :application_letter2, parent: :application_letter do
Expand Down Expand Up @@ -53,6 +54,10 @@
status :alternative
end

factory :application_letter_canceled, parent: :application_letter do
status :canceled
end

factory :accepted_application_with_agreement_letters, parent: :application_letter do
status :accepted
after(:build) do |application_letter|
Expand Down
42 changes: 42 additions & 0 deletions spec/factories/events.rb
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,15 @@
end
end

trait :in_selection_phase_with_participants_locked do
after(:build) do |event|
event.published = true
event.application_deadline = Date.yesterday
event.acceptances_have_been_sent = true
event.rejections_have_been_sent = false
end
end

trait :in_selection_phase_with_acceptances_sent do
after(:build) do |event|
event.published = true
Expand Down Expand Up @@ -150,6 +159,15 @@
end
end

trait :with_no_status_notification_sent_yet do
after(:create) do |event|
event.application_letters.each do |application|
application.status_notification_sent = false
application.save! if application.changed?
end
end
end

factory :event_with_accepted_applications do
name "Event-Name"
description "Event-Description"
Expand All @@ -174,7 +192,31 @@
create_list(:accepted_application_with_agreement_letters, evaluator.accepted_application_letters_count, event: event)
end
end
end

factory :event_with_applications_in_various_states do
name "Event-Name"
description "Event-Description"
max_participants 20
date_ranges { build_list :date_range, 1 }
transient do
accepted_application_letters_count 5
rejected_application_letters_count 5
alternative_application_letters_count 2
canceled_application_letters_count 1
pending_application_letters_count 0
end
organizer "Workshop-Organizer"
knowledge_level "Workshop-Knowledge Level"
application_deadline Date.current

after(:create) do |event, evaluator|
create_list(:application_letter_accepted, evaluator.accepted_application_letters_count, event: event)
create_list(:application_letter_rejected, evaluator.rejected_application_letters_count, event: event)
create_list(:application_letter_alternative, evaluator.alternative_application_letters_count, event: event)
create_list(:application_letter_canceled, evaluator.canceled_application_letters_count, event: event)
create_list(:application_letter_pending, evaluator.pending_application_letters_count, event: event)
end
end
end
end

0 comments on commit 8d9c84c

Please sign in to comment.