Commit aec79283 authored by Jiri Strojil's avatar Jiri Strojil

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
test 'filter semester process volunteer on semester' do
click_button "Semester: #{@current_semester.previous_s[0..3]},#{@current_semester.previous_s[5]}", match: :first
click_link "#{@current_semester.previous_s(2)[5]}. Semester #{@current_semester.previous_s(2)[0..3]}"
assert_not page.has_text? "#{@current_semester.previous_s[5]}. Semester #{@current_semester.previous_s[0..3]}"
assert page.has_text? "#{@current_semester.previous_s(2)[5]}. Semester #{@current_semester.previous_s(2)[0..3]}"
assert_not page.has_text? "#{@current_semester.previous_s(3)[5]}. Semester #{@current_semester.previous_s(3)[0..3]}"
assert_not page.has_text? @one_semester_back.semester_process_volunteers.first.semester_feedbacks.first.goals
assert page.has_text? @two_semesters_back.semester_process_volunteers.first.semester_feedbacks.first.goals
assert_not page.has_text? @three_semesters_back.semester_process_volunteers.first.semester_feedbacks.first.goals
end
end
......@@ -25,7 +25,8 @@ class ActiveSupport::TestCase
Feedback, TrialFeedback, Hour, Journal, BillingExpense, Certificate, Import,
AssignmentLog, Assignment, GroupAssignmentLog, GroupAssignment, GroupOffer,
ClientNotification, LanguageSkill, Relative, Event, EventVolunteer,
Volunteer, Client, User, Contact, Department
Volunteer, Client, User, Contact, Department, SemesterProcess, SemesterFeedback,
SemesterProcessVolunteer, SemesterProcessVolunteerMission
)
super
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment