From b2c9f7d8e096713910632bdc1364239937edf36e Mon Sep 17 00:00:00 2001 From: Diego Steiner Date: Thu, 7 Sep 2023 17:35:48 +0200 Subject: [PATCH 01/17] Implement logic for siblings_in_layer #2147 --- app/decorators/pbs/person_decorator.rb | 6 ++ spec/decorator/person_decorator_spec.rb | 61 +++++++++++++++++++ .../fabricators/people_relation_fabricator.rb | 11 ++++ 3 files changed, 78 insertions(+) create mode 100644 spec/decorator/person_decorator_spec.rb create mode 100644 spec/fabricators/people_relation_fabricator.rb diff --git a/app/decorators/pbs/person_decorator.rb b/app/decorators/pbs/person_decorator.rb index 9b2479dd0..a53c903a4 100644 --- a/app/decorators/pbs/person_decorator.rb +++ b/app/decorators/pbs/person_decorator.rb @@ -20,6 +20,12 @@ def roles_grouped(scope:) end end + def siblings_in_layer(group) + Role.joins(person: :relations_to_tails) + .where(group: group.groups_in_same_layer, person: { people_relations: { kind: :sibling, tail_id: id } }) + .any? + end + end private diff --git a/spec/decorator/person_decorator_spec.rb b/spec/decorator/person_decorator_spec.rb new file mode 100644 index 000000000..c90a527bf --- /dev/null +++ b/spec/decorator/person_decorator_spec.rb @@ -0,0 +1,61 @@ +# encoding: utf-8 + +# Copyright (c) 2017, Pfadibewegung Schweiz. This file is part of +# hitobito_pbs 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_pbs. + +require 'spec_helper' + +describe PersonDecorator do + + let(:decorator) { PersonDecorator.new(person) } + + let(:layer) { Fabricate(Group::Abteilung.name) } + + let(:person) { Fabricate(:person) } + let(:person_group) { Fabricate(Group::Pfadi.name, parent: layer)} + let!(:person_role) { Fabricate(person_group.default_role.name, person: person, group: person_group) } + + let(:sibling) { Fabricate(:person) } + let(:sibling_group) { Fabricate(Group::Woelfe.name, parent: layer)} + let!(:sibling_role) { Fabricate(sibling_group.default_role.name, person: sibling, group: sibling_group) } + + let!(:sibling_relation) { Fabricate(:people_relation, head: person, tail: sibling, kind: :sibling) } + + context 'siblings_in_layer' do + + subject do + decorator.siblings_in_layer(person_group) + end + + context 'without siblings' do + let!(:sibling_relation) { nil } + it { is_expected.to be_falsy } + end + + context 'with siblings in different groups' do + let(:sibling_group) { Fabricate(Group::Woelfe.name, parent: Fabricate(Group::Abteilung.name))} + it { is_expected.to be_falsy } + end + + context 'with siblings in same group' do + let(:sibling_group) { person_group } + it { is_expected.to be_truthy } + end + + context 'with siblings in same layer' do + it { is_expected.to be_truthy } + end + + context 'with siblings with deleted role in same group' do + let!(:sibling_role) do + Fabricate(sibling_group.default_role.name, person: sibling, group: sibling_group, + created_at: 2.months.ago, deleted_at: 1.month.ago) + end + it { is_expected.to be_falsy } + end + + end + +end diff --git a/spec/fabricators/people_relation_fabricator.rb b/spec/fabricators/people_relation_fabricator.rb new file mode 100644 index 000000000..e07216426 --- /dev/null +++ b/spec/fabricators/people_relation_fabricator.rb @@ -0,0 +1,11 @@ +# Copyright (c) 2023, Pfadibewegung Schweiz. This file is part of +# hitobito_pbs 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_pbs. + + +Fabricator(:people_relation) do + head { Fabricate(:person) } + kind { :sibling } + tail { Fabricate(:person) } +end From c2070ce7c2116d6ee9716194198f6638d43241e7 Mon Sep 17 00:00:00 2001 From: Diego Steiner Date: Tue, 12 Sep 2023 16:23:55 +0200 Subject: [PATCH 02/17] switch sibling relation from person_relations to family_members --- app/decorators/pbs/person_decorator.rb | 6 +++--- spec/decorator/person_decorator_spec.rb | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/app/decorators/pbs/person_decorator.rb b/app/decorators/pbs/person_decorator.rb index a53c903a4..e755d3163 100644 --- a/app/decorators/pbs/person_decorator.rb +++ b/app/decorators/pbs/person_decorator.rb @@ -21,9 +21,9 @@ def roles_grouped(scope:) end def siblings_in_layer(group) - Role.joins(person: :relations_to_tails) - .where(group: group.groups_in_same_layer, person: { people_relations: { kind: :sibling, tail_id: id } }) - .any? + Role.joins(person: :family_members) + .where(group: group.groups_in_same_layer, + person: { family_members: { kind: :sibling, other: self } }) end end diff --git a/spec/decorator/person_decorator_spec.rb b/spec/decorator/person_decorator_spec.rb index c90a527bf..010f5f556 100644 --- a/spec/decorator/person_decorator_spec.rb +++ b/spec/decorator/person_decorator_spec.rb @@ -21,12 +21,12 @@ let(:sibling_group) { Fabricate(Group::Woelfe.name, parent: layer)} let!(:sibling_role) { Fabricate(sibling_group.default_role.name, person: sibling, group: sibling_group) } - let!(:sibling_relation) { Fabricate(:people_relation, head: person, tail: sibling, kind: :sibling) } + let!(:sibling_relation) { Fabricate(:family_member, person: person, other: sibling, kind: :sibling) } - context 'siblings_in_layer' do + describe '#has_siblings_in_layer' do subject do - decorator.siblings_in_layer(person_group) + decorator.has_siblings_in_layer(person_group) end context 'without siblings' do From 830cff1fe5d624ab8f077bfd662b2d5361f273ab Mon Sep 17 00:00:00 2001 From: Diego Steiner Date: Tue, 12 Sep 2023 16:24:46 +0200 Subject: [PATCH 03/17] remove column brother_and_sisters from person --- app/models/pbs/person.rb | 3 +-- app/serializers/pbs/person_serializer.rb | 3 +-- ...20642_remove_brother_and_sister_from_persons.rb | 5 +++++ lib/hitobito_pbs/wagon.rb | 2 +- spec/decorator/person_decorator_spec.rb | 14 +++++++------- 5 files changed, 15 insertions(+), 12 deletions(-) create mode 100644 db/migrate/20230912120642_remove_brother_and_sister_from_persons.rb diff --git a/app/models/pbs/person.rb b/app/models/pbs/person.rb index c3c6f71ca..b2f87d6a0 100644 --- a/app/models/pbs/person.rb +++ b/app/models/pbs/person.rb @@ -62,8 +62,7 @@ module Pbs::Person alias_method_chain :full_name, :title - i18n_boolean_setter :brother_and_sisters, :prefers_digital_correspondence - + i18n_boolean_setter :prefers_digital_correspondence belongs_to :kantonalverband, class_name: 'Group' # might also be Group::Bund has_many :crises, foreign_key: :creator_id diff --git a/app/serializers/pbs/person_serializer.rb b/app/serializers/pbs/person_serializer.rb index 693df326a..b374774cb 100644 --- a/app/serializers/pbs/person_serializer.rb +++ b/app/serializers/pbs/person_serializer.rb @@ -11,8 +11,7 @@ module Pbs::PersonSerializer included do extension(:details) do |_| map_properties :pbs_number, :salutation_value, :correspondence_language, - :prefers_digital_correspondence, :grade_of_school, :brother_and_sisters, - :entry_date, :leaving_date + :prefers_digital_correspondence, :grade_of_school, :entry_date, :leaving_date end end diff --git a/db/migrate/20230912120642_remove_brother_and_sister_from_persons.rb b/db/migrate/20230912120642_remove_brother_and_sister_from_persons.rb new file mode 100644 index 000000000..c12f0cabd --- /dev/null +++ b/db/migrate/20230912120642_remove_brother_and_sister_from_persons.rb @@ -0,0 +1,5 @@ +class RemoveBrotherAndSisterFromPersons < ActiveRecord::Migration[6.1] + def change + remove_column :people, :brother_and_sisters, :boolean, default: false, null: false + end +end diff --git a/lib/hitobito_pbs/wagon.rb b/lib/hitobito_pbs/wagon.rb index b2852414c..63f66d52c 100644 --- a/lib/hitobito_pbs/wagon.rb +++ b/lib/hitobito_pbs/wagon.rb @@ -118,7 +118,7 @@ class Wagon < Rails::Engine ### controllers PeopleController.permitted_attrs += [:salutation, :title, :grade_of_school, :entry_date, :leaving_date, :j_s_number, :correspondence_language, - :prefers_digital_correspondence, :brother_and_sisters] + :prefers_digital_correspondence] GroupsController.permitted_attrs += [:hostname] Event::KindsController.permitted_attrs += [:documents_text, :campy, :can_have_confirmations, :confirmation_name] diff --git a/spec/decorator/person_decorator_spec.rb b/spec/decorator/person_decorator_spec.rb index 010f5f556..3fa29bd6a 100644 --- a/spec/decorator/person_decorator_spec.rb +++ b/spec/decorator/person_decorator_spec.rb @@ -23,29 +23,29 @@ let!(:sibling_relation) { Fabricate(:family_member, person: person, other: sibling, kind: :sibling) } - describe '#has_siblings_in_layer' do + describe '#siblings_in_layer' do subject do - decorator.has_siblings_in_layer(person_group) + decorator.siblings_in_layer(person_group) end context 'without siblings' do let!(:sibling_relation) { nil } - it { is_expected.to be_falsy } + it { is_expected.to be_empty } end context 'with siblings in different groups' do let(:sibling_group) { Fabricate(Group::Woelfe.name, parent: Fabricate(Group::Abteilung.name))} - it { is_expected.to be_falsy } + it { is_expected.to be_empty } end context 'with siblings in same group' do let(:sibling_group) { person_group } - it { is_expected.to be_truthy } + it { is_expected.to contain_exactly(sibling_role) } end context 'with siblings in same layer' do - it { is_expected.to be_truthy } + it { is_expected.to contain_exactly(sibling_role) } end context 'with siblings with deleted role in same group' do @@ -53,7 +53,7 @@ Fabricate(sibling_group.default_role.name, person: sibling, group: sibling_group, created_at: 2.months.ago, deleted_at: 1.month.ago) end - it { is_expected.to be_falsy } + it { is_expected.to be_empty } end end From 05c358454dc268c6bd6065a7104b6909be16ef81 Mon Sep 17 00:00:00 2001 From: Diego Steiner Date: Tue, 12 Sep 2023 16:26:07 +0200 Subject: [PATCH 04/17] add siblings in layer to person details view --- app/views/people/_details_pbs.html.haml | 10 +++++++++- app/views/people/_fields_pbs.html.haml | 3 --- config/locales/views.pbs.de.yml | 1 + 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/app/views/people/_details_pbs.html.haml b/app/views/people/_details_pbs.html.haml index 669040b9a..2787d4094 100644 --- a/app/views/people/_details_pbs.html.haml +++ b/app/views/people/_details_pbs.html.haml @@ -4,6 +4,14 @@ -# https://github.com/hitobito/hitobito_pbs. = render_attrs(entry, :pbs_number, :salutation, :correspondence_language, - :grade_of_school, :brother_and_sisters) + :grade_of_school) + +%dl.dl-horizontal + = labeled(t('people.fields_pbs.siblings_in_layer', layer: parent.layer_group)) do + - if entry.has_siblings_in_layer(parent.layer_group) + = simple_list entry.siblings_in_layer(parent.layer_group) do |sibling_role| + - assoc_link(sibling_role.person) + - else + = t('global.associations.no_entry') = render_attrs(entry, :entry_date, :leaving_date) diff --git a/app/views/people/_fields_pbs.html.haml b/app/views/people/_fields_pbs.html.haml index 9db0179f0..37e5ece52 100644 --- a/app/views/people/_fields_pbs.html.haml +++ b/app/views/people/_fields_pbs.html.haml @@ -17,6 +17,3 @@ = field_set_tag do = f.labeled_input_fields(:entry_date, :leaving_date) - -= field_set_tag do - = f.labeled_boolean_field(:brother_and_sisters, caption: t('.in_abteilung')) diff --git a/config/locales/views.pbs.de.yml b/config/locales/views.pbs.de.yml index 5c344f9b3..b536b5974 100644 --- a/config/locales/views.pbs.de.yml +++ b/config/locales/views.pbs.de.yml @@ -349,6 +349,7 @@ de: fields_pbs: non_automatic_field: Dies ist kein automatisches Feld und muss manuell angepasst werden. in_abteilung: (in der Abteilung) + siblings_in_layer: Geschwister in %{layer} qualification_buttons_pbs: print_course_confirmation: Kursbestätigung drucken household_attrs_pbs: From 56224d8d36a471252e4ded32594bad766fcd89d0 Mon Sep 17 00:00:00 2001 From: Diego Steiner Date: Thu, 14 Sep 2023 11:04:42 +0200 Subject: [PATCH 05/17] move sibling finder logic into separate service --- app/decorators/pbs/person_decorator.rb | 12 +++++++++--- app/domain/person/family_member_finder.rb | 19 +++++++++++++++++++ .../person/family_member_finder_spec.rb} | 6 +++--- 3 files changed, 31 insertions(+), 6 deletions(-) create mode 100644 app/domain/person/family_member_finder.rb rename spec/{decorator/person_decorator_spec.rb => domain/person/family_member_finder_spec.rb} (93%) diff --git a/app/decorators/pbs/person_decorator.rb b/app/decorators/pbs/person_decorator.rb index e755d3163..59ff46da4 100644 --- a/app/decorators/pbs/person_decorator.rb +++ b/app/decorators/pbs/person_decorator.rb @@ -21,15 +21,21 @@ def roles_grouped(scope:) end def siblings_in_layer(group) - Role.joins(person: :family_members) - .where(group: group.groups_in_same_layer, - person: { family_members: { kind: :sibling, other: self } }) + family_member_finder.siblings_in_layer(group) + end + + def has_siblings_in_layer(group) + siblings_in_layer.any? end end private + def family_member_finder + @family_member_finder ||= Person::FamilyMemberFinder.new(self) + end + def layer_group_ids @layer_group_ids ||= current_user&.layer_group_ids || [current_service_token&.layer_group_id].compact.presence || diff --git a/app/domain/person/family_member_finder.rb b/app/domain/person/family_member_finder.rb new file mode 100644 index 000000000..2b2373ae0 --- /dev/null +++ b/app/domain/person/family_member_finder.rb @@ -0,0 +1,19 @@ +# Copyright (c) 2018, Pfadibewegung Schweiz. This file is part of +# hitobito 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. + +class Person::FamilyMemberFinder + attr_reader :person + + def initialize(person) + @person = person + end + + def siblings_in_layer(group, kind: :sibling) + Role.joins(person: :family_members) + .where(group: group.groups_in_same_layer, + person: { family_members: { kind: kind, other: person } }) + end + +end diff --git a/spec/decorator/person_decorator_spec.rb b/spec/domain/person/family_member_finder_spec.rb similarity index 93% rename from spec/decorator/person_decorator_spec.rb rename to spec/domain/person/family_member_finder_spec.rb index 3fa29bd6a..92c2fe2f6 100644 --- a/spec/decorator/person_decorator_spec.rb +++ b/spec/domain/person/family_member_finder_spec.rb @@ -7,9 +7,9 @@ require 'spec_helper' -describe PersonDecorator do +describe Person::FamilyMemberFinder do - let(:decorator) { PersonDecorator.new(person) } + let(:service) { described_class.new(person) } let(:layer) { Fabricate(Group::Abteilung.name) } @@ -26,7 +26,7 @@ describe '#siblings_in_layer' do subject do - decorator.siblings_in_layer(person_group) + service.siblings_in_layer(person_group) end context 'without siblings' do From 1e3dff51d60f551a4c24b7f5394edb13124a46f9 Mon Sep 17 00:00:00 2001 From: Diego Steiner Date: Thu, 14 Sep 2023 11:20:32 +0200 Subject: [PATCH 06/17] add logic and specs for finding siblings in events --- app/domain/person/family_member_finder.rb | 8 ++- .../person/family_member_finder_spec.rb | 52 +++++++++++++++---- 2 files changed, 49 insertions(+), 11 deletions(-) diff --git a/app/domain/person/family_member_finder.rb b/app/domain/person/family_member_finder.rb index 2b2373ae0..d31f67e96 100644 --- a/app/domain/person/family_member_finder.rb +++ b/app/domain/person/family_member_finder.rb @@ -10,10 +10,16 @@ def initialize(person) @person = person end - def siblings_in_layer(group, kind: :sibling) + def family_members_in_layer(group, kind: :sibling) Role.joins(person: :family_members) .where(group: group.groups_in_same_layer, person: { family_members: { kind: kind, other: person } }) end + + def family_members_in_event(event, kind: :sibling) + Event::Participation.joins(person: :family_members) + .where(person: { family_members: { kind: kind, other: person } }, + event: event) + end end diff --git a/spec/domain/person/family_member_finder_spec.rb b/spec/domain/person/family_member_finder_spec.rb index 92c2fe2f6..96b7236ca 100644 --- a/spec/domain/person/family_member_finder_spec.rb +++ b/spec/domain/person/family_member_finder_spec.rb @@ -10,23 +10,55 @@ describe Person::FamilyMemberFinder do let(:service) { described_class.new(person) } - - let(:layer) { Fabricate(Group::Abteilung.name) } - let(:person) { Fabricate(:person) } - let(:person_group) { Fabricate(Group::Pfadi.name, parent: layer)} - let!(:person_role) { Fabricate(person_group.default_role.name, person: person, group: person_group) } - let(:sibling) { Fabricate(:person) } - let(:sibling_group) { Fabricate(Group::Woelfe.name, parent: layer)} - let!(:sibling_role) { Fabricate(sibling_group.default_role.name, person: sibling, group: sibling_group) } let!(:sibling_relation) { Fabricate(:family_member, person: person, other: sibling, kind: :sibling) } - describe '#siblings_in_layer' do + describe '#family_members_in_event' do + + let(:person_event) { Fabricate(:event) } + let!(:person_participation) { Fabricate(:event_participation, person: person, event: person_event) } + let(:sibling_event) { Fabricate(:event) } + let!(:sibling_participation) { Fabricate(:event_participation, person: sibling, event: sibling_event) } + + subject do + service.family_members_in_event(person_event, kind: :sibling) + end + + context 'without siblings' do + let!(:sibling_relation) { nil } + it { is_expected.to be_empty } + end + + context 'with siblings in different events' do + it { is_expected.to be_empty } + end + + context 'with siblings in same event' do + let(:sibling_event) { person_event } + it { is_expected.to contain_exactly(sibling_participation) } + end + + context 'with siblings with deleted role in same group' do + let!(:sibling_participation) { Fabricate(:event_participation, person: sibling, event: sibling_event, active: false) } + it { is_expected.to be_empty } + end + + end + + describe '#family_members_in_layer' do + + let(:layer) { Fabricate(Group::Abteilung.name) } + + let(:person_group) { Fabricate(Group::Pfadi.name, parent: layer)} + let!(:person_role) { Fabricate(person_group.default_role.name, person: person, group: person_group) } + + let(:sibling_group) { Fabricate(Group::Woelfe.name, parent: layer)} + let!(:sibling_role) { Fabricate(sibling_group.default_role.name, person: sibling, group: sibling_group) } subject do - service.siblings_in_layer(person_group) + service.family_members_in_layer(person_group, kind: :sibling) end context 'without siblings' do From 8078514c2e856af80b3fe217197a9c21b7823044 Mon Sep 17 00:00:00 2001 From: Diego Steiner Date: Thu, 14 Sep 2023 11:37:39 +0200 Subject: [PATCH 07/17] refactor siblings in context to be more generic --- app/decorators/pbs/person_decorator.rb | 8 ++------ app/domain/person/family_member_finder.rb | 9 +++++++++ app/views/people/_details_pbs.html.haml | 8 +++++--- 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/app/decorators/pbs/person_decorator.rb b/app/decorators/pbs/person_decorator.rb index 59ff46da4..de24e5f10 100644 --- a/app/decorators/pbs/person_decorator.rb +++ b/app/decorators/pbs/person_decorator.rb @@ -20,12 +20,8 @@ def roles_grouped(scope:) end end - def siblings_in_layer(group) - family_member_finder.siblings_in_layer(group) - end - - def has_siblings_in_layer(group) - siblings_in_layer.any? + def siblings_in_context(context) + family_member_finder.family_members_in_context(context, kind: :sibling) end end diff --git a/app/domain/person/family_member_finder.rb b/app/domain/person/family_member_finder.rb index d31f67e96..5be1fd99e 100644 --- a/app/domain/person/family_member_finder.rb +++ b/app/domain/person/family_member_finder.rb @@ -22,4 +22,13 @@ def family_members_in_event(event, kind: :sibling) event: event) end + def family_members_in_context(context, kind: :sibling) + case context + when Event + family_members_in_event(context, kind: kind) + when Group + family_members_in_layer(context, kind: kind) + end + end + end diff --git a/app/views/people/_details_pbs.html.haml b/app/views/people/_details_pbs.html.haml index 2787d4094..cfc28c881 100644 --- a/app/views/people/_details_pbs.html.haml +++ b/app/views/people/_details_pbs.html.haml @@ -7,9 +7,11 @@ :grade_of_school) %dl.dl-horizontal - = labeled(t('people.fields_pbs.siblings_in_layer', layer: parent.layer_group)) do - - if entry.has_siblings_in_layer(parent.layer_group) - = simple_list entry.siblings_in_layer(parent.layer_group) do |sibling_role| + - sibling_context = parent.try(:layer_group) || parent + - siblings_in_context = entry.siblings_in_context(sibling_context) + = labeled(t('people.fields_pbs.siblings_in_context', context: sibling_context)) do + - if siblings_in_context.any? + = simple_list siblings_in_context do |sibling_role| - assoc_link(sibling_role.person) - else = t('global.associations.no_entry') From 469b6d25dd796fab759c9c662dfe6848b87fc7b6 Mon Sep 17 00:00:00 2001 From: Diego Steiner Date: Thu, 14 Sep 2023 11:37:47 +0200 Subject: [PATCH 08/17] refactor siblings in context to be more generic --- config/locales/views.pbs.de.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/config/locales/views.pbs.de.yml b/config/locales/views.pbs.de.yml index b536b5974..15d7cfaa7 100644 --- a/config/locales/views.pbs.de.yml +++ b/config/locales/views.pbs.de.yml @@ -348,8 +348,7 @@ de: no_sensitive_information: In diesem Feld keine besonders schützenswerte Personendaten erfassen. fields_pbs: non_automatic_field: Dies ist kein automatisches Feld und muss manuell angepasst werden. - in_abteilung: (in der Abteilung) - siblings_in_layer: Geschwister in %{layer} + siblings_in_context: Geschwister in %{context} qualification_buttons_pbs: print_course_confirmation: Kursbestätigung drucken household_attrs_pbs: From 3998deea37fc375a4354a921cdba19fc1a954416 Mon Sep 17 00:00:00 2001 From: Diego Steiner Date: Thu, 14 Sep 2023 12:19:54 +0200 Subject: [PATCH 09/17] add has_siblings_in_context to json api --- app/serializers/pbs/event_participation_serializer.rb | 2 ++ app/serializers/pbs/person_serializer.rb | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/app/serializers/pbs/event_participation_serializer.rb b/app/serializers/pbs/event_participation_serializer.rb index 1954b1f88..83e10c3e1 100644 --- a/app/serializers/pbs/event_participation_serializer.rb +++ b/app/serializers/pbs/event_participation_serializer.rb @@ -16,6 +16,8 @@ module Pbs::EventParticipationSerializer translated_label: number.translated_label } end) + + property :has_siblings_in_event, item.person.siblings_in_context(item.event).any? end end end diff --git a/app/serializers/pbs/person_serializer.rb b/app/serializers/pbs/person_serializer.rb index b374774cb..5a230724e 100644 --- a/app/serializers/pbs/person_serializer.rb +++ b/app/serializers/pbs/person_serializer.rb @@ -12,7 +12,11 @@ module Pbs::PersonSerializer extension(:details) do |_| map_properties :pbs_number, :salutation_value, :correspondence_language, :prefers_digital_correspondence, :grade_of_school, :entry_date, :leaving_date + + + property :has_siblings_in_layer, item.siblings_in_context(context[:group]).any? if context[:group] end + end end From 1f2f894528d76da7ca2a504b8985f8fb397346a0 Mon Sep 17 00:00:00 2001 From: Diego Steiner Date: Thu, 14 Sep 2023 13:51:04 +0200 Subject: [PATCH 10/17] add has_siblings_in_layer to people full export --- .../pbs/export/tabular/people/people_full.rb | 15 ++++++++++++++- .../pbs/export/tabular/people/person_row.rb | 11 +++++++++++ app/jobs/pbs/export/people_export_job.rb | 6 +++++- app/serializers/pbs/person_serializer.rb | 5 +++-- config/locales/models.pbs.de.yml | 3 +-- 5 files changed, 34 insertions(+), 6 deletions(-) diff --git a/app/domain/pbs/export/tabular/people/people_full.rb b/app/domain/pbs/export/tabular/people/people_full.rb index 068f2d954..a121640ac 100644 --- a/app/domain/pbs/export/tabular/people/people_full.rb +++ b/app/domain/pbs/export/tabular/people/people_full.rb @@ -17,8 +17,21 @@ module PeopleFull end def person_attributes_with_pbs - person_attributes_without_pbs + [:id, :layer_group_id, :pbs_number] + person_attributes_without_pbs + [:id, :layer_group_id, :pbs_number, + :has_siblings_in_layer] end + + def initialize(list, group) + super(list) + @group = group + end + + private + + def row_for(entry, format = nil) + row_class.new(entry, format, @group) + end + end end end diff --git a/app/domain/pbs/export/tabular/people/person_row.rb b/app/domain/pbs/export/tabular/people/person_row.rb index 0c4e61d8c..b16b416cc 100644 --- a/app/domain/pbs/export/tabular/people/person_row.rb +++ b/app/domain/pbs/export/tabular/people/person_row.rb @@ -12,6 +12,13 @@ module People module PersonRow extend ActiveSupport::Concern + attr_reader :group + + def initialize(entry, format = nil, group = nil) + super(entry, format) + @group = group + end + def salutation entry.salutation_value end @@ -24,6 +31,10 @@ def layer_group_id entry.try(:primary_group).try(:layer_group).try(:id) end + def has_siblings_in_layer + ::Person::FamilyMemberFinder.new(entry) + .family_members_in_context(group, kind: :sibling).any? + end end end end diff --git a/app/jobs/pbs/export/people_export_job.rb b/app/jobs/pbs/export/people_export_job.rb index be7926ac7..d17d14ef8 100644 --- a/app/jobs/pbs/export/people_export_job.rb +++ b/app/jobs/pbs/export/people_export_job.rb @@ -13,8 +13,12 @@ module Pbs::Export::PeopleExportJob end def exporter_with_detail - return Pbs::Export::Tabular::People::HouseholdsFull if @options[:household_details] + return Pbs::Export::Tabular::People::HouseholdsFull if @options[:household_details] exporter_without_detail end + def data + return super unless exporter == ::Export::Tabular::People::PeopleFull + ::Export::Tabular::People::PeopleFull.export(@format, entries, group) + end end diff --git a/app/serializers/pbs/person_serializer.rb b/app/serializers/pbs/person_serializer.rb index 5a230724e..c5f043492 100644 --- a/app/serializers/pbs/person_serializer.rb +++ b/app/serializers/pbs/person_serializer.rb @@ -13,8 +13,9 @@ module Pbs::PersonSerializer map_properties :pbs_number, :salutation_value, :correspondence_language, :prefers_digital_correspondence, :grade_of_school, :entry_date, :leaving_date - - property :has_siblings_in_layer, item.siblings_in_context(context[:group]).any? if context[:group] + if context[:group].present? + property :has_siblings_in_layer, item.siblings_in_context(context[:group]).any? + end end end diff --git a/config/locales/models.pbs.de.yml b/config/locales/models.pbs.de.yml index c6fe931cb..d74e2b4d6 100644 --- a/config/locales/models.pbs.de.yml +++ b/config/locales/models.pbs.de.yml @@ -1259,8 +1259,7 @@ de: leaving_date: Austrittsdatum j_s_number: J+S Personennummer correspondence_language: Korrespondenzsprache - brother_and_sisters: Geschwister - relations_to_tails: Geschwister + has_siblings_in_layer: Geschwister in der Ebene kv: Kantonalverband prefers_digital_correspondence: Digitale Korrespondenz bevorzugt From 04f4e204f3941a90757d744982c2e353a580870d Mon Sep 17 00:00:00 2001 From: Diego Steiner Date: Thu, 14 Sep 2023 14:46:14 +0200 Subject: [PATCH 11/17] add has_siblings_in_event to participations export --- .../pbs/export/tabular/people/participation_row.rb | 7 +++++++ .../pbs/export/tabular/people/participations_full.rb | 7 +++++++ app/domain/pbs/export/tabular/people/people_full.rb | 9 ++++++--- app/domain/pbs/export/tabular/people/person_row.rb | 4 +--- app/jobs/pbs/export/event_participations_export_job.rb | 5 +++++ app/jobs/pbs/export/people_export_job.rb | 2 +- config/locales/models.pbs.de.yml | 1 + 7 files changed, 28 insertions(+), 7 deletions(-) diff --git a/app/domain/pbs/export/tabular/people/participation_row.rb b/app/domain/pbs/export/tabular/people/participation_row.rb index 34152028e..653c1042e 100644 --- a/app/domain/pbs/export/tabular/people/participation_row.rb +++ b/app/domain/pbs/export/tabular/people/participation_row.rb @@ -15,6 +15,13 @@ def bsv_days participation.bsv_days || participation.event.bsv_days end + def has_siblings_in_event + event = participation.event + + ::Person::FamilyMemberFinder.new(participation.person) + .family_members_in_context(event, kind: :sibling).any? + end + end end end diff --git a/app/domain/pbs/export/tabular/people/participations_full.rb b/app/domain/pbs/export/tabular/people/participations_full.rb index d51e647f7..5eda29b9b 100644 --- a/app/domain/pbs/export/tabular/people/participations_full.rb +++ b/app/domain/pbs/export/tabular/people/participations_full.rb @@ -13,12 +13,19 @@ module ParticipationsFull extend ActiveSupport::Concern included do + alias_method_chain :person_attributes, :pbs alias_method_chain :build_attribute_labels, :pbs end + def person_attributes_with_pbs + person_attributes_without_pbs + [:has_siblings_in_event] + end + def build_attribute_labels_with_pbs build_attribute_labels_without_pbs.tap do |labels| labels[:bsv_days] = ::Event::Participation.human_attribute_name(:bsv_days) + labels[:has_siblings_in_event] = + ::Event::Participation.human_attribute_name(:has_siblings_in_event) end end end diff --git a/app/domain/pbs/export/tabular/people/people_full.rb b/app/domain/pbs/export/tabular/people/people_full.rb index a121640ac..e9b668d31 100644 --- a/app/domain/pbs/export/tabular/people/people_full.rb +++ b/app/domain/pbs/export/tabular/people/people_full.rb @@ -17,11 +17,12 @@ module PeopleFull end def person_attributes_with_pbs - person_attributes_without_pbs + [:id, :layer_group_id, :pbs_number, - :has_siblings_in_layer] + attrs = person_attributes_without_pbs + [:id, :layer_group_id, :pbs_number] + attrs += [:has_siblings_in_layer] if @group.present? + attrs end - def initialize(list, group) + def initialize(list, group = nil) super(list) @group = group end @@ -29,6 +30,8 @@ def initialize(list, group) private def row_for(entry, format = nil) + return super unless row_class == ::Export::Tabular::People::PersonRow && + @group.present? row_class.new(entry, format, @group) end diff --git a/app/domain/pbs/export/tabular/people/person_row.rb b/app/domain/pbs/export/tabular/people/person_row.rb index b16b416cc..0f0a05324 100644 --- a/app/domain/pbs/export/tabular/people/person_row.rb +++ b/app/domain/pbs/export/tabular/people/person_row.rb @@ -12,8 +12,6 @@ module People module PersonRow extend ActiveSupport::Concern - attr_reader :group - def initialize(entry, format = nil, group = nil) super(entry, format) @group = group @@ -33,7 +31,7 @@ def layer_group_id def has_siblings_in_layer ::Person::FamilyMemberFinder.new(entry) - .family_members_in_context(group, kind: :sibling).any? + .family_members_in_context(@group, kind: :sibling)&.any? end end end diff --git a/app/jobs/pbs/export/event_participations_export_job.rb b/app/jobs/pbs/export/event_participations_export_job.rb index 3ff4f3a28..b899b17f3 100644 --- a/app/jobs/pbs/export/event_participations_export_job.rb +++ b/app/jobs/pbs/export/event_participations_export_job.rb @@ -33,5 +33,10 @@ def unfiltered_participants references(:people). distinct end + + def data + return super unless exporter == ::Export::Tabular::People::ParticipationsFull + ::Export::Tabular::People::ParticipationsFull.export(@format, entries, @filter.event) + end end diff --git a/app/jobs/pbs/export/people_export_job.rb b/app/jobs/pbs/export/people_export_job.rb index d17d14ef8..162d1d2aa 100644 --- a/app/jobs/pbs/export/people_export_job.rb +++ b/app/jobs/pbs/export/people_export_job.rb @@ -18,7 +18,7 @@ def exporter_with_detail end def data - return super unless exporter == ::Export::Tabular::People::PeopleFull + return super unless exporter == ::Export::Tabular::People::PeopleFull ::Export::Tabular::People::PeopleFull.export(@format, entries, group) end end diff --git a/config/locales/models.pbs.de.yml b/config/locales/models.pbs.de.yml index d74e2b4d6..cb1ca0a2e 100644 --- a/config/locales/models.pbs.de.yml +++ b/config/locales/models.pbs.de.yml @@ -1243,6 +1243,7 @@ de: additional_information: Wie möchtest du dich im Anlass ernähren? Was sind deine Essgewohnheiten? bsv_days: BSV-Tage j_s_data_sharing_accepted: J+S Datenweitergabe + has_siblings_in_event: Geschwister im Anlass event/question: pass_on_to_supercamp: An übergeordnetes Lager weitergeben From 54a81c662b7153fe3b1d1a114df02637b143e7ca Mon Sep 17 00:00:00 2001 From: Diego Steiner Date: Thu, 14 Sep 2023 14:49:20 +0200 Subject: [PATCH 12/17] add entry in changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c08696dfe..e8809ff04 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Hitobito PBS Changelog +## unreleased + +* Das Feld "Geschwister in der Abteilung" wird neu von eingetragenen Geschwistern abgeleitet und pro Ebene bzw. pro Anlass berechnet und angezeigt. (hitobito#2147) + ## Version 1.30 * Das Anwesenheiten-Tab bei Kursen im Status "Qualifikationen erfasst" und "Abgeschlossen" wird neu mit einem Ausrufezeichen markiert, wenn die Anwesenheiten noch gespeichert werden müssen. Merci @ewangler! (hitobito/hitobito_pbs#262) From 08dffb4dc176ac7db6deff2cdd8af0ff913545a6 Mon Sep 17 00:00:00 2001 From: Diego Steiner Date: Thu, 14 Sep 2023 15:02:21 +0200 Subject: [PATCH 13/17] fix failing spec after adding has_siblings_in_event --- app/serializers/pbs/event_participation_serializer.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/serializers/pbs/event_participation_serializer.rb b/app/serializers/pbs/event_participation_serializer.rb index 83e10c3e1..03ca236c8 100644 --- a/app/serializers/pbs/event_participation_serializer.rb +++ b/app/serializers/pbs/event_participation_serializer.rb @@ -17,7 +17,9 @@ module Pbs::EventParticipationSerializer } end) - property :has_siblings_in_event, item.person.siblings_in_context(item.event).any? + property(:has_siblings_in_event, + ::Person::FamilyMemberFinder.new(item.person) + .family_members_in_context(item.event, kind: :sibling).any?) end end end From f3cc8688a9b3341beb5db81d7bc6d3361ed35e4d Mon Sep 17 00:00:00 2001 From: Diego Steiner Date: Fri, 15 Sep 2023 10:53:12 +0200 Subject: [PATCH 14/17] remove dead code --- spec/fabricators/people_relation_fabricator.rb | 11 ----------- 1 file changed, 11 deletions(-) delete mode 100644 spec/fabricators/people_relation_fabricator.rb diff --git a/spec/fabricators/people_relation_fabricator.rb b/spec/fabricators/people_relation_fabricator.rb deleted file mode 100644 index e07216426..000000000 --- a/spec/fabricators/people_relation_fabricator.rb +++ /dev/null @@ -1,11 +0,0 @@ -# Copyright (c) 2023, Pfadibewegung Schweiz. This file is part of -# hitobito_pbs 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_pbs. - - -Fabricator(:people_relation) do - head { Fabricate(:person) } - kind { :sibling } - tail { Fabricate(:person) } -end From f5551b2fd18aebfa69cfc3d8f64cba409c06d68d Mon Sep 17 00:00:00 2001 From: Diego Steiner Date: Thu, 21 Sep 2023 14:19:00 +0200 Subject: [PATCH 15/17] add correct translations to siblings_in_context --- app/views/people/_details_pbs.html.haml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/views/people/_details_pbs.html.haml b/app/views/people/_details_pbs.html.haml index cfc28c881..406750dfd 100644 --- a/app/views/people/_details_pbs.html.haml +++ b/app/views/people/_details_pbs.html.haml @@ -11,9 +11,10 @@ - siblings_in_context = entry.siblings_in_context(sibling_context) = labeled(t('people.fields_pbs.siblings_in_context', context: sibling_context)) do - if siblings_in_context.any? - = simple_list siblings_in_context do |sibling_role| + = t('global.yes') + = simple_list(siblings_in_context, class: 'unstyled mb-0') do |sibling_role| - assoc_link(sibling_role.person) - else - = t('global.associations.no_entry') + = t('global.no') = render_attrs(entry, :entry_date, :leaving_date) From 3e585028938a7270aef8c74ff7829a1e8fc8399a Mon Sep 17 00:00:00 2001 From: Diego Steiner <939106+diegosteiner@users.noreply.github.com> Date: Fri, 27 Oct 2023 14:59:28 +0200 Subject: [PATCH 16/17] Update app/domain/person/family_member_finder.rb Co-authored-by: Carlo Beltrame --- app/domain/person/family_member_finder.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/domain/person/family_member_finder.rb b/app/domain/person/family_member_finder.rb index 5be1fd99e..c529c3160 100644 --- a/app/domain/person/family_member_finder.rb +++ b/app/domain/person/family_member_finder.rb @@ -1,7 +1,7 @@ -# Copyright (c) 2018, Pfadibewegung Schweiz. This file is part of -# hitobito and licensed under the Affero General Public License version 3 +# Copyright (c) 2023, Pfadibewegung Schweiz. This file is part of +# hitobito_pbs 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. +# https://github.com/hitobito/hitobito_pbs. class Person::FamilyMemberFinder attr_reader :person From 16e03cf7e801541a2b1a41cf4bc582eb02aa5e84 Mon Sep 17 00:00:00 2001 From: Nils Rauch Date: Mon, 11 Dec 2023 12:53:33 +0100 Subject: [PATCH 17/17] Fix indentation --- app/domain/person/family_member_finder.rb | 37 +++++++++++------------ 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/app/domain/person/family_member_finder.rb b/app/domain/person/family_member_finder.rb index c529c3160..84776cbdc 100644 --- a/app/domain/person/family_member_finder.rb +++ b/app/domain/person/family_member_finder.rb @@ -10,25 +10,24 @@ def initialize(person) @person = person end - def family_members_in_layer(group, kind: :sibling) - Role.joins(person: :family_members) - .where(group: group.groups_in_same_layer, - person: { family_members: { kind: kind, other: person } }) - end - - def family_members_in_event(event, kind: :sibling) - Event::Participation.joins(person: :family_members) - .where(person: { family_members: { kind: kind, other: person } }, - event: event) - end + def family_members_in_layer(group, kind: :sibling) + Role.joins(person: :family_members) + .where(group: group.groups_in_same_layer, + person: { family_members: { kind: kind, other: person } }) + end - def family_members_in_context(context, kind: :sibling) - case context - when Event - family_members_in_event(context, kind: kind) - when Group - family_members_in_layer(context, kind: kind) - end - end + def family_members_in_event(event, kind: :sibling) + Event::Participation.joins(person: :family_members) + .where(person: { family_members: { kind: kind, other: person } }, + event: event) + end + def family_members_in_context(context, kind: :sibling) + case context + when Event + family_members_in_event(context, kind: kind) + when Group + family_members_in_layer(context, kind: kind) + end + end end