effective_memberships 0.17.7 → 0.17.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/datatables/admin/effective_memberships_datatable.rb +7 -1
- data/app/models/concerns/effective_memberships_applicant.rb +18 -2
- data/app/models/concerns/effective_memberships_applicant_review.rb +10 -0
- data/app/models/concerns/effective_memberships_category.rb +4 -0
- data/app/models/concerns/effective_memberships_owner.rb +46 -0
- data/app/models/concerns/effective_memberships_status.rb +2 -3
- data/app/models/effective/applicant_reference.rb +15 -0
- data/app/models/effective/membership.rb +19 -0
- data/app/models/effective/membership_history.rb +14 -0
- data/app/views/admin/memberships/_form_membership.html.haml +2 -0
- data/app/views/effective/memberships/_dashboard.html.haml +4 -1
- data/app/views/effective/memberships/_reclassification.html.haml +14 -0
- data/app/views/effective/memberships/_reinstatement.html.haml +14 -0
- data/lib/effective_memberships/version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7a7ab7d95194d5d7c49af9f4d8297b4a9f927f9d4a2d97ea2f18ead660488685
|
4
|
+
data.tar.gz: 7412d96bc6f4b1c7329a3fa2b4998e0045d921f1deec09886f024f42b868afc7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6aeaa23fda513f0b707252be4009fa6b25c19a8ee9f7ead8761a15893fa5b56a2b1ddba20da408e42f5d8c7759dc1b53c9faba19b20eecac28b5dfdf863c8703
|
7
|
+
data.tar.gz: d2abd9350b5b98b43db54214b9cdf4a8fdc40858a66a4ea8f0ad301870326d16892287ad5ae1ac4a8dda70db2545e0d4ed12092e2bf265b3ae249137323bc311
|
@@ -64,7 +64,13 @@ module Admin
|
|
64
64
|
membership.owner.try(:addresses).try(:first).try(:postal_code)
|
65
65
|
end
|
66
66
|
|
67
|
-
actions_col
|
67
|
+
actions_col do |membership|
|
68
|
+
if membership.owner_type.include?('Organization')
|
69
|
+
dropdown_link_to 'Show', "/admin/organizations/#{membership.owner.to_param}/edit#tab-membership", 'data-turbolinks': false
|
70
|
+
elsif membership.owner_type.include?('User')
|
71
|
+
dropdown_link_to 'Show', "/admin/users/#{membership.owner.to_param}/edit#tab-membership", 'data-turbolinks': false
|
72
|
+
end
|
73
|
+
end
|
68
74
|
end
|
69
75
|
|
70
76
|
collection do
|
@@ -192,7 +192,7 @@ module EffectiveMembershipsApplicant
|
|
192
192
|
|
193
193
|
# effective_reports
|
194
194
|
def reportable_scopes
|
195
|
-
{ draft: nil, submitted: nil, in_progress: nil, done: nil }
|
195
|
+
{ draft: nil, submitted: nil, missing_info: nil, completed: nil, reviewed: nil, declined: nil, approved: nil, in_progress: nil, done: nil }
|
196
196
|
end
|
197
197
|
|
198
198
|
scope :deep, -> { includes(:user, :organization, :category, :from_category, :from_status, :orders) }
|
@@ -202,7 +202,6 @@ module EffectiveMembershipsApplicant
|
|
202
202
|
scope :done, -> { where(status: [:approved, :declined]) }
|
203
203
|
|
204
204
|
scope :not_draft, -> { where.not(status: :draft) }
|
205
|
-
|
206
205
|
scope :reviewable, -> { where.not(status: [:draft, :submitted, :declined, :approved]) }
|
207
206
|
|
208
207
|
scope :for, -> (user) {
|
@@ -251,6 +250,23 @@ module EffectiveMembershipsApplicant
|
|
251
250
|
validates :category, presence: true
|
252
251
|
end
|
253
252
|
|
253
|
+
# Select Step - Check for expired reclassification or reinstatement dates
|
254
|
+
validate(if: -> { current_step == :select && owner.present? && applicant_type.present? && category.present? }) do
|
255
|
+
# Dates
|
256
|
+
today = (created_at || Time.zone.now).beginning_of_day
|
257
|
+
|
258
|
+
reclassification_expires_on = owner.reclassification_expires_on(from: from_category, to: category)
|
259
|
+
reinstatement_expires_on = owner.reinstatement_expires_on(from: from_status)
|
260
|
+
|
261
|
+
if reclassification? && reclassification_expires_on.present? && reclassification_expires_on <= today
|
262
|
+
errors.add(:base, "Your ability to apply for reclassification expired on #{reclassification_expires_on.strftime('%F')}. Please contact us for assistance.")
|
263
|
+
end
|
264
|
+
|
265
|
+
if reinstatement? && reinstatement_expires_on.present? && reinstatement_expires_on <= today
|
266
|
+
errors.add(:base, "Your ability to apply for reinstatement expired on #{reinstatement_expires_on.strftime('%F')}. Please contact us for assistance.")
|
267
|
+
end
|
268
|
+
end
|
269
|
+
|
254
270
|
# They can checkout with outstanding fees
|
255
271
|
# validate(if: -> { current_step == :select && owner.present? }) do
|
256
272
|
# self.errors.add(:base, 'may not have outstanding fees') if owner.outstanding_fee_payment_fees.present?
|
@@ -29,6 +29,7 @@ module EffectiveMembershipsApplicantReview
|
|
29
29
|
|
30
30
|
included do
|
31
31
|
log_changes(to: :applicant) if respond_to?(:log_changes)
|
32
|
+
acts_as_reportable if respond_to?(:acts_as_reportable)
|
32
33
|
|
33
34
|
acts_as_tokened
|
34
35
|
|
@@ -59,6 +60,15 @@ module EffectiveMembershipsApplicantReview
|
|
59
60
|
timestamps
|
60
61
|
end
|
61
62
|
|
63
|
+
# effective_reports
|
64
|
+
def reportable_scopes
|
65
|
+
{ in_progress: nil, done: nil }
|
66
|
+
end
|
67
|
+
|
68
|
+
def reportable_email
|
69
|
+
reviewer.try(:email)
|
70
|
+
end
|
71
|
+
|
62
72
|
scope :deep, -> { includes(:reviewer, applicant: [:user, :applicant_reviews]) }
|
63
73
|
|
64
74
|
scope :for, -> (user) {
|
@@ -137,6 +137,44 @@ module EffectiveMembershipsOwner
|
|
137
137
|
removed_membership_history.start_on if membership_removed?
|
138
138
|
end
|
139
139
|
|
140
|
+
# Checked by the applicant on the select step
|
141
|
+
def reclassification_expires_on(from: nil, to: nil)
|
142
|
+
return unless membership.present?
|
143
|
+
|
144
|
+
# User/owner might respond to this
|
145
|
+
date = try(:admin_reclassification_expires_on)
|
146
|
+
return date if date.present?
|
147
|
+
|
148
|
+
# When we last reclassified to our current category
|
149
|
+
history = last_membership_history(category: membership.membership_categories.first)
|
150
|
+
reclassified_on = (history&.start_on || membership.registration_on || membership.joined_on)
|
151
|
+
|
152
|
+
# Otherwise consider the membership categories
|
153
|
+
expires_on = membership.categories.select { |category| category.reclassification_expires_in.present? }.map do |category|
|
154
|
+
reclassified_on + category.reclassification_expires_in
|
155
|
+
end.min
|
156
|
+
|
157
|
+
expires_on
|
158
|
+
end
|
159
|
+
|
160
|
+
def reinstatement_expires_on(from: nil)
|
161
|
+
return unless membership_removed?
|
162
|
+
|
163
|
+
# User/owner might respond to this
|
164
|
+
date = try(:admin_reinstatement_expires_on)
|
165
|
+
return date if date.present?
|
166
|
+
|
167
|
+
# When we were removed
|
168
|
+
removed_on = removed_membership_history.start_on
|
169
|
+
|
170
|
+
# Consider any membership statuses that have reinstatement expires in
|
171
|
+
expires_on = removed_membership_history.membership_statuses.select { |status| status.reinstatement_expires_in.present? }.map do |status|
|
172
|
+
removed_on + status.reinstatement_expires_in
|
173
|
+
end.min
|
174
|
+
|
175
|
+
expires_on
|
176
|
+
end
|
177
|
+
|
140
178
|
# The membership history that is removed. Has exit statuses that may affect reinstatement fees.
|
141
179
|
def removed_membership_history
|
142
180
|
membership_histories.reverse.find { |history| history.removed? } if membership_removed?
|
@@ -444,6 +482,14 @@ module EffectiveMembershipsOwner
|
|
444
482
|
membership_histories.find { |history| (history.start_on..history.end_on).cover?(date) } # Ruby 2.6 supports endless ranges
|
445
483
|
end
|
446
484
|
|
485
|
+
def first_membership_history(category: nil)
|
486
|
+
membership_histories.find { |history| category.blank? || history.membership_category_ids.include?(category.id) }
|
487
|
+
end
|
488
|
+
|
489
|
+
def last_membership_history(category: nil)
|
490
|
+
membership_histories.reverse.find { |history| category.blank? || history.membership_category_ids.include?(category.id) }
|
491
|
+
end
|
492
|
+
|
447
493
|
# Point out busted data
|
448
494
|
def membership_history_errors
|
449
495
|
return unless membership.present?
|
@@ -11,6 +11,7 @@ module Effective
|
|
11
11
|
)
|
12
12
|
|
13
13
|
log_changes(to: :applicant) if respond_to?(:log_changes)
|
14
|
+
acts_as_reportable if respond_to?(:acts_as_reportable)
|
14
15
|
|
15
16
|
belongs_to :applicant, polymorphic: true, optional: true
|
16
17
|
|
@@ -52,6 +53,20 @@ module Effective
|
|
52
53
|
timestamps
|
53
54
|
end
|
54
55
|
|
56
|
+
# effective_reports
|
57
|
+
def reportable_scopes
|
58
|
+
{ in_progress: nil, done: nil, expired: nil }
|
59
|
+
end
|
60
|
+
|
61
|
+
scope :in_progress, -> { with_submitted_applicants.where(status: :submitted) }
|
62
|
+
scope :done, -> { where(status: :completed) }
|
63
|
+
|
64
|
+
scope :expired, -> { where(status: :submitted).where.not(with_submitted_applicants) }
|
65
|
+
|
66
|
+
scope :with_submitted_applicants, -> {
|
67
|
+
where(applicant_id: EffectiveMemberships.Applicant.submitted)
|
68
|
+
}
|
69
|
+
|
55
70
|
scope :deep, -> { all }
|
56
71
|
|
57
72
|
# All step validations
|
@@ -11,6 +11,7 @@ module Effective
|
|
11
11
|
has_many :membership_statuses, -> { order(:id) }, inverse_of: :membership, dependent: :delete_all
|
12
12
|
accepts_nested_attributes_for :membership_statuses
|
13
13
|
|
14
|
+
acts_as_reportable if respond_to?(:acts_as_reportable)
|
14
15
|
log_changes(to: :owner) if respond_to?(:log_changes)
|
15
16
|
|
16
17
|
effective_resource do
|
@@ -35,7 +36,23 @@ module Effective
|
|
35
36
|
scope :deep, -> { includes(:owner, membership_categories: :category, membership_statuses: :status) }
|
36
37
|
scope :sorted, -> { order('lower(owner_name)') }
|
37
38
|
|
39
|
+
# effective_reports
|
40
|
+
def reportable_scopes
|
41
|
+
{
|
42
|
+
with_category: :string,
|
43
|
+
with_status: :string,
|
44
|
+
joined_before: :date,
|
45
|
+
joined_after: :date,
|
46
|
+
with_paid_fees_through: :date,
|
47
|
+
with_unpaid_fees_through: :date,
|
48
|
+
in_good_standing: nil,
|
49
|
+
not_in_good_standing: nil
|
50
|
+
}
|
51
|
+
end
|
52
|
+
|
38
53
|
scope :with_status, -> (statuses) {
|
54
|
+
statuses = Resource.new(EffectiveMemberships.Status).search_any(statuses) if statuses.kind_of?(String)
|
55
|
+
|
39
56
|
raise('expected an EffectiveMemberships.Status') unless statuses.class.respond_to?(:effective_memberships_status?) || Array(statuses).all? { |status| status.kind_of?(EffectiveMemberships.Status) }
|
40
57
|
where(id: MembershipStatus.where(status_id: statuses).select(:membership_id))
|
41
58
|
}
|
@@ -46,6 +63,8 @@ module Effective
|
|
46
63
|
}
|
47
64
|
|
48
65
|
scope :with_category, -> (categories) {
|
66
|
+
categories = Resource.new(EffectiveMemberships.Category).search_any(categories) if categories.kind_of?(String)
|
67
|
+
|
49
68
|
raise('expected an EffectiveMemberships.Category') unless categories.class.respond_to?(:effective_memberships_category?) || Array(categories).all? { |cat| cat.kind_of?(EffectiveMemberships.Category) }
|
50
69
|
where(id: MembershipCategory.where(category_id: categories).select(:membership_id))
|
51
70
|
}
|
@@ -2,6 +2,8 @@ module Effective
|
|
2
2
|
class MembershipHistory < ActiveRecord::Base
|
3
3
|
belongs_to :owner, polymorphic: true
|
4
4
|
|
5
|
+
acts_as_reportable if respond_to?(:acts_as_reportable)
|
6
|
+
|
5
7
|
effective_resource do
|
6
8
|
start_on :date
|
7
9
|
end_on :date
|
@@ -13,20 +15,32 @@ module Effective
|
|
13
15
|
categories :text
|
14
16
|
category_ids :text
|
15
17
|
|
18
|
+
statuses :text
|
19
|
+
status_ids :text
|
20
|
+
|
16
21
|
notes :text
|
17
22
|
|
18
23
|
timestamps
|
19
24
|
end
|
20
25
|
|
26
|
+
# TODO: Rename categories to be category_toses
|
27
|
+
# And membreship_categories below should be called categories
|
28
|
+
|
21
29
|
serialize :categories, Array
|
22
30
|
serialize :category_ids, Array
|
23
31
|
|
24
32
|
serialize :statuses, Array
|
25
33
|
serialize :status_ids, Array
|
26
34
|
|
35
|
+
# effective_reports
|
36
|
+
def reportable_scopes
|
37
|
+
{ removed: nil, not_removed: nil }
|
38
|
+
end
|
39
|
+
|
27
40
|
scope :deep, -> { includes(:owner) }
|
28
41
|
scope :sorted, -> { order(:start_on).order(:id) }
|
29
42
|
|
43
|
+
scope :not_removed, -> { where(removed: false) }
|
30
44
|
scope :removed, -> { where(removed: true) }
|
31
45
|
|
32
46
|
validates :owner, presence: true
|
@@ -9,6 +9,8 @@
|
|
9
9
|
|
10
10
|
= f.static_field :current_action, label: 'Current Membership' do
|
11
11
|
= membership.to_s
|
12
|
+
= render('effective/memberships/reclassification', user: membership.owner)
|
13
|
+
= render('effective/memberships/reinstatement', user: membership.owner)
|
12
14
|
|
13
15
|
= f.check_box :current_action, label: 'Yes, update membership information'
|
14
16
|
|
@@ -33,11 +33,14 @@
|
|
33
33
|
- if membership.not_in_good_standing?
|
34
34
|
%p Your membership is Not In Good Standing because of unpurchased fees or dues. Please purchase these dues or contact us.
|
35
35
|
|
36
|
+
- if membership.present?
|
37
|
+
= render('effective/memberships/reclassification', user: current_user)
|
38
|
+
|
36
39
|
- if current_user.membership_removed?
|
37
40
|
%p Your membership was removed on #{current_user.membership_removed_on.strftime('%F')}.
|
38
41
|
|
39
42
|
- if current_user.reinstatement_membership_history.present?
|
40
|
-
|
43
|
+
= render('effective/memberships/reinstatement', user: current_user)
|
41
44
|
|
42
45
|
- if membership_organizations.present?
|
43
46
|
%p You are a representative for #{pluralize(membership_organizations.length, 'member organization')}.
|
@@ -0,0 +1,14 @@
|
|
1
|
+
- if user.membership.present?
|
2
|
+
- now = Time.zone.now.beginning_of_day
|
3
|
+
- applicants = user.applicants.select { |applicant| applicant.in_progress? }
|
4
|
+
|
5
|
+
- if applicants.blank?
|
6
|
+
- expires_on = user.reclassification_expires_on
|
7
|
+
- category = user.membership.categories.to_sentence
|
8
|
+
|
9
|
+
- if expires_on.blank?
|
10
|
+
- # Nothing to do
|
11
|
+
- elsif now < expires_on
|
12
|
+
%p You have until #{expires_on.strftime('%F')}, #{distance_of_time_in_words(now, expires_on)} from now, to Apply for Reclassification from #{category}.
|
13
|
+
- else
|
14
|
+
%p Your ability to Apply for Reclassification from #{category} expired on #{expires_on.strftime('%F')}.
|
@@ -0,0 +1,14 @@
|
|
1
|
+
- if user.reinstatement_membership_history.present?
|
2
|
+
- now = Time.zone.now.beginning_of_day
|
3
|
+
- applicants = user.applicants.select { |applicant| applicant.in_progress? }
|
4
|
+
|
5
|
+
- if applicants.blank?
|
6
|
+
- category = user.reinstatement_membership_category
|
7
|
+
- expires_on = user.reinstatement_expires_on
|
8
|
+
|
9
|
+
- if expires_on.blank?
|
10
|
+
- # Nothing to do
|
11
|
+
- elsif now < expires_on
|
12
|
+
%p You have until #{expires_on.strftime('%F')}, #{distance_of_time_in_words(now, expires_on)} from now, to Apply for Reinstatement to #{category}.
|
13
|
+
- else
|
14
|
+
%p Your ability to Apply for Reinstatement to #{category} expired on #{expires_on.strftime('%F')}.
|
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.17.
|
4
|
+
version: 0.17.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: 2023-05-
|
11
|
+
date: 2023-05-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -525,6 +525,8 @@ files:
|
|
525
525
|
- app/views/effective/membership_directory/show.html.haml
|
526
526
|
- app/views/effective/memberships/_dashboard.html.haml
|
527
527
|
- app/views/effective/memberships/_membership.html.haml
|
528
|
+
- app/views/effective/memberships/_reclassification.html.haml
|
529
|
+
- app/views/effective/memberships/_reinstatement.html.haml
|
528
530
|
- app/views/effective/memberships_mailer/applicant_approved.liquid
|
529
531
|
- app/views/effective/memberships_mailer/applicant_completed.liquid
|
530
532
|
- app/views/effective/memberships_mailer/applicant_declined.liquid
|