dm_event 4.2.3.2 → 4.2.3.3
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 +4 -4
- data/app/controllers/dm_event/admin/workshops_controller.rb +3 -1
- data/app/models/registration.rb +41 -17
- data/app/models/workshop.rb +1 -1
- data/app/models/workshop_price.rb +46 -12
- data/app/views/dm_event/admin/registrations/_form.html.erb +73 -29
- data/app/views/dm_event/admin/workshops/financials.html.erb +13 -6
- data/spec/dummy/log/development.log +16989 -0
- data/spec/dummy/log/test.log +53876 -0
- data/spec/models/registration_spec.rb +120 -15
- data/spec/models/workshop_price_spec.rb +137 -0
- metadata +8 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 166674962a59997e15cc1dd82e97776ea718d6e7
|
4
|
+
data.tar.gz: 14dfe6801c934c2d49f64ee532760138d48e2aac
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2d4c563433c1131e20a8cad5bc2768e033d9dbf3bc94f7f1457d517511a144e2d878c5b8c6e96d1660ee5d223e4e5b022af140adbea611e66041be3e50ed7ba3
|
7
|
+
data.tar.gz: e9f9c5a5fbfac90c1fe75e4363dfedb2acf728f83f080780c9341c27fccec84174fcd84e37f60096871884c7d336788e0bfdde5c13c170cca030ce1a526a4baf
|
@@ -93,7 +93,9 @@ class DmEvent::Admin::WorkshopsController < DmEvent::Admin::AdminController
|
|
93
93
|
def financials
|
94
94
|
authorize! :manage_event_finances, @workshop
|
95
95
|
@financials = @workshop.financial_details
|
96
|
-
@payments
|
96
|
+
@payments = PaymentHistory.where(owner_type: 'Registration', owner_id: @workshop.registrations.pluck(:id)).includes(:user_profile, owner: [:user_profile])
|
97
|
+
@unpaid = @workshop.registrations.unpaid.includes(:user_profile, :workshop_price)
|
98
|
+
@unpaid = @unpaid.to_a.delete_if {|i| i.payment_owed.zero?}.sort_by {|i| i.full_name.downcase}
|
97
99
|
end
|
98
100
|
|
99
101
|
# Generate a list of all outstanding balances across all workshops
|
data/app/models/registration.rb
CHANGED
@@ -36,6 +36,7 @@ class Registration < ActiveRecord::Base
|
|
36
36
|
after_initialize :create_uuid
|
37
37
|
before_create :set_currency
|
38
38
|
after_create :set_receipt_code
|
39
|
+
before_save :clear_reminder_sent_on, if: :amount_paid_cents_changed?
|
39
40
|
|
40
41
|
validates_uniqueness_of :uuid
|
41
42
|
validates_presence_of :workshop_price_id, if: Proc.new { |reg| reg.workshop.workshop_prices.size > 0}
|
@@ -48,6 +49,12 @@ class Registration < ActiveRecord::Base
|
|
48
49
|
|
49
50
|
private
|
50
51
|
|
52
|
+
# when a payment is made, we want reset whether a payment reminder has been sent
|
53
|
+
#------------------------------------------------------------------------------
|
54
|
+
def clear_reminder_sent_on
|
55
|
+
self.payment_reminder_sent_on = nil
|
56
|
+
end
|
57
|
+
|
51
58
|
# the uuid is used to provide a private url to a customer so that they can access
|
52
59
|
# their registration if not logged in. This is particularly important when
|
53
60
|
# a customer registers without having a user account.
|
@@ -110,12 +117,13 @@ public
|
|
110
117
|
end
|
111
118
|
|
112
119
|
# suggested amount of next payment.
|
113
|
-
#
|
120
|
+
# when it's recurring, they payment should be whatever is needed to bring their
|
121
|
+
# payment plan up to date
|
114
122
|
#------------------------------------------------------------------------------
|
115
123
|
def payment_owed
|
116
|
-
if workshop_price
|
117
|
-
|
118
|
-
|
124
|
+
if workshop_price && workshop_price.recurring_payments?
|
125
|
+
to_pay = recurring_what_should_be_paid_by_now(0) - amount_paid
|
126
|
+
to_pay.negative? ? Money.new(0, workshop_price.price.currency) : to_pay
|
119
127
|
else
|
120
128
|
balance_owed
|
121
129
|
end
|
@@ -167,25 +175,43 @@ public
|
|
167
175
|
def unpaid?
|
168
176
|
self.accepted? && self.archived_on == nil
|
169
177
|
end
|
170
|
-
|
178
|
+
|
171
179
|
# Is it time to send a payment reminder?
|
172
|
-
# Due first 7 days after inital registration. Then every 14 days after that
|
180
|
+
# Due first 7 days after inital registration (or a payment period). Then every 14 days after that
|
173
181
|
#------------------------------------------------------------------------------
|
174
182
|
def payment_reminder_due?
|
175
183
|
if preferred_payment_reminder_hold_until.nil? || preferred_payment_reminder_hold_until < Time.now
|
176
184
|
time_period = self.payment_reminder_sent_on.nil? ? (self.created_at + 7.days) : (self.payment_reminder_sent_on + 14.days)
|
177
|
-
|
185
|
+
past_due?(7) ? time_period < Time.now : false
|
186
|
+
else
|
187
|
+
false
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
# past due means they haven't paid what they should have paid by now
|
192
|
+
#------------------------------------------------------------------------------
|
193
|
+
def past_due?(grace_period_in_days = 7)
|
194
|
+
return false if !balance_owed.positive?
|
195
|
+
if workshop_price.recurring_payments?
|
196
|
+
return amount_paid < recurring_what_should_be_paid_by_now(grace_period_in_days)
|
197
|
+
else
|
198
|
+
return Date.today > (self.created_at + grace_period_in_days.days)
|
178
199
|
end
|
200
|
+
end
|
179
201
|
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
# last_payment = payment_histories.order('created_on').last
|
185
|
-
# if workshop_price.recurring?
|
186
|
-
# if
|
202
|
+
#------------------------------------------------------------------------------
|
203
|
+
def recurring_what_should_be_paid_by_now(grace_period_in_days = 7)
|
204
|
+
entry = workshop_price.specific_payment_schedule(self.created_at + grace_period_in_days.days, Date.today)
|
205
|
+
entry ? entry[:total_due] : 0
|
187
206
|
end
|
188
|
-
|
207
|
+
|
208
|
+
# date when the most recent payment was due
|
209
|
+
#------------------------------------------------------------------------------
|
210
|
+
def last_payment_due_on
|
211
|
+
entry = workshop_price.specific_payment_schedule(self.created_at, Date.today)
|
212
|
+
entry ? entry[:due_on] : self.created_at.to_date
|
213
|
+
end
|
214
|
+
|
189
215
|
# Setup the columns for exporting data as csv.
|
190
216
|
#------------------------------------------------------------------------------
|
191
217
|
def self.csv_columns(workshop)
|
@@ -202,9 +228,7 @@ public
|
|
202
228
|
column_definitions << ["State", "item.state.capitalize"]
|
203
229
|
column_definitions << ["Zipcode", "item.zipcode"]
|
204
230
|
column_definitions << ["Country", "item.country.code"]
|
205
|
-
|
206
231
|
column_definitions << ['Registered on', 'item.created_at.to_date', 75, {type: 'DateTime', numberformat: 'd mmm, yyyy'}]
|
207
|
-
|
208
232
|
column_definitions << ["Price", "item.workshop_price.price.to_f", nil, {type: 'Number', numberformat: '#,##0.00'}]
|
209
233
|
column_definitions << ["Price Description", "item.workshop_price.price_description"]
|
210
234
|
column_definitions << ["Price Sub Descr", "item.workshop_price.sub_description"]
|
data/app/models/workshop.rb
CHANGED
@@ -180,7 +180,7 @@ class Workshop < ActiveRecord::Base
|
|
180
180
|
success = failed = 0
|
181
181
|
unpaid_list = ( registration_id == 'all' ? registrations.unpaid : registrations.unpaid.where(id: registration_id) )
|
182
182
|
unpaid_list.each do |registration|
|
183
|
-
if registration.payment_reminder_due? || registration_id != 'all'
|
183
|
+
if (registration.payment_reminder_due? && registration.payment_owed.positive?) || registration_id != 'all'
|
184
184
|
email = PaymentReminderMailer.payment_reminder(registration).deliver_now
|
185
185
|
if email
|
186
186
|
registration.update_attribute(:payment_reminder_sent_on, Time.now)
|
@@ -45,7 +45,7 @@ class WorkshopPrice < ActiveRecord::Base
|
|
45
45
|
# Call this method on the attributes before passing into new() or update_attributes()
|
46
46
|
#------------------------------------------------------------------------------
|
47
47
|
def self.prepare_prices(attributes = {})
|
48
|
-
attributes['price'] = attributes['price'].to_money(attributes['price_currency'])
|
48
|
+
attributes['price'] = attributes['price'].to_money(attributes['price_currency']) if attributes['price'].present? && attributes['price_currency'].present?
|
49
49
|
attributes['alt1_price'] = attributes['alt1_price'].to_money(attributes['alt1_price_currency']) if attributes['alt1_price'].present? && attributes['alt1_price_currency'].present?
|
50
50
|
attributes['alt2_price'] = attributes['alt2_price'].to_money(attributes['alt2_price_currency']) if attributes['alt2_price'].present? && attributes['alt2_price_currency'].present?
|
51
51
|
return attributes
|
@@ -53,14 +53,14 @@ class WorkshopPrice < ActiveRecord::Base
|
|
53
53
|
|
54
54
|
#------------------------------------------------------------------------------
|
55
55
|
def visible?
|
56
|
-
!(disabled? || (!valid_starting_on.nil? && valid_starting_on >
|
56
|
+
!(disabled? || (!valid_starting_on.nil? && valid_starting_on > Date.today) || (!valid_until.nil? && valid_until < Date.today))
|
57
57
|
end
|
58
58
|
|
59
59
|
# If the total_available is nil, then there are unlimited tickets to be sold.
|
60
60
|
# Otherwise, check if we have sold out
|
61
61
|
#------------------------------------------------------------------------------
|
62
62
|
def sold_out?(num_sold)
|
63
|
-
|
63
|
+
total_available.nil? ? false : (num_sold >= total_available)
|
64
64
|
end
|
65
65
|
|
66
66
|
#------------------------------------------------------------------------------
|
@@ -78,12 +78,41 @@ class WorkshopPrice < ActiveRecord::Base
|
|
78
78
|
def recurring_payments?
|
79
79
|
recurring_number.to_i > 1
|
80
80
|
end
|
81
|
-
|
81
|
+
|
82
|
+
# return array of when payments should be made. if `from_date` is specified,
|
83
|
+
# then actual dates are returned. Otherwise number of days
|
84
|
+
#------------------------------------------------------------------------------
|
85
|
+
def payment_schedule(from_date = nil)
|
86
|
+
schedule = []
|
87
|
+
if recurring_payments?
|
88
|
+
(0...recurring_number).each do |period|
|
89
|
+
xdays = period * recurring_period
|
90
|
+
schedule << {due_on: (from_date ? from_date.to_date + xdays.days : xdays),
|
91
|
+
period_payment: payment_price,
|
92
|
+
total_due: (period + 1) * payment_price}
|
93
|
+
end
|
94
|
+
# adjust the last entry
|
95
|
+
schedule.last[:total_due] = price
|
96
|
+
schedule.last[:period_payment] = price - (recurring_number - 1) * payment_price
|
97
|
+
else
|
98
|
+
schedule << {due_on: (from_date ? from_date.to_date : 0), period_payment: payment_price, total_due: payment_price}
|
99
|
+
end
|
100
|
+
schedule
|
101
|
+
end
|
102
|
+
|
103
|
+
# return the payment schedule entry that is before the specified date
|
104
|
+
#------------------------------------------------------------------------------
|
105
|
+
def specific_payment_schedule(from_date, on_date = Date.today)
|
106
|
+
payment_schedule(from_date).reverse.detect {|item| item[:due_on] <= on_date}
|
107
|
+
end
|
108
|
+
|
109
|
+
# return list of currencies used, in a format for a dropdown list
|
110
|
+
# ex: [['USD', 'USD'], ['EUR', 'EUR']]
|
82
111
|
#------------------------------------------------------------------------------
|
83
112
|
def currency_list
|
84
113
|
list = [[price_currency, price_currency]]
|
85
114
|
list << [alt1_price_currency, alt1_price_currency] unless alt1_price_currency.blank?
|
86
|
-
list << [alt2_price_currency,
|
115
|
+
list << [alt2_price_currency, alt2_price_currency] unless alt2_price_currency.blank?
|
87
116
|
return list
|
88
117
|
end
|
89
118
|
|
@@ -95,21 +124,26 @@ class WorkshopPrice < ActiveRecord::Base
|
|
95
124
|
|
96
125
|
# return a bank object filled with the exchange rates, based on the prices.
|
97
126
|
# then you can do: bank.exchange_with(price, 'USD')
|
127
|
+
# note: since JPY doesn't have cents (the price doesn't get multiplied by 100)
|
128
|
+
# then we need to do that in order to calculate the proper exchange rate
|
98
129
|
#------------------------------------------------------------------------------
|
99
130
|
def bank
|
100
131
|
unless @bank
|
101
132
|
@bank = Money::Bank::VariableExchange.new
|
133
|
+
base_cents = price_currency == 'JPY' ? (price_cents.to_f * 100) : price_cents.to_f
|
102
134
|
unless alt1_price_currency.blank?
|
103
|
-
|
104
|
-
@bank.add_rate(
|
135
|
+
alt1_cents = alt1_price_currency == 'JPY' ? (alt1_price_cents.to_f * 100) : alt1_price_cents.to_f
|
136
|
+
@bank.add_rate(price_currency, alt1_price_currency, alt1_cents / base_cents)
|
137
|
+
@bank.add_rate(alt1_price_currency, price_currency, base_cents / alt1_cents)
|
105
138
|
end
|
106
139
|
unless alt2_price_currency.blank?
|
107
|
-
|
108
|
-
@bank.add_rate(
|
140
|
+
alt2_cents = alt2_price_currency == 'JPY' ? (alt2_price_cents.to_f * 100) : alt2_price_cents.to_f
|
141
|
+
@bank.add_rate(price_currency, alt2_price_currency, alt2_cents / base_cents)
|
142
|
+
@bank.add_rate(alt2_price_currency, price_currency, base_cents / alt2_cents)
|
109
143
|
end
|
110
|
-
|
111
|
-
@bank.add_rate(alt1_price_currency, alt2_price_currency,
|
112
|
-
@bank.add_rate(alt2_price_currency, alt1_price_currency,
|
144
|
+
if !alt1_price_currency.blank? && !alt2_price_currency.blank?
|
145
|
+
@bank.add_rate(alt1_price_currency, alt2_price_currency, alt2_cents / alt1_cents)
|
146
|
+
@bank.add_rate(alt2_price_currency, alt1_price_currency, alt1_cents / alt2_cents)
|
113
147
|
end
|
114
148
|
end
|
115
149
|
return @bank
|
@@ -38,6 +38,8 @@
|
|
38
38
|
<div class="col-md-6 col-sm-6">
|
39
39
|
<% if @registration.workshop_price %>
|
40
40
|
<dl class="block">
|
41
|
+
<dt class="text-info">Registered On</dt>
|
42
|
+
<dd><%= format_date(@registration.created_at) %></dd>
|
41
43
|
<dt class="text-info">Price</dt>
|
42
44
|
<dd><%= price_details(@registration.workshop_price) %></dd>
|
43
45
|
<% if @registration.payment_comment %>
|
@@ -106,13 +108,17 @@
|
|
106
108
|
</tr>
|
107
109
|
<% if @registration.payment_owed.positive? %>
|
108
110
|
<tr class="section">
|
109
|
-
<th>
|
111
|
+
<th>Payment Owed
|
110
112
|
<% if @registration.workshop_price.recurring_payments? %>
|
111
113
|
<span style="font-weight: normal"></br>On a payment plan</span>
|
112
114
|
<% end %>
|
113
115
|
</th>
|
114
116
|
<td class="text-info"><%= @registration.payment_owed.format %></td>
|
115
117
|
</tr>
|
118
|
+
<tr>
|
119
|
+
<th>Payment Due On</th>
|
120
|
+
<td class="text-info"><%= format_date(@registration.last_payment_due_on) %></td>
|
121
|
+
</tr>
|
116
122
|
<% end %>
|
117
123
|
</table>
|
118
124
|
</div>
|
@@ -171,39 +177,77 @@
|
|
171
177
|
|
172
178
|
<%#--- Payments Tab %>
|
173
179
|
<div class="tab-pane fade" id="payment_tab">
|
174
|
-
|
175
|
-
<
|
176
|
-
|
180
|
+
<div class="row">
|
181
|
+
<div class="col-md-9 col-sm-9">
|
182
|
+
<%= subsection title: 'Recorded Payments' do %>
|
183
|
+
<table class="table table-condensed table-gradient table-hover" style="margin-bottom: 20px;">
|
184
|
+
<thead>
|
185
|
+
<tr>
|
186
|
+
<th width="100">Date</th>
|
187
|
+
<th>Description</th>
|
188
|
+
<th width="75">Paid</th>
|
189
|
+
<th width="100">Method</th>
|
190
|
+
<th width="18"><%= icons(:edit) %></th>
|
191
|
+
</tr>
|
192
|
+
</thead>
|
193
|
+
<tbody>
|
194
|
+
<% @registration.payment_histories.order('created_on ASC').each do |payment| %>
|
195
|
+
<tr>
|
196
|
+
<td><%= format_date(payment.payment_date) %></td>
|
197
|
+
<td><%= payment.item_ref %></td>
|
198
|
+
<td><%= payment.total.format(no_cents_if_whole: true, symbol: true) %></td>
|
199
|
+
<td><%= payment.payment_method %></td>
|
200
|
+
<td>
|
201
|
+
<% if payment.user_profile #--- only allow editing of manual payments %>
|
202
|
+
<%= link_to(icons('icon-pencil3'), '#', data: { toggle: "modal", target: "#edit_payment_#{payment.id}"}, title: 'Edit Payment') %>
|
203
|
+
<% end %>
|
204
|
+
</td>
|
205
|
+
</tr>
|
206
|
+
<% end %>
|
207
|
+
</tbody>
|
208
|
+
</table>
|
209
|
+
<%= link_to 'Add Payment', '#', data: { toggle: "modal", target: "#enter_new_payment"}, title: 'Add Payment', class: "btn btn-xs btn-primary" %>
|
210
|
+
<%= link_to 'Customer Payment Page', @registration.payment_url, target: '_blank', class: 'btn btn-xs btn-default' %>
|
211
|
+
<% if @registration.payment_owed.positive? %>
|
212
|
+
Next payment should be: <span class="text-info"><%= @registration.payment_owed.format %></span>
|
213
|
+
<% end %>
|
214
|
+
<% end %>
|
215
|
+
</div>
|
216
|
+
<div class="col-md-3 col-sm-3">
|
217
|
+
<table class="accounting" style="width: 100%">
|
177
218
|
<tr>
|
178
|
-
<th
|
179
|
-
<
|
180
|
-
<th width="75">Paid</th>
|
181
|
-
<th width="100">Method</th>
|
182
|
-
<th width="18"><%= icons(:edit) %></th>
|
219
|
+
<th>Price</th>
|
220
|
+
<td><%= @registration.price.format %></td>
|
183
221
|
</tr>
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
222
|
+
<tr>
|
223
|
+
<th>Discount</th>
|
224
|
+
<td class="text-danger"> - <%= @registration.discount.format %></td>
|
225
|
+
</tr>
|
226
|
+
<tr class="section">
|
227
|
+
<th>Total</th>
|
228
|
+
<td><strong><%= @registration.discounted_price.format %></strong></td>
|
229
|
+
</tr>
|
230
|
+
<tr>
|
231
|
+
<th>Paid</th>
|
232
|
+
<td class="text-success"><%= @registration.amount_paid.format %></td>
|
233
|
+
</tr>
|
234
|
+
<% if @registration.payment_owed.positive? %>
|
235
|
+
<tr class="section">
|
236
|
+
<th>Payment Owed
|
237
|
+
<% if @registration.workshop_price.recurring_payments? %>
|
238
|
+
<span style="font-weight: normal"></br>On a payment plan</span>
|
195
239
|
<% end %>
|
196
|
-
</
|
240
|
+
</th>
|
241
|
+
<td class="text-info"><%= @registration.payment_owed.format %></td>
|
242
|
+
</tr>
|
243
|
+
<tr>
|
244
|
+
<th>Payment Due On</th>
|
245
|
+
<td class="text-info"><%= format_date(@registration.last_payment_due_on) %></td>
|
197
246
|
</tr>
|
198
247
|
<% end %>
|
199
|
-
</
|
200
|
-
</
|
201
|
-
|
202
|
-
<%= link_to 'Customer Payment Page', @registration.payment_url, target: '_blank', class: 'btn btn-xs btn-default' %>
|
203
|
-
<% if @registration.payment_owed.positive? %>
|
204
|
-
Next payment should be: <span class="text-info"><%= @registration.payment_owed.format %></span>
|
205
|
-
<% end %>
|
206
|
-
<% end %>
|
248
|
+
</table>
|
249
|
+
</div>
|
250
|
+
</div>
|
207
251
|
|
208
252
|
<%= subsection title: 'Payment Reminders' do %>
|
209
253
|
<%= simple_form_for @registration, url: admin_registration_path,
|
@@ -85,27 +85,34 @@
|
|
85
85
|
</div>
|
86
86
|
</div>
|
87
87
|
|
88
|
-
<% unpaid = @workshop.registrations.unpaid.order('payment_reminder_sent_on ASC') %>
|
89
88
|
<% toolbar = toolbar_btn('Send Payment Reminders', send_payment_reminder_emails_admin_workshop_path(@workshop, registration_id: :all), class: 'btn btn-xs btn-info', method: :patch, data: {confirm: "Are you sure you wish to send a reminder email to those eligible?"}) %>
|
90
|
-
<%= panel body: false, title: "#{unpaid.count} Unpaid Participants", toolbar: toolbar do %>
|
89
|
+
<%= panel body: false, title: "#{@unpaid.count} Unpaid Participants", toolbar: toolbar do %>
|
90
|
+
<div class="panel-body">
|
91
|
+
<p>Shows those that have missed their payment (either a full payment, or a recurring payment). If they have made all the payments
|
92
|
+
up to this point in time, they are not listed.</p>
|
93
|
+
<p>You can send them a payment reminder email at any time using the <em>Send</em> button. A line is marked in blue if we have detected that
|
94
|
+
they should be sent a payment reminder. <em>Send Payment Reminders</em> will send the email to all persons marked in blue.</p>
|
95
|
+
</div>
|
91
96
|
<table class="table table-bordered table-condensed table-striped">
|
92
97
|
<thead>
|
93
98
|
<tr>
|
94
99
|
<th class="receipt_code">Receipt</th>
|
95
100
|
<th class="name">Name</th>
|
96
|
-
<th class="cost">Balance</th>
|
97
|
-
<th class="
|
101
|
+
<th class="cost">Balance Owed</th>
|
102
|
+
<th class="cost">Payment Due</th>
|
103
|
+
<th class="date">Payment Was Due On</th>
|
98
104
|
<th class="date">Reminded</th>
|
99
105
|
<th></th>
|
100
106
|
</tr>
|
101
107
|
</thead>
|
102
108
|
<tbody>
|
103
|
-
<% unpaid.each do |registration| -%>
|
109
|
+
<% @unpaid.each do |registration| -%>
|
104
110
|
<tr>
|
105
111
|
<td class="receipt_code" style="white-space:nowrap"><%= registration.receipt_code %></td>
|
106
112
|
<td class="name"><%= link_to registration.full_name, dm_event.edit_admin_registration_path(registration) %> </td>
|
107
113
|
<td class="cost"><%= registration.balance_owed.format %><%= content_tag(:span, icons('icon-bubble2 inside-content', size: 12), class: 'pull-right') if registration.private_comments.count > 0 %></td>
|
108
|
-
<td class="
|
114
|
+
<td class="cost"><%= registration.payment_owed.format %><%= " <sup>R</sup>".html_safe if registration.try(:workshop_price).try(:recurring_payments?) %></td>
|
115
|
+
<td class="date" style="white-space:nowrap"><%= format_date(registration.last_payment_due_on) %></td>
|
109
116
|
<td class="date" <%= "style='background-color: #B3D4FD;'".html_safe if registration.payment_reminder_due? %>>
|
110
117
|
<% if registration.payment_reminder_sent_on.nil? %>
|
111
118
|
not yet
|