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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 10b912cc8b30e8569dcb1f1d2e9b9282fbc8c4cb
4
- data.tar.gz: 4c7b76303acd61dfa695d381ccac0330520ebe25
3
+ metadata.gz: e580ca759518da7762c5cc5160d5de30136cad5d
4
+ data.tar.gz: 11c47056fb135a003a5b437760dfe0e859565231
5
5
  SHA512:
6
- metadata.gz: 5aa8fe51db11317e5a6570caba27576ee6855c633e0d9204c19dbbe885118edb2ba2342c4ef0df80fb0b640b180c6bf56b491987eed5423517ed7163a7703ca6
7
- data.tar.gz: 020d7efb4def9817166f65d9cc15f5b13bd0d5fcaa12d9acb5818d388eb2230840080ba649cf907ef9f3ce7f1444502f6e905796c1f2ad189d5c03e3c828504e
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 , 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: 'quantity' , nice_name: 'Quantity' , type: 'text' , align: 'right', value: li.quantity , width: 75, fixed_placeholder: false, after_update: function() { that.refresh_invoice(); } }
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' , nice_name: 'Status' , type: 'select', value: that.invoice.status , width: 100, fixed_placeholder: false, options_url: '/admin/invoices/status-options' },
109
- { name: 'payment_terms' , nice_name: 'Terms' , type: 'select', value: that.invoice.payment_terms , width: 200, fixed_placeholder: true , options_url: '/admin/invoices/payment-terms-options' },
110
- { 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(); }},
111
- { 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(); }},
112
- { 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(); }}
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 Status'))
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 Authorization').click(function() { that.send_for_authorization(); })).append(' ');
741
- //p.append($('<input/>').attr('type', 'button').val('Resend Confirmation' ).click(function() { that.resend_confirmation(); })).append(' ');
742
- p.append($('<input/>').attr('type', 'button').val('Add Item' ).click(function() { that.add_variant(); })).append(' ');
743
- p.append($('<input/>').attr('type', 'button').val('Print Invoice' ).click(function() { that.print_invoice(); })).append(' ');
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
- .append($('<span/>').attr('id', 'financial_status').append(that.invoice.financial_status)).append(' ')
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
- 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
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' then
196
+ when 'tax'
197
197
  invoice.tax = value
198
198
  invoice.total = invoice.calculate_total
199
- when 'handling' then
199
+ when 'handling'
200
200
  invoice.handling = value
201
201
  invoice.total = invoice.calculate_total
202
- when 'custom_discount' then
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' then
206
+ when 'status'
207
207
  invoice.status = value
208
- if value == 'Shipped'
209
- invoice.date_shipped = DateTime.now.utc
210
- end
211
- when 'customer_id' then invoice.customer_id = value
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' then li.variant_id = value
50
- when 'parent_id' then li.parent_id = value
51
- #when 'unit_price' then li.unit_price = value
52
- #when 'subtotal' then li.subtotal = value
53
- when 'notes' then li.notes = value
54
- when 'custom1' then li.custom1 = value
55
- when 'custom2' then li.custom2 = value
56
- when 'custom3' then li.custom3 = value
57
- when 'quantity'
58
- li.quantity = value
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
- # 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
- redirect_to "http://#{d.site.primary_domain.domain}/admin/users/#{params[:id]}/su/#{user.token}"
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 => "Order #{@invoice.invoice_number} ready for payment")
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 = 'pending'
70
- FINANCIAL_STATUS_AUTHORIZED = 'authorized'
71
- FINANCIAL_STATUS_CAPTURED = 'captured'
72
- FINANCIAL_STATUS_REFUNDED = 'refunded'
73
- FINANCIAL_STATUS_VOIDED = '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
- Stripe.api_key = sc.stripe_secret_key.strip
651
- charges = Stripe::Charge.list(:limit => 100, :customer => self.customer.stripe_customer_id)
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
- if c.refunded then self.financial_status = Invoice::FINANCIAL_STATUS_REFUNDED
659
- elsif c.status == 'succeeded' && c.captured then self.financial_status = Invoice::FINANCIAL_STATUS_CAPTURED
660
- elsif c.status == 'succeeded' then self.financial_status = Invoice::FINANCIAL_STATUS_AUTHORIZED
661
- end
662
-
663
- auth_trans = InvoiceTransaction.create(
664
- :invoice_id => self.id,
665
- :transaction_id => c.id,
666
- :transaction_type => c.captured ? InvoiceTransaction::TYPE_AUTHCAP : InvoiceTransaction::TYPE_AUTHORIZE,
667
- :payment_processor => sc.pp_name,
668
- :amount => c.amount / 100.0,
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
- :parent_id => auth_trans.id,
680
- :transaction_id => bt.id,
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 => bt.amount / 100.0,
684
- :date_processed => DateTime.strptime(bt.created.to_s, '%s'),
685
- :success => bt.status == 'succeeded' || bt.status == 'pending'
686
- )
687
- end
688
- if c.refunds && c.refunds['total_count'] > 0
689
- total = 0
690
- c.refunds['data'].each do |r|
691
- total = total + r.amount
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 => r.id,
696
- :transaction_type => InvoiceTransaction::TYPE_REFUND,
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 => r.amount / 100.0,
699
- :date_processed => DateTime.strptime(r.created.to_s, '%s'),
700
- :success => r.status == 'succeeded' || r.status == 'pending'
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
- total = total.to_f / 100
704
- if total >= auth_trans.amount
705
- auth_trans.refunded = true
706
- auth_trans.save
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 %>
@@ -1,3 +1,3 @@
1
1
  module Caboose
2
- VERSION = '0.8.34'
2
+ VERSION = '0.8.35'
3
3
  end
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.34
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-03 00:00:00.000000000 Z
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