effective_memberships 0.9.7 → 0.9.9

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c9916218e0d606b59b230debdc5c7a70e1d3754333f786298a4b9f3cf21222ce
4
- data.tar.gz: 7ee9f5e5f4f64ea6764c206b053a81dc0d253a596de57d2e20324e3c64b86aa4
3
+ metadata.gz: 60f83e2a6f429e7a417d5a9b3a9026a1a391ec6fe301230514d66a1a2493574d
4
+ data.tar.gz: aedbc568e9fa8c3679c3bbc99567dd49cf379d735da7372d8460985e4eee401f
5
5
  SHA512:
6
- metadata.gz: 6e6f8b7f49df86cd4461dba072f3106e3a095076d44f298ced308857e7ee86b3f91455d6823716470d6b4dccdb75ed42e8e05cc2be9bc0208e314aaef011e759
7
- data.tar.gz: 936b9c462cede66151ae4a9d186a3b3d6aee60989f284f6157373fb043f73498e486678e09d39af0f75f648a5ace5826f66f0ec553427fbeb77375a1b5822fa9
6
+ metadata.gz: 1adb7214ff9a1b55255c55f076cf7684b3484926db1d2158365f5b367976b7867e65de05f722b8649d53736f214164b08241291c9e8f4170d07867ab33c0429c
7
+ data.tar.gz: 86c67adb9985b2bbbd626f271b3d537f61feb5c8b32daea1dba14669c538681be80d475e2ad06c579c513a1da4dee3b259303b0741cda1ad403c86377a9519e9
@@ -16,6 +16,15 @@ module Effective
16
16
  @memberships = @membership_directory.results(page: params[:page])
17
17
  end
18
18
 
19
+ def show
20
+ @page_title = 'Directory'
21
+
22
+ @membership = Effective::Membership.find_by_token(params[:id])
23
+
24
+ EffectiveResources.authorize!(self, :show, @membership)
25
+ EffectiveResources.authorize!(self, :show, @membership.owner)
26
+ end
27
+
19
28
  def build_membership_directory
20
29
  directory = EffectiveMemberships.MembershipDirectory.new(search_params)
21
30
  directory.current_user = current_user
@@ -63,7 +63,7 @@ module Admin
63
63
  end
64
64
 
65
65
  collection do
66
- EffectiveMemberships.Organization.deep.left_joins(:membership).includes(:addresses, membership: :membership_categories)
66
+ EffectiveMemberships.Organization.deep.left_joins(:membership).includes(:addresses, membership: [membership_categories: :category], representatives: :user)
67
67
  end
68
68
 
69
69
  def categories
@@ -3,25 +3,25 @@ class EffectiveMembershipsDirectoryDatatable < Effective::Datatable
3
3
  datatable do
4
4
  length 100
5
5
 
6
- col(:name) { |membership| membership.owner.to_s }
7
-
6
+ col :owner_name, label: 'Name'
8
7
  col :joined_on
9
8
  col :number
10
- col :categories, search: :string, label: 'Category'
11
- end
12
-
13
- collection do
14
- scope = Effective::Membership.directory.all
15
9
 
16
- archived_klasses.each do |klass|
17
- scope = scope.where.not(owner_id: klass.archived.select('id'), owner_type: klass.name)
10
+ col(:categories, search: categories, label: 'Category', sql_column: true).search do |collection, term|
11
+ collection.with_category(EffectiveMemberships.Category.find(term))
18
12
  end
19
13
 
20
- scope
21
14
  end
22
15
 
23
- def archived_klasses
24
- @archived_klasses ||= Effective::Membership.owner_klasses.select { |klass| klass.try(:acts_as_archived?) }
16
+ collection do
17
+ Effective::Membership.deep.sorted
18
+ .in_good_standing
19
+ .without_archived_owners
20
+ .with_category(categories)
21
+ end
22
+
23
+ def categories
24
+ EffectiveMemberships.Category.membership_directory.all
25
25
  end
26
26
 
27
27
  end
@@ -624,12 +624,12 @@ module EffectiveMembershipsApplicant
624
624
  return categories.where(can_apply_new: true)
625
625
  end
626
626
 
627
- category_ids = user.membership.category_ids
627
+ category_ids = user.membership.category_ids.map(&:to_s) - [nil, '']
628
628
 
629
- categories.select do |cat|
630
- cat.can_apply_new? ||
631
- cat.can_apply_existing? ||
632
- (cat.can_apply_restricted? && (category_ids & cat.can_apply_restricted_ids).present?)
629
+ categories.select do |category|
630
+ category.can_apply_new? ||
631
+ category.can_apply_existing? ||
632
+ (category.can_apply_restricted? && (category_ids & category.can_apply_restricted_ids).present?)
633
633
  end
634
634
  end
635
635
 
@@ -114,6 +114,9 @@ module EffectiveMembershipsCategory
114
114
  .or(where(can_apply_restricted: true))
115
115
  }
116
116
 
117
+ # Can be used to limit which memberships are displayed in the directory
118
+ scope :membership_directory, -> { sorted }
119
+
117
120
  validates :title, presence: true, uniqueness: true
118
121
  validates :category_type, presence: true
119
122
  validates :position, presence: true
@@ -19,18 +19,29 @@ module EffectiveMembershipsDirectory
19
19
  attr_accessor :term
20
20
  attr_accessor :category
21
21
 
22
+ # Users
22
23
  attr_accessor :first_name
23
24
  attr_accessor :last_name
24
25
 
26
+ # Organizations
27
+ attr_accessor :title
28
+
25
29
  validates :term, length: { minimum: 3, allow_blank: true }
26
30
  validates :first_name, length: { minimum: 2, allow_blank: true }
27
31
  validates :last_name, length: { minimum: 2, allow_blank: true }
32
+ validates :title, length: { minimum: 2, allow_blank: true }
33
+ end
34
+
35
+ def categories
36
+ EffectiveMemberships.Category.membership_directory.all
28
37
  end
29
38
 
30
39
  # Base collection to search. Can be configured per tenant.
31
40
  def collection
32
- # Example::User.members.membership_in_good_standing.all
33
- raise('to be implemented by app membership_directory')
41
+ Effective::Membership.deep.sorted
42
+ .in_good_standing
43
+ .without_archived_owners
44
+ .with_category(categories)
34
45
  end
35
46
 
36
47
  # Search Users and Organizations for only these fields. Passed into search_any. Return nil for all.
@@ -44,21 +55,21 @@ module EffectiveMembershipsDirectory
44
55
  end
45
56
 
46
57
  def present?
47
- term.present? || first_name.present? || last_name.present? || category.present?
58
+ term.present? || first_name.present? || last_name.present? || title.present? || category.present?
48
59
  end
49
60
 
50
61
  # Search and assigns the collection
51
62
  # Assigns the entire collection() if there are no search terms
52
63
  # Otherwise validate the search terms
53
64
  def search!
54
- @membership_owners = build_collection()
55
- @membership_owners = @membership_owners.none if present? && !valid?
56
- @membership_owners
65
+ @memberships = build_collection()
66
+ @memberships = @memberships.none if present? && !valid?
67
+ @memberships
57
68
  end
58
69
 
59
70
  # The unpaginated results of the search
60
- def membership_owners
61
- @membership_owners || collection
71
+ def memberships
72
+ @memberships || collection
62
73
  end
63
74
 
64
75
  # The paginated results
@@ -66,38 +77,53 @@ module EffectiveMembershipsDirectory
66
77
  page = (page || 1).to_i
67
78
  offset = [(page - 1), 0].max * per_page
68
79
 
69
- membership_owners.limit(per_page).offset(offset)
80
+ memberships.limit(per_page).offset(offset)
70
81
  end
71
82
 
72
83
  protected
73
84
 
74
85
  def build_collection
75
- owners = collection()
76
- raise('expected an ActiveRecord collection') unless owners.kind_of?(ActiveRecord::Relation)
77
- raise('expected a collection of membership_owners') unless owners.klass.respond_to?(:effective_memberships_owner?)
86
+ memberships = collection()
87
+ raise('expected an ActiveRecord collection') unless memberships.kind_of?(ActiveRecord::Relation)
88
+ raise('expected an ActiveRecord collection of Effective::Memberships') unless memberships.klass.respond_to?(:effective_membership?)
78
89
 
79
90
  # Filter by term
80
91
  if term.present?
81
- owners = Effective::Resource.new(owners).search_any(term, columns: search_any_columns)
92
+ owners = owner_klasses.map { |klass| Effective::Resource.new(klass).search_any(term, columns: search_any_columns) }
93
+ memberships = memberships.where(owner: owners)
82
94
  end
83
95
 
84
96
  # Filter by first name
85
97
  if first_name.present?
86
- owners = Effective::Resource.new(owners).search_any(first_name, columns: :first_name)
98
+ owners = owner_klasses.map { |klass| Effective::Resource.new(klass).search_any(first_name, columns: :first_name) }
99
+ memberships = memberships.where(owner: owners)
87
100
  end
88
101
 
89
102
  # Filter by last name
90
103
  if last_name.present?
91
- owners = Effective::Resource.new(owners).search_any(last_name, columns: :last_name)
104
+ owners = owner_klasses.map { |klass| Effective::Resource.new(klass).search_any(last_name, columns: :last_name) }
105
+ memberships = memberships.where(owner: owners)
106
+ end
107
+
108
+ # Filter by title
109
+ if title.present?
110
+ owners = owner_klasses.map { |klass| Effective::Resource.new(klass).search_any(last_name, columns: :title) }
111
+ memberships = memberships.where(owner: owners)
92
112
  end
93
113
 
94
114
  # Filter by category
95
115
  if category.present?
96
- cat = EffectiveMemberships.Category.where(id: category)
97
- owners = owners.members_with_category(cat) if cat.present?
116
+ memberships = memberships.with_category(EffectiveMemberships.Category.where(id: category))
98
117
  end
99
118
 
100
- owners
119
+ # Return an ActiveRecord::Relation of Effective::Memberships
120
+ memberships
121
+ end
122
+
123
+ private
124
+
125
+ def owner_klasses
126
+ Effective::Membership.owner_klasses
101
127
  end
102
128
 
103
129
  end
@@ -97,4 +97,8 @@ module EffectiveMembershipsOrganization
97
97
  representatives.reject(&:marked_for_destruction?).map(&:user)
98
98
  end
99
99
 
100
+ def membership_users
101
+ users.select { |user| user.is?(:member) && !user.archived? }
102
+ end
103
+
100
104
  end
@@ -1,6 +1,7 @@
1
1
  module Effective
2
2
  class Membership < ActiveRecord::Base
3
3
  belongs_to :owner, polymorphic: true
4
+ has_secure_token
4
5
 
5
6
  attr_accessor :current_action
6
7
 
@@ -24,30 +25,34 @@ module Effective
24
25
  fees_paid_period :date # The most recent period they have paid in. Start date of period.
25
26
  fees_paid_through_period :date # The most recent period they have paid in. End date of period. Kind of an expires.
26
27
 
28
+ # Membership Directory
29
+ owner_name :string
30
+ token :string
31
+
27
32
  timestamps
28
33
  end
29
34
 
30
35
  scope :deep, -> { includes(:owner, membership_categories: :category, membership_statuses: :status) }
31
- scope :sorted, -> { order(:id) }
36
+ scope :sorted, -> { order('lower(owner_name)') }
32
37
 
33
38
  scope :with_status, -> (statuses) {
34
- raise('expected an EffectiveMemberships.Status') unless Array(statuses).all? { |status| status.kind_of?(EffectiveMemberships.Status) }
35
- where(id: MembershipStatus.where(status: statuses).select(:membership_id))
39
+ raise('expected an EffectiveMemberships.Status') unless statuses.class.respond_to?(:effective_memberships_status?) || Array(statuses).all? { |status| status.kind_of?(EffectiveMemberships.Status) }
40
+ where(id: MembershipStatus.where(status_id: statuses).select(:membership_id))
36
41
  }
37
42
 
38
43
  scope :without_status, -> (statuses) {
39
- raise('expected an EffectiveMemberships.Status') unless Array(statuses).all? { |status| status.kind_of?(EffectiveMemberships.Status) }
40
- where.not(id: MembershipStatus.where(status: statuses).select(:membership_id))
44
+ raise('expected an EffectiveMemberships.Status') unless statuses.class.respond_to?(:effective_memberships_status?) || Array(statuses).all? { |status| status.kind_of?(EffectiveMemberships.Status) }
45
+ where.not(id: MembershipStatus.where(status_id: statuses).select(:membership_id))
41
46
  }
42
47
 
43
48
  scope :with_category, -> (categories) {
44
- raise('expected an EffectiveMemberships.Category') unless Array(categories).all? { |cat| cat.kind_of?(EffectiveMemberships.Category) }
45
- where(id: MembershipCategory.where(category: categories).select(:membership_id))
49
+ raise('expected an EffectiveMemberships.Category') unless categories.class.respond_to?(:effective_memberships_category?) || Array(categories).all? { |cat| cat.kind_of?(EffectiveMemberships.Category) }
50
+ where(id: MembershipCategory.where(category_id: categories).select(:membership_id))
46
51
  }
47
52
 
48
53
  scope :without_category, -> (categories) {
49
- raise('expected an EffectiveMemberships.Category') unless Array(categories).all? { |cat| cat.kind_of?(EffectiveMemberships.Category) }
50
- where.not(id: MembershipCategory.where(category: categories).select(:membership_id))
54
+ raise('expected an EffectiveMemberships.Category') unless categories.class.respond_to?(:effective_memberships_category?) || Array(categories).all? { |cat| cat.kind_of?(EffectiveMemberships.Category) }
55
+ where.not(id: MembershipCategory.where(category_id: categories).select(:membership_id))
51
56
  }
52
57
 
53
58
  scope :joined_before, -> (date) {
@@ -73,14 +78,24 @@ module Effective
73
78
  scope :not_in_good_standing, -> { with_status(EffectiveMemberships.Registrar.not_in_good_standing_status) }
74
79
  scope :in_good_standing, -> { without_status(EffectiveMemberships.Registrar.not_in_good_standing_status) }
75
80
 
81
+ scope :without_archived_owners, -> {
82
+ where.not(owner: klass.acts_as_archived_owner_klasses.map { |klass| klass.archived })
83
+ }
84
+
76
85
  before_validation do
77
86
  self.registration_on ||= joined_on
78
87
  end
79
88
 
89
+ before_validation(if: -> { owner.present? }) do
90
+ self.owner_name = owner.to_s
91
+ end
92
+
80
93
  before_validation(if: -> { number_changed? }) do
81
94
  self.number_as_integer = (number.present? ? (Integer(number) rescue nil) : nil)
82
95
  end
83
96
 
97
+ validates :owner_name, presence: true
98
+
84
99
  validates :number, uniqueness: { allow_blank: true }
85
100
  validates :number, presence: true, if: -> { categories.any?(:membership_number_required?) }
86
101
 
@@ -100,11 +115,19 @@ module Effective
100
115
  maximum('number_as_integer') || 0
101
116
  end
102
117
 
118
+ def self.effective_membership?
119
+ true
120
+ end
121
+
103
122
  def self.owner_klasses
104
123
  klasses = Effective::Membership.distinct(:owner_type).pluck(:owner_type)
105
124
  klasses.select { |klass| klass.safe_constantize }.map { |klass| klass.constantize }
106
125
  end
107
126
 
127
+ def self.acts_as_archived_owner_klasses
128
+ owner_klasses.select { |klass| klass.try(:acts_as_archived?) }
129
+ end
130
+
108
131
  def to_s
109
132
  return 'membership' if owner.blank?
110
133
 
@@ -1,11 +1,14 @@
1
1
  = effective_form_with(scope: :q, model: membership_directory, method: :get, url: request.path) do |f|
2
- - if f.object.term.present?
3
- = f.search_field :term, label: 'Name'
2
+ = f.search_field :term, label: 'Name'
4
3
 
5
- = f.search_field :first_name
6
- = f.search_field :last_name
4
+ -# Users only
5
+ /= f.search_field :first_name
6
+ /= f.search_field :last_name
7
7
 
8
- = f.select :category, EffectiveMemberships.Category.all
8
+ - # Organizations only
9
+ /= f.search_field :title
10
+
11
+ = f.select :category, membership_directory.categories
9
12
 
10
13
  = f.save('Search', class: 'btn btn-primary btn-search mr-3', name: nil)
11
14
  = link_to 'Reset filters', request.path
@@ -0,0 +1,20 @@
1
+ = card do
2
+ %h6= membership.owner
3
+ %p= membership.categories.map(&:membership_directory_title).to_sentence
4
+ %p= membership.statuses.map(&:membership_directory_title).to_sentence
5
+
6
+ - if membership.owner.try(:email).present?
7
+ %p= reveal_mail_to(membership.owner.email)
8
+
9
+ - if (organizations = membership.owner.try(:membership_organizations)).present?
10
+ .mb-4.membership-directory-organizations
11
+ - organizations.each do |organization|
12
+ %div= organization
13
+
14
+ - if (users = membership.owner.try(:membership_users)).present?
15
+ .mb-4.membership-directory-users
16
+ - users.each do |user|
17
+ %div= user
18
+
19
+ - if EffectiveResources.authorized?(self, :show, membership) && EffectiveResources.authorized?(self, :show, membership.owner)
20
+ = link_to 'Show more', effective_memberships.membership_directory_path(membership.token)
@@ -4,14 +4,14 @@
4
4
  - results = membership_directory.results(page: params[:page])
5
5
 
6
6
  - if membership_directory.present? && results.length == 0
7
- .alert.alert-info There are no results for your search. Please try again.
7
+ .mt-4.alert.alert-info There are no results for your search. Please try again.
8
8
 
9
9
  - results.in_groups_of(3).each do |group|
10
10
  .row.mt-4
11
- - group.each do |owner|
12
- - next unless owner
11
+ - group.each do |membership|
13
12
  .col-md
14
- = render('effective/membership_directory/membership_owner', membership: owner.membership, owner: owner)
13
+ - next unless membership
14
+ = render('effective/membership_directory/membership', membership: membership)
15
15
 
16
16
  %nav.d-flex.justify-content-center
17
17
  = bootstrap_paginate(results, per_page: membership_directory.per_page)
@@ -0,0 +1,25 @@
1
+ = render 'layout' do
2
+ .effective-membership
3
+
4
+ %h6= @membership.owner
5
+ %p= @membership.categories.map(&:membership_directory_title).to_sentence
6
+ %p= @membership.statuses.map(&:membership_directory_title).to_sentence
7
+
8
+ - if @membership.owner.respond_to?(:rich_text_body)
9
+ .mb-4= @membership.owner.rich_text_body.to_s
10
+
11
+ - if @membership.owner.try(:email).present?
12
+ %p= reveal_mail_to(@membership.owner.email)
13
+
14
+ - if (organizations = @membership.owner.try(:membership_organizations)).present?
15
+ .mb-4.membership-directory-organizations
16
+ - organizations.each do |organization|
17
+ %div= organization
18
+
19
+ - if (users = @membership.owner.try(:membership_users)).present?
20
+ .mb-4.membership-directory-users
21
+ - users.each do |user|
22
+ %div= user
23
+
24
+ %hr
25
+ = link_to 'Return to Directory', effective_memberships.membership_directory_index_path, class: 'btn btn-primary'
data/config/routes.rb CHANGED
@@ -26,7 +26,7 @@ EffectiveMemberships::Engine.routes.draw do
26
26
  resources :build, controller: :fee_payments, only: [:show, :update]
27
27
  end
28
28
 
29
- resources :membership_directory, only: :index
29
+ resources :membership_directory, only: [:index, :show]
30
30
  get '/directory', to: 'membership_directory#index'
31
31
 
32
32
  resources :membership_cards, only: :index
@@ -95,6 +95,9 @@ class CreateEffectiveMemberships < ActiveRecord::Migration[6.0]
95
95
  t.date :fees_paid_period
96
96
  t.date :fees_paid_through_period
97
97
 
98
+ t.string :owner_name
99
+ t.string :token
100
+
98
101
  t.datetime :updated_at
99
102
  t.datetime :created_at
100
103
  end
@@ -1,3 +1,3 @@
1
1
  module EffectiveMemberships
2
- VERSION = '0.9.7'
2
+ VERSION = '0.9.9'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: effective_memberships
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.7
4
+ version: 0.9.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Code and Effect
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-12-01 00:00:00.000000000 Z
11
+ date: 2023-01-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -483,9 +483,10 @@ files:
483
483
  - app/views/effective/membership_cards/index.html.haml
484
484
  - app/views/effective/membership_directory/_form.html.haml
485
485
  - app/views/effective/membership_directory/_layout.html.haml
486
+ - app/views/effective/membership_directory/_membership.html.haml
486
487
  - app/views/effective/membership_directory/_membership_directory.html.haml
487
- - app/views/effective/membership_directory/_membership_owner.html.haml
488
488
  - app/views/effective/membership_directory/index.html.haml
489
+ - app/views/effective/membership_directory/show.html.haml
489
490
  - app/views/effective/memberships/_dashboard.html.haml
490
491
  - app/views/effective/memberships/_membership.html.haml
491
492
  - app/views/effective/memberships_mailer/applicant_approved.liquid
@@ -1,7 +0,0 @@
1
- = card do
2
- %h6= owner
3
- %p= membership.categories.map(&:membership_directory_title).to_sentence
4
- %p= membership.statuses.map(&:membership_directory_title).to_sentence
5
-
6
- - if owner.try(:email).present?
7
- %p= reveal_mail_to(owner.email)