Commit aec79283 authored by Jiri Strojil's avatar Jiri Strojil
Browse files

Resolved conflict

parents 2a659e9d a3eb4e25
Pipeline #31143 passed with stage
in 56 minutes and 51 seconds
.form-group.float.optional.semester_process_volunteer_semester_feedbacks_hour_hours {
display: inline-flex;
}
class SemesterProcessVolunteersController < ApplicationController
before_action :prepare_review, only: [:review_semester, :submit_review]
before_action :initialize_feedback, only: [:review_semester, :submit_review]
before_action :set_semester_process_volunteer, only: [:show, :edit, :update]
before_action :prepare_review, :initialize_nested_objects, only: [:review_semester, :submit_review]
before_action :set_semester_process_volunteer, only: [:show, :edit, :update, :take_responsibility]
before_action :set_semester, only: [:index]
include SemesterProcessVolunteerHelper
def review_semester
@hour = Hour.new
end
def submit_review
assign_reviewed_attributes
# you shall not pass
return if @semester_process_volunteer.commited_at
set_reviewed
assign_volunteer_attributes
build_nested_objects
@semester_process_volunteer.volunteer.validate_waive_and_bank = true
begin
ActiveRecord::Base.transaction do
@semester_process_volunteer.semester_feedbacks << @feedback
@hour.save! unless @hour.hours == 0 || @hour.hours.blank?
@semester_process_volunteer.save!
@volunteer.save!
end
redirect_to(
review_semester_semester_process_volunteer_path(@semester_process_volunteer),
notice: 'Successfully reviewed.'
)
rescue ActiveRecord::RecordInvalid => exception
null_reviewed
@hours.reload
render :review_semester, notice: exception
ActiveRecord::Base.transaction do
@semester_process_volunteer.save!
@volunteer.save!
@nested_objects.each do |_key, hash|
hash.each { |_id, obj| obj.save! }
end
end
redirect_to review_semester_semester_process_volunteer_path(@semester_process_volunteer), notice: t('.success')
rescue ActiveRecord::RecordInvalid => exception
logger.error exception.message
null_reviewed
flash[:alert] = exception.message
render :review_semester
end
def index
authorize SemesterProcessVolunteer
semester = Semester.parse(params[:semester])
@spvs = SemesterProcessVolunteer.index(semester).page(params[:page])
@semester_process = SemesterProcess.find_by_semester(semester).last
@spvs_sorted = @spvs.sort { |spv1, spv2| spv1.volunteer.contact.full_name <=> spv2.volunteer.contact.full_name}
@q = SemesterProcessVolunteer.index(semester).ransack(params[:q])
@q.sorts = ['volunteer_contact_last_name asc'] if @q.sorts.empty?
@spvs = @q.result.paginate(page: params[:page])
set_responsibles
end
def show; end
......@@ -53,23 +58,36 @@ class SemesterProcessVolunteersController < ApplicationController
end
end
def take_responsibility
respond_to do |format|
if @spv.update(responsible: current_user)
format.html { redirect_to(@redirect_back_path, notice: 'Halbjahres-Rapport übernommen.') }
format.json do
render json: { link: url_for(@spv.responsible), at: I18n.l(@spv.responsibility_taken_at.to_date),
email: @spv.responsible.email }, status: :ok
end
else
format.html { redirect_to(@redirect_back_path, notice: 'Fehler: Übernehmen fehlgeschlagen.') }
format.json { render json: { errors: @spv.errors.messages }, status: :unprocessable_entity }
end
end
end
private
def prepare_review
# careful cuz mission id can be present in both missions
@semester_process_volunteer = SemesterProcessVolunteer.find(params[:id])
@hours = @semester_process_volunteer.hours
@volunteer = @semester_process_volunteer.volunteer
@mission = @semester_process_volunteer.missions.first
authorize @semester_process_volunteer
@volunteer = @semester_process_volunteer.volunteer
@missions = @semester_process_volunteer.missions
end
def review_params
params.require(:semester_process_volunteer).permit(
volunteer_attributes: [:waive, :iban, :bank],
semester_feedback: [:goals, :achievements, :future, :comments, :conversation],
hour: [:hours]
)
volunteer_attributes: [:id ,:waive, :iban, :bank],
semester_feedbacks_attributes: [[semester_feedback: [:mission, :goals, :achievements, :future, :comments, :conversation, :spv_mission_id]],
[hour: [:hours, :spv_mission_id ]]])
end
def set_semester_process_volunteer
......@@ -89,6 +107,19 @@ class SemesterProcessVolunteersController < ApplicationController
end
end
def set_responsibles
@responsibles = SemesterProcessVolunteer.joins(responsible: [profile: [:contact]])
.distinct
.select('users.id, contacts.full_name')
.map do |responsible|
{
q: :responsible_id_eq,
text: "Übernommen von #{responsible.full_name}",
value: responsible.id
}
end
end
def semester_process_volunteer_params
params.require(:semester_process_volunteer).permit(:semester)
end
......
module SemesterProcessVolunteerHelper
def initialize_feedback
@feedback = SemesterFeedback.new(mission: @mission, semester_process_volunteer: @semester_process_volunteer,
author: current_user)
end
def set_reviewed
@semester_process_volunteer.commited_by = current_user
@semester_process_volunteer.commited_at = Time.zone.now
end
def assign_reviewed_attributes
@hour = Hour.new(
volunteer: @volunteer,
hourable: @mission,
semester_process_volunteer: @semester_process_volunteer,
meeting_date: Time.zone.now,
)
@hour.assign_attributes(review_params[:hour])
def initialize_nested_objects
@nested_objects = {}
@semester_process_volunteer.semester_process_volunteer_missions.each do |spvm|
@nested_objects[spvm.id.to_s] = { feedback: @semester_process_volunteer.semester_feedback_with_mission(spvm.mission) || SemesterFeedback.new }
end
@nested_objects
end
def build_nested_objects
review_params[:semester_feedbacks_attributes].each do |_key, hash|
spv_mission = SemesterProcessVolunteerMission.find(hash[:semester_feedback][:spv_mission_id])
@nested_objects[spv_mission.id.to_s][:feedback] = SemesterFeedback.new(hash[:semester_feedback].merge({
author: current_user, semester_process_volunteer: @semester_process_volunteer
}))
if hash[:hour][:hours].to_i.positive?
@nested_objects[spv_mission.id.to_s][:hours] = Hour.new(hash[:hour].merge({
volunteer: spv_mission.volunteer,
meeting_date: Time.zone.now,
semester_process_volunteer: @semester_process_volunteer
}))
end
end
end
def assign_volunteer_attributes
@volunteer.assign_attributes(review_params[:volunteer_attributes]
.slice(:waive, :bank, :iban))
@feedback.assign_attributes(review_params[:semester_feedback])
end
def null_reviewed
......
......@@ -8,6 +8,8 @@ module MissionEitherOneRelation
validate :validate_group_assignment_or_assignment_present
attr_accessor :mission_id
def mission=(mission)
if mission.class.name == 'Assignment'
self.assignment = mission
......
......@@ -45,6 +45,13 @@ class Hour < ApplicationRecord
group_offer.where(hourable_id: group_offer_ids)
}
attr_reader :spv_mission_id
def spv_mission_id= id
spv_mission = SemesterProcessVolunteerMission.find(id)
self.hourable = spv_mission.mission.group_assignment? ? spv_mission.mission.group_offer : spv_mission.mission
end
def assignment?
hourable_type == 'Assignment'
end
......
......@@ -5,6 +5,11 @@ class SemesterFeedback < ApplicationRecord
belongs_to :semester_process_volunteer
has_one :semester_process, through: :semester_process_volunteer
has_one :volunteer, through: :semester_process_volunteer
validates :goals, :achievements, :future, presence: true
attr_reader :spv_mission_id
def spv_mission_id= id
self.mission = SemesterProcessVolunteerMission.find(id).mission
end
end
......@@ -28,7 +28,7 @@ class SemesterProcessVolunteer < ApplicationRecord
has_many :reminders, -> { where(kind: 'reminder') }, class_name: 'SemesterProcessMail',
foreign_key: 'semester_process_volunteer_id', inverse_of: 'semester_process_volunteer'
accepts_nested_attributes_for :hours, :volunteer, :semester_feedbacks
accepts_nested_attributes_for :group_assignments, :assignments , :semester_process_volunteer_missions , :hours, :volunteer, :semester_feedbacks
validates_associated :hours, :semester_feedbacks, :volunteer
......@@ -44,6 +44,11 @@ class SemesterProcessVolunteer < ApplicationRecord
end
}
def semester_feedback_with_mission(mission)
self.semester_feedbacks.order(:created_at).select{|sf| sf.mission == mission}.last
end
# will only return an array, not a AD-result
def missions
semester_process_volunteer_missions.map(&:mission)
......@@ -70,4 +75,9 @@ class SemesterProcessVolunteer < ApplicationRecord
def render_feedback(field)
semester_feedbacks.map(&field).join(', ')
end
def responsible=(responsible_user)
self.responsibility_taken_at = Time.zone.now
super(responsible_user)
end
end
class SemesterProcessVolunteerMission < ApplicationRecord
include MissionEitherOneRelation
delegate :volunteer, to: :semester_process_volunteer
belongs_to :semester_process_volunteer
end
......@@ -7,13 +7,14 @@ class SemesterProcessVolunteerPolicy < ApplicationPolicy
end
# Actions
alias_method :index?, :superadmin?
alias_method :review_semester?, :superadmin_or_volunteer_related?
alias_method :submit_review?, :superadmin_or_volunteer_related?
alias_method :new?, :superadmin?
alias_method :show?, :superadmin?
alias_method :edit?, :superadmin?
alias_method :create?, :superadmin?
alias_method :update?, :superadmin?
alias_method :destroy?, :superadmin?
alias_method :index?, :superadmin?
alias_method :review_semester?, :superadmin_or_volunteer_related?
alias_method :submit_review?, :superadmin_or_volunteer_related?
alias_method :new?, :superadmin?
alias_method :show?, :superadmin?
alias_method :edit?, :superadmin?
alias_method :create?, :superadmin?
alias_method :update?, :superadmin?
alias_method :destroy?, :superadmin?
alias_method :take_responsibility?, :superadmin?
end
nav.navbar.section-navigation
hr
ul.list-inline
li= clear_filter_button
li= button_link 'Neuen Semester Prozess erstellen', new_semester_process_path, dimension: 'sm'
li= render 'semester_filter'
- if @semester_process
li= button_link 'Semester Prozess bearbeiten', edit_semester_process_path(@semester_process), dimension: 'sm'
= custom_filter_dropdown('Übernommen',
{ q: :responsible_id_null, text: 'Offen', value: 'true' },
{ q: :responsible_id_not_null, text: 'Übernommen', value: 'true' },
*@responsibles)
hr
......@@ -12,16 +12,16 @@ h1= t_title(:index)
th Status
th Freiwilige/r
th Einsätze
th Missions
th Ziele
th Erfolge
th Zukunft
th Bemerkungen
th= t_attr(:commited_by)
th Letzte Bestätigung
th= sort_link @q, :responsible_profile_contact_full_name, 'Übernommen'
tbody
- @spvs_sorted.each do |spv|
- @spvs.each do |spv|
tr
td.index-action-cell.hidden-print
= button_link icon_span(:edit), review_semester_semester_process_volunteer_path(spv), title: 'Bearbeiten'
......@@ -31,7 +31,6 @@ h1= t_title(:index)
- else
.label.label-warning Unbestätigt
td= link_to_if policy(Volunteer).edit?, spv.volunteer.contact.full_name, edit_volunteer_path(spv.volunteer)
td= spv.semester_t
td= render_missions(spv)
= td_truncate_content_modal(spv.render_feedback(:goals), 'Ziele', shorten_size: 300)
= td_truncate_content_modal(spv.render_feedback(:achievements), 'Erfolge', shorten_size: 300)
......@@ -39,6 +38,15 @@ h1= t_title(:index)
= td_truncate_content_modal(spv.render_feedback(:comments), 'Bemerkungen', shorten_size: 300)
td= spv.commited_by
td= spv.commited_at && l(spv.commited_at)
td.index-action-cell.hidden-print
- if spv.responsible.present?
= 'Übernommen durch '
= link_to spv.responsible.email, spv.responsible
= " am #{l(spv.responsibility_taken_at.to_date)}"
- else
= api_button('Übernehmen', subject: [spv],
action: :take_responsibility, extra_class: 'm-t-10',
template: 'Übernommen durch <a href="<%= data.link %>"><%= data.email %></a> am <%= data.at %>')
= bootstrap_paginate(@spvs)
......
......@@ -3,24 +3,31 @@
= simple_error_notice f
h1 Halbjahres-Rapporte #{@semester_process_volunteer.semester_t} für #{@semester_process_volunteer.volunteer.contact.full_name}
h2.m-b-20.m-t-30
'Einsatz
= link_to @mission.to_label, polymorphic_path([@mission.volunteer, @mission.polymorph_url_object]), target: '_blank'
= f.simple_fields_for :semester_feedbacks, @semester_process_volunteer.semester_process_volunteer_missions do |spvm|
- mission = spvm.object.mission
h2.m-b-20.m-t-30
'Einsatz
= link_to mission.to_label,
url: polymorphic_path([mission.volunteer, mission.polymorph_url_object]),
target: '_blank'
= f.simple_fields_for @feedback do |ff|
- [:goals, :achievements, :future, :comments, :conversation].each do |field|
.row
.col-xs-12= ff.input field
= spvm.simple_fields_for :semester_feedback, @nested_objects[spvm.object.id.to_s][:feedback] do |ff|
= ff.input :spv_mission_id, as: :hidden, input_html: { value: spvm.object.id }
- [:goals, :achievements, :future, :comments, :conversation].each do |field|
.row
.col-xs-12= ff.input field
- if @hours.any?
h3 Stunden
= render 'hours/last_submitted_hours', hours: @hours
- if mission.hours.any?
h3 Stunden
= render 'hours/last_submitted_hours', hours: mission.hours
= spvm.simple_fields_for :hour, Hour.new do |hf|
= hf.input :spv_mission_id, as: :hidden, input_html: { value: spvm.object.id}
.row
.col-xs-12= hf.input :hours, label: "Restliche Stunden in diesem Semester #{@semester_process_volunteer.semester_period}",
input_html: { value: f.object.hours == 0 ? '' : f.object.hours, min: 0},
required: false
= f.simple_fields_for @hour do |hf|
.row
.col-xs-2= hf.input :hours,
label: "Restliche Stunden in diesem Semester #{@semester_process_volunteer.semester_period}",
required: false, input_html: { value: f.object.hours == 0 ? '' : f.object.hours}
h3 Spesen
= f.simple_fields_for :volunteer, @volunteer do |vf|
......
......@@ -193,6 +193,8 @@ de:
semester_process_volunteers:
show:
title: 'Semester Prozess %{semester} von %{name}'
submit_review:
success: Erfolgreich überprüft
salutation: &id-salutations
all: Alle
family: Familie
......
......@@ -100,6 +100,7 @@ Rails.application.routes.draw do
resources :semester_process_volunteers do
get :review_semester, on: :member
patch :submit_review, on: :member
put :take_responsibility, on: :member
end
resources :semester_processes, except: [:destroy]
......
......@@ -30,6 +30,7 @@ FactoryBot.define do
end
sem_fb.volunteer = sem_fb.semester_process_volunteer.volunteer
sem_fb.author = sem_fb.volunteer.user
sem_fb.goals = sem_fb.semester_process_volunteer.semester_t
end
after(:create) do |sem_fb, evl|
......
......@@ -19,7 +19,7 @@ FactoryBot.define do
after(:create) do |sem_proc, evaluator|
if evaluator.build_volunteers
evaluator.volunteers_count.times do
create :semester_process_volunteer, :with_mission, semester_process: sem_proc
create :semester_process_volunteer, :with_mission, :with_feedbacks, semester_process: sem_proc
end
end
end
......
require 'test_helper'
class SemesterProcessVolunteerTest < ActiveSupport::TestCase
def setup
@volunteer = create(:volunteer_with_user)
@assignment = create(:assignment, volunteer: @volunteer)
@group_assignment = create(:group_assignment, volunteer: @volunteer)
@subject = create(:semester_process_volunteer, volunteer: @volunteer)
end
test 'set responsible also sets responsibility taken at' do
@subject.update(responsible: create(:user))
assert @subject.responsibility_taken_at.present?
end
end
require 'application_system_test_case'
class SemesterProcessVolunteerActionsTest < ApplicationSystemTestCase
setup do
@superadmin = create :user
@volunteer = create :volunteer_with_user
@volunteer.contact.update(first_name: 'Walter', last_name: 'White')
@assignment = create :assignment, volunteer: @volunteer
@group_assignment = create :group_assignment, volunteer: @volunteer
@semester_process = create :semester_process
@spv1 = create(:semester_process_volunteer, :with_mission, volunteer: @volunteer,
semester_process: @semester_process)
login_as @superadmin
end
test 'take responsibility for semester process volunteer works' do
visit semester_process_volunteers_path
within 'tbody' do
page.find("[data-url$=\"#{take_responsibility_semester_process_volunteer_path(@spv1)}\"]").click
end
wait_for_ajax
@spv1.reload
assert page.has_text? "Übernommen durch #{@superadmin.email}"\
" am #{I18n.l(@spv1.responsibility_taken_at.to_date)}"
end
test 'take responsibility for semester process volunteer filter works' do
login_as @superadmin
visit semester_process_volunteers_path
## SETUP ##
# Offen/open -> @spv1
# Übernommen/responsibility taken over from superadmin1
@volunteer2 = create :volunteer_with_user
@volunteer2.contact.update(first_name: 'volunteer2', last_name: 'volunteer2')
@spv2 = create(:semester_process_volunteer, :with_mission, volunteer: @volunteer2,
semester_process: create(:semester_process))
@superadmin2 = create :user
@spv2.update(responsible: @superadmin2)
# Übernommen/responsibility taken over from superadmin2
@volunteer3 = create :volunteer_with_user
@volunteer3.contact.update(first_name: 'volunteer3', last_name: 'volunteer3')
@spv3 = create(:semester_process_volunteer, :with_mission, volunteer: @volunteer3,
semester_process: create(:semester_process))
@superadmin3 = create :user
@spv3.update(responsible: @superadmin3)
## SETUP END ##
# filter for Alle/all
within page.find_all('nav.section-navigation').last do
click_link 'Übernommen'
click_link 'Alle'
end
visit current_url
within 'tbody' do
assert page.find("[data-url$=\"#{take_responsibility_semester_process_volunteer_path(@spv1)}\"]")
end
assert page.has_text? "Übernommen durch #{@superadmin2.email}"\
" am #{I18n.l(@spv2.responsibility_taken_at.to_date)}"
assert page.has_text? "Übernommen durch #{@superadmin3.email}"\
" am #{I18n.l(@spv3.responsibility_taken_at.to_date)}"
# filter for Offen/open
within page.find_all('nav.section-navigation').last do
click_link 'Übernommen'
click_link 'Offen'
end
visit current_url
within 'tbody' do
assert page.find("[data-url$=\"#{take_responsibility_semester_process_volunteer_path(@spv1)}\"]")
end
refute page.has_text? "Übernommen durch #{@superadmin2.email}"\
" am #{I18n.l(@spv2.responsibility_taken_at.to_date)}"
refute page.has_text? "Übernommen durch #{@superadmin3.email}"\
" am #{I18n.l(@spv3.responsibility_taken_at.to_date)}"
# filter for Übernommen/responsibility taken over in general
click_link 'Übernommen: Offen', match: :first
within 'li.dropdown.open' do
click_link 'Übernommen'
end
visit current_url
refute page.has_link? 'Übernehmen', href: take_responsibility_semester_process_volunteer_path(@spv1)
assert page.has_text? "Übernommen durch #{@superadmin2.email}"\
" am #{I18n.l(@spv2.responsibility_taken_at.to_date)}"
assert page.has_text? "Übernommen durch #{@superadmin3.email}"\
" am #{I18n.l(@spv3.responsibility_taken_at.to_date)}"
# filter for Übernommen von superadmin1/responsibility taken over by superadmin1
click_link 'Übernommen: Übernommen', match: :first
within 'li.dropdown.open' do
assert page.has_link? "Übernommen von #{@superadmin2.profile.contact.full_name}"
assert page.has_link? "Übernommen von #{@superadmin3.profile.contact.full_name}"
click_link "Übernommen von #{@superadmin2.profile.contact.full_name}"
end
visit current_url
refute page.has_link? 'Übernehmen', href: take_responsibility_semester_process_volunteer_path(@spv1)
assert page.has_text? "Übernommen durch #{@superadmin2.email}"\
" am #{I18n.l(@spv2.responsibility_taken_at.to_date)}"
refute page.has_text? "Übernommen durch #{@superadmin3.email}"\
" am #{I18n.l(@spv3.responsibility_taken_at.to_date)}"
end
end
......@@ -3,23 +3,23 @@ require 'application_system_test_case'
class SemesterProcessVolunteersTest < ApplicationSystemTestCase
setup do
@current_semester = Semester.new
create :semester_process, :with_volunteers, semester: @current_semester.previous_s
create :semester_process, :with_volunteers, semester: @current_semester.previous_s(2)
create :semester_process, :with_volunteers, semester: @current_semester.previous_s(3)
@one_semester_back = create :semester_process, :with_volunteers, semester: @current_semester.previous_s
@two_semesters_back = create :semester_process, :with_volunteers, semester: @current_semester.previous_s(2)
@three_semesters_back = create :semester_process, :with_volunteers, semester: @current_semester.previous_s(3)
login_as create(:user)
visit semester_process_volunteers_path
end
test 'filter semester process volunteer shows previous semester by default' do
assert page.has_text? "#{@current_semester.previous_s[5]}. Semester #{@current_semester.previous_s[0..3]}"
assert_not page.has_text? "#{@current_semester.previous_s(2)[5]}. Semester #{@current_semester.previous_s(2)[0..3]}"
assert page.has_text? @one_semester_back.semester_process_volunteers.first.semester_feedbacks.first.goals
assert_not page.has_text? @two_semesters_back.semester_process_volunteers.first.semester_feedbacks.first.goals
end