caboose-cms 0.8.34 → 0.8.35
Sign up to get free protection for your applications and to get access to all the features.
- 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
|