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_SHIPPED =
'shipped'
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'
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



526
527
528
529
# File 'app/models/caboose/invoice.rb', line 526

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

#authorized?Boolean

Returns:

  • (Boolean)


143
144
145
# File 'app/models/caboose/invoice.rb', line 143

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

#calculateObject

def refund

PaymentProcessor.refund(self)

end

def void

PaymentProcessor.void(self)

end



155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
# File 'app/models/caboose/invoice.rb', line 155

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



225
226
227
228
229
230
231
232
233
234
# File 'app/models/caboose/invoice.rb', line 225

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)
  end
  return 0.00 if invalid_cost
  return x            
end

#calculate_discountObject



209
210
211
212
213
214
215
216
217
218
219
# File 'app/models/caboose/invoice.rb', line 209

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



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

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



194
195
196
197
# File 'app/models/caboose/invoice.rb', line 194

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



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

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



187
188
189
190
191
192
# File 'app/models/caboose/invoice.rb', line 187

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



175
176
177
178
179
180
181
# File 'app/models/caboose/invoice.rb', line 175

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



183
184
185
# File 'app/models/caboose/invoice.rb', line 183

def calculate_tax      
  return TaxCalculator.tax(self)
end

#calculate_totalObject



221
222
223
# File 'app/models/caboose/invoice.rb', line 221

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



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
331
332
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
# File 'app/models/caboose/invoice.rb', line 291

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



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

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



566
567
568
569
570
571
572
573
574
575
576
577
578
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
610
611
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
# File 'app/models/caboose/invoice.rb', line 566

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



123
124
125
126
127
# File 'app/models/caboose/invoice.rb', line 123

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



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
# File 'app/models/caboose/invoice.rb', line 492

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)


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

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)


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

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)


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

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)


283
284
285
286
287
288
# File 'app/models/caboose/invoice.rb', line 283

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)


519
520
521
522
523
524
# File 'app/models/caboose/invoice.rb', line 519

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



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

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



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

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

#refresh_transactionsObject



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
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
# File 'app/models/caboose/invoice.rb', line 644

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
      
      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

#refund(amount = nil) ⇒ Object

Refund an order



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
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
# File 'app/models/caboose/invoice.rb', line 429

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



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

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

#send_payment_authorization_emailObject



488
489
490
# File 'app/models/caboose/invoice.rb', line 488

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

#shipping_and_handlingObject



241
242
243
# File 'app/models/caboose/invoice.rb', line 241

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

#take_gift_card_fundsObject



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

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)


139
140
141
# File 'app/models/caboose/invoice.rb', line 139

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

#verify_invoice_packagesObject



533
534
535
536
537
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 533

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



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
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
# File 'app/models/caboose/invoice.rb', line 372

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