caboose-cms 0.8.34 → 0.8.35
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/assets/javascripts/caboose/admin_edit_invoice.js +55 -19
- data/app/controllers/caboose/invoice_packages_controller.rb +38 -38
- data/app/controllers/caboose/invoices_controller.rb +32 -12
- data/app/controllers/caboose/line_items_controller.rb +18 -13
- data/app/controllers/caboose/users_controller.rb +18 -13
- data/app/mailers/caboose/invoices_mailer.rb +7 -1
- data/app/models/caboose/invoice.rb +67 -59
- data/app/models/caboose/tax_calculator.rb +1 -1
- data/app/views/caboose/invoices_mailer/customer_receipt.html.erb +75 -0
- data/lib/caboose/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e580ca759518da7762c5cc5160d5de30136cad5d
|
4
|
+
data.tar.gz: 11c47056fb135a003a5b437760dfe0e859565231
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1b159c76555d47fb10f9bd58b89c806a8095bbce445a8704e7ee46841c6b057ea2ef5a75f68a1cd165d87e112823a02fbb1375890b883fc047dd9c340cd18d3e
|
7
|
+
data.tar.gz: f79ba2f659c609466058f6f49a341bcc615b447fd59d8d3758639b9079916b596e987ee49c9dfac6f7f334a76525d518d2593abef2b316d4a860a24b9a0da823
|
@@ -79,7 +79,7 @@ InvoiceController.prototype = {
|
|
79
79
|
update_url: '/admin/invoices/' + op.invoice_id + '/packages/' + op.id,
|
80
80
|
authenticity_token: that.authenticity_token,
|
81
81
|
attributes: [
|
82
|
-
{ name: 'status' , nice_name: 'Status' , type: 'select' , value: op.status , width: 300, fixed_placeholder: true , options_url: '/admin/invoices/line-items/status-options' },
|
82
|
+
{ name: 'status' , nice_name: 'Status' , type: 'select' , value: op.status , width: 300, fixed_placeholder: true , options_url: '/admin/invoices/line-items/status-options' },
|
83
83
|
{ name: 'package_method' , nice_name: 'Package/Method' , type: 'select' , value: op.shipping_package_id + '_' + op.shipping_method_id , width: 300, fixed_placeholder: false, options_url: '/admin/shipping-packages/package-method-options' },
|
84
84
|
{ name: 'tracking_number' , nice_name: 'Tracking Number' , type: 'text' , value: op.tracking_number , width: 300, fixed_placeholder: true, align: 'right' },
|
85
85
|
{ name: 'total' , nice_name: 'Shipping Total' , type: 'text' , value: curr(op.total) , width: 300, fixed_placeholder: true, align: 'right' , after_update: function() { that.refresh_invoice(); }}
|
@@ -93,9 +93,10 @@ InvoiceController.prototype = {
|
|
93
93
|
update_url: '/admin/invoices/' + li.invoice_id + '/line-items/' + li.id,
|
94
94
|
authenticity_token: that.authenticity_token,
|
95
95
|
attributes: [
|
96
|
-
{ name: 'status' , nice_name: 'Status' , type: 'select' , align: 'left' , value: li.status
|
97
|
-
{ name: 'tracking_number' , nice_name: 'Tracking Number' , type: 'text' , align: 'left' , value: li.tracking_number
|
98
|
-
{ name: '
|
96
|
+
{ name: 'status' , nice_name: 'Status' , type: 'select' , align: 'left' , value: li.status , text: li.status, width: 150, fixed_placeholder: false, options_url: '/admin/invoices/line-items/status-options' },
|
97
|
+
{ name: 'tracking_number' , nice_name: 'Tracking Number' , type: 'text' , align: 'left' , value: li.tracking_number , width: 200, fixed_placeholder: false },
|
98
|
+
{ name: 'unit_price' , nice_name: 'Unit Price' , type: 'text' , align: 'right', value: curr(li.unit_price) , width: 75, fixed_placeholder: false, after_update: function() { that.refresh_invoice(); } },
|
99
|
+
{ name: 'quantity' , nice_name: 'Quantity' , type: 'text' , align: 'right', value: li.quantity , width: 75, fixed_placeholder: false, after_update: function() { that.refresh_invoice(); } }
|
99
100
|
]
|
100
101
|
});
|
101
102
|
});
|
@@ -105,11 +106,12 @@ InvoiceController.prototype = {
|
|
105
106
|
update_url: '/admin/invoices/' + that.invoice.id,
|
106
107
|
authenticity_token: that.authenticity_token,
|
107
108
|
attributes: [
|
108
|
-
{ name: 'status'
|
109
|
-
{ name: '
|
110
|
-
{ name: '
|
111
|
-
{ name: '
|
112
|
-
{ name: '
|
109
|
+
{ name: 'status' , nice_name: 'Status' , type: 'select', value: that.invoice.status , width: 100, fixed_placeholder: false, options_url: '/admin/invoices/status-options' },
|
110
|
+
{ name: 'financial_status' , nice_name: 'Status' , type: 'select', value: that.invoice.financial_status , width: 100, fixed_placeholder: true , width: 200, options_url: '/admin/invoices/financial-status-options' },
|
111
|
+
{ name: 'payment_terms' , nice_name: 'Terms' , type: 'select', value: that.invoice.payment_terms , width: 200, fixed_placeholder: true , width: 200, options_url: '/admin/invoices/payment-terms-options' },
|
112
|
+
{ name: 'tax' , nice_name: 'Tax' , type: 'text' , value: curr(that.invoice.tax) , width: 100, fixed_placeholder: false, align: 'right' , after_update: function() { that.refresh_invoice(); }},
|
113
|
+
{ name: 'handling' , nice_name: 'Handling' , type: 'text' , value: curr(that.invoice.handling) , width: 100, fixed_placeholder: false, align: 'right' , after_update: function() { that.refresh_invoice(); }},
|
114
|
+
{ name: 'custom_discount' , nice_name: 'Discount' , type: 'text' , value: curr(that.invoice.custom_discount) , width: 100, fixed_placeholder: false, align: 'right' , after_update: function() { that.refresh_invoice(); }}
|
113
115
|
]
|
114
116
|
});
|
115
117
|
},
|
@@ -227,7 +229,13 @@ InvoiceController.prototype = {
|
|
227
229
|
{
|
228
230
|
var that = this;
|
229
231
|
window.open('/admin/invoices/' + that.invoice.id + '/print');
|
230
|
-
},
|
232
|
+
},
|
233
|
+
|
234
|
+
print_invoice: function()
|
235
|
+
{
|
236
|
+
var that = this;
|
237
|
+
window.open('/admin/invoices/' + that.invoice.id + '/print');
|
238
|
+
},
|
231
239
|
|
232
240
|
line_items_for_invoice_package: function(invoice_package_id)
|
233
241
|
{
|
@@ -267,7 +275,7 @@ InvoiceController.prototype = {
|
|
267
275
|
.append($('<th/>').html('Shipping Address'))
|
268
276
|
.append($('<th/>').html('Billing Address'))
|
269
277
|
.append($('<th/>').html('Invoice Status'))
|
270
|
-
.append($('<th/>').html('Payment
|
278
|
+
.append($('<th/>').html('Payment'))
|
271
279
|
);
|
272
280
|
table.append($('<tr/>')
|
273
281
|
.append($('<td/>').attr('valign', 'top')
|
@@ -285,6 +293,8 @@ InvoiceController.prototype = {
|
|
285
293
|
.append($('<td/>').attr('valign', 'top').append($('<div/>').attr('id', 'invoice_' + that.invoice.id + '_status')))
|
286
294
|
.append($('<td/>').attr('valign', 'top')
|
287
295
|
.append($('<div/>').attr('id', 'invoice_' + that.invoice.id + '_payment_terms'))
|
296
|
+
.append($('<div/>').attr('id', 'invoice_' + that.invoice.id + '_payment_terms'))
|
297
|
+
.append($('<div/>').attr('id', 'invoice_' + that.invoice.id + '_financial_status'))
|
288
298
|
.append($('<div/>').attr('id', 'transactions').attr('align', 'center').append(transactions))
|
289
299
|
)
|
290
300
|
);
|
@@ -494,7 +504,8 @@ InvoiceController.prototype = {
|
|
494
504
|
.append($('<div/>').attr('id', 'line_item_' + li.id + '_message'))
|
495
505
|
);
|
496
506
|
tr.append($('<td/>').append($('<div/>').attr('id', 'lineitem_' + li.id + '_status')))
|
497
|
-
tr.append($('<td/>').attr('align', 'right').html(curr(li.unit_price)));
|
507
|
+
//tr.append($('<td/>').attr('align', 'right').html(curr(li.unit_price)));
|
508
|
+
tr.append($('<td/>').attr('align', 'right').append($('<div/>').attr('id', 'lineitem_' + li.id + '_unit_price')));
|
498
509
|
tr.append($('<td/>').attr('align', 'right').append($('<div/>').attr('id', 'lineitem_' + li.id + '_quantity')));
|
499
510
|
tr.append($('<td/>').attr('align', 'right').attr('id', 'li_' + li.id + '_subtotal').html(curr(li.subtotal)));
|
500
511
|
table.append(tr);
|
@@ -680,7 +691,8 @@ InvoiceController.prototype = {
|
|
680
691
|
.append($('<div/>').attr('id', 'line_item_' + li.id + '_message'))
|
681
692
|
);
|
682
693
|
tr.append($('<td/>').append($('<div/>').attr('id', 'lineitem_' + li.id + '_status')))
|
683
|
-
tr.append($('<td/>').attr('align', 'right').html(curr(li.unit_price)));
|
694
|
+
//tr.append($('<td/>').attr('align', 'right').html(curr(li.unit_price)));
|
695
|
+
tr.append($('<td/>').attr('align', 'right').append($('<div/>').attr('id', 'lineitem_' + li.id + '_unit_price')));
|
684
696
|
tr.append($('<td/>').attr('align', 'right').append($('<div/>').attr('id', 'lineitem_' + li.id + '_quantity')));
|
685
697
|
tr.append($('<td/>').attr('align', 'right').attr('id', 'li_' + li.id + '_subtotal').html(curr(li.subtotal)));
|
686
698
|
table.append(tr);
|
@@ -737,10 +749,11 @@ InvoiceController.prototype = {
|
|
737
749
|
var p = $('<p/>');
|
738
750
|
p.append($('<input/>').attr('type', 'button').val('< Back').click(function() { window.location = '/admin/invoices'; })).append(' ');
|
739
751
|
if (that.invoice.total > 0 && that.invoice.financial_status == 'pending')
|
740
|
-
p.append($('<input/>').attr('type', 'button').val('Send for
|
741
|
-
|
742
|
-
|
743
|
-
p.append($('<input/>').attr('type', 'button').val('
|
752
|
+
p.append($('<input/>').attr('type', 'button').val('Send for Payment').click(function() { that.send_for_authorization(); })).append(' ');
|
753
|
+
if (that.invoice.total > 0 && (that.invoice.financial_status == 'captured' || that.invoice.financial_status == 'paid by check' || that.invoice.financial_status == 'paid by other means'))
|
754
|
+
p.append($('<input/>').attr('type', 'button').val('Send Receipt to Customer' ).click(function() { that.send_receipt(); })).append(' ');
|
755
|
+
p.append($('<input/>').attr('type', 'button').val('Add Item' ).click(function() { that.add_variant(); })).append(' ');
|
756
|
+
p.append($('<input/>').attr('type', 'button').val('Print Invoice' ).click(function() { that.print_invoice(); })).append(' ');
|
744
757
|
$('#controls').empty().append(p);
|
745
758
|
},
|
746
759
|
|
@@ -842,8 +855,8 @@ InvoiceController.prototype = {
|
|
842
855
|
{
|
843
856
|
var that = this;
|
844
857
|
var div = $('<div/>')
|
845
|
-
|
846
|
-
.append($('<a/>').attr('href', '#').html('refresh').click(function(e) { e.preventDefault(); that.refresh_transactions(); }))
|
858
|
+
//.append($('<span/>').attr('id', 'financial_status').append(that.invoice.financial_status)).append(' ')
|
859
|
+
.append($('<a/>').attr('href', '#').html('refresh transactions').click(function(e) { e.preventDefault(); that.refresh_transactions(); }))
|
847
860
|
.append($('<div/>').attr('id', 'transactions_message'));
|
848
861
|
if (that.invoice.invoice_transactions.length > 0)
|
849
862
|
{
|
@@ -1000,6 +1013,29 @@ InvoiceController.prototype = {
|
|
1000
1013
|
}
|
1001
1014
|
});
|
1002
1015
|
},
|
1016
|
+
|
1017
|
+
send_receipt: function(confirm)
|
1018
|
+
{
|
1019
|
+
var that = this;
|
1020
|
+
if (!confirm)
|
1021
|
+
{
|
1022
|
+
var p = $('<p/>').addClass('note confirm')
|
1023
|
+
.append("Are you sure you want to send a receipt to the customer? ")
|
1024
|
+
.append($('<input/>').attr('type','button').val('Yes').click(function() { that.send_receipt(true); }))
|
1025
|
+
.append(' ')
|
1026
|
+
.append($('<input/>').attr('type','button').val('No').click(function() { $('#message').empty(); }));
|
1027
|
+
$('#message').empty().append(p);
|
1028
|
+
return;
|
1029
|
+
}
|
1030
|
+
$('#message').html("<p class='loading'>Sending receipt...</p>");
|
1031
|
+
$.ajax({
|
1032
|
+
url: '/admin/invoices/' + that.invoice.id + '/send-receipt',
|
1033
|
+
success: function(resp) {
|
1034
|
+
if (resp.error) { that.flash_error(resp.error); }
|
1035
|
+
if (resp.success) { that.refresh(function() { that.flash_success("A receipt email has been sent successfully to the customer."); }); }
|
1036
|
+
}
|
1037
|
+
});
|
1038
|
+
},
|
1003
1039
|
|
1004
1040
|
calculate_tax: function()
|
1005
1041
|
{
|
@@ -67,44 +67,44 @@ module Caboose
|
|
67
67
|
render :json => resp
|
68
68
|
end
|
69
69
|
|
70
|
-
# @route PUT /admin/invoices/:invoice_id/line-items/:id
|
71
|
-
def admin_update_line_item
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
end
|
70
|
+
# @ route PUT /admin/invoices/:invoice_id/line-items/:id
|
71
|
+
#def admin_update_line_item
|
72
|
+
# return if !user_is_allowed('invoices', 'edit')
|
73
|
+
#
|
74
|
+
# resp = Caboose::StdClass.new({'attributes' => {}})
|
75
|
+
# li = LineItem.find(params[:id])
|
76
|
+
#
|
77
|
+
# save = true
|
78
|
+
# send_status_email = false
|
79
|
+
# params.each do |name,value|
|
80
|
+
# case name
|
81
|
+
# when 'quantity'
|
82
|
+
# li.quantity = value
|
83
|
+
# li.save
|
84
|
+
#
|
85
|
+
# # Recalculate everything
|
86
|
+
# r = ShippingCalculator.rate(li.invoice, li.invoice.shipping_method_code)
|
87
|
+
# li.invoice.shipping = r['negotiated_rate'] / 100
|
88
|
+
# li.invoice.handling = (r['negotiated_rate'] / 100) * 0.05
|
89
|
+
# li.invoice.tax = TaxCalculator.tax(li.invoice)
|
90
|
+
# li.invoice.calculate_total
|
91
|
+
# li.invoice.save
|
92
|
+
#
|
93
|
+
# when 'tracking_number'
|
94
|
+
# li.tracking_number = value
|
95
|
+
# send_status_email = true
|
96
|
+
# when 'status'
|
97
|
+
# li.status = value
|
98
|
+
# resp.attributes['status'] = {'text' => value}
|
99
|
+
# send_status_email = true
|
100
|
+
# end
|
101
|
+
# end
|
102
|
+
# if send_status_email
|
103
|
+
# InvoicesMailer.configure_for_site(@site.id).customer_status_updated(li.invoice).deliver
|
104
|
+
# end
|
105
|
+
# resp.success = save && li.save
|
106
|
+
# render :json => resp
|
107
|
+
#end
|
108
108
|
|
109
109
|
# @route DELETE /admin/invoices/:invoice_id/packages/:id
|
110
110
|
def admin_delete
|
@@ -189,26 +189,27 @@ module Caboose
|
|
189
189
|
|
190
190
|
resp = Caboose::StdClass.new({'attributes' => {}})
|
191
191
|
invoice = Invoice.find(params[:id])
|
192
|
-
|
192
|
+
|
193
193
|
save = true
|
194
|
-
params.each do |name,value|
|
194
|
+
params.each do |name,value|
|
195
195
|
case name
|
196
|
-
when 'tax'
|
196
|
+
when 'tax'
|
197
197
|
invoice.tax = value
|
198
198
|
invoice.total = invoice.calculate_total
|
199
|
-
when 'handling'
|
199
|
+
when 'handling'
|
200
200
|
invoice.handling = value
|
201
201
|
invoice.total = invoice.calculate_total
|
202
|
-
when 'custom_discount'
|
202
|
+
when 'custom_discount'
|
203
203
|
invoice.custom_discount = value
|
204
204
|
invoice.discount = invoice.calculate_discount
|
205
205
|
invoice.total = invoice.calculate_total
|
206
|
-
when 'status'
|
206
|
+
when 'status'
|
207
207
|
invoice.status = value
|
208
|
-
if value == 'Shipped'
|
209
|
-
|
210
|
-
|
211
|
-
when 'customer_id'
|
208
|
+
invoice.date_shipped = DateTime.now.utc if value == 'Shipped'
|
209
|
+
when 'financial_status'
|
210
|
+
invoice.financial_status = value
|
211
|
+
when 'customer_id'
|
212
|
+
invoice.customer_id = value
|
212
213
|
end
|
213
214
|
end
|
214
215
|
|
@@ -216,7 +217,7 @@ module Caboose
|
|
216
217
|
#invoice.calculate_total
|
217
218
|
#resp.attributes['total'] = { 'value' => invoice.total }
|
218
219
|
|
219
|
-
resp.success = save && invoice.save
|
220
|
+
resp.success = save && invoice.save
|
220
221
|
render :json => resp
|
221
222
|
end
|
222
223
|
|
@@ -237,6 +238,14 @@ module Caboose
|
|
237
238
|
render :json => { :success => true }
|
238
239
|
end
|
239
240
|
|
241
|
+
# @route GET /admin/invoices/:id/send-receipt
|
242
|
+
def admin_send_for_authorization
|
243
|
+
return if !user_is_allowed('invoices', 'edit')
|
244
|
+
invoice = Invoice.find(params[:id])
|
245
|
+
invoice.delay(:queue => 'caboose_store').send_receipt_email
|
246
|
+
render :json => { :success => true }
|
247
|
+
end
|
248
|
+
|
240
249
|
# @route GET /admin/invoices/city-report
|
241
250
|
def admin_city_report
|
242
251
|
return if !user_is_allowed('invoices', 'view')
|
@@ -273,7 +282,18 @@ module Caboose
|
|
273
282
|
Invoice::STATUS_SHIPPED,
|
274
283
|
Invoice::STATUS_CANCELED
|
275
284
|
]
|
276
|
-
options = statuses.collect{ |s| { 'text' => s.capitalize, 'value' => s }}
|
285
|
+
options = statuses.collect{ |s| { 'text' => s.capitalize, 'value' => s }}
|
286
|
+
when 'financial-status'
|
287
|
+
statuses = [
|
288
|
+
Invoice::FINANCIAL_STATUS_PENDING ,
|
289
|
+
Invoice::FINANCIAL_STATUS_AUTHORIZED ,
|
290
|
+
Invoice::FINANCIAL_STATUS_CAPTURED ,
|
291
|
+
Invoice::FINANCIAL_STATUS_REFUNDED ,
|
292
|
+
Invoice::FINANCIAL_STATUS_VOIDED ,
|
293
|
+
Invoice::FINANCIAL_STATUS_PAID_BY_CHECK ,
|
294
|
+
Invoice::FINANCIAL_STATUS_PAID_BY_OTHER_MEANS
|
295
|
+
]
|
296
|
+
options = statuses.collect{ |s| { 'text' => s.capitalize, 'value' => s }}
|
277
297
|
when 'payment-terms'
|
278
298
|
options = [
|
279
299
|
{ 'value' => Invoice::PAYMENT_TERMS_PIA , 'text' => 'Pay In Advance' },
|
@@ -46,21 +46,26 @@ module Caboose
|
|
46
46
|
case name
|
47
47
|
when 'invoice_id' then li.invoice_id = value
|
48
48
|
when 'invoice_package_id' then li.invoice_package_id = value
|
49
|
-
when 'variant_id'
|
50
|
-
when 'parent_id'
|
51
|
-
#when '
|
52
|
-
|
53
|
-
when '
|
54
|
-
when '
|
55
|
-
when '
|
56
|
-
when '
|
57
|
-
|
58
|
-
li.
|
49
|
+
when 'variant_id' then li.variant_id = value
|
50
|
+
when 'parent_id' then li.parent_id = value
|
51
|
+
#when 'subtotal' then li.subtotal = value
|
52
|
+
when 'notes' then li.notes = value
|
53
|
+
when 'custom1' then li.custom1 = value
|
54
|
+
when 'custom2' then li.custom2 = value
|
55
|
+
when 'custom3' then li.custom3 = value
|
56
|
+
when 'unit_price'
|
57
|
+
Caboose.log("li.unit_price = #{li.unit_price}")
|
58
|
+
li.unit_price = value
|
59
|
+
li.save
|
60
|
+
Caboose.log("li.unit_price = #{li.unit_price}")
|
59
61
|
li.subtotal = li.unit_price * li.quantity
|
60
|
-
|
61
62
|
li.save
|
62
|
-
|
63
|
-
|
63
|
+
li.invoice.subtotal = li.invoice.calculate_subtotal
|
64
|
+
li.invoice.total = li.invoice.calculate_total
|
65
|
+
when 'quantity'
|
66
|
+
li.quantity = value
|
67
|
+
li.subtotal = li.unit_price * li.quantity
|
68
|
+
li.save
|
64
69
|
li.invoice.subtotal = li.invoice.calculate_subtotal
|
65
70
|
li.invoice.total = li.invoice.calculate_total
|
66
71
|
|
@@ -269,19 +269,24 @@ module Caboose
|
|
269
269
|
return if !user_is_allowed('users', 'sudo')
|
270
270
|
user = User.find(params[:id])
|
271
271
|
|
272
|
-
|
273
|
-
d = Caboose::Domain.where(:domain => request.host_with_port).first
|
274
|
-
|
275
|
-
if d.primary == true
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
end
|
280
|
-
|
281
|
-
|
282
|
-
user.token = (0...20).map { ('a'..'z').to_a[rand(26)] }.join
|
283
|
-
user.save
|
284
|
-
|
272
|
+
## See if we're on the default domain
|
273
|
+
#d = Caboose::Domain.where(:domain => request.host_with_port).first
|
274
|
+
#
|
275
|
+
#if d.primary == true
|
276
|
+
# logout_user
|
277
|
+
# login_user(user, false) # Login the new user
|
278
|
+
# redirect_to "/"
|
279
|
+
#end
|
280
|
+
#
|
281
|
+
## Set a random token for the user
|
282
|
+
#user.token = (0...20).map { ('a'..'z').to_a[rand(26)] }.join
|
283
|
+
#user.save
|
284
|
+
#
|
285
|
+
#redirect_to "http://#{d.site.primary_domain.domain}/admin/users/#{params[:id]}/su/#{user.token}"
|
286
|
+
|
287
|
+
logout_user
|
288
|
+
login_user(user, false) # Login the new user
|
289
|
+
redirect_to "/"
|
285
290
|
end
|
286
291
|
|
287
292
|
# @route GET /admin/users/:id/su/:token
|
@@ -47,7 +47,13 @@ module Caboose
|
|
47
47
|
# Sends an email to the customer telling them they need to authorize payment on an invoice
|
48
48
|
def customer_payment_authorization(invoice)
|
49
49
|
@invoice = invoice
|
50
|
-
mail(:to => invoice.customer.email, :subject => "
|
50
|
+
mail(:to => invoice.customer.email, :subject => "Invoice #{@invoice.invoice_number} ready for payment")
|
51
|
+
end
|
52
|
+
|
53
|
+
# Sends an email to the customer telling them they need to authorize payment on an invoice
|
54
|
+
def customer_receipt(invoice)
|
55
|
+
@invoice = invoice
|
56
|
+
mail(:to => invoice.customer.email, :subject => "Invoice #{@invoice.invoice_number} receipt")
|
51
57
|
end
|
52
58
|
end
|
53
59
|
end
|
@@ -66,12 +66,14 @@ module Caboose
|
|
66
66
|
#STATUS_CANCELED = 'Canceled'
|
67
67
|
#STATUS_WAIVED = 'Waived'
|
68
68
|
|
69
|
-
FINANCIAL_STATUS_PENDING
|
70
|
-
FINANCIAL_STATUS_AUTHORIZED
|
71
|
-
FINANCIAL_STATUS_CAPTURED
|
72
|
-
FINANCIAL_STATUS_REFUNDED
|
73
|
-
FINANCIAL_STATUS_VOIDED
|
74
|
-
|
69
|
+
FINANCIAL_STATUS_PENDING = 'pending'
|
70
|
+
FINANCIAL_STATUS_AUTHORIZED = 'authorized'
|
71
|
+
FINANCIAL_STATUS_CAPTURED = 'captured'
|
72
|
+
FINANCIAL_STATUS_REFUNDED = 'refunded'
|
73
|
+
FINANCIAL_STATUS_VOIDED = 'voided'
|
74
|
+
FINANCIAL_STATUS_PAID_BY_CHECK = 'paid by check'
|
75
|
+
FINANCIAL_STATUS_PAID_BY_OTHER_MEANS = 'paid by other means'
|
76
|
+
|
75
77
|
PAYMENT_TERMS_PIA = 'pia'
|
76
78
|
PAYMENT_TERMS_NET7 = 'net7'
|
77
79
|
PAYMENT_TERMS_NET10 = 'net10'
|
@@ -104,7 +106,7 @@ module Caboose
|
|
104
106
|
}
|
105
107
|
|
106
108
|
validates :financial_status, :inclusion => {
|
107
|
-
:in => ['pending', 'authorized', 'captured', 'refunded', 'voided'],
|
109
|
+
:in => ['pending', 'authorized', 'captured', 'refunded', 'voided', 'paid by check', 'paid by other means'],
|
108
110
|
:message => "%{value} is not a valid financial status. Must be 'authorized', 'captured', 'refunded' or 'voided'"
|
109
111
|
}
|
110
112
|
|
@@ -489,6 +491,10 @@ module Caboose
|
|
489
491
|
InvoicesMailer.configure_for_site(self.site_id).customer_payment_authorization(self).deliver
|
490
492
|
end
|
491
493
|
|
494
|
+
def send_receipt_email
|
495
|
+
InvoicesMailer.configure_for_site(self.site_id).customer_receipt(self).deliver
|
496
|
+
end
|
497
|
+
|
492
498
|
def determine_statuses
|
493
499
|
|
494
500
|
auth = false
|
@@ -647,67 +653,69 @@ module Caboose
|
|
647
653
|
case sc.pp_name
|
648
654
|
when StoreConfig::PAYMENT_PROCESSOR_STRIPE
|
649
655
|
|
650
|
-
|
651
|
-
|
652
|
-
|
653
|
-
self.financial_status = Invoice::FINANCIAL_STATUS_PENDING
|
654
|
-
charges.each do |c|
|
655
|
-
invoice_id = c.metadata && c.metadata['invoice_id'] ? c.metadata['invoice_id'].to_i : nil
|
656
|
-
next if invoice_id.nil? || invoice_id != self.id
|
656
|
+
if sc.stripe_secret_key && sc.stripe_secret_key.strip.length > 0
|
657
|
+
Stripe.api_key = sc.stripe_secret_key.strip
|
658
|
+
charges = Stripe::Charge.list(:limit => 100, :customer => self.customer.stripe_customer_id)
|
657
659
|
|
658
|
-
|
659
|
-
|
660
|
-
|
661
|
-
|
662
|
-
|
663
|
-
|
664
|
-
|
665
|
-
|
666
|
-
|
667
|
-
|
668
|
-
|
669
|
-
:amount_refunded => c.amount_refunded,
|
670
|
-
:date_processed => DateTime.strptime(c.created.to_s, '%s'),
|
671
|
-
:success => c.status == 'succeeded',
|
672
|
-
:captured => c.captured,
|
673
|
-
:refunded => c.refunded
|
674
|
-
)
|
675
|
-
if c.balance_transaction
|
676
|
-
bt = Stripe::BalanceTransaction.retrieve(c.balance_transaction)
|
677
|
-
capture_trans = InvoiceTransaction.create(
|
660
|
+
self.financial_status = Invoice::FINANCIAL_STATUS_PENDING
|
661
|
+
charges.each do |c|
|
662
|
+
invoice_id = c.metadata && c.metadata['invoice_id'] ? c.metadata['invoice_id'].to_i : nil
|
663
|
+
next if invoice_id.nil? || invoice_id != self.id
|
664
|
+
|
665
|
+
if c.refunded then self.financial_status = Invoice::FINANCIAL_STATUS_REFUNDED
|
666
|
+
elsif c.status == 'succeeded' && c.captured then self.financial_status = Invoice::FINANCIAL_STATUS_CAPTURED
|
667
|
+
elsif c.status == 'succeeded' then self.financial_status = Invoice::FINANCIAL_STATUS_AUTHORIZED
|
668
|
+
end
|
669
|
+
|
670
|
+
auth_trans = InvoiceTransaction.create(
|
678
671
|
:invoice_id => self.id,
|
679
|
-
:
|
680
|
-
:
|
681
|
-
:transaction_type => InvoiceTransaction::TYPE_CAPTURE,
|
672
|
+
:transaction_id => c.id,
|
673
|
+
:transaction_type => c.captured ? InvoiceTransaction::TYPE_AUTHCAP : InvoiceTransaction::TYPE_AUTHORIZE,
|
682
674
|
:payment_processor => sc.pp_name,
|
683
|
-
:amount =>
|
684
|
-
:
|
685
|
-
:
|
686
|
-
|
687
|
-
|
688
|
-
|
689
|
-
|
690
|
-
c.
|
691
|
-
|
692
|
-
InvoiceTransaction.create(
|
675
|
+
:amount => c.amount / 100.0,
|
676
|
+
:amount_refunded => c.amount_refunded,
|
677
|
+
:date_processed => DateTime.strptime(c.created.to_s, '%s'),
|
678
|
+
:success => c.status == 'succeeded',
|
679
|
+
:captured => c.captured,
|
680
|
+
:refunded => c.refunded
|
681
|
+
)
|
682
|
+
if c.balance_transaction
|
683
|
+
bt = Stripe::BalanceTransaction.retrieve(c.balance_transaction)
|
684
|
+
capture_trans = InvoiceTransaction.create(
|
693
685
|
:invoice_id => self.id,
|
694
|
-
:parent_id => auth_trans.id,
|
695
|
-
:transaction_id =>
|
696
|
-
:transaction_type => InvoiceTransaction::
|
686
|
+
:parent_id => auth_trans.id,
|
687
|
+
:transaction_id => bt.id,
|
688
|
+
:transaction_type => InvoiceTransaction::TYPE_CAPTURE,
|
697
689
|
:payment_processor => sc.pp_name,
|
698
|
-
:amount =>
|
699
|
-
:date_processed => DateTime.strptime(
|
700
|
-
:success =>
|
701
|
-
)
|
690
|
+
:amount => bt.amount / 100.0,
|
691
|
+
:date_processed => DateTime.strptime(bt.created.to_s, '%s'),
|
692
|
+
:success => bt.status == 'succeeded' || bt.status == 'pending'
|
693
|
+
)
|
702
694
|
end
|
703
|
-
|
704
|
-
|
705
|
-
|
706
|
-
|
695
|
+
if c.refunds && c.refunds['total_count'] > 0
|
696
|
+
total = 0
|
697
|
+
c.refunds['data'].each do |r|
|
698
|
+
total = total + r.amount
|
699
|
+
InvoiceTransaction.create(
|
700
|
+
:invoice_id => self.id,
|
701
|
+
:parent_id => auth_trans.id,
|
702
|
+
:transaction_id => r.id,
|
703
|
+
:transaction_type => InvoiceTransaction::TYPE_REFUND,
|
704
|
+
:payment_processor => sc.pp_name,
|
705
|
+
:amount => r.amount / 100.0,
|
706
|
+
:date_processed => DateTime.strptime(r.created.to_s, '%s'),
|
707
|
+
:success => r.status == 'succeeded' || r.status == 'pending'
|
708
|
+
)
|
709
|
+
end
|
710
|
+
total = total.to_f / 100
|
711
|
+
if total >= auth_trans.amount
|
712
|
+
auth_trans.refunded = true
|
713
|
+
auth_trans.save
|
714
|
+
end
|
707
715
|
end
|
708
716
|
end
|
717
|
+
self.save
|
709
718
|
end
|
710
|
-
self.save
|
711
719
|
end
|
712
720
|
end
|
713
721
|
|
@@ -4,7 +4,7 @@ module Caboose
|
|
4
4
|
class TaxCalculator
|
5
5
|
|
6
6
|
def self.custom_tax(store_config, invoice)
|
7
|
-
return eval(store_config.custom_tax_function)
|
7
|
+
return store_config.custom_tax_function && store_config.custom_tax_function.strip.length > 0 ? eval(store_config.custom_tax_function) : 0.00
|
8
8
|
end
|
9
9
|
|
10
10
|
def self.tax(invoice)
|
@@ -0,0 +1,75 @@
|
|
1
|
+
<p><img src='<%= @invoice.site.logo.url(:thumb) %>' /></p>
|
2
|
+
|
3
|
+
<h1>Receipt</h1>
|
4
|
+
|
5
|
+
<p>
|
6
|
+
Invoice #<%= @invoice.id %><br />
|
7
|
+
Status: <% @invoice.status %><br />
|
8
|
+
Financial status: <% @invoice.financial_status %>
|
9
|
+
</p>
|
10
|
+
|
11
|
+
<table border='1' style='border-collapse: collapse;'>
|
12
|
+
<tr>
|
13
|
+
<th>Line Item</th>
|
14
|
+
<th>Unit Price</th>
|
15
|
+
<th>Quantity</th>
|
16
|
+
<th>Subtotal</th>
|
17
|
+
</tr>
|
18
|
+
<% @invoice.line_items.each do |li| %>
|
19
|
+
<% v = li.variant %>
|
20
|
+
<% p = v.product %>
|
21
|
+
<tr>
|
22
|
+
<td>
|
23
|
+
<p><%= p.title %></td></p>
|
24
|
+
<% if li.is_gift %>
|
25
|
+
<p>This item is a gift.</p>
|
26
|
+
<ul>
|
27
|
+
<li><% if li.gift_wrap %>Gift wrap (<%= number_to_currency(p.gift_wrap_price) %>)<% else %>Do not gift wrap<% end %></li>
|
28
|
+
<li><% if li.include_gift_message %>Gift message: <%= li.gift_message %><% else %>No gift message<% end %></li>
|
29
|
+
<li><% if li.hide_prices %>Hide all prices<% else %>Show all prices<% end %></li>
|
30
|
+
</ul>
|
31
|
+
<% end %>
|
32
|
+
</td>
|
33
|
+
<td align='right'><%= number_to_currency(li.unit_price) %></td>
|
34
|
+
<td align='right'><%= li.quantity %></td>
|
35
|
+
<td align='right'><%= number_to_currency(li.subtotal) %></td>
|
36
|
+
</tr>
|
37
|
+
<% end %>
|
38
|
+
<tr><td colspan="4" align='right'>Subtotal: </td><td align='right'><%= number_to_currency(@invoice.subtotal) %></td></tr>
|
39
|
+
<tr><td colspan="4" align='right'>Tax: </td><td align='right'><%= number_to_currency(@invoice.tax) %></td></tr>
|
40
|
+
<tr><td colspan="4" align='right'>Shipping and Handling: </td><td align='right'><%= number_to_currency(@invoice.shipping + @invoice.handling) %></td></tr>
|
41
|
+
<% if @invoice.gift_wrap && @invoice.gift_wrap > 0 %>
|
42
|
+
<tr><td colspan="4" align='right'>Gift wrap: </td><td align='right'><%= number_to_currency(@invoice.gift_wrap) %></td></tr>
|
43
|
+
<% end %>
|
44
|
+
<% if @invoice.discounts %>
|
45
|
+
<% @invoice.discounts.each do |d| %>
|
46
|
+
<tr><td colspan="4" align='right'>"<%= d.gift_card.code %>" gift card: </td><td align='right'><%= number_to_currency(d.amount) %></td></tr>
|
47
|
+
<% end %>
|
48
|
+
<% end %>
|
49
|
+
<% if @invoice.custom_discount %>
|
50
|
+
<tr><td colspan="4" align='right'>Discount: </td><td align='right'><%= number_to_currency(@invoice.custom_discount) %></td></tr>
|
51
|
+
<% end %>
|
52
|
+
<tr><td colspan="4" align='right'>Total: </td><td align='right'><%= number_to_currency(@invoice.total) %></td></tr>
|
53
|
+
</table>
|
54
|
+
|
55
|
+
<% if @invoice.shipping_address %>
|
56
|
+
<% sa = @invoice.shipping_address %>
|
57
|
+
<h2>Shipping Address</h2>
|
58
|
+
<p>
|
59
|
+
<%= sa.first_name %> <%= sa.last_name %><br />
|
60
|
+
<%= sa.address1 %><br />
|
61
|
+
<% if sa.address2 && sa.address2.strip.length > 0 %><%= sa.address2 %><br /><% end %>
|
62
|
+
<%= sa.city %>, <%= sa.state %> <%= sa.zip %>
|
63
|
+
</p>
|
64
|
+
<% end %>
|
65
|
+
|
66
|
+
<% if @invoice.billing_address %>
|
67
|
+
<% ba = @invoice.billing_address %>
|
68
|
+
<h2>Billing Address</h2>
|
69
|
+
<p>
|
70
|
+
<%= ba.first_name %> <%= ba.last_name %><br />
|
71
|
+
<%= ba.address1 %><br />
|
72
|
+
<% if ba.address2 && ba.address2.strip.length > 0 %><%= ba.address2 %><br /><% end %>
|
73
|
+
<%= ba.city %>, <%= ba.state %> <%= ba.zip %>
|
74
|
+
</p>
|
75
|
+
<% end %>
|
data/lib/caboose/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: caboose-cms
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.8.
|
4
|
+
version: 0.8.35
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- William Barry
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-08-
|
11
|
+
date: 2016-08-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: pg
|
@@ -1057,6 +1057,7 @@ files:
|
|
1057
1057
|
- app/views/caboose/invoices/admin_summary_report.html.erb
|
1058
1058
|
- app/views/caboose/invoices_mailer/customer_new_invoice.html.erb
|
1059
1059
|
- app/views/caboose/invoices_mailer/customer_payment_authorization.html.erb
|
1060
|
+
- app/views/caboose/invoices_mailer/customer_receipt.html.erb
|
1060
1061
|
- app/views/caboose/invoices_mailer/customer_status_updated.html.erb
|
1061
1062
|
- app/views/caboose/invoices_mailer/fulfillment_new_invoice.html.erb
|
1062
1063
|
- app/views/caboose/invoices_mailer/shipping_invoice_ready.html.erb
|