effective_memberships 0.4.3 → 0.4.6

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: 1de9f1b37bb81729fcb68686af4113263a847742ef6c763679c74ad75e0633ca
4
- data.tar.gz: 930ceb5ab018318e39331a02d9fbf725129b997c09d5019fc8a3bb03e7e916e4
3
+ metadata.gz: 20a57ae6829f25668b31b12a6a67ca6b0fb648810a6efba12c516a30a969144f
4
+ data.tar.gz: 7b67ecef9d09b021e924b8f8e1a0eb33a741a8a10c8a8912c6aae5aff7fd8545
5
5
  SHA512:
6
- metadata.gz: 3872b4f4e30ec2e6c2f5a3068cfcb2dc5fbcadd557cf1146942f95dfd6663b04d586cf6137990b2742e410e8eac6b36a0d6f05b15ed537ef0a7aec1328b68dcf
7
- data.tar.gz: 8806de111fc454554070e6d93213ce3a6c0f2bb6db1dd0bf4b5d07f4f9d352014be9f1da1ae078d1a0f99653be5613834449fccadebe02e67b55bf1512162848
6
+ metadata.gz: 14d942c1d353f5b439392fe6a5646efd1f5dbd2d74959c65a776394c339e3bbc6aaf794bbd7d352cb192416bd04ea7f97db21931ab88ff48c3f773f4c707322c
7
+ data.tar.gz: 5ac8508dd130358939656a248d568b8257c3f751dafb2a5d9b49e5cc4d036982750e8f33bcae7a9b5be9957eb0b9a9f3e28f942ece9dfb26b7ac83684d36b4f4
@@ -48,7 +48,7 @@ module Admin
48
48
  end
49
49
 
50
50
  if attributes[:user_id].present?
51
- applicants = applicants.where(user_id: attributes[:owner_id])
51
+ applicants = applicants.where(user_id: attributes[:user_id])
52
52
  end
53
53
 
54
54
  if attributes[:organization_id].present?
@@ -17,6 +17,10 @@ module Admin
17
17
  col :tax_exempt
18
18
  col :qb_item_name, visible: false
19
19
 
20
+ col :create_renewal_fees, visible: false
21
+ col :create_late_fees, visible: false
22
+ col :create_bad_standing, visible: false
23
+
20
24
  col :category_type, search: EffectiveMemberships.Category.category_types
21
25
 
22
26
  col :optional_applicant_wizard_steps, label: 'Applicant Steps'
@@ -1,7 +1,12 @@
1
1
  module Admin
2
2
  class EffectiveOrganizationsDatatable < Effective::Datatable
3
- datatable do
3
+ filters do
4
+ scope :unarchived, label: 'All'
5
+ scope :members
6
+ scope :archived
7
+ end
4
8
 
9
+ datatable do
5
10
  col :updated_at, visible: false
6
11
  col :created_at, visible: false
7
12
 
@@ -11,16 +16,54 @@ module Admin
11
16
  col :category, search: categories
12
17
  end
13
18
 
14
- col :title
19
+ col(:to_s, label: 'Organization', sql_column: true, action: :edit)
20
+ .search do |collection, term|
21
+ collection.where(id: effective_resource.search_any(term))
22
+ end.sort do |collection, direction|
23
+ collection.order(title: direction)
24
+ end
25
+
26
+ col :title, visible: false
27
+
28
+ col 'membership.joined_on'
29
+ col 'membership.fees_paid_through_period', label: 'Fees Paid Through'
30
+ col 'membership.categories'
15
31
 
16
32
  col :representatives_count
17
33
  col :representatives
18
34
 
35
+ col :email, visible: false
36
+
37
+ col :address1, visible: false do |organization|
38
+ organization.billing_address&.address1
39
+ end
40
+ col :address2, visible: false do |organization|
41
+ organization.billing_address&.address2
42
+ end
43
+ col :city, visible: false do |organization|
44
+ organization.billing_address&.city
45
+ end
46
+ col :state_code, label: 'Prov', visible: false do |organization|
47
+ organization.billing_address&.state_code
48
+ end
49
+ col :postal_code, label: 'Postal', visible: false do |organization|
50
+ organization.billing_address&.postal_code
51
+ end
52
+ col :country_code, label: 'Country', visible: false do |organization|
53
+ organization.billing_address&.country_code
54
+ end
55
+
56
+ col :phone, visible: false
57
+ col :fax, visible: false
58
+ col :website, visible: false
59
+ col :category, visible: false
60
+ col :notes, visible: false
61
+
19
62
  actions_col
20
63
  end
21
64
 
22
65
  collection do
23
- EffectiveMemberships.Organization.deep.all
66
+ EffectiveMemberships.Organization.deep.left_joins(:membership).includes(membership: :membership_categories)
24
67
  end
25
68
 
26
69
  def categories
@@ -110,11 +110,6 @@ module EffectiveMembershipsCategory
110
110
  .or(where(can_apply_restricted: true))
111
111
  }
112
112
 
113
- # For the create_fees rake task
114
- scope :create_renewal_fees, -> { where(create_renewal_fees: true) }
115
- scope :create_late_fees, -> { where(create_late_fees: true) }
116
- scope :create_bad_standing, -> { where(create_bad_standing: true) }
117
-
118
113
  validates :title, presence: true, uniqueness: true
119
114
  validates :category_type, presence: true
120
115
  validates :position, presence: true
@@ -23,6 +23,7 @@ module EffectiveMembershipsOrganization
23
23
  effective_memberships_owner
24
24
 
25
25
  acts_as_addressable :billing # effective_addresses
26
+ acts_as_archived unless respond_to?(:acts_as_archived?)
26
27
  log_changes(except: [:representatives, :users]) if respond_to?(:log_changes)
27
28
 
28
29
  # rich_text_body
@@ -160,9 +160,21 @@ module EffectiveMembershipsOwner
160
160
  fee
161
161
  end
162
162
 
163
+ # These should be singular fees anyway.
164
+ def membership_period_fee(category:, period:, except: nil)
165
+ raise('expected except to be a string like Renewal') if except.present? && !except.kind_of?(String)
166
+ fees.find { |fee| fee.membership_period_fee? && fee.period == period && fee.category_id == category.id && fee.category_type == category.class.name && (except.blank? || fee.fee_type != except) }
167
+ end
168
+
163
169
  def build_renewal_fee(category:, period:, late_on: nil, bad_standing_on: nil)
164
170
  raise('must have an existing membership') unless membership.present?
165
171
 
172
+ # Sanity check.
173
+ # If there's already a purchased or unpurchased Prorated (or other membership period advancing fee) in this period
174
+ # We shouldn't be building renewal fees for the same period a prorated fee is purcahsed in
175
+ prorated = membership_period_fee(category: category, period: period, except: 'Renewal')
176
+ raise('must not have an existing membership_period (prorated) fee in this period') if prorated.present?
177
+
166
178
  fee = fees.find { |fee| fee.fee_type == 'Renewal' && fee.period == period && fee.category_id == category.id && fee.category_type == category.class.name }
167
179
  return fee if fee&.purchased?
168
180
 
@@ -33,6 +33,15 @@ module EffectiveMembershipsRegistrar
33
33
  raise('to be implemented by app registrar')
34
34
  end
35
35
 
36
+ # Should two could be overridden if we do non 1-year periods
37
+ def advance_period(period:, number:)
38
+ period.advance(years: number).beginning_of_year
39
+ end
40
+
41
+ def period_end_on(date:)
42
+ period(date: date).end_of_year
43
+ end
44
+
36
45
  def assign!(owner, categories:, date: nil, number: nil)
37
46
  categories = Array(categories)
38
47
 
@@ -243,18 +252,41 @@ module EffectiveMembershipsRegistrar
243
252
  period(date: Time.zone.now)
244
253
  end
245
254
 
255
+ def last_period
256
+ advance_period(period: current_period, number: -1)
257
+ end
258
+
246
259
  # Returns a date of Jan 1, Year
247
260
  def period(date:)
248
261
  cutoff = renewal_fee_date(date: date) # period_end_on
249
- period = (date < cutoff) ? date.beginning_of_year : date.advance(years: 1).beginning_of_year
262
+ period = (date < cutoff) ? advance_period(period: date, number: 0) : advance_period(period: date, number: 1)
250
263
  period.to_date
251
264
  end
252
265
 
253
- def period_end_on(date:)
254
- period(date: date).end_of_year
266
+ # This is only used for a form collection on admin memberships
267
+ def periods(from:, to: nil)
268
+ to ||= Time.zone.now
269
+
270
+ raise('expected to date') unless to.respond_to?(:strftime)
271
+ raise('expected from date') unless from.respond_to?(:strftime)
272
+
273
+ from = period(date: from)
274
+ to = period(date: to)
275
+
276
+ retval = []
277
+
278
+ loop do
279
+ retval << from
280
+ from = advance_period(period: from, number: 1)
281
+ break if from > to
282
+ end
283
+
284
+ retval
255
285
  end
256
286
 
287
+
257
288
  # This is intended to be run once per day in a rake task
289
+ # rake effective_memberships:create_fees
258
290
  # Create Renewal and Late fees
259
291
  def create_fees!(period: nil, late_on: nil, bad_standing_on: nil)
260
292
  # The current period, based on Time.zone.now
@@ -263,13 +295,17 @@ module EffectiveMembershipsRegistrar
263
295
  bad_standing_on ||= bad_standing_date(period: period)
264
296
 
265
297
  # Create Renewal Fees
266
- Effective::Membership.create_renewal_fees(period).find_each do |membership|
267
-
298
+ Effective::Membership.deep.with_unpaid_fees_through(period).find_each do |membership|
268
299
  membership.categories.select(&:create_renewal_fees?).map do |category|
300
+ existing = membership.owner.membership_period_fee(category: category, period: period, except: 'Renewal')
301
+ next if existing.present? # This might be an existing Prorated fee
302
+
269
303
  fee = membership.owner.build_renewal_fee(category: category, period: period, late_on: late_on, bad_standing_on: bad_standing_on)
270
304
  raise("expected build_renewal_fee to return a fee for period #{period}") unless fee.kind_of?(Effective::Fee)
271
305
  next if fee.purchased?
272
306
 
307
+ puts("Created renewal fee for #{membership.owner}") if fee.new_record? && !Rails.env.test?
308
+
273
309
  fee.save!
274
310
  end
275
311
  end
@@ -277,7 +313,7 @@ module EffectiveMembershipsRegistrar
277
313
  GC.start
278
314
 
279
315
  # Create Late Fees
280
- Effective::Membership.create_late_fees(period).find_each do |membership|
316
+ Effective::Membership.deep.with_unpaid_fees_through(period).find_each do |membership|
281
317
  membership.categories.select(&:create_late_fees?).map do |category|
282
318
  fee = membership.owner.build_late_fee(category: category, period: period)
283
319
  next if fee.blank? || fee.purchased?
@@ -42,18 +42,6 @@ module Effective
42
42
  .or(where(fees_paid_period: nil))
43
43
  }
44
44
 
45
- scope :create_renewal_fees, -> (period = nil) {
46
- deep.with_unpaid_fees_through(period).where.not(fees_paid_period: nil) # Must have purchased a Prorated or Renewal Fee before
47
- }
48
-
49
- scope :create_late_fees, -> (period = nil) {
50
- deep.with_unpaid_fees_through(period).where.not(fees_paid_period: nil) # Must have purchased a Prorated or Renewal Fee before
51
- }
52
-
53
- scope :create_bad_standing, -> (period = nil) {
54
- deep.with_unpaid_fees_through(period).where.not(fees_paid_period: nil) # Must have purchased a Prorated or Renewal Fee before
55
- }
56
-
57
45
  before_validation do
58
46
  self.registration_on ||= joined_on
59
47
  end
@@ -134,5 +122,18 @@ module Effective
134
122
  fees_paid_period == EffectiveMemberships.Registrar.current_period
135
123
  end
136
124
 
125
+ def change_fees_paid_period
126
+ fees_paid_period
127
+ end
128
+
129
+ def change_fees_paid_period=(date)
130
+ date = (date.respond_to?(:strftime) ? date : Date.parse(date))
131
+
132
+ period = EffectiveMemberships.Registrar.period(date: date)
133
+ period_end_on = EffectiveMemberships.Registrar.period_end_on(date: date)
134
+
135
+ assign_attributes(fees_paid_period: period, fees_paid_through_period: period_end_on)
136
+ end
137
+
137
138
  end
138
139
  end
@@ -17,6 +17,12 @@
17
17
  = f.date_field :registration_on, label: 'Registered', hint: 'When the membership category last changed'
18
18
  = f.text_field :number, hint: 'The membership number. Must be unique.'
19
19
 
20
+ - registrar = EffectiveMemberships.Registrar
21
+ - periods = registrar.periods(from: f.object.joined_on)
22
+ - collection = periods.reverse.map { |period| [registrar.period_end_on(date: period), period] }
23
+
24
+ = f.select :change_fees_paid_period, collection, label: 'Fees Paid Through', hint: 'Which period this user has fees paid through. Can change how renewal fees are created.'
25
+
20
26
  %p.text-muted To update the current membership categories, use the 'Assign' or 'Reclassify' actions below
21
27
 
22
28
  = f.submit 'Update Membership', border: false, center: true, 'data-confirm': "Really update #{f.object.owner}?"
@@ -2,5 +2,3 @@
2
2
 
3
3
  - if categories.present?
4
4
  = f.select :category, categories, required: true
5
-
6
- = f.text_field :title
@@ -5,7 +5,7 @@
5
5
  - if organization.persisted?
6
6
  - if can?(:index, Effective::Membership)
7
7
  = tab 'Membership' do
8
- = render 'admin/registrar_actions/form', owner: organization
8
+ = render 'admin/memberships/form', owner: organization
9
9
 
10
10
  = tab 'Representatives' do
11
11
  = render_datatable(Admin::EffectiveRepresentativesDatatable.new(organization: organization), inline: true, namespace: :admin)
@@ -18,10 +18,6 @@
18
18
  = tab 'Fee Payments' do
19
19
  = render_inline_datatable(Admin::EffectiveFeePaymentsDatatable.new(organization: organization))
20
20
 
21
- - if can?(:index, Effective::MembershipHistory)
22
- = tab 'History' do
23
- = render_datatable(Admin::EffectiveMembershipHistoriesDatatable.new(owner: organization))
24
-
25
21
  - if can?(:index, Effective::Order)
26
22
  = tab 'Orders' do
27
23
  = render_datatable(Admin::EffectiveOrdersDatatable.new(user: organization))
@@ -3,9 +3,7 @@
3
3
  .col-sm-6
4
4
  %h2 Demographics
5
5
  = render 'admin/organizations/fields', f: f
6
-
7
- %h2 Billing Address
8
- = effective_address_fields(f, :billing)
6
+ = render 'organizations/fields_demographics', f: f
9
7
 
10
8
  .col-sm-6
11
9
  %h2 Membership
@@ -1,3 +1,3 @@
1
1
  module EffectiveMemberships
2
- VERSION = '0.4.3'
2
+ VERSION = '0.4.6'
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.4.3
4
+ version: 0.4.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Code and Effect
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-03-30 00:00:00.000000000 Z
11
+ date: 2022-04-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails