Class: Caboose::Invoice

Inherits:
ActiveRecord::Base
  • Object
show all
Defined in:
app/models/caboose/invoice.rb

Constant Summary collapse

STATUS_CART =
'cart'
STATUS_PENDING =
'pending'
STATUS_CANCELED =
'canceled'
STATUS_READY_TO_SHIP =
'ready to ship'
STATUS_PROCESSED =
'processed'
STATUS_TESTING =
'testing'
FINANCIAL_STATUS_PENDING =

New STATUS_PENDING = 'Pending' STATUS_OVERDUE = 'Overdue' STATUS_UNDER_REVIEW = 'Under Review' STATUS_PAID = 'Paid' STATUS_PAID_BY_CHECK = 'Paid By Check' STATUS_CANCELED = 'Canceled' STATUS_WAIVED = 'Waived'

'pending'
FINANCIAL_STATUS_AUTHORIZED =
'authorized'
FINANCIAL_STATUS_CAPTURED =
'captured'
FINANCIAL_STATUS_REFUNDED =
'refunded'
FINANCIAL_STATUS_VOIDED =
'voided'
FINANCIAL_STATUS_WAIVED =
'waived'
FINANCIAL_STATUS_OVERDUE =
'overdue'
FINANCIAL_STATUS_PAID_BY_CHECK =
'paid by check'
FINANCIAL_STATUS_PAID_BY_OTHER_MEANS =
'paid by other means'
PAYMENT_TERMS_PIA =
'pia'
PAYMENT_TERMS_NET7 =
'net7'
PAYMENT_TERMS_NET10 =
'net10'
PAYMENT_TERMS_NET30 =
'net30'
PAYMENT_TERMS_NET60 =
'net60'
PAYMENT_TERMS_NET90 =
'net90'
PAYMENT_TERMS_EOM =
'eom'

Instance Method Summary collapse

Instance Method Details

#amount_not_paidObject


572
573
574
575
# File 'app/models/caboose/invoice.rb', line 572

def amount_not_paid
  amount = self.vendor_transactions.where(:success => true).all.collect{ |vt| vt.amount }.sum
  return self.total - amount
end

#authorize_and_captureObject

Authorize and capture funds


282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
# File 'app/models/caboose/invoice.rb', line 282

def authorize_and_capture
  
  resp = StdClass.new                        
  if self.financial_status == Invoice::FINANCIAL_STATUS_CAPTURED
    resp.error = "Funds for this invoice have already been captured."
  else
                    
    sc = self.site.store_config                
    case sc.pp_name                                    
      when StoreConfig::PAYMENT_PROCESSOR_STRIPE
                                                                          
        Stripe.api_key = sc.stripe_secret_key.strip
        bt = nil
        begin
          c = Stripe::Charge.create(
            :amount => (self.total * 100).to_i,
            :currency => 'usd',
            :customer => self.customer.stripe_customer_id,
            :capture => true,
            :metadata => { :invoice_id => self.id },
            :statement_descriptor => "#{self.site.description.truncate(22)}"
          )                        
        rescue Exception => ex
          resp.error = "Error during capture process\n#{ex.message}"                
        end            
        if resp.error.nil?
          InvoiceTransaction.create(
            :invoice_id => self.id,
            :transaction_id => c.id,
            :transaction_type => InvoiceTransaction::TYPE_AUTHCAP,
            :payment_processor => sc.pp_name,
            :amount => c.amount / 100.0,
            :captured => true,
            :date_processed => DateTime.now.utc,
            :success => c.status == 'succeeded'
          )
          if c.status == 'succeeded'
            self.financial_status = Invoice::FINANCIAL_STATUS_CAPTURED
            self.save
            resp.success = true
          else
            resp.error = "Error capturing funds."
          end
        end
                  
    end        
  end      
  return resp
end

#authorized?Boolean

Returns:

  • (Boolean)

134
135
136
# File 'app/models/caboose/invoice.rb', line 134

def authorized?
  self.financial_status == 'authorized'
end

#calculateObject

def refund

PaymentProcessor.refund(self)

end

def void

PaymentProcessor.void(self)

end


146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
# File 'app/models/caboose/invoice.rb', line 146

def calculate        
  self.update_column(:subtotal  , self.calculate_subtotal  )
  self.update_column(:tax       , self.calculate_tax       )
  self.update_column(:shipping  , self.calculate_shipping  )
  self.update_column(:handling  , self.calculate_handling  )
  self.update_column(:gift_wrap , self.calculate_gift_wrap )
  
  # Calculate the total without the discounts first       
  self.discounts.each{ |d| d.update_column(:amount, 0.0) } if self.discounts
  self.update_column(:discount  , 0.00)
  self.update_column(:total     , self.calculate_total     )
        
  # Now calculate the discounts and re-calculate the total
  self.update_column(:discount  , self.calculate_discount  )
  self.update_column(:total     , self.calculate_total     )      
  
  self.update_column(:cost      , self.calculate_cost      )
  self.update_column(:profit    , self.calculate_profit    )              
end

#calculate_costObject


216
217
218
219
220
221
222
223
224
225
# File 'app/models/caboose/invoice.rb', line 216

def calculate_cost      
  x = 0.0
  invalid_cost = false
  self.line_items.each do |li|
    invalid_cost = true if li.variant.nil? || li.variant.cost.nil?
    x = (x + (li.variant.cost * li.quantity)) if (!li.variant.cost.blank? && !li.quantity.blank?)
  end
  return 0.00 if invalid_cost
  return x            
end

#calculate_discountObject


200
201
202
203
204
205
206
207
208
209
210
# File 'app/models/caboose/invoice.rb', line 200

def calculate_discount              
  x = 0.0
  if self.discounts && self.discounts.count > 0                              
    self.discounts.each do |d|
      d.calculate_amount                    
      x = x + d.amount
    end
  end
  x = x + self.custom_discount if self.custom_discount
  return x
end

#calculate_gift_wrapObject


190
191
192
193
194
195
196
197
198
# File 'app/models/caboose/invoice.rb', line 190

def calculate_gift_wrap      
  x = 0.0
  self.line_items.each do |li|
    next if !li.gift_wrap
    next if !li.variant.product.allow_gift_wrap
    x = x + li.variant.product.gift_wrap_price * li.quantity
  end
  return x
end

#calculate_handlingObject


185
186
187
188
# File 'app/models/caboose/invoice.rb', line 185

def calculate_handling
  return 0.0 if self.site.nil? || self.site.store_config.nil?      
  self.subtotal * self.site.store_config.handling_percentage.to_f
end

#calculate_profitObject


227
228
229
230
# File 'app/models/caboose/invoice.rb', line 227

def calculate_profit
  return 0.00 if self.cost.nil?
  return (self.total - (self.tax ? self.tax : 0.00) - (self.shipping ? self.shipping : 0.00) - (self.handling ? self.handling : 0.00) - (self.gift_wrap ? self.gift_wrap : 0.00)) - self.cost
end

#calculate_shippingObject


178
179
180
181
182
183
# File 'app/models/caboose/invoice.rb', line 178

def calculate_shipping      
  return 0.0 if self.invoice_packages.nil? || self.invoice_packages.count == 0
  x = 0.0
  self.invoice_packages.all.each{ |op| x = x + op.total }
  return x
end

#calculate_subtotalObject


166
167
168
169
170
171
172
# File 'app/models/caboose/invoice.rb', line 166

def calculate_subtotal
  return 0.0 if self.line_items.empty?
  self.line_items.each{ |li| li.verify_unit_price } # Make sure the unit prices are populated        
  x = 0.0      
  self.line_items.each{ |li| x = x + (li.unit_price * li.quantity) } # Fixed issue with quantity 
  return x
end

#calculate_taxObject


174
175
176
# File 'app/models/caboose/invoice.rb', line 174

def calculate_tax      
  return TaxCalculator.tax(self)
end

#calculate_totalObject


212
213
214
# File 'app/models/caboose/invoice.rb', line 212

def calculate_total
  return (self.subtotal + self.tax + self.shipping + self.handling + self.gift_wrap) - self.discount
end

#capture_fundsObject

Capture funds from a previously authorized transaction


333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
# File 'app/models/caboose/invoice.rb', line 333

def capture_funds
  
  resp = StdClass.new      
  it = InvoiceTransaction.where(:invoice_id => self.id, :success => true).first
        
  if self.financial_status == Invoice::FINANCIAL_STATUS_CAPTURED
    resp.error = "Funds for this invoice have already been captured."    
  elsif self.total > it.amount
    resp.error = "The invoice total exceeds the authorized amount."
  elsif it.nil?
    resp.error = "This invoice doesn't seem to be authorized."
  else
                    
    sc = self.site.store_config                
    case sc.pp_name
      
      #when 'authorize.net'
      #  transaction = AuthorizeNet::AIM::Transaction.new(sc.authnet_api_login_id, sc.authnet_api_transaction_key)
      #  response = transaction.prior_auth_capture(t.transaction_id, self.total)
      #  
      #  ot = Caboose::InvoiceTransaction.create(
      #    :invoice_id        => self.id,
      #    :date_processed    => DateTime.now.utc,
      #    :transaction_type  => InvoiceTransaction::TYPE_CAPTURE,
      #    :payment_processor => sc.pp_name,
      #    :amount            => self.total,        
      #    :success           => response.response_code && response.response_code == '1',            
      #    :transaction_id    => response.transaction_id,
      #    :auth_code         => response.authorization_code,
      #    :response_code     => response.response_code
      #  )
      #  if ot.success
      #    self.date_captured = DateTime.now.utc
      #    self.save              
      #  end                                    
      #  self.update_attribute(:financial_status, Invoice::FINANCIAL_STATUS_CAPTURED)
      #  resp.success = 'Captured funds successfully'
                                
      when StoreConfig::PAYMENT_PROCESSOR_STRIPE
                                      
        it = Caboose::InvoiceTransaction.where(:invoice_id => self.id, :success => true).first
        if it.nil?
          resp.error = "Error capturing funds for invoice #{self.id}. No previous successful authorization for this invoice exists."
          return false
        else                        
          Stripe.api_key = sc.stripe_secret_key.strip
          bt = nil
          begin
            c = Stripe::Charge.retrieve(it.transaction_id)
            c = c.capture
            bt = Stripe::BalanceTransaction.retrieve(c.balance_transaction)
          rescue Exception => ex
            resp.error = "Error during capture process\n#{ex.message}"                
          end
          
          if resp.error.nil?
            InvoiceTransaction.create(
              :invoice_id => self.id,
              :transaction_id => bt.id,
              :transaction_type => InvoiceTransaction::TYPE_CAPTURE,
              :payment_processor => sc.pp_name,
              :amount => bt.amount / 100,                
              :date_processed => DateTime.strptime(bt.created.to_s, '%s'),
              :success => bt.status == 'succeeded' || bt.status == 'pending'
            )
            if bt.status == 'succeeded' || bt.status == 'pending'
              self.financial_status = Invoice::FINANCIAL_STATUS_CAPTURED
              self.save
              resp.success = true
            else
              resp.error = "Error capturing funds."
            end
          end
        end
      
    end        
  end      
  return resp
end

#check_nil_fieldsObject


104
105
106
107
108
109
110
111
112
# File 'app/models/caboose/invoice.rb', line 104

def check_nil_fields
  self.subtotal        = 0.00 if self.subtotal.nil?       
  self.tax             = 0.00 if self.tax.nil?
  self.shipping        = 0.00 if self.shipping.nil?
  self.handling        = 0.00 if self.handling.nil?
  self.custom_discount = 0.00 if self.custom_discount.nil?
  self.discount        = 0.00 if self.discount.nil?
  self.total           = 0.00 if self.total.nil?
end

#create_invoice_packagesObject

Calculates the shipping packages required for all the items in the invoice


612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
# File 'app/models/caboose/invoice.rb', line 612

def create_invoice_packages
  
  Caboose.log("Creating invoice packages...")
  
  store_config = self.site.store_config            
  if !store_config.auto_calculate_packages                        
    InvoicePackage.custom_invoice_packages(store_config, self)
    return
  end
              
  # Make sure all the line items in the invoice have a quantity of 1
  extra_line_items = []
  self.line_items.each do |li|        
    if li.quantity > 1          
      (1..li.quantity).each{ |i|            
        extra_line_items << li.copy 
      }
      li.quantity = 1
      li.save
    end        
  end
  extra_line_items.each do |li|         
    li.quantity = 1                        
    li.save 
  end 
  
  # Make sure all the items in the invoice have attributes set
  self.line_items.each do |li|              
    v = li.variant
    next if v.downloadable
    Caboose.log("Error: variant #{v.id} has a zero weight") and return false if v.weight.nil? || v.weight == 0
    next if v.volume && v.volume > 0
    Caboose.log("Error: variant #{v.id} has a zero length") and return false if v.length.nil? || v.length == 0
    Caboose.log("Error: variant #{v.id} has a zero width" ) and return false if v.width.nil?  || v.width  == 0
    Caboose.log("Error: variant #{v.id} has a zero height") and return false if v.height.nil? || v.height == 0        
    v.volume = v.length * v.width * v.height
    v.save
  end
        
  # Reorder the items in the invoice by volume
  line_items = self.line_items.sort_by{ |li| li.quantity * (li.variant.volume ? li.variant.volume : 0.00) * -1 }
                  
  # Get all the packages we're going to use      
  all_packages = ShippingPackage.where(:site_id => self.site_id).reorder(:flat_rate_price).all      
  
  # Now go through each variant and fit it in a new or existing package            
  line_items.each do |li|        
    next if li.variant.downloadable
    
    # See if the item will fit in any of the existing packages
    it_fits = false
    self.invoice_packages.all.each do |op|
      it_fits = op.fits(li)
      if it_fits            
        li.invoice_package_id = op.id
        li.save            
        break
      end
    end        
    next if it_fits
    
    # Otherwise find the cheapest package the item will fit into
    it_fits = false
    all_packages.each do |sp|
      it_fits = sp.fits(li.variant)          
      if it_fits            
        op = InvoicePackage.create(:invoice_id => self.id, :shipping_package_id => sp.id)
        li.invoice_package_id = op.id
        li.save                          
        break
      end
    end
    next if it_fits
    
    Caboose.log("Error: line item #{li.id} (#{li.variant.product.title}) does not fit into any package.")               
  end      
end

#decrement_quantitiesObject


114
115
116
117
118
# File 'app/models/caboose/invoice.rb', line 114

def decrement_quantities            
  self.line_items.each do |line_item|
    line_item.variant.update_attribute(:quantity_in_stock, line_item.variant.quantity_in_stock - line_item.quantity)
  end            
end

#determine_statusesObject


538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
# File 'app/models/caboose/invoice.rb', line 538

def determine_statuses
  
  auth    = false
  capture = false
  void    = false
  refund  = false
  
  self.invoice_transactions.each do |it|
    auth    = true if it.transaction_type == InvoiceTransaction::TYPE_AUTHORIZE && it.success == true
    capture = true if it.transaction_type == InvoiceTransaction::TYPE_CAPTURE   && it.success == true
    void    = true if it.transaction_type == InvoiceTransaction::TYPE_VOID      && it.success == true
    refund  = true if it.transaction_type == InvoiceTransaction::TYPE_REFUND    && it.success == true
  end
  
  if    refund  then self.financial_status = Invoice::FINANCIAL_STATUS_REFUNDED
  elsif void    then self.financial_status = Invoice::FINANCIAL_STATUS_VOIDED
  elsif capture then self.financial_status = Invoice::FINANCIAL_STATUS_CAPTURED
  elsif auth    then self.financial_status = Invoice::FINANCIAL_STATUS_AUTHORIZED
  else               self.financial_status = Invoice::FINANCIAL_STATUS_PENDING
  end

  self.status = Invoice::STATUS_PENDING if self.status == Invoice::STATUS_CART && (refund || void || capture || auth) 
  
  self.save

end

#has_downloadable_items?Boolean

Returns:

  • (Boolean)

260
261
262
263
264
265
# File 'app/models/caboose/invoice.rb', line 260

def has_downloadable_items?
  self.line_items.each do |li|
    return true if li.variant.downloadable
  end
  return false
end

#has_empty_shipping_methods?Boolean

Returns:

  • (Boolean)

251
252
253
254
255
256
257
258
# File 'app/models/caboose/invoice.rb', line 251

def has_empty_shipping_methods?
  return true if self.invoice_packages.nil?
  return true if self.invoice_packages.count == 0
  self.invoice_packages.all.each do |op|
    return true if op.shipping_method_id.nil?
  end
  return false
end

#has_shippable_items?Boolean

Returns:

  • (Boolean)

267
268
269
270
271
272
# File 'app/models/caboose/invoice.rb', line 267

def has_shippable_items?
  self.line_items.each do |li|
    return true if !li.variant.downloadable
  end
  return false
end

#has_taxable_items?Boolean

Returns:

  • (Boolean)

274
275
276
277
278
279
# File 'app/models/caboose/invoice.rb', line 274

def has_taxable_items?
  self.line_items.each do |li|
    return true if li.variant.taxable && li.variant.taxable == true
  end
  return false
end

#hide_prices_for_any_line_item?Boolean

Returns:

  • (Boolean)

565
566
567
568
569
570
# File 'app/models/caboose/invoice.rb', line 565

def hide_prices_for_any_line_item?
  self.line_items.each do |li|
    return true if li.hide_prices
  end
  return false
end

#increment_quantitiesObject


120
121
122
123
124
# File 'app/models/caboose/invoice.rb', line 120

def increment_quantities            
  self.line_items.each do |line_item|
    line_item.variant.update_attribute(:quantity_in_stock, line_item.variant.quantity_in_stock - line_item.quantity)
  end            
end

#item_countObject


236
237
238
239
240
# File 'app/models/caboose/invoice.rb', line 236

def item_count
  count = 0
  self.line_items.each{ |li| count = count + li.quantity } if self.line_items
  return count
end

#refresh_transactionsObject


690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
# File 'app/models/caboose/invoice.rb', line 690

def refresh_transactions  
  InvoiceTransaction.where(:invoice_id => self.id).destroy_all        
  sc = self.site.store_config
  case sc.pp_name          
    when StoreConfig::PAYMENT_PROCESSOR_STRIPE
      
      if sc.stripe_secret_key && sc.stripe_secret_key.strip.length > 0            
        Stripe.api_key = sc.stripe_secret_key.strip
        charges = Stripe::Charge.list(:limit => 100, :customer => self.customer.stripe_customer_id)
        
        self.financial_status = Invoice::FINANCIAL_STATUS_PENDING                      
        charges.each do |c|            
          invoice_id = c. && c.['invoice_id'] ? c.['invoice_id'].to_i : nil            
          next if invoice_id.nil? || invoice_id != self.id
          
          if c.refunded                               then self.financial_status = Invoice::FINANCIAL_STATUS_REFUNDED
          elsif c.status == 'succeeded' && c.captured then self.financial_status = Invoice::FINANCIAL_STATUS_CAPTURED
          elsif c.status == 'succeeded'               then self.financial_status = Invoice::FINANCIAL_STATUS_AUTHORIZED            
          end                                    
                      
          auth_trans = InvoiceTransaction.create(
            :invoice_id => self.id,
            :transaction_id => c.id,
            :transaction_type => c.captured ? InvoiceTransaction::TYPE_AUTHCAP : InvoiceTransaction::TYPE_AUTHORIZE,
            :payment_processor => sc.pp_name,
            :amount => c.amount / 100.0,
            :amount_refunded => c.amount_refunded,
            :date_processed => DateTime.strptime(c.created.to_s, '%s'),              
            :success => c.status == 'succeeded',
            :captured => c.captured,
            :refunded => c.refunded              
          )
          if c.balance_transaction
            bt = Stripe::BalanceTransaction.retrieve(c.balance_transaction)
            capture_trans = InvoiceTransaction.create(
              :invoice_id => self.id,
              :parent_id => auth_trans.id, 
              :transaction_id => bt.id,
              :transaction_type => InvoiceTransaction::TYPE_CAPTURE,
              :payment_processor => sc.pp_name,
              :amount => bt.amount / 100.0,                
              :date_processed => DateTime.strptime(bt.created.to_s, '%s'),
              :success => bt.status == 'succeeded' || bt.status == 'pending'
            )                            
          end
          if c.refunds && c.refunds['total_count'] > 0
            total = 0
            c.refunds['data'].each do |r|
              total = total + r.amount
              InvoiceTransaction.create(
                :invoice_id => self.id,
                :parent_id => auth_trans.id,
                :transaction_id => r.id,
                :transaction_type => InvoiceTransaction::TYPE_REFUND,
                :payment_processor => sc.pp_name,
                :amount => r.amount / 100.0,                
                :date_processed => DateTime.strptime(r.created.to_s, '%s'),
                :success => r.status == 'succeeded' || r.status == 'pending'
              )
            end
            total = total.to_f / 100
            if total >= auth_trans.amount
              auth_trans.refunded = true
              auth_trans.save
            end
          end
        end
        self.save
      end
  end
end

#refund(amount = nil) ⇒ Object

Refund an order


471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
# File 'app/models/caboose/invoice.rb', line 471

def refund(amount = nil)
  
  resp = StdClass.new      
  it = InvoiceTransaction.where(:invoice_id => self.id, :success => true).first
  amount = self.total - self.amount_refunded if amount.nil?
        
  if self.financial_status == Invoice::FINANCIAL_STATUS_REFUNDED
    resp.error = "Funds for this invoice have already been refunded."    
  elsif amount > self.amount_refunded
    resp.error = "The amount to refund exceeds the amount available to refund."
  elsif it.nil?
    resp.error = "This invoice doesn't seem to be authorized."
  else
                    
    sc = self.site.store_config                
    case sc.pp_name
                                
      when StoreConfig::PAYMENT_PROCESSOR_STRIPE
                                      
        it = Caboose::InvoiceTransaction.where(:invoice_id => self.id, :success => true).first
        if it.nil?
          resp.error = "Error capturing funds for invoice #{self.id}. No previous successful authorization for this invoice exists."
          return false
        else                        
          Stripe.api_key = sc.stripe_secret_key.strip
          bt = nil
          begin
            c = Stripe::Charge.retrieve(it.transaction_id)
            c = c.capture
            bt = Stripe::BalanceTransaction.retrieve(c.balance_transaction)
          rescue Exception => ex
            resp.error = "Error during capture process\n#{ex.message}"                
          end
          
          if resp.error.nil?
            InvoiceTransaction.create(
              :invoice_id => self.id,
              :transaction_id => bt.id,
              :transaction_type => InvoiceTransaction::TYPE_CAPTURE,
              :payment_processor => sc.pp_name,
              :amount => bt.amount / 100,                
              :date_processed => DateTime.strptime(bt.created.to_s, '%s'),
              :success => bt.status == 'succeeded' || bt.status == 'pending'
            )
            if bt.status == 'succeeded' || bt.status == 'pending'
              self.financial_status = Invoice::FINANCIAL_STATUS_CAPTURED
              self.save
              resp.success = true
            else
              resp.error = "Error capturing funds."
            end
          end
        end
      
    end        
  end      
  return resp
end

#resend_confirmationObject


126
127
128
# File 'app/models/caboose/invoice.rb', line 126

def resend_confirmation
  InvoicesMailer.configure_for_site(self.site_id).customer_new_invoice(self).deliver
end

#send_payment_authorization_emailObject


530
531
532
# File 'app/models/caboose/invoice.rb', line 530

def send_payment_authorization_email
  InvoicesMailer.configure_for_site(self.site_id).customer_payment_authorization(self).deliver
end

#send_receipt_emailObject


534
535
536
# File 'app/models/caboose/invoice.rb', line 534

def send_receipt_email
  InvoicesMailer.configure_for_site(self.site_id).customer_receipt(self).deliver
end

#shipping_and_handlingObject


232
233
234
# File 'app/models/caboose/invoice.rb', line 232

def shipping_and_handling
  (self.shipping ? self.shipping : 0.0) + (self.handling ? self.handling : 0.0)      
end

#take_gift_card_fundsObject


242
243
244
245
246
247
248
249
# File 'app/models/caboose/invoice.rb', line 242

def take_gift_card_funds
  return if self.discounts.nil? || self.discounts.count == 0
  self.discounts.each do |d|        
    gc = d.gift_card
    gc.balance = gc.balance - d.amount
    gc.save
  end
end

#test?Boolean

Returns:

  • (Boolean)

130
131
132
# File 'app/models/caboose/invoice.rb', line 130

def test?
  self.status == 'testing'
end

#verify_invoice_packagesObject


579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
# File 'app/models/caboose/invoice.rb', line 579

def verify_invoice_packages
  
  Caboose.log("Verifying invoice packages....")
  
  # See if any there are any empty invoice packages          
  self.invoice_packages.each do |ip|
    count = 0
    self.line_items.each do |li|
      count = count + 1 if li.invoice_package_id == ip.id
    end
    ip.destroy if count == 0
  end
  
  # See if any line items aren't associated with an invoice package
  line_items_attached = true      
  self.line_items.each do |li|
    line_items_attached = false if li.invoice_package_id.nil?
  end
  shipping_packages_attached = true
  self.invoice_packages.each do |ip|    
    shipping_packages_attached = false if ip.shipping_package_id.nil?                          
  end
  ips = self.invoice_packages
  if ips.count == 0 || !line_items_attached || !shipping_packages_attached        
    self.calculate
    LineItem.where(:invoice_id => self.id).update_all(:invoice_package_id => nil)
    InvoicePackage.where(:invoice_id => self.id).destroy_all          
    self.create_invoice_packages
  end
              
end

#voidObject

Void an authorized invoice


414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
# File 'app/models/caboose/invoice.rb', line 414

def void
        
  resp = StdClass.new
  t = InvoiceTransaction.where(:invoice_id => self.id, :transaction_type => InvoiceTransaction::TYPE_AUTHORIZE, :success => true).first
  
  if self.financial_status == Invoice::FINANCIAL_STATUS_CAPTURED
    resp.error = "This invoice has already been captured, you will need to refund instead"
  elsif t.nil?
    resp.error = "This invoice doesn't seem to be authorized."
  else
            
    sc = self.site.store_config
    ot = Caboose::InvoiceTransaction.new(
      :invoice_id => self.id,
      :date_processed => DateTime.now.utc,
      :transaction_type => InvoiceTransaction::TYPE_VOID,
      :payment_processor => sc.pp_name,
      :amount => self.total
    )
    
    case sc.pp_name
      when 'authorize.net'            
        response = AuthorizeNet::SIM::Transaction.new(
          sc., 
          sc.authnet_api_transaction_key,                      
          self.total,
          :transaction_type => InvoiceTransaction::TYPE_VOID,
          :transaction_id => t.transaction_id,
          :test => sc.pp_testing
        )                    
        self.update_attributes(
          :financial_status => Invoice::FINANCIAL_STATUS_VOIDED,
          :status => Invoice::STATUS_CANCELED
        )
        self.save          
        # TODO: Add the variant quantities invoiceed back        
        resp.success = "Invoice voided successfully"
                    
        ot.success        = response.response_code && response.response_code == '1'            
        ot.transaction_id = response.transaction_id
        #ot.auth_code      = response.authorization_code
        ot.response_code  = response.response_code            
        ot.save
      
      when 'stripe'
        # TODO: Implement void invoice for strip
        
      when 'payscape'
        # TODO: Implement void invoice for payscape
        
    end
    
  end
  return resp      
end