effective_memberships 0.4.1 → 0.4.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/app/controllers/admin/membership_histories_controller.rb +24 -0
- data/app/controllers/admin/memberships_controller.rb +15 -0
- data/app/controllers/admin/organizations_controller.rb +1 -1
- data/app/controllers/effective/applicant_references_controller.rb +1 -1
- data/app/datatables/admin/effective_applicant_references_datatable.rb +22 -20
- data/app/datatables/admin/effective_applicants_datatable.rb +1 -1
- data/app/datatables/admin/effective_fees_datatable.rb +2 -2
- data/app/datatables/admin/effective_membership_histories_datatable.rb +7 -3
- data/app/datatables/admin/effective_memberships_datatable.rb +2 -2
- data/app/models/concerns/effective_memberships_owner.rb +44 -0
- data/app/models/effective/membership.rb +24 -2
- data/app/models/effective/membership_history.rb +15 -0
- data/app/views/admin/membership_histories/_form.html.haml +19 -0
- data/app/views/admin/membership_histories/_validation.html.haml +7 -0
- data/app/views/admin/memberships/_form.html.haml +17 -0
- data/app/views/admin/memberships/_form_membership.html.haml +22 -0
- data/app/views/effective/membership_cards/index.html.haml +1 -1
- data/config/routes.rb +2 -1
- data/lib/effective_memberships/version.rb +1 -1
- metadata +7 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1e5b6f09a47c7b274a7719fa302b98201fc0bcdfe574c290d217ad7b1720646b
|
4
|
+
data.tar.gz: 43a42af2d316ac1ba9279dbf366ef343532e808f1b21c444b8945ea78f61536a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f9e710cb88c81069d68cebad01b05d6db0fe4c7cbf0feca67d28836f03518bd1deb57ec0d41ba5bc3624128bc2d528932e5aaba48f638da49c69144873e6adf7
|
7
|
+
data.tar.gz: fa0176f7fa8e24ca28073ae54678c33b99ccde6e65ae2d107ad77301423fac0fcec3a6ee46a348de77a67be99fad6311643e1444b8e266e1593032570ecd6204
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Admin
|
2
|
+
class MembershipHistoriesController < ApplicationController
|
3
|
+
before_action(:authenticate_user!) if defined?(Devise)
|
4
|
+
before_action { EffectiveResources.authorize!(self, :admin, :effective_memberships) }
|
5
|
+
|
6
|
+
include Effective::CrudController
|
7
|
+
|
8
|
+
submit :save, 'Update History',
|
9
|
+
success: -> { "Membership history successfully updated. Please double check the history is correct." },
|
10
|
+
redirect: -> { admin_owners_path(resource) }
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def permitted_params
|
15
|
+
model = (params.key?(:effective_membership_history) ? :effective_membership_history : :membership_history)
|
16
|
+
params.require(model).permit!
|
17
|
+
end
|
18
|
+
|
19
|
+
def admin_owners_path(resource)
|
20
|
+
Effective::Resource.new(resource.owner, namespace: :admin).action_path(:edit) + '?tab=membership'
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
@@ -5,5 +5,20 @@ module Admin
|
|
5
5
|
|
6
6
|
include Effective::CrudController
|
7
7
|
|
8
|
+
submit :save, 'Update Membership',
|
9
|
+
success: -> { "#{resource.owner} has been successfully updated. Please double check the membership history is correct" },
|
10
|
+
redirect: -> { admin_owners_path(resource) }
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def permitted_params
|
15
|
+
model = (params.key?(:effective_membership) ? :effective_membership : :membership)
|
16
|
+
params.require(model).permit!
|
17
|
+
end
|
18
|
+
|
19
|
+
def admin_owners_path(resource)
|
20
|
+
Effective::Resource.new(resource.owner, namespace: :admin).action_path(:edit) + '?tab=membership'
|
21
|
+
end
|
22
|
+
|
8
23
|
end
|
9
24
|
end
|
@@ -6,7 +6,7 @@ module Admin
|
|
6
6
|
include Effective::CrudController
|
7
7
|
|
8
8
|
resource_scope -> { EffectiveMemberships.Organization.deep.all }
|
9
|
-
datatable -> { EffectiveResources.best('Admin::
|
9
|
+
datatable -> { EffectiveResources.best('Admin::EffectiveOrganizationsDatatable').new }
|
10
10
|
|
11
11
|
private
|
12
12
|
|
@@ -25,7 +25,7 @@ module Effective
|
|
25
25
|
def permitted_params
|
26
26
|
permitted = params.require(:effective_applicant_reference).permit!.except(:token, :last_notified_at, :status, :status_steps)
|
27
27
|
|
28
|
-
if current_user && current_user.
|
28
|
+
if current_user && current_user.memberships_owners.include?(resource.applicant&.owner)
|
29
29
|
permitted.except(:reservations, :reservations_reason, :work_history, :accept_declaration)
|
30
30
|
else
|
31
31
|
permitted
|
@@ -1,31 +1,33 @@
|
|
1
|
-
|
1
|
+
module Admin
|
2
|
+
class EffectiveApplicantReferencesDatatable < Effective::Datatable
|
2
3
|
|
3
|
-
|
4
|
-
|
4
|
+
datatable do
|
5
|
+
order :name
|
5
6
|
|
6
|
-
|
7
|
+
col :applicant
|
7
8
|
|
8
|
-
|
9
|
-
|
10
|
-
|
9
|
+
col :name
|
10
|
+
col :email
|
11
|
+
col :phone
|
11
12
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
13
|
+
col :status do |reference|
|
14
|
+
if reference.submitted?
|
15
|
+
'Waiting on response'
|
16
|
+
elsif reference.completed?
|
17
|
+
'Completed'
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
col :last_notified_at do |reference|
|
22
|
+
reference.last_notified_at&.strftime('%F') unless reference.completed?
|
17
23
|
end
|
18
|
-
end
|
19
24
|
|
20
|
-
|
21
|
-
reference.last_notified_at&.strftime('%F') unless reference.completed?
|
25
|
+
actions_col
|
22
26
|
end
|
23
27
|
|
24
|
-
|
25
|
-
|
28
|
+
collection do
|
29
|
+
Effective::ApplicantReference.deep.all
|
30
|
+
end
|
26
31
|
|
27
|
-
collection do
|
28
|
-
Effective::ApplicantReference.deep.all
|
29
32
|
end
|
30
|
-
|
31
33
|
end
|
@@ -49,8 +49,8 @@ module Admin
|
|
49
49
|
|
50
50
|
raise('expected an owner_id, not user_id') if attributes[:user_id].present?
|
51
51
|
|
52
|
-
if attributes[:owner_id]
|
53
|
-
scope = scope.where(owner_id: attributes[:owner_id])
|
52
|
+
if attributes[:owner_id] && attributes[:owner_type]
|
53
|
+
scope = scope.where(owner_id: attributes[:owner_id], owner_type: attributes[:owner_type])
|
54
54
|
end
|
55
55
|
|
56
56
|
if attributes[:applicant_id]
|
@@ -12,8 +12,6 @@ module Admin
|
|
12
12
|
|
13
13
|
col :owner
|
14
14
|
|
15
|
-
col :number
|
16
|
-
|
17
15
|
col :categories, label: 'Category' do |history|
|
18
16
|
history.categories.map.with_index do |category, index|
|
19
17
|
category_id = history.category_ids[index]
|
@@ -23,6 +21,8 @@ module Admin
|
|
23
21
|
end.join.html_safe
|
24
22
|
end
|
25
23
|
|
24
|
+
col :number
|
25
|
+
|
26
26
|
col :category_ids, visible: false
|
27
27
|
|
28
28
|
col :bad_standing
|
@@ -35,7 +35,11 @@ module Admin
|
|
35
35
|
raise('expected an owner_id, not user_id') if attributes[:user_id].present?
|
36
36
|
|
37
37
|
scope = Effective::MembershipHistory.deep.all
|
38
|
-
|
38
|
+
|
39
|
+
if attributes[:owner_id] && attributes[:owner_type]
|
40
|
+
scope = scope.where(owner_id: attributes[:owner_id], owner_type: attributes[:owner_type])
|
41
|
+
end
|
42
|
+
|
39
43
|
scope
|
40
44
|
end
|
41
45
|
|
@@ -69,8 +69,8 @@ module Admin
|
|
69
69
|
|
70
70
|
raise('expected an owner_id, not user_id') if attributes[:user_id].present?
|
71
71
|
|
72
|
-
if attributes[:owner_id].present?
|
73
|
-
memberships = memberships.where(owner_id: attributes[:owner_id])
|
72
|
+
if attributes[:owner_id].present? && attributes[:owner_type].present?
|
73
|
+
memberships = memberships.where(owner_id: attributes[:owner_id], owner_type: attributes[:owner_type])
|
74
74
|
end
|
75
75
|
|
76
76
|
memberships
|
@@ -265,4 +265,48 @@ module EffectiveMembershipsOwner
|
|
265
265
|
membership_histories.find { |history| (history.start_on..history.end_on).cover?(date) } # Ruby 2.6 supports endless ranges
|
266
266
|
end
|
267
267
|
|
268
|
+
# Point out busted data
|
269
|
+
def membership_history_errors
|
270
|
+
return unless membership.present?
|
271
|
+
return unless membership_histories.present?
|
272
|
+
|
273
|
+
errors = []
|
274
|
+
history = membership_histories.first
|
275
|
+
last_history = membership_histories.last
|
276
|
+
|
277
|
+
# Check membership joined on date matches first history start date
|
278
|
+
if membership.joined_on != history.start_on
|
279
|
+
errors << "The joined date #{membership.joined_on.strftime('%F')} does not match the first history start date of #{history.start_on.strftime('%F')}. Please change the first history start date to #{membership.joined_on.strftime('%F')} or update the joined date above."
|
280
|
+
end
|
281
|
+
|
282
|
+
# Check that there is a membership history row if the registered date is unique
|
283
|
+
if membership.joined_on != membership.registration_on && membership_histories.none? { |mh| mh.start_on == membership.registration_on }
|
284
|
+
errors << "The registered date #{membership.registration_on.strftime('%F')} is missing a history with this date. Please create a history with a start date of #{membership.registration_on.strftime('%F')} or update the registered date above."
|
285
|
+
end
|
286
|
+
|
287
|
+
# Check numbers
|
288
|
+
if membership.number.present? && membership_histories.none? { |history| history.number == membership.number }
|
289
|
+
errors << "The membership number ##{membership.number} is missing a history with this number. Please create a history with the #{membership.number} number or update the membership number above."
|
290
|
+
end
|
291
|
+
|
292
|
+
# Check that the last history does not have an end_on date
|
293
|
+
|
294
|
+
if last_history.end_on.present? && !last_history.removed?
|
295
|
+
errors << "The most recent history must have a blank end date. Please remove the end date of the most recent history entry or create another history."
|
296
|
+
elsif membership_histories.any? { |history| history.end_on.blank? && history != last_history }
|
297
|
+
errors << "The end date must be present for all past histories. Please add the end date to all histories, except the most recent history."
|
298
|
+
elsif !membership_history_continuous?
|
299
|
+
errors << "The start and end dates are overlapping or non-continuous. Please make sure each history start date has a matching history end date"
|
300
|
+
end
|
301
|
+
|
302
|
+
errors
|
303
|
+
end
|
304
|
+
|
305
|
+
def membership_history_continuous?
|
306
|
+
membership_histories.all? do |history|
|
307
|
+
history.end_on.blank? || (history.end_on.present? && history.removed?) || membership_histories.find { |h| h.start_on == history.end_on }.present?
|
308
|
+
end
|
309
|
+
end
|
310
|
+
|
311
|
+
|
268
312
|
end
|
@@ -2,6 +2,8 @@ module Effective
|
|
2
2
|
class Membership < ActiveRecord::Base
|
3
3
|
belongs_to :owner, polymorphic: true
|
4
4
|
|
5
|
+
attr_accessor :current_action
|
6
|
+
|
5
7
|
has_many :membership_categories, -> { order(:id) }, inverse_of: :membership, dependent: :delete_all
|
6
8
|
accepts_nested_attributes_for :membership_categories
|
7
9
|
|
@@ -54,7 +56,10 @@ module Effective
|
|
54
56
|
|
55
57
|
before_validation do
|
56
58
|
self.registration_on ||= joined_on
|
57
|
-
|
59
|
+
end
|
60
|
+
|
61
|
+
before_validation(if: -> { number_changed? }) do
|
62
|
+
self.number_as_integer = (Integer(number) rescue nil)
|
58
63
|
end
|
59
64
|
|
60
65
|
validates :number, presence: true, uniqueness: true
|
@@ -66,12 +71,29 @@ module Effective
|
|
66
71
|
self.errors.add(:owner_id, 'must be a memberships owner') unless owner.class.effective_memberships_owner?
|
67
72
|
end
|
68
73
|
|
74
|
+
validate(if: -> { registration_on.present? && joined_on.present? }) do
|
75
|
+
self.errors.add(:registration_on, 'must match or be greater than the joined date') if registration_on < joined_on
|
76
|
+
end
|
77
|
+
|
69
78
|
def self.max_number
|
70
79
|
maximum('number_as_integer') || 0
|
71
80
|
end
|
72
81
|
|
73
82
|
def to_s
|
74
|
-
'membership'
|
83
|
+
return 'membership' if owner.blank?
|
84
|
+
|
85
|
+
summary = [
|
86
|
+
owner.to_s,
|
87
|
+
'is',
|
88
|
+
(categories.to_sentence),
|
89
|
+
'member',
|
90
|
+
"##{number_was}",
|
91
|
+
"who joined #{joined_on&.strftime('%F') || '-'}",
|
92
|
+
("and last registered #{registration_on.strftime('%F')}" if registration_on > joined_on),
|
93
|
+
(". Membership is Not In Good Standing because #{bad_standing_reason}" if bad_standing?)
|
94
|
+
].compact.join(' ')
|
95
|
+
|
96
|
+
(summary + '.').html_safe
|
75
97
|
end
|
76
98
|
|
77
99
|
# We can't use the polymorphic has_many. So this is a helper.
|
@@ -36,5 +36,20 @@ module Effective
|
|
36
36
|
'membership history'
|
37
37
|
end
|
38
38
|
|
39
|
+
# These two accessors are for the memberships history form.
|
40
|
+
# But we just assign categories and category_ids directly in registrar.
|
41
|
+
def membership_categories
|
42
|
+
category_ids.present? ? EffectiveMemberships.Category.where(id: category_ids) : []
|
43
|
+
end
|
44
|
+
|
45
|
+
def membership_category_ids
|
46
|
+
membership_categories.map(&:id)
|
47
|
+
end
|
48
|
+
|
49
|
+
def membership_category_ids=(ids)
|
50
|
+
categories = EffectiveMemberships.Category.where(id: ids)
|
51
|
+
assign_attributes(categories: categories.map(&:to_s), category_ids: categories.map(&:id))
|
52
|
+
end
|
53
|
+
|
39
54
|
end
|
40
55
|
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
= effective_form_with(model: [:admin, membership_history], engine: true) do |f|
|
2
|
+
- if inline_datatable?
|
3
|
+
= f.hidden_field :owner_id
|
4
|
+
= f.hidden_field :owner_type
|
5
|
+
- else
|
6
|
+
- raise('todo')
|
7
|
+
- collection = EffectiveMembershipsOwner.descendants.map { |d| [d.name.to_s, d.members.sorted] }.to_h
|
8
|
+
= f.select :owner_id, collection, polymorphic: true
|
9
|
+
|
10
|
+
= f.date_field :start_on, hint: 'The start date of this period in history. Must be present.'
|
11
|
+
|
12
|
+
= f.date_field :end_on, hint: 'The end date of this period in history. Must be present for all past histories. Must be blank in the most recent history, unless membership removed.'
|
13
|
+
= f.text_field :number, hint: 'The membership number'
|
14
|
+
= f.select :membership_category_ids, EffectiveMemberships.Category.all.sorted, label: 'Membership Categories', hint: 'The membership category or categories held during this period in history.'
|
15
|
+
|
16
|
+
= f.check_box :bad_standing, hint: 'Membership in bad standing'
|
17
|
+
= f.check_box :removed, hint: 'Membership removed'
|
18
|
+
|
19
|
+
= f.submit 'Update History', border: false, center: true, 'data-confirm': "Really update #{f.object.owner}?"
|
@@ -0,0 +1,17 @@
|
|
1
|
+
- membership ||= owner.membership
|
2
|
+
- owner ||= membership.owner
|
3
|
+
|
4
|
+
- if membership.present?
|
5
|
+
= card('Member Information') do
|
6
|
+
= render 'admin/memberships/form_membership', membership: membership
|
7
|
+
|
8
|
+
= card('History') do
|
9
|
+
= render 'admin/membership_histories/validation', owner: owner
|
10
|
+
= render_datatable(Admin::EffectiveMembershipHistoriesDatatable.new(owner: owner), inline: true, simple: true)
|
11
|
+
|
12
|
+
- # Always render this one
|
13
|
+
= render 'admin/registrar_actions/form', owner: owner
|
14
|
+
|
15
|
+
- if membership.blank? && owner.membership_histories.present?
|
16
|
+
= card('History') do
|
17
|
+
= render_datatable(Admin::EffectiveMembershipHistoriesDatatable.new(owner: owner), inline: true, simple: true)
|
@@ -0,0 +1,22 @@
|
|
1
|
+
= effective_form_with(model: [:admin, membership], engine: true) do |f|
|
2
|
+
= f.hidden_field :owner_id
|
3
|
+
= f.hidden_field :owner_type
|
4
|
+
|
5
|
+
%p.text-muted
|
6
|
+
Change a member's information.
|
7
|
+
|
8
|
+
- f.object.current_action = true if f.errors.present?
|
9
|
+
|
10
|
+
= f.static_field :current_action, label: 'Current Membership' do
|
11
|
+
= membership.to_s
|
12
|
+
|
13
|
+
= f.check_box :current_action, label: 'Yes, update membership information'
|
14
|
+
|
15
|
+
= f.show_if :current_action, true do
|
16
|
+
= f.date_field :joined_on, label: 'Joined', hint: 'When the member first received any membership category'
|
17
|
+
= f.date_field :registration_on, label: 'Registered', hint: 'When the membership category last changed'
|
18
|
+
= f.text_field :number, hint: 'The membership number. Must be unique.'
|
19
|
+
|
20
|
+
%p.text-muted To update the current membership categories, use the 'Assign' or 'Reclassify' actions below
|
21
|
+
|
22
|
+
= f.submit 'Update Membership', border: false, center: true, 'data-confirm': "Really update #{f.object.owner}?"
|
data/config/routes.rb
CHANGED
@@ -43,7 +43,8 @@ EffectiveMemberships::Engine.routes.draw do
|
|
43
43
|
resources :applicant_course_names, except: [:show]
|
44
44
|
|
45
45
|
resources :fee_payments, only: [:index, :show]
|
46
|
-
resources :memberships, only: [:index]
|
46
|
+
resources :memberships, only: [:index, :update]
|
47
|
+
resources :membership_histories, except: [:show]
|
47
48
|
resources :registrar_actions, only: [:create]
|
48
49
|
|
49
50
|
resources :organizations, except: [:show] do
|
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.4.
|
4
|
+
version: 0.4.4
|
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-03-
|
11
|
+
date: 2022-03-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -247,6 +247,7 @@ files:
|
|
247
247
|
- app/controllers/admin/categories_controller.rb
|
248
248
|
- app/controllers/admin/fee_payments_controller.rb
|
249
249
|
- app/controllers/admin/fees_controller.rb
|
250
|
+
- app/controllers/admin/membership_histories_controller.rb
|
250
251
|
- app/controllers/admin/memberships_controller.rb
|
251
252
|
- app/controllers/admin/organizations_controller.rb
|
252
253
|
- app/controllers/admin/registrar_actions_controller.rb
|
@@ -334,6 +335,10 @@ files:
|
|
334
335
|
- app/views/admin/fee_payments/_fee_payment.html.haml
|
335
336
|
- app/views/admin/fees/_fee.html.haml
|
336
337
|
- app/views/admin/fees/_form.html.haml
|
338
|
+
- app/views/admin/membership_histories/_form.html.haml
|
339
|
+
- app/views/admin/membership_histories/_validation.html.haml
|
340
|
+
- app/views/admin/memberships/_form.html.haml
|
341
|
+
- app/views/admin/memberships/_form_membership.html.haml
|
337
342
|
- app/views/admin/memberships/_status.html.haml
|
338
343
|
- app/views/admin/organizations/_fields.html.haml
|
339
344
|
- app/views/admin/organizations/_form.html.haml
|