effective_memberships 0.4.16 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (35) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/admin/registrar_actions_controller.rb +8 -0
  3. data/app/controllers/admin/statuses_controller.rb +19 -0
  4. data/app/datatables/admin/effective_membership_histories_datatable.rb +10 -0
  5. data/app/datatables/admin/effective_memberships_datatable.rb +2 -1
  6. data/app/datatables/admin/effective_statuses_datatable.rb +21 -0
  7. data/app/models/concerns/effective_memberships_applicant.rb +3 -0
  8. data/app/models/concerns/effective_memberships_category.rb +2 -1
  9. data/app/models/concerns/effective_memberships_fee_payment.rb +2 -1
  10. data/app/models/concerns/effective_memberships_owner.rb +37 -7
  11. data/app/models/concerns/effective_memberships_registrar.rb +50 -3
  12. data/app/models/concerns/effective_memberships_status.rb +71 -0
  13. data/app/models/effective/applicant_experience.rb +1 -1
  14. data/app/models/effective/membership.rb +41 -3
  15. data/app/models/effective/membership_history.rb +17 -4
  16. data/app/models/effective/membership_status.rb +13 -0
  17. data/app/models/effective/registrar_action.rb +38 -4
  18. data/app/models/effective/status.rb +7 -0
  19. data/app/views/admin/applicants/_form.html.haml +1 -54
  20. data/app/views/admin/applicants/_form_applicant.html.haml +56 -0
  21. data/app/views/admin/membership_histories/_form.html.haml +2 -0
  22. data/app/views/admin/registrar_actions/_form.html.haml +7 -0
  23. data/app/views/admin/registrar_actions/_form_assign.html.haml +29 -9
  24. data/app/views/admin/registrar_actions/_form_register.html.haml +7 -2
  25. data/app/views/admin/registrar_actions/_form_status_change.html.haml +41 -0
  26. data/app/views/admin/statuses/_form.html.haml +8 -0
  27. data/app/views/admin/statuses/_form_status.html.haml +9 -0
  28. data/app/views/effective/applicants/select.html.haml +1 -0
  29. data/config/effective_memberships.rb +4 -0
  30. data/config/routes.rb +2 -1
  31. data/db/migrate/01_create_effective_memberships.rb.erb +31 -0
  32. data/lib/effective_memberships/engine.rb +1 -0
  33. data/lib/effective_memberships/version.rb +1 -1
  34. data/lib/effective_memberships.rb +9 -6
  35. metadata +11 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 774b42acc07d3dae76bd17888dd5c323b3a47463cb339caa96162ea323ddf4a7
4
- data.tar.gz: e9ee1f7769177827ad627d61e68d294a6d868ac26ec133396b8c861b221a0b2f
3
+ metadata.gz: e719afd32d55f610b718c370497cceb43760450cfca029e618efc99dd73a8d28
4
+ data.tar.gz: 4564cce2a02072ad8db4c81b4c7507b522a4a1a03683899797d9c2d8aa1f89b5
5
5
  SHA512:
6
- metadata.gz: 7684254166c10f7f1c826e2e5d2a747f0d8061818355e45242303bdd8438f612a1836228298416f7f6d5bb7ee132cd92a09ecd4334fc72301755e6432d57811c
7
- data.tar.gz: 555d6bbfd89c287031d106998548f76a0d26a5c5e560a018cabb1f82ae8344126e26bdb398a8ff3508ac7e51cca6d8dfc7137d08f0784da4bd43670065719f01
6
+ metadata.gz: 0d711bedd67af762919f71c2d52a3848c70c14af8e756cab24018a4b45d616f92f42510329f53c2e5f886bfceb248e522a9d87f62a89f24641add4b208f8d0c8
7
+ data.tar.gz: 0f11ce742fc500785d1203c87fe3dae05d855deb4f7a51953de4a6efe3e1dff4dc12b06f72631da580cdda039552265abcf2d3c94bdc0291fb787e76c69773c8
@@ -14,6 +14,14 @@ module Admin
14
14
  success: -> { "#{resource.owner} has been reclassified to #{resource.owner.membership.category}" },
15
15
  redirect: -> { admin_owners_path(resource) }
16
16
 
17
+ submit :status_change, 'Change Status',
18
+ success: -> { "#{resource.owner} has been status changed to #{resource.owner.membership.status || 'None'}" },
19
+ redirect: -> { admin_owners_path(resource) }
20
+
21
+ submit :status_remove, 'Remove Status',
22
+ success: -> { "#{resource.owner} has had their status removed" },
23
+ redirect: -> { admin_owners_path(resource) }
24
+
17
25
  submit :assign, 'Assign',
18
26
  success: -> { "#{resource.owner} has been assigned to #{resource.owner.membership.categories.to_sentence}" },
19
27
  redirect: -> { admin_owners_path(resource) }
@@ -0,0 +1,19 @@
1
+ module Admin
2
+ class StatusesController < 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
+ resource_scope -> { EffectiveMemberships.Status.deep.all }
9
+ datatable -> { Admin::EffectiveStatusesDatatable.new }
10
+
11
+ private
12
+
13
+ def permitted_params
14
+ model = (params.key?(:effective_status) ? :effective_status : :status)
15
+ params.require(model).permit!
16
+ end
17
+
18
+ end
19
+ end
@@ -21,9 +21,19 @@ module Admin
21
21
  end.join.html_safe
22
22
  end
23
23
 
24
+ col :statuses, label: 'Status' do |history|
25
+ history.statuses.map.with_index do |status, index|
26
+ status_id = history.status_ids[index]
27
+ link = link_to(status, effective_memberships.edit_admin_status_path(status_id))
28
+
29
+ content_tag(:div, link, class: 'col-resource_item')
30
+ end.join.html_safe
31
+ end
32
+
24
33
  col :number
25
34
 
26
35
  col :category_ids, visible: false
36
+ col :status_ids, visible: false
27
37
 
28
38
  col :bad_standing
29
39
  col :removed
@@ -9,7 +9,8 @@ module Admin
9
9
  col :owner_type, visible: false
10
10
 
11
11
  val :owner
12
- col :categories
12
+ col :categories, search: EffectiveMemberships.Category.sorted.map(&:to_s)
13
+ col :statuses, search: EffectiveMemberships.Status.sorted.map(&:to_s)
13
14
 
14
15
  col :number
15
16
  col :number_as_integer, visible: false
@@ -0,0 +1,21 @@
1
+ module Admin
2
+ class EffectiveStatusesDatatable < Effective::Datatable
3
+ datatable do
4
+ reorder :position
5
+
6
+ col :updated_at, visible: false
7
+ col :created_at, visible: false
8
+ col :id, visible: false
9
+
10
+ col :title
11
+ col :status_type, search: EffectiveMemberships.Status.status_types
12
+
13
+ actions_col
14
+ end
15
+
16
+ collection do
17
+ EffectiveMemberships.Status.deep.all
18
+ end
19
+
20
+ end
21
+ end
@@ -92,7 +92,9 @@ module EffectiveMembershipsApplicant
92
92
  accepts_nested_attributes_for :organization
93
93
 
94
94
  belongs_to :category, polymorphic: true, optional: true
95
+
95
96
  belongs_to :from_category, polymorphic: true, optional: true
97
+ belongs_to :from_status, polymorphic: true, optional: true
96
98
 
97
99
  has_many :applicant_reviews, -> { order(:id) }, as: :applicant, inverse_of: :applicant, dependent: :destroy
98
100
  accepts_nested_attributes_for :applicant_reviews, reject_if: :all_blank, allow_destroy: true
@@ -186,6 +188,7 @@ module EffectiveMembershipsApplicant
186
188
  before_validation(if: -> { (new_record? || current_step == :select) && owner.present? }) do
187
189
  self.applicant_type = (owner.membership.blank? ? 'Apply to Join' : 'Apply to Reclassify')
188
190
  self.from_category = owner.membership&.category
191
+ self.from_status = owner.membership&.status
189
192
  end
190
193
 
191
194
  before_validation(if: -> { current_step == :experience }) do
@@ -42,7 +42,7 @@ module EffectiveMembershipsCategory
42
42
  category_type :string
43
43
 
44
44
  title :string
45
- category :string
45
+ category :string # Unused but must belong to self.class.categories
46
46
  position :integer
47
47
 
48
48
  # Applicants
@@ -101,6 +101,7 @@ module EffectiveMembershipsCategory
101
101
 
102
102
  serialize :can_apply_restricted_ids, Array
103
103
  serialize :applicant_wizard_steps, Array
104
+ serialize :applicant_review_wizard_steps, Array
104
105
  serialize :fee_payment_wizard_steps, Array
105
106
 
106
107
  scope :deep, -> { includes(:rich_texts) }
@@ -56,8 +56,8 @@ module EffectiveMembershipsFeePayment
56
56
  belongs_to :organization, polymorphic: true, optional: true
57
57
  accepts_nested_attributes_for :organization
58
58
 
59
- # Like maybe optionally it makes sense.
60
59
  belongs_to :category, polymorphic: true, optional: true
60
+ belongs_to :from_status, polymorphic: true, optional: true
61
61
 
62
62
  # Effective Namespace
63
63
  has_many :fees, -> { order(:id) }, as: :parent, class_name: 'Effective::Fee', dependent: :nullify
@@ -102,6 +102,7 @@ module EffectiveMembershipsFeePayment
102
102
 
103
103
  before_validation(if: -> { current_step == :start && user && user.membership }) do
104
104
  self.category ||= user.membership.categories.first if user.membership.categories.length == 1
105
+ self.from_status ||= user.membership.statuses.first if user.membership.statuses.length == 1
105
106
  end
106
107
 
107
108
  # All Steps validations
@@ -53,6 +53,24 @@ module EffectiveMembershipsOwner
53
53
  where(id: with_paid_fees_through.select(:owner_id))
54
54
  }
55
55
 
56
+ scope :members_with_category, -> (categories) {
57
+ raise('expected an EffectiveMemberships.Category') unless Array(categories).all? { |cat| cat.kind_of?(EffectiveMemberships.Category) }
58
+
59
+ membership_categories = Effective::MembershipCategory.where(category: categories)
60
+ memberships = Effective::Membership.where(id: membership_categories.select(:membership_id))
61
+
62
+ where(id: memberships.where(owner_type: name).select(:owner_id))
63
+ }
64
+
65
+ scope :members_with_status, -> (statuses) {
66
+ raise('expected an EffectiveMemberships.Status') unless Array(statuses).all? { |status| status.kind_of?(EffectiveMemberships.Status) }
67
+
68
+ membership_statuses = Effective::MembershipStatus.where(status: statuses)
69
+ memberships = Effective::Membership.where(id: membership_statuses.select(:membership_id))
70
+
71
+ where(id: memberships.where(owner_type: name).select(:owner_id))
72
+ }
73
+
56
74
  end
57
75
 
58
76
  def assign_member_role
@@ -103,6 +121,10 @@ module EffectiveMembershipsOwner
103
121
  EffectiveMemberships.Category.sorted.all
104
122
  end
105
123
 
124
+ def registrar_action_statuses(action)
125
+ EffectiveMemberships.Status.sorted.all
126
+ end
127
+
106
128
  # Instance Methods
107
129
  def build_prorated_fee(date: nil)
108
130
  raise('must have an existing membership') unless membership.present?
@@ -271,21 +293,29 @@ module EffectiveMembershipsOwner
271
293
 
272
294
  # The date of change
273
295
  start_on ||= Time.zone.now
274
- removed = membership.marked_for_destruction?
275
296
 
276
297
  # End the other membership histories
277
298
  membership_histories.each { |history| history.end_on ||= start_on }
278
299
 
279
300
  # Snapshot of the current membership at this time
280
- membership_histories.build(
301
+ history = membership_histories.build(
281
302
  start_on: start_on,
282
303
  end_on: nil,
283
- removed: removed,
284
- bad_standing: membership.bad_standing?,
285
- categories: (membership.categories.map(&:to_s) unless removed),
286
- category_ids: (membership.categories.map(&:id) unless removed),
287
- number: (membership.number unless removed)
304
+ removed: membership.marked_for_destruction?,
305
+ bad_standing: membership.bad_standing?
288
306
  )
307
+
308
+ unless history.removed?
309
+ history.assign_attributes(
310
+ number: membership.number,
311
+ categories: membership.categories.map(&:to_s),
312
+ category_ids: membership.categories.map(&:id),
313
+ statuses: membership.statuses.map(&:to_s),
314
+ status_ids: membership.statuses.map(&:id)
315
+ )
316
+ end
317
+
318
+ history
289
319
  end
290
320
 
291
321
  def membership_history_on(date)
@@ -42,11 +42,14 @@ module EffectiveMembershipsRegistrar
42
42
  period(date: date).end_of_year
43
43
  end
44
44
 
45
- def assign!(owner, categories:, date: nil, number: nil)
45
+ # Category is required, statuses are optional
46
+ def assign!(owner, categories:, statuses: nil, date: nil, number: nil)
46
47
  categories = Array(categories)
48
+ statuses = Array(statuses)
47
49
 
48
50
  raise('expecting a memberships owner') unless owner.class.respond_to?(:effective_memberships_owner?)
49
- raise('expecting a membership category') unless categories.present? && categories.all? { |cat| cat.class.respond_to?(:effective_memberships_category?) }
51
+ raise('expecting a membership category') if categories.blank? || categories.any? { |cat| !cat.class.respond_to?(:effective_memberships_category?) }
52
+ raise('expecting an membership status (optional)') if statuses.present? && statuses.any? { |status| !status.class.respond_to?(:effective_memberships_status?) }
50
53
 
51
54
  # Default Date and next number
52
55
  date ||= Time.zone.now
@@ -64,6 +67,17 @@ module EffectiveMembershipsRegistrar
64
67
  membership.number ||= number
65
68
  membership.number_as_integer ||= (Integer(number) rescue nil)
66
69
 
70
+ # Delete any removed statuses
71
+ membership.membership_statuses.each do |membership_status|
72
+ next if statuses.include?(membership_status.status)
73
+ membership_status.mark_for_destruction
74
+ end
75
+
76
+ # Build any additional statuses
77
+ statuses.each do |status|
78
+ membership.build_membership_status(status: status)
79
+ end
80
+
67
81
  # Delete any removed categories
68
82
  membership.membership_categories.each do |membership_category|
69
83
  next if categories.include?(membership_category.category)
@@ -76,6 +90,7 @@ module EffectiveMembershipsRegistrar
76
90
  end
77
91
 
78
92
  changed = membership.membership_categories.any? { |mc| mc.new_record? || mc.marked_for_destruction? }
93
+ changed ||= membership.membership_statuses.any? { |ms| ms.new_record? || ms.marked_for_destruction? }
79
94
 
80
95
  if changed
81
96
  membership.registration_on = date # Always new registration_on
@@ -88,9 +103,10 @@ module EffectiveMembershipsRegistrar
88
103
  owner.update_membership_status!
89
104
  end
90
105
 
91
- def register!(owner, to:, date: nil, number: nil, skip_fees: false)
106
+ def register!(owner, to:, status: nil, date: nil, number: nil, skip_fees: false)
92
107
  raise('expecting a memberships owner') unless owner.class.respond_to?(:effective_memberships_owner?)
93
108
  raise('expecting a memberships category') unless to.class.respond_to?(:effective_memberships_category?)
109
+ raise('expecting a memberships status') unless status.nil? || status.class.respond_to?(:effective_memberships_status?)
94
110
  raise('owner has existing membership. use reclassify! instead.') if owner.membership.present?
95
111
 
96
112
  # Default Date and next number
@@ -113,6 +129,9 @@ module EffectiveMembershipsRegistrar
113
129
  # Assign Category
114
130
  membership.build_membership_category(category: to)
115
131
 
132
+ # Assign Status
133
+ membership.build_membership_status(status: status) if status.present?
134
+
116
135
  # Assign fees paid through period
117
136
  if skip_fees
118
137
  membership.fees_paid_period = period
@@ -164,6 +183,34 @@ module EffectiveMembershipsRegistrar
164
183
  save!(owner, date: date)
165
184
  end
166
185
 
186
+ # This clears the status entirely from user
187
+ def status_remove!(owner, date: nil)
188
+ status_change!(owner, to: nil, date: date)
189
+ end
190
+
191
+ # To can be nil to clear the status entirely
192
+ def status_change!(owner, to:, date: nil)
193
+ raise('expecting a memberships owner') unless owner.class.respond_to?(:effective_memberships_owner?)
194
+ raise('owner must have an existing membership. use register! instead') if owner.membership.blank?
195
+
196
+ from = owner.membership.status
197
+
198
+ raise('expecting a to memberships status') if to.present? && !to.class.respond_to?(:effective_memberships_status?)
199
+ raise('expecting a from memberships status') if from.present? && !from.class.respond_to?(:effective_memberships_status?)
200
+ raise('expected to and from to be different') if from == to
201
+
202
+ date ||= Time.zone.now
203
+
204
+ membership = owner.membership
205
+
206
+ # Assign Status
207
+ membership.build_membership_status(status: to) if to.present?
208
+ membership.membership_status(status: from).mark_for_destruction if from.present?
209
+
210
+ # Save
211
+ save!(owner, date: date)
212
+ end
213
+
167
214
  def remove!(owner, date: nil)
168
215
  raise('expecting a memberships owner') unless owner.class.respond_to?(:effective_memberships_owner?)
169
216
  raise('expected a member') unless owner.membership.present?
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ # EffectiveMembershipsStatus
4
+ #
5
+ # Mark your status model with effective_memberships_status to get all the includes
6
+
7
+ module EffectiveMembershipsStatus
8
+ extend ActiveSupport::Concern
9
+
10
+ module Base
11
+ def effective_memberships_status
12
+ include ::EffectiveMembershipsStatus
13
+ end
14
+ end
15
+
16
+ module ClassMethods
17
+ def effective_memberships_status?; true; end
18
+
19
+ def status_types
20
+ ['Individual', 'Organization']
21
+ end
22
+
23
+ def statuses
24
+ []
25
+ end
26
+ end
27
+
28
+ included do
29
+ log_changes(except: :memberships) if respond_to?(:log_changes)
30
+
31
+ has_many :membership_statuses, class_name: 'Effective::MembershipStatus', as: :status
32
+
33
+ effective_resource do
34
+ status_type :string
35
+
36
+ title :string
37
+ status :string # Unused but must belong to self.class.statuses
38
+ position :integer
39
+
40
+ timestamps
41
+ end
42
+
43
+ scope :deep, -> { all }
44
+ scope :sorted, -> { order(:position) }
45
+
46
+ validates :title, presence: true, uniqueness: true
47
+ validates :status_type, presence: true
48
+ validates :position, presence: true
49
+
50
+ before_validation do
51
+ self.position ||= (self.class.pluck(:position).compact.max || -1) + 1
52
+ self.status_type ||= self.class.status_types.first
53
+ end
54
+
55
+ end
56
+
57
+ # Instance Methods
58
+
59
+ def to_s
60
+ title.presence || 'New Membership Status'
61
+ end
62
+
63
+ def individual?
64
+ status_type == 'Individual'
65
+ end
66
+
67
+ def organization?
68
+ status_type == 'Organization'
69
+ end
70
+
71
+ end
@@ -34,7 +34,7 @@ module Effective
34
34
  validates :position, presence: true
35
35
  validates :employer, presence: true
36
36
  validates :start_on, presence: true
37
- validates :end_on, presence: true
37
+ validates :end_on, presence: true, unless: -> { still_work_here? }
38
38
  validates :level, presence: true, inclusion: { in: LEVELS }
39
39
  validates :months, presence: true
40
40
 
@@ -7,6 +7,9 @@ module Effective
7
7
  has_many :membership_categories, -> { order(:id) }, inverse_of: :membership, dependent: :delete_all
8
8
  accepts_nested_attributes_for :membership_categories
9
9
 
10
+ has_many :membership_statuses, -> { order(:id) }, inverse_of: :membership, dependent: :delete_all
11
+ accepts_nested_attributes_for :membership_statuses
12
+
10
13
  log_changes(to: :owner) if respond_to?(:log_changes)
11
14
 
12
15
  effective_resource do
@@ -74,7 +77,8 @@ module Effective
74
77
  summary = [
75
78
  owner.to_s,
76
79
  'is',
77
- (categories.to_sentence),
80
+ (statuses.to_sentence if statuses.present?),
81
+ (categories.to_sentence if categories.present?),
78
82
  'member',
79
83
  "##{number_was}",
80
84
  "who joined #{joined_on&.strftime('%F') || '-'}",
@@ -85,6 +89,8 @@ module Effective
85
89
  (summary + '.').html_safe
86
90
  end
87
91
 
92
+ ## Membership Categories
93
+
88
94
  # We can't use the polymorphic has_many. So this is a helper.
89
95
  def categories
90
96
  membership_categories.reject(&:marked_for_destruction?).map(&:category)
@@ -96,12 +102,12 @@ module Effective
96
102
 
97
103
  # We might want to use singular memberships.
98
104
  def category
99
- raise('expected singular usage but there are more than one membership') if categories.length > 1
105
+ raise('expected singular usage but there are more than one membership category') if categories.length > 1
100
106
  categories.first
101
107
  end
102
108
 
103
109
  def category_id
104
- raise('expected singular usage but there are more than one membership') if categories.length > 1
110
+ raise('expected singular usage but there are more than one membership category') if categories.length > 1
105
111
  categories.first.id
106
112
  end
107
113
 
@@ -115,6 +121,38 @@ module Effective
115
121
  membership_category(category: category) || membership_categories.build(category: category)
116
122
  end
117
123
 
124
+ ## Membership Statuses
125
+
126
+ # We can't use the polymorphic has_many. So this is a helper.
127
+ def statuses
128
+ membership_statuses.reject(&:marked_for_destruction?).map(&:status)
129
+ end
130
+
131
+ def status_ids
132
+ membership_statuses.reject(&:marked_for_destruction?).map(&:status_id)
133
+ end
134
+
135
+ # We might want to use singular memberships.
136
+ def status
137
+ raise('expected singular usage but there are more than one membership status') if statuses.length > 1
138
+ statuses.first
139
+ end
140
+
141
+ def status_id
142
+ raise('expected singular usage but there are more than one membership status') if statuses.length > 1
143
+ statuses.first.id
144
+ end
145
+
146
+ def membership_status(status:)
147
+ raise('expected a status') unless status.class.respond_to?(:effective_memberships_status?)
148
+ membership_statuses.find { |ms| ms.status_id == status.id && ms.status_type == status.class.name }
149
+ end
150
+
151
+ # find or build
152
+ def build_membership_status(status:)
153
+ membership_status(status: status) || membership_statuses.build(status: status)
154
+ end
155
+
118
156
  def good_standing?
119
157
  !bad_standing?
120
158
  end
@@ -22,16 +22,15 @@ module Effective
22
22
  serialize :categories, Array
23
23
  serialize :category_ids, Array
24
24
 
25
+ serialize :statuses, Array
26
+ serialize :status_ids, Array
27
+
25
28
  scope :deep, -> { includes(:owner) }
26
29
  scope :sorted, -> { order(:start_on) }
27
30
 
28
31
  scope :removed, -> { where(removed: true) }
29
32
 
30
33
  validates :owner, presence: true
31
-
32
- # validates :categories, presence: true, unless: -> { removed? }
33
- # validates :category_ids, presence: true, unless: -> { removed? }
34
-
35
34
  validates :start_on, presence: true
36
35
 
37
36
  def to_s
@@ -44,6 +43,10 @@ module Effective
44
43
  category_ids.present? ? EffectiveMemberships.Category.where(id: category_ids) : []
45
44
  end
46
45
 
46
+ def membership_statuses
47
+ status_ids.present? ? EffectiveMemberships.Status.where(id: status_ids) : []
48
+ end
49
+
47
50
  def membership_category_ids
48
51
  membership_categories.map(&:id)
49
52
  end
@@ -53,5 +56,15 @@ module Effective
53
56
  assign_attributes(categories: categories.map(&:to_s), category_ids: categories.map(&:id))
54
57
  end
55
58
 
59
+ def membership_status_ids
60
+ membership_statuses.map(&:id)
61
+ end
62
+
63
+ def membership_status_ids=(ids)
64
+ statuses = EffectiveMemberships.Status.where(id: ids)
65
+ assign_attributes(statuses: statuses.map(&:to_s), status_ids: statuses.map(&:id))
66
+ end
67
+
68
+
56
69
  end
57
70
  end
@@ -0,0 +1,13 @@
1
+ module Effective
2
+ class MembershipStatus < ActiveRecord::Base
3
+ belongs_to :status, polymorphic: true
4
+ belongs_to :membership, polymorphic: true
5
+
6
+ log_changes(to: :membership) if respond_to?(:log_changes)
7
+
8
+ def to_s
9
+ status&.to_s || 'membership status'
10
+ end
11
+
12
+ end
13
+ end
@@ -12,13 +12,21 @@ module Effective
12
12
  # Bad Standing
13
13
  attr_accessor :bad_standing_reason
14
14
 
15
+ # Register
16
+ attr_accessor :status_id
17
+
15
18
  # Reclassify & Register
16
19
  attr_accessor :category_id
17
20
  attr_accessor :membership_number
18
21
  attr_accessor :skip_fees
19
22
 
23
+ # Status Change
24
+ attr_accessor :status_id
25
+ attr_accessor :status_remove_action
26
+
20
27
  # Assign
21
28
  attr_accessor :category_ids
29
+ attr_accessor :status_ids
22
30
 
23
31
  # Mark Fees Paid - Order Attributes
24
32
  attr_accessor :payment_provider
@@ -38,6 +46,10 @@ module Effective
38
46
  validates :category_id, presence: true,
39
47
  if: -> { current_action == :reclassify || current_action == :register }
40
48
 
49
+ # Status Change
50
+ validates :status_id, presence: true, if: -> { current_action == :status_change }
51
+
52
+ # Assign
41
53
  validates :category_ids, presence: true, if: -> { current_action == :assign }
42
54
 
43
55
  def to_s
@@ -46,7 +58,7 @@ module Effective
46
58
 
47
59
  def register!
48
60
  update!(current_action: :register)
49
- EffectiveMemberships.Registrar.register!(owner, to: category, number: membership_number.presence, skip_fees: skip_fees?)
61
+ EffectiveMemberships.Registrar.register!(owner, to: category, status: status, number: number, skip_fees: skip_fees?)
50
62
  end
51
63
 
52
64
  def reclassify!
@@ -54,9 +66,19 @@ module Effective
54
66
  EffectiveMemberships.Registrar.reclassify!(owner, to: category, skip_fees: skip_fees?)
55
67
  end
56
68
 
69
+ def status_change!
70
+ update!(current_action: :status_change)
71
+ EffectiveMemberships.Registrar.status_change!(owner, to: status)
72
+ end
73
+
74
+ def status_remove!
75
+ update!(current_action: :status_remove)
76
+ EffectiveMemberships.Registrar.status_remove!(owner)
77
+ end
78
+
57
79
  def assign!
58
80
  update!(current_action: :assign)
59
- EffectiveMemberships.Registrar.assign!(owner, categories: categories, number: membership_number.presence)
81
+ EffectiveMemberships.Registrar.assign!(owner, categories: categories, statuses: statuses, number: number)
60
82
  end
61
83
 
62
84
  def good_standing!
@@ -102,11 +124,23 @@ module Effective
102
124
  private
103
125
 
104
126
  def category
105
- EffectiveMemberships.Category.find(@category_id) if @category_id
127
+ EffectiveMemberships.Category.find(@category_id) if @category_id.present?
106
128
  end
107
129
 
108
130
  def categories
109
- EffectiveMemberships.Category.where(id: @category_ids) if @category_ids
131
+ EffectiveMemberships.Category.where(id: @category_ids) if @category_ids.present?
132
+ end
133
+
134
+ def status
135
+ EffectiveMemberships.Status.find(@status_id) if @status_id.present?
136
+ end
137
+
138
+ def statuses
139
+ EffectiveMemberships.Status.where(id: @status_ids) if @status_ids.present?
140
+ end
141
+
142
+ def number
143
+ membership_number.presence
110
144
  end
111
145
 
112
146
  def order_attributes
@@ -0,0 +1,7 @@
1
+ module Effective
2
+ class Status < ActiveRecord::Base
3
+ self.table_name = EffectiveMemberships.statuses_table_name.to_s
4
+
5
+ effective_memberships_status
6
+ end
7
+ end
@@ -1,54 +1 @@
1
- = tabs do
2
- - # Done applicants have the Applicant tab first. In progress ones the Status tab
3
- - if applicant.done?
4
- = tab 'Applicant' do
5
- .mb-4= render 'effective/applicants/summary', applicant: applicant, namespace: :admin
6
- = render 'effective/applicants/applicant', applicant: applicant, namespace: :admin
7
-
8
- = tab 'Status' do
9
- = render 'admin/applicants/status', applicant: applicant, namespace: :admin
10
-
11
- - if applicant.in_progress?
12
- = tab 'Status' do
13
- = render 'admin/applicants/status', applicant: applicant, namespace: :admin
14
-
15
- = tab 'Applicant' do
16
- .mb-4= render 'effective/applicants/summary', applicant: applicant, namespace: :admin
17
- = render 'effective/applicants/applicant', applicant: applicant, namespace: :admin
18
-
19
- - # Just normal tabs now
20
- - if applicant.was_submitted? && !applicant.was_approved?
21
- = tab 'Process' do
22
- = render 'admin/applicants/form_process', applicant: applicant
23
-
24
- - if applicant.applicant_references.present?
25
- = tab 'References' do
26
- .mb-4= render_inline_datatable(Admin::EffectiveApplicantReferencesDatatable.new(applicant: applicant))
27
-
28
- - if applicant.applicant_endorsements.present?
29
- = tab 'Endorsements' do
30
- .mb-4= render_inline_datatable(Admin::EffectiveApplicantEndorsementsDatatable.new(applicant: applicant))
31
-
32
- - if applicant.transcripts_required?
33
- = tab 'Transcripts' do
34
- = render 'admin/applicants/form_transcripts', applicant: applicant
35
-
36
- - if applicant.fees.present? || applicant.orders.present?
37
- = tab 'Fees' do
38
- .mb-4
39
- %h2 Fees
40
- - datatable = Admin::EffectiveFeesDatatable.new(applicant: applicant, total: false)
41
- = render_datatable(datatable, simple: true, inline: true)
42
-
43
- .mb-4
44
- %h2 Orders
45
- - datatable = Admin::EffectiveOrdersDatatable.new(parent: applicant, owner: applicant.owner, user: applicant.owner, total: false)
46
- = render_datatable(datatable, simple: true)
47
-
48
- - if applicant.owner.applicants.any? { |other| other.was_submitted? && other.id != applicant.id }
49
- = tab 'Other Applications' do
50
- = render_datatable(Admin::EffectiveApplicantsDatatable.new(owner: applicant.owner, except_id: applicant.id))
51
-
52
- - if applicant.persisted? && applicant.respond_to?(:log_changes_datatable)
53
- = tab 'Logs' do
54
- = render_inline_datatable(applicant.log_changes_datatable)
1
+ = render('admin/applicants/form_applicant', applicant: applicant)
@@ -0,0 +1,56 @@
1
+ = tabs do
2
+ - # Done applicants have the Applicant tab first. In progress ones the Status tab
3
+ - if applicant.done?
4
+ = tab 'Applicant' do
5
+ .mb-4= render 'effective/applicants/summary', applicant: applicant, namespace: :admin
6
+ = render 'effective/applicants/applicant', applicant: applicant, namespace: :admin
7
+
8
+ = tab 'Status' do
9
+ = render 'admin/applicants/status', applicant: applicant, namespace: :admin
10
+
11
+ - if applicant.in_progress?
12
+ = tab 'Status' do
13
+ = render 'admin/applicants/status', applicant: applicant, namespace: :admin
14
+
15
+ = tab 'Applicant' do
16
+ .mb-4= render 'effective/applicants/summary', applicant: applicant, namespace: :admin
17
+ = render 'effective/applicants/applicant', applicant: applicant, namespace: :admin
18
+
19
+ - # Just normal tabs now
20
+ - if applicant.was_submitted? && !applicant.was_approved?
21
+ = tab 'Process' do
22
+ = render 'admin/applicants/form_process', applicant: applicant
23
+
24
+ - if applicant.applicant_references.present?
25
+ = tab 'References' do
26
+ .mb-4= render_inline_datatable(Admin::EffectiveApplicantReferencesDatatable.new(applicant: applicant))
27
+
28
+ - if applicant.applicant_endorsements.present?
29
+ = tab 'Endorsements' do
30
+ .mb-4= render_inline_datatable(Admin::EffectiveApplicantEndorsementsDatatable.new(applicant: applicant))
31
+
32
+ - if applicant.transcripts_required?
33
+ = tab 'Transcripts' do
34
+ = render 'admin/applicants/form_transcripts', applicant: applicant
35
+
36
+ = yield
37
+
38
+ - if applicant.fees.present? || applicant.orders.present?
39
+ = tab 'Fees' do
40
+ .mb-4
41
+ %h2 Fees
42
+ - datatable = Admin::EffectiveFeesDatatable.new(applicant: applicant, total: false)
43
+ = render_datatable(datatable, simple: true, inline: true)
44
+
45
+ .mb-4
46
+ %h2 Orders
47
+ - datatable = Admin::EffectiveOrdersDatatable.new(parent: applicant, owner: applicant.owner, user: applicant.owner, total: false)
48
+ = render_datatable(datatable, simple: true)
49
+
50
+ - if applicant.owner.applicants.any? { |other| other.was_submitted? && other.id != applicant.id }
51
+ = tab 'Other Applications' do
52
+ = render_datatable(Admin::EffectiveApplicantsDatatable.new(owner: applicant.owner, except_id: applicant.id))
53
+
54
+ - if applicant.persisted? && applicant.respond_to?(:log_changes_datatable)
55
+ = tab 'Logs' do
56
+ = render_inline_datatable(applicant.log_changes_datatable)
@@ -11,7 +11,9 @@
11
11
 
12
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
13
  = f.text_field :number, hint: 'The membership number'
14
+
14
15
  = f.select :membership_category_ids, EffectiveMemberships.Category.all.sorted, label: 'Membership Categories', hint: 'The membership category or categories held during this period in history.'
16
+ = f.select :membership_status_ids, EffectiveMemberships.Status.all.sorted, label: 'Membership Statuses', hint: 'The membership status or statuses held during this period in history.'
15
17
 
16
18
  = f.check_box :bad_standing, hint: 'Membership in bad standing'
17
19
  = f.check_box :removed, hint: 'Membership removed'
@@ -1,10 +1,17 @@
1
1
  - registrar_action = Effective::RegistrarAction.new(current_user: current_user, owner: owner)
2
2
 
3
+ -# This form is great if we want to do multiple categories or statuses
4
+ -#.mb-4= render 'admin/registrar_actions/form_assign', registrar_action: registrar_action
5
+
3
6
  - if owner.membership.blank?
4
7
  .mb-4= render 'admin/registrar_actions/form_register', registrar_action: registrar_action
5
8
 
6
9
  - if owner.membership.present?
7
10
  .mb-4= render 'admin/registrar_actions/form_reclassify', registrar_action: registrar_action
11
+
12
+ - if owner.registrar_action_statuses(:status_change).present?
13
+ .mb-4= render 'admin/registrar_actions/form_status_change', registrar_action: registrar_action
14
+
8
15
  .mb-4= render 'admin/registrar_actions/form_bad_standing', registrar_action: registrar_action
9
16
  .mb-4= render 'admin/registrar_actions/form_fees_paid', registrar_action: registrar_action
10
17
  .mb-4= render 'admin/registrar_actions/form_remove', registrar_action: registrar_action
@@ -8,21 +8,41 @@
8
8
 
9
9
  - membership = f.object.owner.membership
10
10
 
11
+ - categories = f.object.owner.registrar_action_categories(:assign)
12
+ - statuses = f.object.owner.registrar_action_statuses(:assign)
13
+ - label = [('categories' if categories.present?), ('statuses' if statuses.present?)].join(' or ')
14
+
15
+ - if membership.present?
16
+ - f.object.category_ids = membership.category_ids
17
+ - f.object.status_ids = membership.status_ids
18
+
11
19
  %p.text-muted
12
- Assign to one or more categories.
20
+ Assign to #{label}.
21
+
22
+ - if categories.present?
23
+ = f.static_field :current_action, label: 'Current Categories' do
24
+ - Array(membership&.categories).each do |category|
25
+ %div= link_to(category, effective_memberships.edit_admin_category_path(category))
13
26
 
14
- = f.static_field :current_action, label: 'Current Categories' do
15
- - Array(membership&.categories).each do |category|
16
- %div= link_to(category, effective_memberships.edit_admin_category_path(category))
27
+ - if membership&.categories.blank?
28
+ None
17
29
 
18
- - if membership.blank?
19
- None
30
+ - if statuses.present?
31
+ = f.static_field :current_action, label: 'Current Statuses' do
32
+ - Array(membership&.statuses).each do |status|
33
+ %div= link_to(status, effective_memberships.edit_admin_status_path(status))
20
34
 
21
- = f.check_box :current_action, label: 'Yes, assign this member to categories'
35
+ - if membership&.statuses.blank?
36
+ None
37
+
38
+ = f.check_box :current_action, label: "Yes, assign this member to #{label}"
22
39
 
23
40
  = f.show_if :current_action, true do
24
- - categories = f.object.owner.registrar_action_categories(:assign)
25
- = f.select :category_ids, categories, label: 'Assign to', required: true, multiple: true
41
+ - if categories.present?
42
+ = f.select :category_ids, categories, label: 'Assign to', required: true, multiple: true
43
+
44
+ - if statuses.present?
45
+ = f.select :status_ids, statuses, label: false, required: true, multiple: true
26
46
 
27
47
  - if membership.present?
28
48
  %p The member will keep their existing membership number: #{membership.number}.
@@ -7,6 +7,8 @@
7
7
  = f.hidden_field :owner_type
8
8
 
9
9
  - period = EffectiveMemberships.Registrar.current_period
10
+ - categories = f.object.owner.registrar_action_categories(:register)
11
+ - statuses = f.object.owner.registrar_action_statuses(:register)
10
12
 
11
13
  %p.text-muted
12
14
  Register into a new category and optionally create fees.
@@ -17,8 +19,11 @@
17
19
  = f.check_box :current_action, label: 'Yes, register to a membership'
18
20
 
19
21
  = f.show_if :current_action, true do
20
- - categories = f.object.owner.registrar_action_categories(:register)
21
- = f.select :category_id, categories, label: 'Register to'
22
+ - if categories.present?
23
+ = f.select :category_id, categories, label: 'Register to'
24
+
25
+ - if statuses.present?
26
+ = f.select :status_id, statuses, label: false
22
27
 
23
28
  = f.text_field :membership_number, hint: "leave blank to assign the next number"
24
29
 
@@ -0,0 +1,41 @@
1
+ .card
2
+ .card-body
3
+ %h5.card-title Status Change
4
+
5
+ = effective_form_with(model: [:admin, registrar_action], url: effective_memberships.admin_registrar_actions_path) do |f|
6
+ = f.hidden_field :owner_id
7
+ = f.hidden_field :owner_type
8
+
9
+ - membership = f.object.owner.membership
10
+ - period = EffectiveMemberships.Registrar.current_period
11
+
12
+ %p.text-muted
13
+ Change or remove a member's existing status.
14
+
15
+ = f.static_field :current_action, label: 'Current Status' do
16
+ = (membership.status || 'None').to_s
17
+
18
+ = f.check_box :current_action, label: 'Yes, change member status'
19
+
20
+ = f.show_if :current_action, true do
21
+ %p The member will keep their existing membership number: #{membership.number}.
22
+
23
+ - statuses = f.object.owner.registrar_action_statuses(:status_change) - membership.statuses
24
+ = f.select :status_id, statuses, label: 'Change status to', required: true
25
+
26
+ %p No fees will be created
27
+
28
+ = f.submit 'Change Status', border: false, center: true, 'data-confirm': "Really change #{f.object.owner}?"
29
+
30
+ - # Remove Action
31
+ - if membership.status.present?
32
+ = f.check_box :status_remove_action, label: "Yes, remove #{membership.status} status"
33
+
34
+ = f.show_if :status_remove_action, true do
35
+ %p The member will keep their existing membership number: #{membership.number}
36
+
37
+ %p This action will remove the #{membership.status} status
38
+
39
+ %p No fees will be created
40
+
41
+ = f.submit 'Remove Status', border: false, center: true, 'data-confirm': "Really remove status #{f.object.owner}?"
@@ -0,0 +1,8 @@
1
+ = tabs do
2
+ = tab 'Status' do
3
+ = render 'admin/statuses/form_status', status: status
4
+
5
+ - if status.persisted?
6
+ - if status.respond_to?(:log_changes_datatable)
7
+ = tab 'Logs' do
8
+ = render_inline_datatable(status.log_changes_datatable)
@@ -0,0 +1,9 @@
1
+ = effective_form_with(model: [:admin, status], engine: true) do |f|
2
+ = f.text_field :title
3
+
4
+ = f.select :status_type, f.object.class.status_types
5
+
6
+ - if f.object.class.statuses.present?
7
+ = f.select :status, f.object.class.statuses
8
+
9
+ = f.submit
@@ -16,6 +16,7 @@
16
16
  = effective_form_with(model: resource, url: wizard_path(step), method: :put) do |f|
17
17
  = f.hidden_field :id
18
18
 
19
+ = f.hidden_field :stream, value: nil
19
20
  = f.hidden_field :organization_id, value: nil
20
21
  = f.hidden_field :organization_type, value: nil
21
22
  = f.hidden_field :category_type, value: EffectiveMemberships.Category.name
@@ -5,6 +5,7 @@ EffectiveMemberships.setup do |config|
5
5
  config.fee_payments_table_name = :fee_payments
6
6
  config.organizations_table_name = :organizations
7
7
  config.representatives_table_name = :representatives
8
+ config.statuses_table_name = :statuses
8
9
 
9
10
  # Layout Settings
10
11
  # Configure the Layout per controller, or all at once
@@ -17,8 +18,11 @@ EffectiveMemberships.setup do |config|
17
18
  # config.category_class_name = 'Effective::Category'
18
19
  # config.applicant_class_name = 'Effective::Applicant'
19
20
  # config.applicant_review_class_name = 'Effective::ApplicantReview'
21
+ # config.fee_payment_class_name = 'Effective::FeePayment'
22
+ # config.membership_card_class_name = 'Effective::MembershipCard'
20
23
  # config.registrar_class_name = 'Effective::Registrar'
21
24
  # config.organization_class_name = 'Effective::Organization'
25
+ # config.status_class_name = 'Effective::Status'
22
26
 
23
27
  # Fee Categories
24
28
  # The defaults include: Applicant, Prorated, Renewal, Late, Admin
data/config/routes.rb CHANGED
@@ -46,7 +46,7 @@ EffectiveMemberships::Engine.routes.draw do
46
46
  end
47
47
 
48
48
  resources :fees
49
- resources :categories, except: [:show]
49
+ resources :categories, only: [:index, :edit, :update]
50
50
 
51
51
  resources :applicant_course_areas, except: [:show]
52
52
  resources :applicant_course_names, except: [:show]
@@ -62,6 +62,7 @@ EffectiveMemberships::Engine.routes.draw do
62
62
  end
63
63
 
64
64
  resources :representatives, except: [:show]
65
+ resources :statuses, only: [:index, :edit, :update]
65
66
  end
66
67
 
67
68
  end
@@ -65,6 +65,22 @@ class CreateEffectiveMemberships < ActiveRecord::Migration[6.0]
65
65
  add_index :categories, :title
66
66
  add_index :categories, :position
67
67
 
68
+ # Statuses
69
+ create_table :statuses do |t|
70
+ t.string :status_type # Individual or Organization
71
+
72
+ t.string :title
73
+ t.string :status # Freeform
74
+
75
+ t.integer :position
76
+
77
+ t.datetime :updated_at
78
+ t.datetime :created_at
79
+ end
80
+
81
+ add_index :statuses, :title
82
+ add_index :statuses, :position
83
+
68
84
  # Memberships
69
85
  create_table :memberships do |t|
70
86
  t.integer :owner_id
@@ -98,6 +114,15 @@ class CreateEffectiveMemberships < ActiveRecord::Migration[6.0]
98
114
  t.string :membership_type
99
115
  end
100
116
 
117
+ # Membership Statuses Join table
118
+ create_table :membership_statuses do |t|
119
+ t.integer :status_id
120
+ t.string :status_type
121
+
122
+ t.integer :membership_id
123
+ t.string :membership_type
124
+ end
125
+
101
126
  # Membership Histories
102
127
  create_table :membership_histories do |t|
103
128
  t.integer :owner_id
@@ -106,6 +131,9 @@ class CreateEffectiveMemberships < ActiveRecord::Migration[6.0]
106
131
  t.text :categories
107
132
  t.text :category_ids
108
133
 
134
+ t.text :statuses
135
+ t.text :status_ids
136
+
109
137
  t.date :start_on
110
138
  t.date :end_on
111
139
 
@@ -182,6 +210,9 @@ class CreateEffectiveMemberships < ActiveRecord::Migration[6.0]
182
210
  t.integer :from_category_id
183
211
  t.string :from_category_type
184
212
 
213
+ t.integer :from_status_id
214
+ t.string :from_status_type
215
+
185
216
  # Acts as Statused
186
217
  t.string :status
187
218
  t.text :status_steps
@@ -12,6 +12,7 @@ module EffectiveMemberships
12
12
  ActiveSupport.on_load :active_record do
13
13
  ActiveRecord::Base.extend(EffectiveMembershipsOwner::Base)
14
14
  ActiveRecord::Base.extend(EffectiveMembershipsCategory::Base)
15
+ ActiveRecord::Base.extend(EffectiveMembershipsStatus::Base)
15
16
 
16
17
  ActiveRecord::Base.extend(EffectiveMembershipsUser::Base)
17
18
  ActiveRecord::Base.extend(EffectiveMembershipsOrganization::Base)
@@ -1,3 +1,3 @@
1
1
  module EffectiveMemberships
2
- VERSION = '0.4.16'
2
+ VERSION = '0.5.0'
3
3
  end
@@ -6,8 +6,8 @@ module EffectiveMemberships
6
6
 
7
7
  def self.config_keys
8
8
  [
9
- :categories_table_name, :applicants_table_name, :applicant_reviews_table_name, :fee_payments_table_name, :organizations_table_name, :representatives_table_name,
10
- :category_class_name, :organization_class_name, :applicant_class_name, :applicant_review_class_name, :fee_payment_class_name, :registrar_class_name, :membership_card_class_name,
9
+ :categories_table_name, :applicants_table_name, :applicant_reviews_table_name, :fee_payments_table_name, :organizations_table_name, :representatives_table_name, :statuses_table_name,
10
+ :category_class_name, :organization_class_name, :applicant_class_name, :applicant_review_class_name, :fee_payment_class_name, :registrar_class_name, :membership_card_class_name, :status_class_name,
11
11
  :additional_fee_types, :applicant_reviews, :applicant_endorsements_endorser_collection,
12
12
  :layout,
13
13
  :mailer, :parent_mailer, :deliver_method, :mailer_layout, :mailer_sender, :mailer_admin, :mailer_subject, :use_effective_email_templates
@@ -40,14 +40,13 @@ module EffectiveMemberships
40
40
  membership_card_class_name&.constantize || Effective::MembershipCard
41
41
  end
42
42
 
43
- def self.applicant_reviews?
44
- applicant_reviews == true
43
+ def self.Status
44
+ status_class_name&.constantize || Effective::Status
45
45
  end
46
46
 
47
47
  # Singleton
48
48
  def self.Registrar
49
- klass = registrar_class_name&.constantize || Effective::Registrar
50
- klass.new
49
+ (registrar_class_name&.constantize || Effective::Registrar).new
51
50
  end
52
51
 
53
52
  def self.mailer_class
@@ -66,4 +65,8 @@ module EffectiveMemberships
66
65
  ['Admin']
67
66
  end
68
67
 
68
+ def self.applicant_reviews?
69
+ applicant_reviews == true
70
+ end
71
+
69
72
  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.4.16
4
+ version: 0.5.0
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-07-06 00:00:00.000000000 Z
11
+ date: 2022-08-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -267,6 +267,7 @@ files:
267
267
  - app/controllers/admin/organizations_controller.rb
268
268
  - app/controllers/admin/registrar_actions_controller.rb
269
269
  - app/controllers/admin/representatives_controller.rb
270
+ - app/controllers/admin/statuses_controller.rb
270
271
  - app/controllers/effective/applicant_endorsements_controller.rb
271
272
  - app/controllers/effective/applicant_references_controller.rb
272
273
  - app/controllers/effective/applicants_controller.rb
@@ -287,6 +288,7 @@ files:
287
288
  - app/datatables/admin/effective_memberships_datatable.rb
288
289
  - app/datatables/admin/effective_organizations_datatable.rb
289
290
  - app/datatables/admin/effective_representatives_datatable.rb
291
+ - app/datatables/admin/effective_statuses_datatable.rb
290
292
  - app/datatables/effective_applicant_courses_datatable.rb
291
293
  - app/datatables/effective_applicant_educations_datatable.rb
292
294
  - app/datatables/effective_applicant_endorsements_datatable.rb
@@ -308,6 +310,7 @@ files:
308
310
  - app/models/concerns/effective_memberships_organization.rb
309
311
  - app/models/concerns/effective_memberships_owner.rb
310
312
  - app/models/concerns/effective_memberships_registrar.rb
313
+ - app/models/concerns/effective_memberships_status.rb
311
314
  - app/models/concerns/effective_memberships_user.rb
312
315
  - app/models/effective/applicant.rb
313
316
  - app/models/effective/applicant_course.rb
@@ -326,10 +329,12 @@ files:
326
329
  - app/models/effective/membership_card.rb
327
330
  - app/models/effective/membership_category.rb
328
331
  - app/models/effective/membership_history.rb
332
+ - app/models/effective/membership_status.rb
329
333
  - app/models/effective/organization.rb
330
334
  - app/models/effective/registrar.rb
331
335
  - app/models/effective/registrar_action.rb
332
336
  - app/models/effective/representative.rb
337
+ - app/models/effective/status.rb
333
338
  - app/views/admin/applicant_course_areas/_form.html.haml
334
339
  - app/views/admin/applicant_course_areas/_form_applicant_course_area.html.haml
335
340
  - app/views/admin/applicant_course_areas/index.html.haml
@@ -337,6 +342,7 @@ files:
337
342
  - app/views/admin/applicant_endorsements/_applicant_endorsement.html.haml
338
343
  - app/views/admin/applicant_references/_applicant_reference.html.haml
339
344
  - app/views/admin/applicants/_form.html.haml
345
+ - app/views/admin/applicants/_form_applicant.html.haml
340
346
  - app/views/admin/applicants/_form_approve.html.haml
341
347
  - app/views/admin/applicants/_form_complete.html.haml
342
348
  - app/views/admin/applicants/_form_decline.html.haml
@@ -373,8 +379,11 @@ files:
373
379
  - app/views/admin/registrar_actions/_form_reclassify.html.haml
374
380
  - app/views/admin/registrar_actions/_form_register.html.haml
375
381
  - app/views/admin/registrar_actions/_form_remove.html.haml
382
+ - app/views/admin/registrar_actions/_form_status_change.html.haml
376
383
  - app/views/admin/representatives/_form.html.haml
377
384
  - app/views/admin/representatives/_user_fields.html.haml
385
+ - app/views/admin/statuses/_form.html.haml
386
+ - app/views/admin/statuses/_form_status.html.haml
378
387
  - app/views/admin/users/_col.html.haml
379
388
  - app/views/effective/applicant_endorsements/_applicant_endorsement.html.haml
380
389
  - app/views/effective/applicant_endorsements/_datatable_actions.html.haml