effective_memberships 0.16.2 → 0.17.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/datatables/admin/effective_categories_datatable.rb +5 -0
- data/app/models/concerns/effective_memberships_category.rb +20 -1
- data/app/models/concerns/effective_memberships_owner.rb +28 -0
- data/app/models/concerns/effective_memberships_registrar.rb +66 -8
- data/app/models/effective/fee.rb +5 -4
- data/app/models/effective/membership.rb +1 -1
- data/app/models/effective/registrar.rb +8 -0
- data/app/views/admin/categories/_fees_early.html.haml +14 -0
- data/app/views/admin/categories/_fees_late.html.haml +4 -3
- data/app/views/admin/categories/_fees_renewal.html.haml +2 -2
- data/app/views/admin/categories/_form_fees.html.haml +16 -3
- data/config/locales/effective_memberships.en.yml +1 -0
- data/db/migrate/01_create_effective_memberships.rb.erb +3 -0
- data/lib/effective_memberships/version.rb +1 -1
- data/lib/effective_memberships.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: '09fbb8a22bb53806fe272999514bc8cc4d8b8cf5784aaab5428777ffe43af61e'
|
4
|
+
data.tar.gz: cc6fd66a60a0db18c98a44849e3768e8c6d892b6af9cd297485b18f65290457b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e286896d066c61cb0bb65b325837152d275f43c158e0f8df95302c36aee81ef1fcd3359efd37a71ec3f78b182a87fa0ee587c6ffe017d3971013af32b3647e67
|
7
|
+
data.tar.gz: 37c79f3c9a254275346c352832082bf9014690144720fd3ea2fef642dfe2740f3e72f3597870754f4c0076574ade33c65a1227d8fefa4f2325903aaacef9bd7f
|
@@ -35,9 +35,14 @@ module Admin
|
|
35
35
|
col :qb_item_name, visible: false
|
36
36
|
|
37
37
|
col :create_renewal_fees, visible: false
|
38
|
+
col :create_early_fees, visible: false
|
38
39
|
col :create_late_fees, visible: false
|
39
40
|
col :create_not_in_good_standing, visible: false
|
40
41
|
|
42
|
+
col :renewal_fee, as: :price, visible: false
|
43
|
+
col :early_fee, as: :price, visible: false
|
44
|
+
col :late_fee, as: :price, visible: false
|
45
|
+
|
41
46
|
col :category_type, search: EffectiveMemberships.Category.category_types, visible: false
|
42
47
|
|
43
48
|
col :optional_applicant_wizard_steps, label: 'Applicant Steps', visible: false
|
@@ -99,13 +99,19 @@ module EffectiveMembershipsCategory
|
|
99
99
|
fee_payment_wizard_steps :text
|
100
100
|
fee_payment_cpd_step_requirement :string
|
101
101
|
|
102
|
-
#
|
102
|
+
# Renewal Fees
|
103
103
|
create_renewal_fees :boolean
|
104
104
|
renewal_fee :integer
|
105
105
|
|
106
|
+
# Early Fees
|
107
|
+
create_early_fees :boolean
|
108
|
+
early_fee :integer
|
109
|
+
|
110
|
+
# Late Fees
|
106
111
|
create_late_fees :boolean
|
107
112
|
late_fee :integer
|
108
113
|
|
114
|
+
# NIGS Status
|
109
115
|
create_not_in_good_standing :boolean
|
110
116
|
|
111
117
|
# Pricing
|
@@ -167,6 +173,19 @@ module EffectiveMembershipsCategory
|
|
167
173
|
validates :qb_item_name, presence: true
|
168
174
|
validates :tax_exempt, inclusion: { in: [true, false] }
|
169
175
|
end
|
176
|
+
|
177
|
+
with_options(if: -> { create_renewal_fees? }) do
|
178
|
+
validates :renewal_fee, presence: true, numericality: { greater_than_or_equal_to: 0 }
|
179
|
+
end
|
180
|
+
|
181
|
+
with_options(if: -> { create_early_fees? }) do
|
182
|
+
validates :early_fee, presence: true, numericality: { less_than_or_equal_to: 0 }
|
183
|
+
end
|
184
|
+
|
185
|
+
with_options(if: -> { create_late_fees? }) do
|
186
|
+
validates :late_fee, presence: true, numericality: { greater_than_or_equal_to: 0 }
|
187
|
+
end
|
188
|
+
|
170
189
|
end
|
171
190
|
|
172
191
|
# Instance Methods
|
@@ -304,6 +304,34 @@ module EffectiveMembershipsOwner
|
|
304
304
|
fee
|
305
305
|
end
|
306
306
|
|
307
|
+
def build_early_fee(category:, period:)
|
308
|
+
raise('must have an existing membership') unless membership.present?
|
309
|
+
|
310
|
+
# Return existing but do not build yet
|
311
|
+
fee = fees.find { |fee| fee.fee_type == 'Early' && fee.period == period && fee.category_id == category.id && fee.category_type == category.class.name }
|
312
|
+
return fee if fee&.purchased?
|
313
|
+
|
314
|
+
# Only continue if there is an early renewal fee for the same period
|
315
|
+
renewal_fee = fees.find { |fee| fee.fee_type == 'Renewal' && fee.period == period && fee.category_id == category.id && fee.category_type == category.class.name }
|
316
|
+
return if fee.blank? && (renewal_fee.blank? || renewal_fee.early? == false)
|
317
|
+
|
318
|
+
# Build the early fee
|
319
|
+
fee ||= fees.build()
|
320
|
+
|
321
|
+
fee.assign_attributes(
|
322
|
+
fee_type: 'Early',
|
323
|
+
category: category,
|
324
|
+
period: period,
|
325
|
+
price: category.early_fee.to_i,
|
326
|
+
tax_exempt: category.tax_exempt,
|
327
|
+
qb_item_name: category.qb_item_name
|
328
|
+
)
|
329
|
+
|
330
|
+
after_build_fee(fee)
|
331
|
+
|
332
|
+
fee
|
333
|
+
end
|
334
|
+
|
307
335
|
def build_late_fee(category:, period:)
|
308
336
|
raise('must have an existing membership') unless membership.present?
|
309
337
|
|
@@ -24,7 +24,7 @@ module EffectiveMembershipsRegistrar
|
|
24
24
|
end
|
25
25
|
|
26
26
|
def late_fee_date(period:)
|
27
|
-
Time.zone.local(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
|
|
@@ -33,6 +33,22 @@ module EffectiveMembershipsRegistrar
|
|
33
33
|
raise('to be implemented by app registrar')
|
34
34
|
end
|
35
35
|
|
36
|
+
# The early fee dates are calculated based on period
|
37
|
+
# The period is a date that starts on Jan 1st of a year.
|
38
|
+
# When Time.zone.now is December the period will be one ahead.
|
39
|
+
|
40
|
+
# Assumed to be the same as renewal_fee_date
|
41
|
+
def early_fee_date(period:)
|
42
|
+
Time.zone.local(period.year - 1, 12, 1) # Fees roll over every December 1st
|
43
|
+
raise('to be implemented by app registrar')
|
44
|
+
end
|
45
|
+
|
46
|
+
# Assumed to be just before the period actually starts
|
47
|
+
def early_fee_end_date(period:)
|
48
|
+
Time.zone.local(period.year - 1, 12, 31) # Early fees are destroyed on December 31st
|
49
|
+
raise('to be implemented by app registrar')
|
50
|
+
end
|
51
|
+
|
36
52
|
# A renewal fee must be at least this old to be considered late?
|
37
53
|
# Must be less than (late_fee_date - renewal_fee_date) but this is not enforced
|
38
54
|
def min_late_duration
|
@@ -112,6 +128,10 @@ module EffectiveMembershipsRegistrar
|
|
112
128
|
periods(from: from, to: to).reverse.map { |period| [period_end_on(date: period), period] }
|
113
129
|
end
|
114
130
|
|
131
|
+
def early_fee_date_range(period:)
|
132
|
+
(early_fee_date(period: period).beginning_of_day)..(early_fee_end_date(period: period).beginning_of_day)
|
133
|
+
end
|
134
|
+
|
115
135
|
# Category is required, statuses are optional
|
116
136
|
def assign!(owner, categories:, statuses: nil, date: nil, number: nil)
|
117
137
|
categories = Array(categories)
|
@@ -492,31 +512,48 @@ module EffectiveMembershipsRegistrar
|
|
492
512
|
# rake effective_memberships:create_fees
|
493
513
|
# Create Renewal and Late fees
|
494
514
|
# Assigns NIGS
|
495
|
-
def create_all_fees!(period: nil)
|
515
|
+
def create_all_fees!(period: nil, force: false)
|
496
516
|
period ||= current_period
|
497
517
|
memberships = Effective::Membership.deep.with_unpaid_fees_through(period)
|
498
518
|
|
499
519
|
memberships.find_each do |membership|
|
500
|
-
create_fees!(membership, period: period); GC.start
|
520
|
+
create_fees!(membership, period: period, force: force); GC.start
|
501
521
|
end
|
502
522
|
|
503
523
|
true
|
504
524
|
end
|
505
525
|
|
506
|
-
def create_fees!(resource, period: nil)
|
526
|
+
def create_fees!(resource, period: nil, force: false)
|
527
|
+
today = Time.zone.now.beginning_of_day
|
507
528
|
period ||= current_period
|
508
529
|
|
509
530
|
membership = (resource.class.respond_to?(:effective_memberships_owner?) ? resource.membership : resource)
|
510
531
|
raise('expected a membership') unless membership.present? && membership.kind_of?(Effective::Membership)
|
511
532
|
|
512
533
|
# Create Renewal Fees
|
513
|
-
|
534
|
+
if force || today == renewal_fee_date(date: today)
|
535
|
+
create_renewal_fees!(membership, period: period)
|
536
|
+
end
|
537
|
+
|
538
|
+
# Create Early Fees
|
539
|
+
if force || today == early_fee_date(period: period)
|
540
|
+
create_early_fees!(membership, period: period)
|
541
|
+
end
|
542
|
+
|
543
|
+
# Destroy Early Fees
|
544
|
+
if force || today == early_fee_end_date(period: period)
|
545
|
+
destroy_early_fees!(membership, period: period)
|
546
|
+
end
|
514
547
|
|
515
548
|
# Create Late Fees
|
516
|
-
|
549
|
+
if force || today == late_fee_date(period: period)
|
550
|
+
create_late_fees!(membership, period: period)
|
551
|
+
end
|
517
552
|
|
518
553
|
# Update Membership Status - Assign Not In Good Standing
|
519
|
-
|
554
|
+
if force || today == not_in_good_standing_date(period: period)
|
555
|
+
create_not_in_good_standing!(membership, period: period)
|
556
|
+
end
|
520
557
|
|
521
558
|
true
|
522
559
|
end
|
@@ -536,6 +573,28 @@ module EffectiveMembershipsRegistrar
|
|
536
573
|
end
|
537
574
|
end
|
538
575
|
|
576
|
+
def create_early_fees!(membership, period:)
|
577
|
+
membership.categories.select(&:create_early_fees?).map do |category|
|
578
|
+
fee = membership.owner.build_early_fee(category: category, period: period)
|
579
|
+
next if fee.blank? || fee.persisted?
|
580
|
+
|
581
|
+
puts("Created early fee for #{membership.owner}") if debug?
|
582
|
+
|
583
|
+
fee.save!
|
584
|
+
end
|
585
|
+
end
|
586
|
+
|
587
|
+
def destroy_early_fees!(membership, period:)
|
588
|
+
membership.categories.select(&:create_early_fees?).map do |category|
|
589
|
+
fee = membership.owner.build_early_fee(category: category, period: period)
|
590
|
+
next if fee.blank? || fee.early? || fee.purchased? || fee.deferred?
|
591
|
+
|
592
|
+
puts("Destroyed early fee for #{membership.owner}") if debug?
|
593
|
+
|
594
|
+
fee.destroy!
|
595
|
+
end
|
596
|
+
end
|
597
|
+
|
539
598
|
def create_late_fees!(membership, period:)
|
540
599
|
membership.categories.select(&:create_late_fees?).map do |category|
|
541
600
|
fee = membership.owner.build_late_fee(category: category, period: period)
|
@@ -548,7 +607,6 @@ module EffectiveMembershipsRegistrar
|
|
548
607
|
end
|
549
608
|
|
550
609
|
def create_not_in_good_standing!(membership, period:)
|
551
|
-
return unless Time.zone.now.beginning_of_day == not_in_good_standing_date(period: period).beginning_of_day
|
552
610
|
return unless membership.categories.any?(&:create_not_in_good_standing?)
|
553
611
|
|
554
612
|
membership.owner.update_membership_status!
|
data/app/models/effective/fee.rb
CHANGED
@@ -92,6 +92,11 @@ module Effective
|
|
92
92
|
title.presence || default_title()
|
93
93
|
end
|
94
94
|
|
95
|
+
def early?
|
96
|
+
return false if purchased?
|
97
|
+
EffectiveMemberships.Registrar.early_fee_date_range(period: period).cover?(Time.zone.now)
|
98
|
+
end
|
99
|
+
|
95
100
|
def late?
|
96
101
|
return false if late_on.blank?
|
97
102
|
return false if purchased?
|
@@ -144,10 +149,6 @@ module Effective
|
|
144
149
|
['Prorated', 'Renewal'].include?(fee_type)
|
145
150
|
end
|
146
151
|
|
147
|
-
def renewal_fee?
|
148
|
-
fee_type == 'Renewal'
|
149
|
-
end
|
150
|
-
|
151
152
|
def custom_fee?
|
152
153
|
EffectiveMemberships.custom_fee_types.include?(fee_type)
|
153
154
|
end
|
@@ -306,7 +306,7 @@ module Effective
|
|
306
306
|
|
307
307
|
# Otherwise build fees right now
|
308
308
|
EffectiveMemberships.Registrar.delete_fees!(self)
|
309
|
-
EffectiveMemberships.Registrar.create_fees!(self, period: period)
|
309
|
+
EffectiveMemberships.Registrar.create_fees!(self, period: period, force: true)
|
310
310
|
|
311
311
|
true
|
312
312
|
end
|
@@ -15,5 +15,13 @@ module Effective
|
|
15
15
|
Time.zone.local(period.year, 3, 1) # Membership are Not In Good Standing after March 1st
|
16
16
|
end
|
17
17
|
|
18
|
+
def early_fee_date(period:)
|
19
|
+
Time.zone.local(period.year - 1, 12, 1) # Fees roll over every December 1st
|
20
|
+
end
|
21
|
+
|
22
|
+
def early_fee_end_date(period:)
|
23
|
+
Time.zone.local(period.year - 1, 12, 31) # Early fees are destroyed on December 31st
|
24
|
+
end
|
25
|
+
|
18
26
|
end
|
19
27
|
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
%h3= ets('effective_memberships.fees.early')
|
2
|
+
|
3
|
+
= f.check_box :create_early_fees, label: "Yes, #{ets('effective_memberships.fees.early')} should be created"
|
4
|
+
|
5
|
+
= f.show_if(:create_early_fees, true) do
|
6
|
+
- period = EffectiveMemberships.Registrar.current_period
|
7
|
+
- date = EffectiveMemberships.Registrar.early_fee_date(period: period)
|
8
|
+
- end_date = EffectiveMemberships.Registrar.early_fee_end_date(period: period)
|
9
|
+
|
10
|
+
%p Charged to members, between #{date.strftime('%B %e')} and #{end_date.strftime('%B %e')}, with outstanding renewal dues.
|
11
|
+
|
12
|
+
.row
|
13
|
+
.col-md-3
|
14
|
+
= f.price_field :early_fee, hint: 'Expecting a price less than zero. Please enter the early fee discount from the regular price'
|
@@ -1,5 +1,6 @@
|
|
1
|
-
%h3
|
2
|
-
|
1
|
+
%h3= ets('effective_memberships.fees.late')
|
2
|
+
|
3
|
+
= f.check_box :create_late_fees, label: "Yes, #{ets('effective_memberships.fees.late')} should be created"
|
3
4
|
|
4
5
|
= f.show_if(:create_late_fees, true) do
|
5
6
|
- period = EffectiveMemberships.Registrar.current_period
|
@@ -7,4 +8,4 @@
|
|
7
8
|
|
8
9
|
%p Charged to members, on #{date.strftime('%B %e')}, with outstanding renewal dues or other fees.
|
9
10
|
.row
|
10
|
-
.col-3= f.price_field :late_fee
|
11
|
+
.col-md-3= f.price_field :late_fee
|
@@ -1,5 +1,5 @@
|
|
1
|
-
%h3
|
2
|
-
= f.check_box :create_renewal_fees, label:
|
1
|
+
%h3= ets('effective_memberships.fees.renewal')
|
2
|
+
= f.check_box :create_renewal_fees, label: "Yes, #{ets('effective_memberships.fees.renewal')} should be created"
|
3
3
|
|
4
4
|
= f.show_if(:create_renewal_fees, true) do
|
5
5
|
- date = EffectiveMemberships.Registrar.renewal_fee_date(date: Time.zone.now)
|
@@ -1,7 +1,20 @@
|
|
1
1
|
= effective_form_with(model: [:admin, category], engine: true) do |f|
|
2
2
|
= render('admin/categories/fees_applicant', f: f)
|
3
|
-
|
4
|
-
|
3
|
+
|
4
|
+
- now = Time.zone.now
|
5
|
+
|
6
|
+
- if EffectiveMemberships.Registrar.renewal_fee_date(date: now).present?
|
7
|
+
= render('admin/categories/fees_renewal', f: f)
|
8
|
+
|
9
|
+
- if EffectiveMemberships.Registrar.early_fee_date(period: now).present?
|
10
|
+
= render('admin/categories/fees_early', f: f)
|
11
|
+
|
12
|
+
- if EffectiveMemberships.Registrar.late_fee_date(period: now).present?
|
13
|
+
= render('admin/categories/fees_late', f: f)
|
14
|
+
|
5
15
|
= render('admin/categories/fees_additional', f: f)
|
6
|
-
|
16
|
+
|
17
|
+
- if EffectiveMemberships.Registrar.not_in_good_standing_date(period: now).present?
|
18
|
+
= render('admin/categories/fees_nigs', f: f)
|
19
|
+
|
7
20
|
= f.submit
|
@@ -52,6 +52,9 @@ class CreateEffectiveMemberships < ActiveRecord::Migration[6.0]
|
|
52
52
|
t.boolean :create_renewal_fees, default: false
|
53
53
|
t.integer :renewal_fee
|
54
54
|
|
55
|
+
t.boolean :create_early_fees, default: false
|
56
|
+
t.integer :early_fee
|
57
|
+
|
55
58
|
t.boolean :create_late_fees, default: false
|
56
59
|
t.integer :late_fee
|
57
60
|
|
@@ -58,7 +58,7 @@ module EffectiveMemberships
|
|
58
58
|
end
|
59
59
|
|
60
60
|
def self.fee_types
|
61
|
-
required = ['Applicant', 'Reinstatement', 'Prorated', 'Discount', 'Renewal', 'Late', 'Admin']
|
61
|
+
required = ['Applicant', 'Reinstatement', 'Prorated', 'Discount', 'Renewal', 'Early', 'Late', 'Admin']
|
62
62
|
additional = Array(additional_fee_types)
|
63
63
|
|
64
64
|
(required + additional).uniq.sort
|
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
|
+
version: 0.17.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-04-
|
11
|
+
date: 2023-04-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -367,6 +367,7 @@ files:
|
|
367
367
|
- app/views/admin/applicants/_status.html.haml
|
368
368
|
- app/views/admin/categories/_fees_additional.html.haml
|
369
369
|
- app/views/admin/categories/_fees_applicant.html.haml
|
370
|
+
- app/views/admin/categories/_fees_early.html.haml
|
370
371
|
- app/views/admin/categories/_fees_late.html.haml
|
371
372
|
- app/views/admin/categories/_fees_nigs.html.haml
|
372
373
|
- app/views/admin/categories/_fees_renewal.html.haml
|