Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add explicit #start_on/#end_on to Role, remove FutureRole, Role#delete_on #118

Merged
merged 12 commits into from
Nov 18, 2024
16 changes: 16 additions & 0 deletions app/domain/alumni.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# frozen_string_literal: true

# Copyright (c) 2024, Jungwacht Blauring Schweiz. This file is part of
# hitobito_jubla and licensed under the Affero General Public License version 3
# or later. See the COPYING file at the top-level directory or at
# https://github.com/hitobito/hitobito_jubla.
#
module Alumni
EXCLUDED_ROLE_TYPES = [
Jubla::Role::External,
Jubla::Role::DispatchAddress,
Jubla::Role::Alumnus
].freeze

APPLICABLE_ROLE_TYPES = (::Role.all_types - EXCLUDED_ROLE_TYPES)
end
2 changes: 1 addition & 1 deletion app/domain/group_originator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ def roles
end

def find_with_deleted
yield(roles) || yield(roles.with_deleted)
yield(roles) || yield(roles.with_inactive)
end

def find_flock(roles)
Expand Down
2 changes: 1 addition & 1 deletion app/domain/member_counter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ def members
Person.joins(:roles)
.where(roles: {group_id: flock.self_and_descendants,
type: self.class.counted_roles,
deleted_at: nil})
end_on: [nil, ..Time.zone.today]})
.distinct
end

Expand Down
36 changes: 36 additions & 0 deletions app/jobs/alumni_manager_job.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# frozen_string_literal: true

# Copyright (c) 2024, Jungwacht Blauring Schweiz. This file is part of
# hitobito_jubla and licensed under the Affero General Public License version 3
# or later. See the COPYING file at the top-level directory or at
# https://github.com/hitobito/hitobito_jubla.

class AlumniManagerJob < RecurringJob
run_every 1.day

APPLICABLE_ROLE_TYPES = Alumni::APPLICABLE_ROLE_TYPES.map(&:sti_name)

def perform_internal
destroy_obsolete
create_missing
end

def create_missing
alumni = Person.joins(:roles).merge(Role.alumnus_members).distinct
inactive = Role.ended_or_archived.where(type: APPLICABLE_ROLE_TYPES)
inactive.where.not(person_id: alumni).find_each do |role|
Jubla::Role::AlumnusManager.new(role).create
end
end

def destroy_obsolete
active = Person.joins(:roles).merge(Role.where(type: APPLICABLE_ROLE_TYPES)).distinct
Role.alumnus_members.where(person_id: active).find_each do |role|
Jubla::Role::AlumnusManager.new(role).destroy
end
end

def next_run
interval.from_now.midnight + 1.minute
end
end
2 changes: 1 addition & 1 deletion app/jobs/census_invitation_job.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ def perform

def recipients
Person.joins(:roles)
.where(roles: {type: RECIPIENT_ROLES.collect(&:sti_name), deleted_at: nil})
.where(roles: {type: RECIPIENT_ROLES.collect(&:sti_name), end_on: [nil, ..Time.zone.today]})
.distinct
end

Expand Down
2 changes: 1 addition & 1 deletion app/models/jubla/group.rb
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ module Jubla::Group
def delete_alumni_groups
alumni_groups = children.where(type: ALUMNI_GROUPS_CLASSES)
# Hard delete alumni roles because the alumni groups are also hard deleted
Role.with_deleted.where(group_id: alumni_groups.select(:id)).delete_all
Role.with_inactive.where(group_id: alumni_groups.select(:id)).delete_all
alumni_groups.delete_all
end
end
Expand Down
4 changes: 1 addition & 3 deletions app/models/jubla/role.rb
Original file line number Diff line number Diff line change
Expand Up @@ -103,9 +103,7 @@ def alumnus_member?
end

def alumnus_applicable?
[Jubla::Role::External,
Jubla::Role::DispatchAddress,
Jubla::Role::Alumnus].none? { |r| is_a?(r) } && !group.alumnus?
!group.alumnus? && Alumni::EXCLUDED_ROLE_TYPES.none? { |type| is_a?(type) }
end

def roles_in_layer
Expand Down
2 changes: 2 additions & 0 deletions app/views/people/_roles.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,5 @@

= render 'roles_aside', title: 'Aktive Rollen', grouped_roles: entry.active_roles_grouped, primary_group_link: true
= render 'roles_aside_jubla', title: 'Ehemalige Rollen', grouped_roles: entry.inactive_roles_grouped
- if entry.future_roles_grouped.any?
= render 'roles_aside', title: t('.convertable_title'), grouped_roles: entry.future_roles_grouped
6 changes: 3 additions & 3 deletions app/views/people/_roles_aside_jubla.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
- grouped_roles.each do |group, roles|
%tr
%td
- if can?(:primary_group, entry) && !roles.any? { |role|role.deleted_at }
- if can?(:primary_group, entry) && !roles.any? { |role| role.end_on }
= link_to(icon('star', filled: (entry.primary_group_id == group.id)),
primary_group_group_person_path(@group, entry, primary_group_id: group.id),
title: t('.set_main_group'),
Expand All @@ -30,11 +30,11 @@
%td
%strong
= role.to_s
- unless role.deleted_at
- unless role.end_on
%td= link_action_edit(edit_group_role_path(role.group, role)) if can?(:edit, role)
%td= link_action_destroy(group_role_path(role.group, role)) if can?(:destroy, role)
- else
%td{colspan: 2, class: "nowrap"}
= role.created_at.year
= "-"
= role.deleted_at.year
= role.end_on.year
7 changes: 4 additions & 3 deletions config/locales/models.de.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@

de:
activerecord:

models:
group/root: Organisation
group/root/admin:
Expand Down Expand Up @@ -330,7 +329,6 @@ de:

jubla/event/course/advisor: Betreuung


attributes:
person:
name_mother: Name Mutter
Expand Down Expand Up @@ -371,6 +369,9 @@ de:
employment_percent: Stellenprozente
honorary: Ehrenamt
class:
permission:
description:
alumnus_below_full: Lesen und Schreiben auf dieser Gruppe und allen darunter liegenden Alumnus Gruppen.
kind:
alumnus:
one: Ehemalig
Expand Down Expand Up @@ -418,4 +419,4 @@ de:
messages:
must_be_multiple_of: muss ein vielfaches von %{multiple} sein.
other_roles_exists: Es befinden sich noch andere aktive Rollen in diesem Layer
cannot_import_alumnus: '%{name} wird nicht als Ehemaligenmitglied hinzugefügt, da er/sie noch eine aktive Rolle hat'
cannot_import_alumnus: "%{name} wird nicht als Ehemaligenmitglied hinzugefügt, da er/sie noch eine aktive Rolle hat"
159 changes: 74 additions & 85 deletions db/migrate/20121218090000_extract_different_group_types.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
# encoding: utf-8

# Copyright (c) 2012-2013, Jungwacht Blauring Schweiz. This file is part of
# hitobito_jubla and licensed under the Affero General Public License version 3
# or later. See the COPYING file at the top-level directory or at
Expand All @@ -8,118 +6,109 @@
class ExtractDifferentGroupTypes < ActiveRecord::Migration[4.2]
def up
# work groups
update_types(:groups, 'Group::WorkGroup', 'Group::Federation', 'Group::FederalWorkGroup')
update_types(:roles, 'Group::WorkGroup::Leader', 'Group::Federation', 'Group::FederalWorkGroup::Leader')
update_types(:roles, 'Group::WorkGroup::Member', 'Group::Federation', 'Group::FederalWorkGroup::Member')

update_types(:groups, 'Group::WorkGroup', 'Group::State', 'Group::StateWorkGroup')
update_types(:roles, 'Group::WorkGroup::Leader', 'Group::State', 'Group::StateWorkGroup::Leader')
update_types(:roles, 'Group::WorkGroup::Member', 'Group::State', 'Group::StateWorkGroup::Member')
update_types(:groups, "Group::WorkGroup", "Group::Federation", "Group::FederalWorkGroup")
update_types(:roles, "Group::WorkGroup::Leader", "Group::Federation", "Group::FederalWorkGroup::Leader")
update_types(:roles, "Group::WorkGroup::Member", "Group::Federation", "Group::FederalWorkGroup::Member")

update_types(:groups, 'Group::WorkGroup', 'Group::Region', 'Group::RegionalWorkGroup')
update_types(:roles, 'Group::WorkGroup::Leader', 'Group::Region', 'Group::RegionalWorkGroup::Leader')
update_types(:roles, 'Group::WorkGroup::Member', 'Group::Region', 'Group::RegionalWorkGroup::Member')
update_types(:groups, "Group::WorkGroup", "Group::State", "Group::StateWorkGroup")
update_types(:roles, "Group::WorkGroup::Leader", "Group::State", "Group::StateWorkGroup::Leader")
update_types(:roles, "Group::WorkGroup::Member", "Group::State", "Group::StateWorkGroup::Member")

update_types(:groups, "Group::WorkGroup", "Group::Region", "Group::RegionalWorkGroup")
update_types(:roles, "Group::WorkGroup::Leader", "Group::Region", "Group::RegionalWorkGroup::Leader")
update_types(:roles, "Group::WorkGroup::Member", "Group::Region", "Group::RegionalWorkGroup::Member")

# professional groups
update_types(:groups, 'Group::ProfessionalGroup', 'Group::Federation', 'Group::FederalProfessionalGroup')
update_types(:roles, 'Group::ProfessionalGroup::Leader', 'Group::Federation', 'Group::FederalProfessionalGroup::Leader')
update_types(:roles, 'Group::ProfessionalGroup::Member', 'Group::Federation', 'Group::FederalProfessionalGroup::Member')

update_types(:groups, 'Group::ProfessionalGroup', 'Group::State', 'Group::StateProfessionalGroup')
update_types(:roles, 'Group::ProfessionalGroup::Leader', 'Group::State', 'Group::StateProfessionalGroup::Leader')
update_types(:roles, 'Group::ProfessionalGroup::Member', 'Group::State', 'Group::StateProfessionalGroup::Member')
update_types(:groups, "Group::ProfessionalGroup", "Group::Federation", "Group::FederalProfessionalGroup")
update_types(:roles, "Group::ProfessionalGroup::Leader", "Group::Federation", "Group::FederalProfessionalGroup::Leader")
update_types(:roles, "Group::ProfessionalGroup::Member", "Group::Federation", "Group::FederalProfessionalGroup::Member")

update_types(:groups, 'Group::ProfessionalGroup', 'Group::Region', 'Group::RegionalProfessionalGroup')
update_types(:roles, 'Group::ProfessionalGroup::Leader', 'Group::Region', 'Group::RegionalProfessionalGroup::Leader')
update_types(:roles, 'Group::ProfessionalGroup::Member', 'Group::Region', 'Group::RegionalProfessionalGroup::Member')
update_types(:groups, "Group::ProfessionalGroup", "Group::State", "Group::StateProfessionalGroup")
update_types(:roles, "Group::ProfessionalGroup::Leader", "Group::State", "Group::StateProfessionalGroup::Leader")
update_types(:roles, "Group::ProfessionalGroup::Member", "Group::State", "Group::StateProfessionalGroup::Member")

update_types(:groups, "Group::ProfessionalGroup", "Group::Region", "Group::RegionalProfessionalGroup")
update_types(:roles, "Group::ProfessionalGroup::Leader", "Group::Region", "Group::RegionalProfessionalGroup::Leader")
update_types(:roles, "Group::ProfessionalGroup::Member", "Group::Region", "Group::RegionalProfessionalGroup::Member")

# coaches
update_types(:roles, 'Jubla::Role::Coach', 'Group::State', 'Group::State::Coach')
update_types(:roles, 'Jubla::Role::Coach', 'Group::Region', 'Group::Region::Coach')

update_types(:roles, "Jubla::Role::Coach", "Group::State", "Group::State::Coach")
update_types(:roles, "Jubla::Role::Coach", "Group::Region", "Group::Region::Coach")

# filters
role_types = defined?(PeopleFilter::RoleType) ? PeopleFilter::RoleType : RelatedRoleType
role_types.where(role_type: %w(Group::WorkGroup::Leader
Group::WorkGroup::Member
Group::ProfessionalGroup::Leader
Group::ProfessionalGroup::Member
Jubla::Role::Coach)).
destroy_all
role_types.where(role_type: %w[Group::WorkGroup::Leader
Group::WorkGroup::Member
Group::ProfessionalGroup::Leader
Group::ProfessionalGroup::Member
Jubla::Role::Coach])
.destroy_all
end

def down
# professional groups
Group.with_deleted.
where(type: %w(Group::FederalProfessionalGroup
Group::StateProfessionalGroup
Group::RegionalProfessionalGroup)).
update_all(type: 'Group::ProfessionalGroup')

Role.with_deleted.
where(type: %w(Group::FederalProfessionalGroup::Leader
Group::StateProfessionalGroup::Leader
Group::RegionalProfessionalGroup::Leader)).
update_all(type: 'Group::ProfessionalGroup::Leader')

Role.with_deleted.
where(type: %w(Group::FederalProfessionalGroup::Member
Group::StateProfessionalGroup::Member
Group::RegionalProfessionalGroup::Member)).
update_all(type: 'Group::ProfessionalGroup::Member')

Group.with_deleted
.where(type: %w[Group::FederalProfessionalGroup
Group::StateProfessionalGroup
Group::RegionalProfessionalGroup])
.update_all(type: "Group::ProfessionalGroup")

Role.with_inactive
.where(type: %w[Group::FederalProfessionalGroup::Leader
Group::StateProfessionalGroup::Leader
Group::RegionalProfessionalGroup::Leader])
.update_all(type: "Group::ProfessionalGroup::Leader")

Role.with_inactive
.where(type: %w[Group::FederalProfessionalGroup::Member
Group::StateProfessionalGroup::Member
Group::RegionalProfessionalGroup::Member])
.update_all(type: "Group::ProfessionalGroup::Member")

# work groups
Group.with_deleted.
where(type: %w(Group::FederalWorkGroup
Group::StateWorkGroup
Group::RegionalWorkGroup)).
update_all(type: 'Group::WorkGroup')

Role.with_deleted.
where(type: %w(Group::FederalWorkGroup::Leader
Group::StateWorkGroup::Leader
Group::RegionalWorkGroup::Leader)).
update_all(type: 'Group::WorkGroup::Leader')

Role.with_deleted.
where(type: %w(Group::FederalWorkGroup::Member
Group::StateWorkGroup::Member
Group::RegionalWorkGroup::Member)).
update_all(type: 'Group::WorkGroup::Member')
Group.with_deleted
.where(type: %w[Group::FederalWorkGroup
Group::StateWorkGroup
Group::RegionalWorkGroup])
.update_all(type: "Group::WorkGroup")

Role.with_inactive
.where(type: %w[Group::FederalWorkGroup::Leader
Group::StateWorkGroup::Leader
Group::RegionalWorkGroup::Leader])
.update_all(type: "Group::WorkGroup::Leader")

Role.with_inactive
.where(type: %w[Group::FederalWorkGroup::Member
Group::StateWorkGroup::Member
Group::RegionalWorkGroup::Member])
.update_all(type: "Group::WorkGroup::Member")

# coaches
Role.with_deleted.
where(type: %w(Group::State::Coach
Group::Region::Coach)).
update_all(type: 'Jubla::Role::Coach')
Role.with_inactive
.where(type: %w[Group::State::Coach
Group::Region::Coach])
.update_all(type: "Jubla::Role::Coach")
end

private

def update_types(kind, old_type, layer, new_type)
key = mysql? ? "`#{kind}`.type" : 'type'
send(kind, old_type, layer).update_all("#{key} = '#{new_type}'")
send(kind, old_type, layer).update_all("type = '#{new_type}'")
end

def roles(type, layer)
Role.with_deleted.
joins("LEFT JOIN #{Group.quoted_table_name} AS #{Group.quoted_table_name} ON #{Group.quoted_table_name}.id = roles.group_id " +
"LEFT JOIN #{Group.quoted_table_name} AS layer ON #{Group.quoted_table_name}.layer_group_id = layer.id").
where(type: type).
where('layer.type = ?', layer)
Role.with_inactive
.joins("LEFT JOIN #{Group.quoted_table_name} AS #{Group.quoted_table_name} ON #{Group.quoted_table_name}.id = roles.group_id " \
"LEFT JOIN #{Group.quoted_table_name} AS layer ON #{Group.quoted_table_name}.layer_group_id = layer.id")
.where(type: type)
.where("layer.type = ?", layer)
end

def groups(type, layer)
Group.with_deleted.
joins("LEFT JOIN #{Group.quoted_table_name} AS layer ON #{Group.quoted_table_name}.layer_group_id = layer.id").
where(type: type).
where('layer.type = ?', layer)
end

def mysql?
Role.connection.adapter_name.downcase =~ /mysql/
Group.with_deleted
.joins("LEFT JOIN #{Group.quoted_table_name} AS layer ON #{Group.quoted_table_name}.layer_group_id = layer.id")
.where(type: type)
.where("layer.type = ?", layer)
end
end
Loading
Loading