effective_memberships 0.3.10 → 0.3.13

Sign up to get free protection for your applications and to get access to all the features.
Files changed (28) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/admin/applicants_controller.rb +14 -0
  3. data/app/controllers/effective/applicants_controller.rb +2 -0
  4. data/app/datatables/admin/effective_applicants_datatable.rb +7 -2
  5. data/app/datatables/admin/effective_fees_datatable.rb +5 -3
  6. data/app/datatables/effective_applicants_datatable.rb +10 -4
  7. data/app/helpers/effective_memberships_helper.rb +9 -0
  8. data/app/mailers/effective/memberships_mailer.rb +19 -8
  9. data/app/models/concerns/effective_memberships_applicant.rb +71 -18
  10. data/app/models/concerns/effective_memberships_owner.rb +8 -2
  11. data/app/views/admin/applicants/_form.html.haml +10 -6
  12. data/app/views/admin/applicants/_form_approve.html.haml +1 -5
  13. data/app/views/admin/applicants/_form_complete.html.haml +8 -0
  14. data/app/views/admin/applicants/_form_missing_info.html.haml +11 -0
  15. data/app/views/admin/applicants/_form_process.html.haml +16 -12
  16. data/app/views/admin/applicants/_status.html.haml +67 -49
  17. data/app/views/effective/applicants/_missing_info.html.haml +18 -0
  18. data/app/views/effective/applicants/_summary.html.haml +1 -1
  19. data/app/views/effective/applicants/submitted.html.haml +11 -9
  20. data/app/views/effective/applicants/summary.html.haml +7 -1
  21. data/app/views/effective/memberships_mailer/applicant_completed.liquid +15 -0
  22. data/app/views/effective/memberships_mailer/applicant_missing_info.liquid +17 -0
  23. data/config/effective_memberships.rb +19 -21
  24. data/db/migrate/01_create_effective_memberships.rb.erb +4 -0
  25. data/lib/effective_memberships/version.rb +1 -1
  26. data/lib/effective_memberships.rb +5 -29
  27. metadata +7 -3
  28. data/app/views/layouts/effective_memberships_mailer_layout.html.haml +0 -7
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c506926f876b0fe6e4559cce6784e0c0ac8f30891dca21183f74dd5ab1fc5ee6
4
- data.tar.gz: 980454f32127c3423d33aaaf4136615fac433dbede09f718ae7ebfb1c0cc3b39
3
+ metadata.gz: 38134acc9619d9ea0404332803f0c17535fee985688ddcc628db39c1cbf9987c
4
+ data.tar.gz: 781c42e6cdeb6c501aa696c1a13bc9917db90c5090b05a845754b2547b4a9689
5
5
  SHA512:
6
- metadata.gz: 29813982537ac083f937e2c1d8df597676b51eb26c7512f773f018fd91e0e2a3a389b6095f89ba8e8acdb44086313b2ff3638f926f380490366b8c7148eaaf46
7
- data.tar.gz: 436039fe95ff3c095bb755663ec6f51674ffe620957b2f1a0557d598f634eeb651aa317476a887d818cd71bacf5a9708eb34eab2df06a3456201c6b02e1af890
6
+ metadata.gz: 6ea602b5671e84066f96d77d996c08f6524ff46659ff1ede3b0b730a133c95693aa83b1e4dbf837b06f271c8d01ee73fa9c1c44528a2fd4bb3b3e10123e60888
7
+ data.tar.gz: dc6909b2b20ef4db2200be6cd8bcbf2bcc2ea5492e2c745ae64b48158b4092b78db8305b43d0ae46f2fa800e41767bbb1faf9ad13a9547b0676b3dd8ff283520
@@ -8,6 +8,20 @@ module Admin
8
8
  resource_scope -> { EffectiveMemberships.Applicant.deep.all }
9
9
  datatable -> { Admin::EffectiveApplicantsDatatable.new }
10
10
 
11
+ submit :complete, 'Complete Applicant', success: -> {
12
+ [
13
+ "Successfully completed #{resource.owner} #{resource}",
14
+ ("and sent #{resource.owner.email} a notification" unless resource.email_form_skip)
15
+ ].compact.join(' ')
16
+ }
17
+
18
+ submit :missing, 'Missing Info Applicant', success: -> {
19
+ [
20
+ "Successfully marked #{resource.owner} #{resource} as missing info",
21
+ ("and sent #{resource.owner.email} a notification" unless resource.email_form_skip)
22
+ ].compact.join(' ')
23
+ }
24
+
11
25
  submit :approve, 'Approve Applicant', success: -> {
12
26
  [
13
27
  "Successfully approved #{resource.owner} #{resource}",
@@ -6,5 +6,7 @@ module Effective
6
6
 
7
7
  resource_scope -> { EffectiveMemberships.Applicant.deep.where(owner: current_user.effective_memberships_owners) }
8
8
 
9
+ submit :resubmit, 'Submit Application'
10
+
9
11
  end
10
12
  end
@@ -11,14 +11,19 @@ module Admin
11
11
  order :id
12
12
  col :id, visible: false
13
13
 
14
- col :status
14
+ col :status, search: effective_memberships_status_collection()
15
15
 
16
16
  col :created_at, label: 'Created', as: :date, visible: false
17
17
  col :updated_at, label: 'Updated', visible: false
18
18
 
19
19
  col :submitted_at, label: 'Submitted', visible: false, as: :date
20
20
  col :completed_at, label: 'Completed', visible: false, as: :date
21
- col :reviewed_at, label: 'Reviewed', visible: false, as: :date
21
+ col :missing_info_at, label: 'Missing Info', visible: false, as: :date
22
+
23
+ if EffectiveMemberships.applicant_reviews?
24
+ col :reviewed_at, label: 'Reviewed', visible: false, as: :date
25
+ end
26
+
22
27
  col :approved_at, label: 'Approved', visible: false, as: :date
23
28
 
24
29
  col :owner
@@ -33,7 +33,9 @@ module Admin
33
33
 
34
34
  col :category, search: { collection: EffectiveMemberships.Category.all, polymorphic: false }
35
35
 
36
- aggregate :total
36
+ unless attributes[:total] == false
37
+ aggregate :total
38
+ end
37
39
 
38
40
  if attributes[:applicant_id]
39
41
  actions_col(new: false)
@@ -63,11 +65,11 @@ module Admin
63
65
  end
64
66
 
65
67
  def applicant
66
- @applicant ||= EffectiveMemberships.Applicant.find(attributes[:applicant_id])
68
+ @applicant ||= EffectiveMemberships.Applicant.where(id: attributes[:applicant_id]).first!
67
69
  end
68
70
 
69
71
  def fee_payment
70
- @fee_payment ||= EffectiveMemberships.FeePayment.find(attributes[:fee_payment_id])
72
+ @fee_payment ||= EffectiveMemberships.FeePayment.where(id: attributes[:fee_payment_id]).first!
71
73
  end
72
74
 
73
75
  end
@@ -6,14 +6,20 @@ class EffectiveApplicantsDatatable < Effective::Datatable
6
6
  col :id, visible: false
7
7
 
8
8
  col :category, label: 'Category'
9
- col :status
9
+ col :status, search: effective_memberships_status_collection()
10
10
 
11
11
  col :created_at, label: 'Created', as: :date
12
12
  col :updated_at, label: 'Updated', as: :date, visible: false
13
+
13
14
  col :submitted_at, label: 'Submitted', as: :date
14
- col :completed_at, label: 'Completed', as: :date
15
- col :reviewed_at, label: 'Reviewed', as: :date
16
- col :approved_at, label: 'Approved', visible: false, as: :date
15
+ col :completed_at, label: 'Completed', as: :date, visible: false
16
+ col :missing_info_at, label: 'Missing Info', as: :date, visible: false
17
+
18
+ if EffectiveMemberships.applicant_reviews?
19
+ col :reviewed_at, label: 'Reviewed', as: :date
20
+ end
21
+
22
+ col :approved_at, label: 'Approved', as: :date
17
23
 
18
24
  col :orders
19
25
 
@@ -1,2 +1,11 @@
1
1
  module EffectiveMembershipsHelper
2
+
3
+ def effective_memberships_status_collection
4
+ EffectiveMemberships.Applicant::STATUSES.map do |status|
5
+ next if status == :reviewed && !EffectiveMemberships.applicant_reviews?
6
+
7
+ [status.to_s.gsub('_', ' '), status]
8
+ end.compact
9
+ end
10
+
2
11
  end
@@ -1,18 +1,29 @@
1
1
  module Effective
2
2
  class MembershipsMailer < EffectiveMemberships.parent_mailer_class
3
- include EffectiveEmailTemplatesMailer
3
+
4
+ include EffectiveEmailTemplatesMailer if EffectiveMemberships.use_effective_email_templates
4
5
 
5
6
  default from: -> { EffectiveMemberships.mailer_sender }
6
- layout -> { EffectiveMemberships.mailer_layout || 'effective_memberships_mailer_layout' }
7
+ layout -> { EffectiveMemberships.mailer_layout }
8
+
9
+ def applicant_completed(resource, opts = {})
10
+ @assigns = assigns_for(resource)
11
+ mail(to: resource.owner.email, **headers_for(resource, opts))
12
+ end
13
+
14
+ def applicant_missing_info(resource, opts = {})
15
+ @assigns = assigns_for(resource)
16
+ mail(to: resource.owner.email, **headers_for(resource, opts))
17
+ end
7
18
 
8
19
  def applicant_approved(resource, opts = {})
9
20
  @assigns = assigns_for(resource)
10
- mail(to: EffectiveMemberships.mailer_admin, **headers_for(resource, opts))
21
+ mail(to: resource.owner.email, **headers_for(resource, opts))
11
22
  end
12
23
 
13
24
  def applicant_declined(resource, opts = {})
14
25
  @assigns = assigns_for(resource)
15
- mail(to: EffectiveMemberships.mailer_admin, **headers_for(resource, opts))
26
+ mail(to: resource.owner.email, **headers_for(resource, opts))
16
27
  end
17
28
 
18
29
  def applicant_reference_notification(resource, opts = {})
@@ -49,11 +60,11 @@ module Effective
49
60
 
50
61
  url: effective_memberships.applicant_url(applicant),
51
62
  admin_url: effective_memberships.edit_admin_applicant_url(applicant),
52
- }
53
63
 
54
- if applicant.declined_reason.present?
55
- values.merge!(declined_reason: applicant.declined_reason)
56
- end
64
+ # Optional
65
+ declined_reason: applicant.declined_reason.presence,
66
+ missing_info_reason: applicant.missing_info_reason.presence
67
+ }.compact
57
68
 
58
69
  { applicant: values }
59
70
  end
@@ -32,12 +32,13 @@ module EffectiveMembershipsApplicant
32
32
  acts_as_tokened
33
33
 
34
34
  acts_as_statused(
35
- :draft, # Just Started
36
- :submitted, # Completed wizard. Paid applicant fee.
37
- :completed, # Admin has received all deliverables. The application is complete and ready for review.
38
- :reviewed, # All applicant reviews completed
39
- :declined, # Exit state. Application was declined.
40
- :approved # Exit state. Application was approved.
35
+ :draft, # Just Started
36
+ :submitted, # Completed wizard. Paid applicant fee.
37
+ :missing_info, # Admin has indicated information is missing. The applicant can edit applicant and add info
38
+ :completed, # Admin has received all deliverables. The application is complete and ready for review.
39
+ :reviewed, # All applicant reviews completed
40
+ :declined, # Exit state. Application was declined.
41
+ :approved # Exit state. Application was approved.
41
42
  )
42
43
 
43
44
  acts_as_wizard(
@@ -121,18 +122,22 @@ module EffectiveMembershipsApplicant
121
122
  declined_at :datetime
122
123
  declined_reason :text
123
124
 
125
+ # Missing Info
126
+ missing_info_at :datetime
127
+ missing_info_reason :text
128
+
124
129
  # Applicant Educations
125
- applicant_educations_details :text
130
+ applicant_educations_details :text
126
131
 
127
132
  # Applicant Experiences
128
- applicant_experiences_months :integer
129
- applicant_experiences_details :text
133
+ applicant_experiences_months :integer
134
+ applicant_experiences_details :text
130
135
 
131
136
  # Additional Information
132
- additional_information :text
137
+ additional_information :text
133
138
 
134
139
  # Acts as Wizard
135
- wizard_steps :text, permitted: false
140
+ wizard_steps :text, permitted: false
136
141
 
137
142
  timestamps
138
143
  end
@@ -264,9 +269,12 @@ module EffectiveMembershipsApplicant
264
269
  # Admin Decline
265
270
  validates :declined_reason, presence: true, if: -> { declined? }
266
271
 
272
+ # Admin Missing Info
273
+ validates :missing_info_reason, presence: true, if: -> { missing_info? }
274
+
267
275
  # These two try completed and try reviewed
268
- before_save(if: -> { submitted? }) { complete! }
269
- before_save(if: -> { completed? }) { review! }
276
+ # before_save(if: -> { submitted? }) { complete! }
277
+ # before_save(if: -> { completed? }) { review! }
270
278
 
271
279
  # Clear required steps memoization
272
280
  after_save { @_required_steps = nil }
@@ -290,6 +298,14 @@ module EffectiveMembershipsApplicant
290
298
  end
291
299
  end
292
300
 
301
+ def can_visit_step?(step)
302
+ if missing_info?
303
+ return [:start, :select, :billing, :checkout].exclude?(step)
304
+ end
305
+
306
+ can_revisit_completed_steps(step)
307
+ end
308
+
293
309
  # All Fees and Orders
294
310
  def submit_fees
295
311
  # Find or build submit fee
@@ -374,6 +390,10 @@ module EffectiveMembershipsApplicant
374
390
  approved? || declined?
375
391
  end
376
392
 
393
+ def status_label
394
+ (status_was || status).to_s.gsub('_', ' ')
395
+ end
396
+
377
397
  def summary
378
398
  case status_was
379
399
  when 'draft'
@@ -388,6 +408,8 @@ module EffectiveMembershipsApplicant
388
408
  else
389
409
  "This application has been completed and is now ready for an admin to approve or decline it. If approved, prorated fees will be generated."
390
410
  end
411
+ when 'missing_info'
412
+ "Missing the following information: <ul><li>#{missing_info_reason}</li></ul>"
391
413
  when 'reviewed'
392
414
  "This application has been reviewed and is now ready for an admin to approve or decline it. If approved, prorated fees will be generated."
393
415
  when 'approved'
@@ -489,7 +511,8 @@ module EffectiveMembershipsApplicant
489
511
  min_applicant_references > 0
490
512
  end
491
513
 
492
- # When an application is submitted, these must be done to go to completed
514
+ # When an application is submitted, these must be done to go to completed.
515
+ # An Admin can override this and just set them to completed.
493
516
  def completed_requirements
494
517
  {
495
518
  'Applicant References' => (!applicant_references_required? || applicant_references.count(&:completed?) >= min_applicant_references)
@@ -497,9 +520,34 @@ module EffectiveMembershipsApplicant
497
520
  end
498
521
 
499
522
  def complete!
500
- return false unless submitted? && completed_requirements.values.all?
501
- # Could send registrar an email here saying this applicant is ready to review
523
+ raise('applicant must have been submitted to complete!') unless was_submitted?
524
+
525
+ # Let an admin ignore these requirements if need be
526
+ # return false unless submitted? && completed_requirements.values.all?
527
+
528
+ assign_attributes(missing_info_reason: nil)
502
529
  completed!
530
+
531
+ after_commit { send_email(:applicant_completed) }
532
+ true
533
+ end
534
+
535
+ def missing!
536
+ raise('applicant must have been submitted to missing!') unless was_submitted?
537
+
538
+ missing_info!
539
+
540
+ after_commit { send_email(:applicant_missing_info) }
541
+ true
542
+ end
543
+
544
+ def resubmit!
545
+ raise('applicant must have been submitted and missing info to resubmit!') unless was_submitted? && was_missing_info?
546
+ raise('already submitted') if submitted?
547
+ raise('expected a purchased order') unless submit_order&.purchased?
548
+
549
+ assign_attributes(skip_to_step: :submitted, submitted_at: Time.zone.now)
550
+ submitted!
503
551
  end
504
552
 
505
553
  # Completed -> Reviewed requirements
@@ -512,6 +560,7 @@ module EffectiveMembershipsApplicant
512
560
  end
513
561
 
514
562
  # When an application is completed, these must be done to go to reviewed
563
+ # An Admin can override this and just set them to reviewed.
515
564
  def reviewed_requirements
516
565
  {
517
566
  'Applicant Reviews' => (!applicant_reviews_required? || applicant_reviews.count(&:completed?) >= min_applicant_reviews)
@@ -519,8 +568,10 @@ module EffectiveMembershipsApplicant
519
568
  end
520
569
 
521
570
  def review!
522
- return false unless completed? && reviewed_requirements.values.all?
523
- # Could send registrar an email here saying this applicant is ready to approve
571
+ raise('applicant must have been submitted to review!') unless was_submitted?
572
+
573
+ # Let an admin ignore these requirements if need be
574
+ # return false unless completed? && reviewed_requirements.values.all?
524
575
  reviewed!
525
576
  end
526
577
 
@@ -532,6 +583,8 @@ module EffectiveMembershipsApplicant
532
583
  # Complete the wizard step. Just incase this is run out of order.
533
584
  wizard_steps[:checkout] ||= Time.zone.now
534
585
  wizard_steps[:submitted] ||= Time.zone.now
586
+ assign_attributes(missing_info_reason: nil)
587
+
535
588
  approved!
536
589
 
537
590
  if apply_to_join?
@@ -56,7 +56,9 @@ module EffectiveMembershipsOwner
56
56
  owners = organizations if self.class.respond_to?(:effective_organizations_user?)
57
57
  owners = users if self.class.respond_to?(:effective_organizations_organization?)
58
58
 
59
- owners = Array(owners).reject { |owner| owner.try(:archived?) }
59
+ owners = Array(owners)
60
+ .select { |owner| owner.class.respond_to?(:effective_memberships_owner?) }
61
+ .reject { |owner| owner.try(:archived?) }
60
62
 
61
63
  owners.presence || [self]
62
64
  end
@@ -73,7 +75,11 @@ module EffectiveMembershipsOwner
73
75
 
74
76
  def organization_membership_present?(except: nil)
75
77
  return false unless self.class.respond_to?(:effective_organizations_user?)
76
- organizations.any? { |organization| organization != except && organization.membership_present? }
78
+
79
+ organizations
80
+ .select { |organization| organization.class.respond_to?(:effective_memberships_owner?) }
81
+ .reject { |organization| organization.try(:archived?) }
82
+ .any? { |organization| organization != except && organization.membership_present? }
77
83
  end
78
84
 
79
85
  def assign_member_role
@@ -25,13 +25,17 @@
25
25
  = tab 'References' do
26
26
  .mb-4= render_inline_datatable(Admin::EffectiveApplicantReferencesDatatable.new(applicant: applicant))
27
27
 
28
- - if applicant.fees.present?
28
+ - if applicant.fees.present? || applicant.orders.present?
29
29
  = tab 'Fees' do
30
- .mb-4= render_inline_datatable(Admin::EffectiveFeesDatatable.new(applicant_id: applicant.to_param))
31
-
32
- - if applicant.orders.present?
33
- = tab 'Orders' do
34
- .mb-4= render_datatable(Admin::EffectiveOrdersDatatable.new(parent_id: applicant.id, parent_type: EffectiveMemberships.Applicant.name, owner_id: applicant.owner_id, user_type: applicant.owner_type))
30
+ .mb-4
31
+ %h2 Fees
32
+ - datatable = Admin::EffectiveFeesDatatable.new(applicant: applicant, total: false)
33
+ = render_datatable(datatable, simple: true, inline: true)
34
+
35
+ .mb-4
36
+ %h2 Orders
37
+ - datatable = Admin::EffectiveOrdersDatatable.new(parent: applicant, owner: applicant.owner, user: applicant.owner, total: false)
38
+ = render_datatable(datatable, simple: true)
35
39
 
36
40
  - if applicant.owner.applicants.any? { |other| other.was_submitted? && other.id != applicant.id }
37
41
  = tab 'Other Applications' do
@@ -1,13 +1,9 @@
1
1
  = effective_form_with(model: [:admin, applicant], engine: true) do |f|
2
- %p The #{applicant} will be <strong>approved</strong> to the following membership category.
3
-
4
- %h3 Category
5
- = f.static_field :category, label: 'Applied for'
2
+ %p The #{applicant} will be <strong>approved</strong> to the following membership category:
6
3
 
7
4
  - categories = EffectiveMemberships.Category.all
8
5
  = f.select :category_id, categories, label: 'Approve to'
9
6
 
10
- %h3 Number
11
7
  %p
12
8
  - if applicant.owner.membership&.number_was.present?
13
9
  The member will keep their existing membership number: #{applicant.owner.membership.number}.
@@ -0,0 +1,8 @@
1
+ = effective_form_with(model: [:admin, applicant], engine: true) do |f|
2
+ %p The #{applicant} will be <strong>completed</strong>. All deliverables have been received and all requirements completed.
3
+
4
+ %h3 Email to send
5
+ %p The following email will be sent:
6
+ = email_form_fields(f, :applicant_completed)
7
+
8
+ = f.submit 'Complete Applicant', border: false, center: true, 'data-confirm': "Complete #{f.object.owner}?"
@@ -0,0 +1,11 @@
1
+ = effective_form_with(model: [:admin, applicant], engine: true) do |f|
2
+ %p This applicant will be marked as <strong>missing information</strong> with the following:
3
+
4
+ = f.text_field :missing_info_reason, required: true, label: 'Explanation of missing info'
5
+
6
+ %h3 Email to send
7
+
8
+ %p The following email will be sent:
9
+ = email_form_fields(f, :applicant_missing_info)
10
+
11
+ = f.submit 'Missing Info Applicant', border: false, center: true, 'data-confirm': "Missing Info #{f.object.owner}?"
@@ -1,18 +1,22 @@
1
1
  %p
2
- %span.badge.badge-secondary= applicant.status
2
+ %span.badge.badge-secondary= applicant.status_label
3
3
  = applicant.summary
4
4
 
5
- = tabs(list: { class: 'nav nav-pills'}) do
5
+ %p Process applicant:
6
+
7
+ = accordion do
8
+ - if EffectiveResources.authorized?(self, :complete, applicant)
9
+ = collapse 'Complete this Applicant' do
10
+ = render('admin/applicants/form_complete', applicant: applicant)
11
+
12
+ - if EffectiveResources.authorized?(self, :missing, applicant)
13
+ = collapse 'Missing Information' do
14
+ = render('admin/applicants/form_missing_info', applicant: applicant)
15
+
6
16
  - if EffectiveResources.authorized?(self, :approve, applicant)
7
- = tab 'Approve this Applicant' do
8
- .card.mt-4
9
- .card-body
10
- %h5.card-title Approve
11
- = render('admin/applicants/form_approve', applicant: applicant)
17
+ = collapse 'Approve this Applicant' do
18
+ = render('admin/applicants/form_approve', applicant: applicant)
12
19
 
13
20
  - if EffectiveResources.authorized?(self, :decline, applicant)
14
- = tab 'Decline this Applicant' do
15
- .card.mt-4
16
- .card-body
17
- %h5.card-title Decline
18
- = render('admin/applicants/form_decline', applicant: applicant)
21
+ = collapse 'Decline this Applicant' do
22
+ = render('admin/applicants/form_decline', applicant: applicant)
@@ -1,5 +1,5 @@
1
1
  %p
2
- %span.badge.badge-secondary= applicant.status_was
2
+ %span.badge.badge-secondary= applicant.status_label
3
3
  = applicant.summary
4
4
 
5
5
  %table.table.table-sm.table-striped
@@ -11,6 +11,8 @@
11
11
  %th
12
12
  - # Next action button
13
13
  %tbody
14
+
15
+ -# Draft
14
16
  %tr
15
17
  %td In Progress
16
18
  %td= applicant.created_at.strftime('%F')
@@ -21,6 +23,8 @@
21
23
  - else
22
24
  = '-'
23
25
  %td
26
+
27
+ - # Submitted
24
28
  %tr
25
29
  %td Application Submitted
26
30
  %td= applicant.submitted_at&.strftime('%F') || '-'
@@ -30,6 +34,8 @@
30
34
  - else
31
35
  = '-'
32
36
  %td
37
+
38
+ - # Waiting to Complete
33
39
  %tr
34
40
  %td Waiting to Complete
35
41
  %td= applicant.submitted_at&.strftime('%F') || '-'
@@ -63,71 +69,83 @@
63
69
  References Not Required
64
70
 
65
71
  %td
66
- -# - if !applicant.was_approved? && applicant.transcripts_required? && !applicant.transcripts_approved?
67
- -# = link_to 'Process Transcripts', '#transcripts', 'data-click-tab': true, class: 'btn btn-sm btn-primary'
72
+ - if applicant.submitted?
73
+ = link_to 'Complete Applicant', '#process', 'data-click-tab': true, class: 'btn btn-sm btn-primary'
68
74
 
69
- -# - if !applicant.was_approved? && applicant.nwpta_form_required? && !applicant.nwpta_form_received?
70
- -# = link_to 'Receive NWPTA Form', '#nwpta-verification-form', 'data-click-tab': true, class: 'btn btn-sm btn-primary'
75
+ - # Missing Information
76
+ %tr
77
+ %td Missing Information
78
+ %td= applicant.missing_info_at&.strftime('%F') || '-'
79
+ %td= applicant.missing_info_reason
80
+ %td
71
81
 
82
+ - # Completed
72
83
  %tr
73
- %td Application Complete
84
+ %td Application Completed
74
85
  %td= applicant.completed_at&.strftime('%F') || '-'
75
86
  %td
87
+ - if applicant.completed_at.present?
88
+ = icon('check', class: 'small-1')
89
+ Done
76
90
  %td
77
91
 
78
- %tr
79
- %td Reviews
80
- %td= applicant.reviewed_at&.strftime('%F') || '-'
81
- %td
82
- - applicant.reviewed_requirements.each do |requirement, completed|
83
- - next if requirement.to_s == 'Applicant Reviews'
92
+ - # Reviewed
93
+ - if EffectiveMemberships.applicant_reviews?
94
+ %tr.effective-memberships-applicant-status-reviewed
95
+ %td Reviews
96
+ %td= applicant.reviewed_at&.strftime('%F') || '-'
97
+ %td
98
+ - applicant.reviewed_requirements.each do |requirement, completed|
99
+ - next if requirement.to_s == 'Applicant Reviews'
84
100
 
85
- %p
86
- = icon((completed ? 'check' : 'x'), class: 'small-1')
87
- = requirement
101
+ %p
102
+ = icon((completed ? 'check' : 'x'), class: 'small-1')
103
+ = requirement
88
104
 
89
- - if applicant.applicant_reviews_required?
90
- %p
91
- - if applicant.reviewed_requirements['Applicant Reviews']
105
+ - if applicant.applicant_reviews_required?
106
+ %p
107
+ - if applicant.reviewed_requirements['Applicant Reviews']
108
+ = icon('check', class: 'small-1')
109
+
110
+ = applicant.applicant_reviews.count(&:completed?)
111
+ = '/'
112
+ = applicant.min_applicant_reviews
113
+ Reviews Completed
114
+ - else
115
+ %p
92
116
  = icon('check', class: 'small-1')
117
+ Reviews Not Required
93
118
 
94
- = applicant.applicant_reviews.count(&:completed?)
95
- = '/'
96
- = applicant.min_applicant_reviews
97
- Reviews Completed
98
- - else
99
- %p
100
- = icon('check', class: 'small-1')
101
- Reviews Not Required
119
+ %td
120
+ - # Button to create reviews here
102
121
 
122
+ %tr
123
+ %td Waiting to Process
103
124
  %td
104
- - if applicant.was_reviewed? && !applicant.was_approved?
125
+ - if EffectiveMemberships.applicant_reviews?
126
+ = applicant.reviewed_at&.strftime('%F') || '-'
127
+ - else
128
+ = applicant.completed_at&.strftime('%F') || '-'
129
+ %td
130
+ %td
131
+ - if applicant.was_submitted? && !(applicant.approved? || applicant.declined?)
105
132
  = link_to 'Process Applicant', '#process', 'data-click-tab': true, class: 'btn btn-sm btn-primary'
106
133
 
107
- - if applicant.declined_at.present?
108
- %tr
109
- %td Processed
110
- %td= applicant.declined_at.strftime('%F')
111
- %td
134
+ %tr
135
+ %td Processed
136
+ %td= (applicant.approved_at&.strftime('%F') || applicant.declined_at&.strftime('%F') || '-')
137
+ %td
138
+ - if applicant.was_approved? && !applicant.approved?
139
+ = icon('check', class: 'small-1')
140
+ Approved
141
+
142
+ - elsif applicant.was_declined? || applicant.declined?
112
143
  = icon('check', class: 'small-1')
113
144
  Declined
114
145
  %br
115
146
  = applicant.declined_reason
116
- %td
117
147
 
118
- - if applicant.was_approved?
119
- %tr
120
- %td Processed
121
- %td= applicant.approved_at&.strftime('%F')
122
- %td
123
- - if applicant.was_approved?
124
- = icon('check', class: 'small-1')
125
- Approved
126
- - elsif applicant.declined?
127
- = icon('check', class: 'small-1')
128
- Declined
129
- %br
130
- = applicant.declined_reason
131
- - else
132
- = '-'
133
- %td
148
+ - elsif applicant.approved?
149
+ = icon('check', class: 'small-1')
150
+ Approved
151
+ %td
@@ -0,0 +1,18 @@
1
+ %h3 Missing Information
2
+ %p The following information is missing: #{resource.missing_info_reason}.
3
+
4
+ %p
5
+ Please revisit each wizard step and
6
+ = link_to 'complete all missing information', wizard_path(:demographics)
7
+ for this application.
8
+
9
+ %p
10
+ Once you're ready, click below to re-submit your application with the updated information.
11
+
12
+ %p
13
+ = effective_form_with(model: resource, url: wizard_path(step), method: :put) do |f|
14
+ = f.hidden_field :id
15
+ = f.save 'Submit Application', 'data-confirm': "Really submit application?"
16
+
17
+ %p
18
+ %small * No additional payment required.
@@ -36,5 +36,5 @@
36
36
  %tr
37
37
  %th Status
38
38
  %td
39
- %span.badge.badge-secondary= applicant.status
39
+ %span.badge.badge-secondary= applicant.status_label
40
40
  = applicant.summary
@@ -5,8 +5,7 @@
5
5
  - raise('expected a purchased applicant submit_order') unless resource.submit_order&.purchased?
6
6
 
7
7
  .alert.alert-success.mb-4
8
- This application was submitted on
9
- = resource.submit_order.purchased_at.strftime('%F')
8
+ This application was submitted on #{resource.submitted_at.strftime('%F')}
10
9
 
11
10
  - unless resource.approved?
12
11
  .card
@@ -20,15 +19,18 @@
20
19
  .card
21
20
  .card-body= render 'effective/applicants/summary', applicant: resource
22
21
 
22
+ - if resource.missing_info?
23
+ = card do
24
+ = render 'effective/applicants/missing_info', applicant: resource
25
+
23
26
  - if resource.min_applicant_references.to_i > 0 || resource.applicant_references.present?
24
- .card
25
- .card-body
26
- %h3 Confidential References
27
- %p
28
- References are automatically sent a reference request.
29
- Click 'New' to add an additional reference, or click 'Notify' to resend the reference request.
27
+ = card do
28
+ %h3 Confidential References
29
+ %p
30
+ References are automatically sent a reference request.
31
+ Click 'New' to add an additional reference, or click 'Notify' to resend the reference request.
30
32
 
31
- = render_datatable(EffectiveApplicantReferencesDatatable.new(applicant: resource), inline: true, simple: true)
33
+ = render_datatable(EffectiveApplicantReferencesDatatable.new(applicant: resource), inline: true, simple: true)
32
34
 
33
35
  .mb-4
34
36
  = collapse('Show application...', card_class: 'my-2') do
@@ -5,4 +5,10 @@
5
5
 
6
6
  = effective_form_with(model: resource, url: wizard_path(step), method: :put) do |f|
7
7
  = f.hidden_field :id
8
- = f.submit 'Save and Continue', border: false, left: true
8
+
9
+ = f.submit(border: false, left: true) do
10
+ -# Missing Info
11
+ - if EffectiveResources.authorized?(self, :resubmit, resource)
12
+ = f.save 'Submit Application'
13
+ - else
14
+ = f.save 'Save and Continue'
@@ -0,0 +1,15 @@
1
+ ---
2
+ subject: 'Your application was marked as completed!'
3
+ from: 'admin@example.com'
4
+ ---
5
+ Hello {{ user.name }},
6
+
7
+ Your application for {{ applicant.to_category }} has been marked completed.
8
+
9
+ It is ready for review and a final decision to approve or decline.
10
+
11
+ {{ applicant.url }}
12
+
13
+ Thank you.
14
+
15
+ Please contact us for assistance.
@@ -0,0 +1,17 @@
1
+ ---
2
+ subject: 'Your application is missing information'
3
+ from: 'admin@example.com'
4
+ ---
5
+ Hello {{ user.name }},
6
+
7
+ Your application for {{ applicant.to_category }} is missing information:
8
+
9
+ {{ applicant.missing_info_reason }}
10
+
11
+ Please update your application with this info.
12
+
13
+ {{ applicant.url }}
14
+
15
+ Thank you.
16
+
17
+ Please contact us for assistance.
@@ -21,27 +21,25 @@ EffectiveMemberships.setup do |config|
21
21
  # The defaults include: Applicant, Prorated, Renewal, Late, Admin
22
22
  # config.additional_fee_types = []
23
23
 
24
- # Mailer Configuration
24
+ # Applicant Reviews
25
+ # When true, display the reviewed state and require Category.min_applicant_reviews
26
+ # When false, hide the reviewed state entirely
27
+ # config.applicant_reviews = false
28
+
29
+ # Mailer Settings
30
+ # Please see config/initializers/effective_resources.rb for default effective_* gem mailer settings
31
+ #
25
32
  # Configure the class responsible to send e-mails.
26
33
  # config.mailer = 'Effective::MembershipsMailer'
27
-
28
- # Configure the parent class responsible to send e-mails.
29
- # config.parent_mailer = 'ActionMailer::Base'
30
-
31
- # Default deliver method
32
- # config.deliver_method = :deliver_later
33
-
34
- # Default layout
35
- # config.mailer_layout = 'effective_memberships_mailer_layout'
36
-
37
- # Default From
38
- config.mailer_sender = "no-reply@example.com"
39
-
40
- # Send Admin correspondence To
41
- config.mailer_admin = "admin@example.com"
42
-
43
- # Will work with effective_email_templates gem:
44
- # - The audit and audit review email content will be preopulated based off the template
45
- # - Uses an EmailTemplatesMailer mailer instead of ActionMailer::Base for default parent_mailer
46
- config.use_effective_email_templates = false
34
+ #
35
+ # Override effective_resource mailer defaults
36
+ #
37
+ # config.parent_mailer = nil # The parent class responsible for sending emails
38
+ # config.deliver_method = nil # The deliver method, deliver_later or deliver_now
39
+ # config.mailer_layout = nil # Default mailer layout
40
+ # config.mailer_sender = nil # Default From value
41
+ # config.mailer_admin = nil # Default To value for Admin correspondence
42
+
43
+ # Will work with effective_email_templates gem
44
+ config.use_effective_email_templates = true
47
45
  end
@@ -151,6 +151,10 @@ class CreateEffectiveMemberships < ActiveRecord::Migration[6.0]
151
151
  t.datetime :declined_at
152
152
  t.text :declined_reason
153
153
 
154
+ # Missing
155
+ t.datetime :missing_info_at
156
+ t.text :missing_info_reason
157
+
154
158
  # Applicant Educations
155
159
  t.text :applicant_educations_details
156
160
 
@@ -1,3 +1,3 @@
1
1
  module EffectiveMemberships
2
- VERSION = '0.3.10'
2
+ VERSION = '0.3.13'
3
3
  end
@@ -8,7 +8,7 @@ module EffectiveMemberships
8
8
  [
9
9
  :categories_table_name, :applicants_table_name, :applicant_reviews_table_name, :fee_payments_table_name,
10
10
  :category_class_name, :applicant_class_name, :applicant_review_class_name, :fee_payment_class_name, :registrar_class_name, :membership_card_class_name,
11
- :additional_fee_types,
11
+ :additional_fee_types, :applicant_reviews,
12
12
  :layout,
13
13
  :mailer, :parent_mailer, :deliver_method, :mailer_layout, :mailer_sender, :mailer_admin, :use_effective_email_templates
14
14
  ]
@@ -36,6 +36,10 @@ module EffectiveMemberships
36
36
  membership_card_class_name&.constantize || Effective::MembershipCard
37
37
  end
38
38
 
39
+ def self.applicant_reviews?
40
+ applicant_reviews == true
41
+ end
42
+
39
43
  # Singleton
40
44
  def self.Registrar
41
45
  klass = registrar_class_name&.constantize || Effective::Registrar
@@ -46,17 +50,6 @@ module EffectiveMemberships
46
50
  mailer&.constantize || Effective::MembershipsMailer
47
51
  end
48
52
 
49
- def self.parent_mailer_class
50
- return parent_mailer.constantize if parent_mailer.present?
51
-
52
- if use_effective_email_templates
53
- require 'effective_email_templates'
54
- Effective::EmailTemplatesMailer
55
- else
56
- ActionMailer::Base
57
- end
58
- end
59
-
60
53
  def self.fee_types
61
54
  required = ['Applicant', 'Prorated', 'Discount', 'Renewal', 'Late', 'Admin']
62
55
  additional = Array(additional_fee_types)
@@ -69,21 +62,4 @@ module EffectiveMemberships
69
62
  ['Admin']
70
63
  end
71
64
 
72
- def self.send_email(email, *args)
73
- raise('expected args to be an Array') unless args.kind_of?(Array)
74
-
75
- if defined?(Tenant)
76
- tenant = Tenant.current || raise('expected a current tenant')
77
- args.last.kind_of?(Hash) ? args.last.merge!(tenant: tenant) : args << { tenant: tenant }
78
- end
79
-
80
- deliver_method = EffectiveMemberships.deliver_method || EffectiveResources.deliver_method
81
-
82
- begin
83
- EffectiveMemberships.mailer_class.send(email, *args).send(deliver_method)
84
- rescue => e
85
- raise if Rails.env.development? || Rails.env.test?
86
- end
87
- end
88
-
89
65
  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.3.10
4
+ version: 0.3.13
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-02-24 00:00:00.000000000 Z
11
+ date: 2022-03-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -317,7 +317,9 @@ files:
317
317
  - app/views/admin/applicant_references/_applicant_reference.html.haml
318
318
  - app/views/admin/applicants/_form.html.haml
319
319
  - app/views/admin/applicants/_form_approve.html.haml
320
+ - app/views/admin/applicants/_form_complete.html.haml
320
321
  - app/views/admin/applicants/_form_decline.html.haml
322
+ - app/views/admin/applicants/_form_missing_info.html.haml
321
323
  - app/views/admin/applicants/_form_process.html.haml
322
324
  - app/views/admin/applicants/_status.html.haml
323
325
  - app/views/admin/categories/_form.html.haml
@@ -360,6 +362,7 @@ files:
360
362
  - app/views/effective/applicants/_experience.html.haml
361
363
  - app/views/effective/applicants/_files.html.haml
362
364
  - app/views/effective/applicants/_layout.html.haml
365
+ - app/views/effective/applicants/_missing_info.html.haml
363
366
  - app/views/effective/applicants/_orders.html.haml
364
367
  - app/views/effective/applicants/_references.html.haml
365
368
  - app/views/effective/applicants/_select.html.haml
@@ -403,9 +406,10 @@ files:
403
406
  - app/views/effective/memberships/_membership.html.haml
404
407
  - app/views/effective/memberships_directory/index.html.haml
405
408
  - app/views/effective/memberships_mailer/applicant_approved.liquid
409
+ - app/views/effective/memberships_mailer/applicant_completed.liquid
406
410
  - app/views/effective/memberships_mailer/applicant_declined.liquid
411
+ - app/views/effective/memberships_mailer/applicant_missing_info.liquid
407
412
  - app/views/effective/memberships_mailer/applicant_reference_notification.liquid
408
- - app/views/layouts/effective_memberships_mailer_layout.html.haml
409
413
  - config/effective_memberships.rb
410
414
  - config/routes.rb
411
415
  - db/migrate/01_create_effective_memberships.rb.erb
@@ -1,7 +0,0 @@
1
- !!!
2
- %html{style: 'background: #fff;'}
3
- %head
4
- %meta{:content => 'text/html; charset=UTF-8', 'http-equiv' => 'Content-Type'}
5
-
6
- %body{style: 'background: #fff;'}
7
- = yield