effective_memberships 0.12.2 → 0.13.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: eee6457653137fc81d4b2bbb9523c2158da073a2a3742678f17e305047854b45
4
- data.tar.gz: 5ad84fb485691eda2cef81d3b08b7de3c41306e07bd2adf62cef22903b42cdb6
3
+ metadata.gz: ef95cbbf40f72c47c5ca64efd70d28d1cb879e52431b22471f2d570ef759d495
4
+ data.tar.gz: a150c327ec0869e26822f7d484cdc99c414cd666679150e9ee0c83efc3b125aa
5
5
  SHA512:
6
- metadata.gz: da419613c6a9c13734575d280cbfbbc9d25c7cda500db77f3fd062d181b3c1a03de55a9915aedbbd2943e79d7f206be285945b723fb123fbeb8ba39f4d31bd90
7
- data.tar.gz: 1f58b027945b279185489021ef228ecd21cf6df2cefd9a473d67ed50002fa1b8a2bc847efd1cf1cd6ad70a6e06357db62439613ab8e0d5e81ce208fafb32c3ea
6
+ metadata.gz: cc04a6003782b0c39e4b67d03c012dc3e2247c93b5f43bd38fd47a843da7ee0c9fa11e5a02d56672724f95c453e5cf266179ea22f9e06da851c1d484a583edd2
7
+ data.tar.gz: dc070be5820ad2f616c4320a745879ff26b8e153f24ddc99fb92913d753f96198c387b58b8656e443737cec8ea1b5417032faceb394eae2ea640c61efbb05cf4
@@ -208,6 +208,7 @@ module EffectiveMembershipsOwner
208
208
  fee.assign_attributes(
209
209
  fee_type: 'Discount',
210
210
  category: category,
211
+ from_category: from,
211
212
  period: period,
212
213
  price: price,
213
214
  tax_exempt: category.tax_exempt,
@@ -19,17 +19,17 @@ module EffectiveMembershipsRegistrar
19
19
  end
20
20
 
21
21
  def renewal_fee_date(date:)
22
- Date.new(date.year, 12, 1) # Fees roll over every December 1st
22
+ Time.zone.local(date.year, 12, 1) # Fees roll over every December 1st
23
23
  raise('to be implemented by app registrar')
24
24
  end
25
25
 
26
26
  def late_fee_date(period:)
27
- Date.new(period.year, 2, 1) # Fees are late after February 1st
27
+ Time.zone.local(period.year, 2, 1) # Fees are late after February 1st
28
28
  raise('to be implemented by app registrar')
29
29
  end
30
30
 
31
31
  def not_in_good_standing_date(period:)
32
- Date.new(period.year, 3, 1) # Membership in bad standing after March 1st
32
+ Time.zone.local(period.year, 3, 1) # Membership in bad standing after March 1st
33
33
  raise('to be implemented by app registrar')
34
34
  end
35
35
 
@@ -54,7 +54,7 @@ module EffectiveMembershipsRegistrar
54
54
  EffectiveMemberships.Status.where(title: 'Not In Good Standing').first!
55
55
  end
56
56
 
57
- # Should two could be overridden if we do non 1-year periods
57
+ # These two could be overridden if we do non 1-year periods
58
58
  def advance_period(period:, number:)
59
59
  period.advance(years: number).beginning_of_year
60
60
  end
@@ -147,8 +147,8 @@ module EffectiveMembershipsRegistrar
147
147
 
148
148
  # Or, Build Fees
149
149
  unless skip_fees
150
- fee = owner.build_prorated_fee(date: date)
151
- raise('already has purchased prorated fee') if fee.purchased?
150
+ fees = build_register_fees(owner: owner, membership: membership, date: date)
151
+ raise('unexpected purchased fee') if Array(fees).compact.any?(&:purchased?)
152
152
  end
153
153
 
154
154
  # Assign member role
@@ -159,6 +159,10 @@ module EffectiveMembershipsRegistrar
159
159
  owner.save!
160
160
  end
161
161
 
162
+ def build_register_fees(owner:, membership:, date:)
163
+ owner.build_prorated_fee(date: date)
164
+ end
165
+
162
166
  def reclassify!(owner, to:, status: nil, date: nil, skip_fees: false)
163
167
  raise('expecting a memberships owner') unless owner.class.respond_to?(:effective_memberships_owner?)
164
168
  raise('owner must have an existing membership. use register! instead') if owner.membership.blank?
@@ -187,18 +191,8 @@ module EffectiveMembershipsRegistrar
187
191
  membership.build_membership_status(status: status) if status.present?
188
192
 
189
193
  unless skip_fees
190
- existing = owner.membership_period_fee(category: from, period: period)
191
-
192
- if existing
193
- fee = owner.build_prorated_fee(date: date)
194
- raise('already has purchased prorated fee') if fee.purchased?
195
-
196
- fee = owner.build_discount_fee(date: date, from: from)
197
- raise('already has purchased discount fee') if fee.purchased?
198
- else
199
- fee = owner.build_renewal_fee(category: to, period: period)
200
- raise('already has purchased renewal fee') if fee.purchased?
201
- end
194
+ fees = build_reclassify_fees(owner: owner, membership: membership, to: to, from: from, period: period, date: date)
195
+ raise('unexpected purchased fee') if Array(fees).compact.any?(&:purchased?)
202
196
  end
203
197
 
204
198
  # Save owner
@@ -206,6 +200,19 @@ module EffectiveMembershipsRegistrar
206
200
  owner.save!
207
201
  end
208
202
 
203
+ def build_reclassify_fees(owner:, membership:, to:, from:, period:, date:)
204
+ existing = owner.membership_period_fee(category: from, period: period)
205
+
206
+ if existing
207
+ [
208
+ owner.build_prorated_fee(date: date),
209
+ owner.build_discount_fee(date: date, from: from)
210
+ ]
211
+ else
212
+ owner.build_renewal_fee(category: to, period: period)
213
+ end
214
+ end
215
+
209
216
  def reinstate!(owner, to: nil, date: nil, skip_fees: false)
210
217
  raise('expecting a memberships owner') unless owner.class.respond_to?(:effective_memberships_owner?)
211
218
 
@@ -251,7 +258,7 @@ module EffectiveMembershipsRegistrar
251
258
 
252
259
  # Or, Build Fees
253
260
  unless skip_fees
254
- fee = owner.build_prorated_fee(date: date)
261
+ build_reinstate_fees(owner: owner, membership: membership, date: date)
255
262
  # This might already be present and purchased if joined and reinstated in the same period
256
263
  end
257
264
 
@@ -263,6 +270,10 @@ module EffectiveMembershipsRegistrar
263
270
  owner.save!
264
271
  end
265
272
 
273
+ def build_reinstate_fees(owner:, membership:, date:)
274
+ owner.build_prorated_fee(date: date)
275
+ end
276
+
266
277
  def status_clear!(owner, date: nil)
267
278
  raise('expecting a memberships owner') unless owner.class.respond_to?(:effective_memberships_owner?)
268
279
  raise('owner must have an existing membership. use register! instead') if owner.membership.blank?
@@ -464,8 +475,7 @@ module EffectiveMembershipsRegistrar
464
475
  memberships = Effective::Membership.deep.with_unpaid_fees_through(period)
465
476
 
466
477
  memberships.find_each do |membership|
467
- create_fees!(membership, period: period)
468
- GC.start
478
+ create_fees!(membership, period: period); GC.start
469
479
  end
470
480
 
471
481
  true
@@ -496,9 +506,9 @@ module EffectiveMembershipsRegistrar
496
506
 
497
507
  fee = membership.owner.build_renewal_fee(category: category, period: period)
498
508
  raise("expected build_renewal_fee to return a fee for period #{period}") unless fee.kind_of?(Effective::Fee)
499
- next if fee.purchased?
509
+ next if fee.blank? || fee.persisted?
500
510
 
501
- puts("Created renewal fee for #{membership.owner}") if fee.new_record? && debug?
511
+ puts("Created renewal fee for #{membership.owner}") if debug?
502
512
 
503
513
  fee.save!
504
514
  end
@@ -507,16 +517,18 @@ module EffectiveMembershipsRegistrar
507
517
  def create_late_fees!(membership, period:)
508
518
  membership.categories.select(&:create_late_fees?).map do |category|
509
519
  fee = membership.owner.build_late_fee(category: category, period: period)
510
- next if fee.blank? || fee.purchased?
520
+ next if fee.blank? || fee.persisted?
511
521
 
512
- puts("Created late fee for #{membership.owner}") if fee.new_record? && debug?
522
+ puts("Created late fee for #{membership.owner}") if debug?
513
523
 
514
524
  fee.save!
515
525
  end
516
526
  end
517
527
 
518
528
  def create_not_in_good_standing!(membership, period:)
529
+ return unless Time.zone.now.beginning_of_day == not_in_good_standing_date(period: period).beginning_of_day
519
530
  return unless membership.categories.any?(&:create_not_in_good_standing?)
531
+
520
532
  membership.owner.update_membership_status!
521
533
  end
522
534
 
@@ -13,6 +13,9 @@ module Effective
13
13
  # The membership category for this fee, if there's only 1 membership.categories
14
14
  belongs_to :category, polymorphic: true, optional: true
15
15
 
16
+ # Only set on the Discount fee right now
17
+ belongs_to :from_category, polymorphic: true, optional: true
18
+
16
19
  # The membership status for this fee, if there's only 1 membership.statuses
17
20
  belongs_to :with_status, polymorphic: true, optional: true
18
21
 
@@ -149,7 +152,7 @@ module Effective
149
152
  [
150
153
  period.strftime('%Y'),
151
154
  category,
152
- EffectiveResources.et("effective_memberships.fees.#{fee_type.downcase}")
155
+ EffectiveResources.et("effective_memberships.fees.#{fee_type.parameterize.underscore}")
153
156
  ].join(' ')
154
157
  end
155
158
 
@@ -4,15 +4,15 @@ module Effective
4
4
  include EffectiveMembershipsRegistrar
5
5
 
6
6
  def renewal_fee_date(date:)
7
- Date.new(date.year, 12, 1) # Fees roll over every December 1st
7
+ Time.zone.local(date.year, 12, 1) # Fees roll over every December 1st
8
8
  end
9
9
 
10
10
  def late_fee_date(period:)
11
- Date.new(period.year, 2, 1) # Fees are late after February 1st
11
+ Time.zone.local(period.year, 2, 1) # Fees are late after February 1st
12
12
  end
13
13
 
14
14
  def not_in_good_standing_date(period:)
15
- Date.new(period.year, 3, 1) # Membership are Not In Good Standing after March 1st
15
+ Time.zone.local(period.year, 3, 1) # Membership are Not In Good Standing after March 1st
16
16
  end
17
17
 
18
18
  end
@@ -0,0 +1,17 @@
1
+ %h3 Fees
2
+ %p The following fees will be created:
3
+ - month = Time.zone.now.strftime('%B')
4
+
5
+ %ul
6
+ - if applicant.apply_to_join?
7
+ %li A #{month} prorated fee
8
+
9
+ - if applicant.reclassification?
10
+ - if applicant.owner.outstanding_renewal_fees.present?
11
+ %li A renewal fee in their new category
12
+ - else
13
+ %li A #{month} prorated fee to the new category
14
+ %li A #{month} discount fee from their old category
15
+
16
+ - if applicant.reinstatement?
17
+ %li A #{month} prorated fee to their reinstatement category
@@ -22,23 +22,7 @@
22
22
  - if applicant.reinstatement? && reinstatement.present?
23
23
  %p The member will be reinstated with their previous status: #{badges(reinstatement.membership_statuses) || 'None'}.
24
24
 
25
- %h3 Fees
26
- %p The following fees will be created:
27
- - month = Time.zone.now.strftime('%B')
28
-
29
- %ul
30
- - if applicant.apply_to_join?
31
- %li A #{month} prorated fee
32
-
33
- - if applicant.reclassification?
34
- - if applicant.owner.outstanding_renewal_fees.present?
35
- %li A renewal fee in their new category
36
- - else
37
- %li A #{month} prorated fee to the new category
38
- %li A #{month} discount fee from their old category
39
-
40
- - if applicant.reinstatement?
41
- %li A #{month} prorated fee to their reinstatement category
25
+ = render('admin/applicants/fees_approve', f: f, applicant: applicant)
42
26
 
43
27
  %p The following unpurchased fees will be deleted:
44
28
  - outstanding_fee_payment_fees = applicant.owner.outstanding_fee_payment_fees
@@ -0,0 +1 @@
1
+ - # Intentionally blank. Used to extend category fees form.
@@ -0,0 +1,23 @@
1
+ %h3 Applicant Fees
2
+ .row
3
+ .col= f.price_field :applicant_fee
4
+ .col= f.text_field :qb_item_name, label: "Quickbooks Item Name"
5
+
6
+ %h3 Pro-rated fees based on date of approval
7
+ .row
8
+ .col-lg-3
9
+ = f.price_field :prorated_jan, label: "January"
10
+ = f.price_field :prorated_feb, label: "February"
11
+ = f.price_field :prorated_mar, label: "March"
12
+ .col-lg-3
13
+ = f.price_field :prorated_apr, label: "April"
14
+ = f.price_field :prorated_may, label: "May"
15
+ = f.price_field :prorated_jun, label: "June"
16
+ .col-lg-3
17
+ = f.price_field :prorated_jul, label: "July"
18
+ = f.price_field :prorated_aug, label: "August"
19
+ = f.price_field :prorated_sep, label: "September"
20
+ .col-lg-3
21
+ = f.price_field :prorated_oct, label: "October"
22
+ = f.price_field :prorated_nov, label: "November"
23
+ = f.price_field :prorated_dec, label: "December"
@@ -0,0 +1,10 @@
1
+ %h3 Late Fees
2
+ = f.check_box :create_late_fees, label: 'Yes, late fees should be created'
3
+
4
+ = f.show_if(:create_late_fees, true) do
5
+ - period = EffectiveMemberships.Registrar.current_period
6
+ - date = EffectiveMemberships.Registrar.late_fee_date(period: period)
7
+
8
+ %p Charged to members, on #{date.strftime('%B %e')}, with outstanding renewal dues or other fees.
9
+ .row
10
+ .col-3= f.price_field :late_fee
@@ -0,0 +1,8 @@
1
+ %h3 Not In Good Standing
2
+ = f.check_box :create_not_in_good_standing, label: 'Yes, Not in Good Standing status should be applied'
3
+
4
+ = f.show_if(:create_not_in_good_standing, true) do
5
+ - period = EffectiveMemberships.Registrar.current_period
6
+ - date = EffectiveMemberships.Registrar.not_in_good_standing_date(period: period)
7
+
8
+ %p Members with outstanding fees, on #{date.strftime('%B %e')}, will automatically be marked #{badge('Not In Good Standing')}.
@@ -0,0 +1,9 @@
1
+ %h3 Renewal Fees
2
+ = f.check_box :create_renewal_fees, label: 'Yes, annual renewal fees should be created'
3
+
4
+ = f.show_if(:create_renewal_fees, true) do
5
+ - date = EffectiveMemberships.Registrar.renewal_fee_date(date: Time.zone.now)
6
+
7
+ %p Charged to members, every #{date.strftime('%B %e')}, to renew their dues.
8
+ .row
9
+ .col-3= f.price_field :renewal_fee
@@ -1,56 +1,7 @@
1
1
  = effective_form_with(model: [:admin, category], engine: true) do |f|
2
- %h3 Applicant Fees
3
- .row
4
- .col= f.price_field :applicant_fee
5
- .col= f.text_field :qb_item_name, label: "Quickbooks Item Name"
6
-
7
- %h3 Pro-rated fees based on date of approval
8
- .row
9
- .col-lg-3
10
- = f.price_field :prorated_jan, label: "January"
11
- = f.price_field :prorated_feb, label: "February"
12
- = f.price_field :prorated_mar, label: "March"
13
- .col-lg-3
14
- = f.price_field :prorated_apr, label: "April"
15
- = f.price_field :prorated_may, label: "May"
16
- = f.price_field :prorated_jun, label: "June"
17
- .col-lg-3
18
- = f.price_field :prorated_jul, label: "July"
19
- = f.price_field :prorated_aug, label: "August"
20
- = f.price_field :prorated_sep, label: "September"
21
- .col-lg-3
22
- = f.price_field :prorated_oct, label: "October"
23
- = f.price_field :prorated_nov, label: "November"
24
- = f.price_field :prorated_dec, label: "December"
25
-
26
- %h3 Renewal Fees
27
- = f.check_box :create_renewal_fees, label: 'Yes, annual renewal fees should be created'
28
-
29
- = f.show_if(:create_renewal_fees, true) do
30
- - date = EffectiveMemberships.Registrar.renewal_fee_date(date: Time.zone.now)
31
-
32
- %p Charged to members, every #{date.strftime('%B %e')}, to renew their dues.
33
- .row
34
- .col-3= f.price_field :renewal_fee
35
-
36
- %h3 Late Fees
37
- = f.check_box :create_late_fees, label: 'Yes, late fees should be created'
38
-
39
- = f.show_if(:create_late_fees, true) do
40
- - period = EffectiveMemberships.Registrar.current_period
41
- - date = EffectiveMemberships.Registrar.late_fee_date(period: period)
42
-
43
- %p Charged to members, on #{date.strftime('%B %e')}, with outstanding renewal fees
44
- .row
45
- .col-3= f.price_field :late_fee
46
-
47
- %h3 Bad Standing
48
- = f.check_box :create_not_in_good_standing, label: 'Yes, Not in Good Standing status should be applied'
49
-
50
- = f.show_if(:create_not_in_good_standing, true) do
51
- - period = EffectiveMemberships.Registrar.current_period
52
- - date = EffectiveMemberships.Registrar.not_in_good_standing_date(period: period)
53
-
54
- %p Members with outstanding fees, on #{date.strftime('%B %e')}, will automatically be marked #{badge('Not In Good Standing')}.
55
-
2
+ = render('admin/categories/fees_applicant', f: f)
3
+ = render('admin/categories/fees_renewal', f: f)
4
+ = render('admin/categories/fees_late', f: f)
5
+ = render('admin/categories/fees_additional', f: f)
6
+ = render('admin/categories/fees_nigs', f: f)
56
7
  = f.submit
@@ -457,6 +457,9 @@ class CreateEffectiveMemberships < ActiveRecord::Migration[6.0]
457
457
  t.integer :category_id
458
458
  t.string :category_type
459
459
 
460
+ t.integer :from_category_id
461
+ t.string :from_category_type
462
+
460
463
  t.integer :with_status_id
461
464
  t.string :with_status_type
462
465
 
@@ -1,3 +1,3 @@
1
1
  module EffectiveMemberships
2
- VERSION = '0.12.2'
2
+ VERSION = '0.13.0'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: effective_memberships
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.12.2
4
+ version: 0.13.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: 2023-03-10 00:00:00.000000000 Z
11
+ date: 2023-03-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -354,6 +354,7 @@ files:
354
354
  - app/views/admin/applicant_endorsements/_applicant_endorsement.html.haml
355
355
  - app/views/admin/applicant_references/_applicant_reference.html.haml
356
356
  - app/views/admin/applicant_reviews/_applicant_review.html.haml
357
+ - app/views/admin/applicants/_fees_approve.html.haml
357
358
  - app/views/admin/applicants/_form.html.haml
358
359
  - app/views/admin/applicants/_form_applicant.html.haml
359
360
  - app/views/admin/applicants/_form_approve.html.haml
@@ -363,6 +364,11 @@ files:
363
364
  - app/views/admin/applicants/_form_process.html.haml
364
365
  - app/views/admin/applicants/_form_transcripts.html.haml
365
366
  - app/views/admin/applicants/_status.html.haml
367
+ - app/views/admin/categories/_fees_additional.html.haml
368
+ - app/views/admin/categories/_fees_applicant.html.haml
369
+ - app/views/admin/categories/_fees_late.html.haml
370
+ - app/views/admin/categories/_fees_nigs.html.haml
371
+ - app/views/admin/categories/_fees_renewal.html.haml
366
372
  - app/views/admin/categories/_form.html.haml
367
373
  - app/views/admin/categories/_form_applicant_content.html.haml
368
374
  - app/views/admin/categories/_form_applicant_steps.html.haml