Class: CreditMemo

Overview

== Schema Information

Table name: credit_memos
Database name: primary

id :integer not null, primary key
category :string(255)
currency :string(255)
discount :decimal(8, 2)
document_date :date
gl_date :date
line_offset :decimal(8, 2)
line_total :decimal(10, 2)
line_total_discounted :decimal(8, 2)
old_line_total :decimal(8, 2)
old_tax_total :decimal(8, 2)
old_total :decimal(8, 2)
order_type :string(255)
original_order_missing_reason :string(255)
original_po_number :string(255)
reference_number :string(255) not null
remark :text
report_grouping :string
request_date :date
shipping_cost :decimal(8, 2)
shipping_coupon :decimal(8, 2)
state :string(255)
tax_date :date
tax_exempt :boolean
tax_offset :decimal(8, 2)
tax_total :decimal(8, 2)
taxable_total :decimal(12, 2)
taxjar_state :string
total :decimal(10, 2)
transmission_state :string(255)
uploads_count :integer
created_at :datetime
updated_at :datetime
account_specialist_id :integer
billing_address_id :integer
billing_customer_id :integer
company_id :integer
creator_id :integer
credit_order_id :integer
customer_id :integer
local_sales_rep_id :integer
original_invoice_id :integer
original_order_id :integer
primary_sales_rep_id :integer
purchase_order_id :integer
resource_tax_rate_id :integer
rma_id :integer
secondary_sales_rep_id :integer
shipping_address_id :integer
support_case_id :integer
updater_id :integer

Indexes

idx_billing_address_id (billing_address_id)
idx_company_id_customer_id_gl_date (company_id,customer_id,gl_date)
idx_credit_order_id (credit_order_id)
idx_customer_id_state (customer_id,state)
idx_original_order_id (original_order_id)
idx_rma_id (rma_id)
idx_shipping_address_id (shipping_address_id)
index_credit_memos_on_billing_customer_id (billing_customer_id)
index_credit_memos_on_local_sales_rep_id (local_sales_rep_id)
index_credit_memos_on_original_invoice_id (original_invoice_id)
index_credit_memos_on_reference_number (reference_number) UNIQUE
index_credit_memos_on_report_grouping (report_grouping)
index_credit_memos_on_resource_tax_rate_id (resource_tax_rate_id)
index_credit_memos_on_state_and_transmission_state (state,transmission_state)
index_credit_memos_on_support_case_id (support_case_id)

Foreign Keys

fk_credit_memos_resource_tax_rates (resource_tax_rate_id => resource_tax_rates.id) ON DELETE => cascade
fk_rails_... (billing_address_id => addresses.id)
fk_rails_... (billing_customer_id => parties.id)
fk_rails_... (customer_id => parties.id)
fk_rails_... (local_sales_rep_id => parties.id)
fk_rails_... (shipping_address_id => addresses.id)
fk_rails_... (support_case_id => support_cases.id)

Defined Under Namespace

Classes: PdfGenerator, SubmitToTaxjar

Constant Summary collapse

REFERENCE_NUMBER_PATTERN =
/^CM\d+/i
CATEGORIES =
%w[rma standalone]
LINE_ITEM_CATEGORIES =
[{ name: 'Warranty',       account_number: WARRANTY_CLAIMS_ACCOUNT, business_unit: 'default' },
{ name: 'Rebate',         account_number: REBATES_STANDALONE_ACCOUNT, business_unit: 'default' },
{ name: 'Lead Protection', account_number: RETURN_COUPONS_ACCOUNT, business_unit: 'default' },
{ name: 'Trade Discount', account_number: RETURN_COUPONS_ACCOUNT,  business_unit: 'default' },
{ name: 'Coupon (Goods)', account_number: RETURN_COUPONS_ACCOUNT,  business_unit: 'default' },
{ name: 'Coupon (Freight)', account_number: RETURN_FREIGHT_COUPONS_ACCOUNT,  business_unit: 'sales' },
{ name: 'Freight',        account_number: RETURN_FREIGHT_COUPONS_ACCOUNT,    business_unit: 'sales' },
{ name: 'Misc',           account_number: RETURN_COUPONS_ACCOUNT,  business_unit: 'default' },
{ name: 'Item',           account_number: CUSTOMER_RETURNS,        business_unit: 'default' }]

Constants included from Models::Auditable

Models::Auditable::ALWAYS_IGNORED

Instance Attribute Summary collapse

Attributes included from Models::Itemizable

#force_total_reset, #total_reset

Belongs to collapse

Methods included from Models::SupportCaseLinkable

#support_case

Methods included from Models::Auditable

#creator, #updater

Methods included from Models::TaxableResource

#resource_tax_rate

Methods included from Models::Itemizable

#account_specialist, #local_sales_rep, #primary_sales_rep, #secondary_sales_rep

Has one collapse

Has many collapse

Methods included from Models::Itemizable

#coupons, #discounts

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Models::TaxjarSubmittable

#customer_sync_instance, #delete_from_taxjar, #evaluate_taxjar_submission, #record_already_exists_on_taxjar?, #resubmit_to_taxjar, #should_be_submitted_to_taxjar?, #should_sync_customer_with_taxjar?, #submit_to_taxjar, #sync_customer_with_taxjar, #taxjar_customer_id, #taxjar_submission_instance

Methods included from Models::SupportCaseLinkable

#support_case_ref, #support_case_ref=

Methods included from Models::AccountingDocumentTransmittable

#can_be_transmitted?, #fallback_notification_channel_type, #notification_channel_sort_order, #notification_channel_types, #notification_channels, #own_notification_channel_type, #post_communication_exception_hook, #post_communication_sent_hook, #primary_transmission_contact, #primary_transmission_contact_point_id, #transmission_contact_points

Methods included from Models::Auditable

#all_skipped_columns, #audit_reference_data, #should_not_save_version, #stamp_record

Methods included from Models::TaxableResource

#apply_tax_rate_to_line_items, #build_tax_params, #calculate_tax_for_all_lines, #copy_tax_rate, #effective_date, #get_rates_for_line, #get_tax_rate, #manual_rate_goods, #manual_rate_services, #manual_rate_shipping, #origin_address, #refresh_tax_rate, #resource_not_taxable?, #set_initial_tax_rate, #should_refresh_tax_rate?, #state_code, #state_code_sym, #taxes_grouped_by_rate, #taxes_grouped_by_type

Methods included from Models::Itemizable

#add_line_item, #additional_items, #assign_sequence, #billing_entity, #breakdown_of_prices, #calculate_actual_insured_value, #calculate_discounts, #calculate_shipping_cost, #coupon_search, #customer_applied_coupons, #customer_can_apply_coupon?, #discounts_changed?, #discounts_grouped_by_coupon, #discounts_subtotal, #effective_discount, #effective_shipping_discount, #has_kits?, #has_kits_or_serial_numbers?, #has_serial_numbers?, #is_credit_order?, #line_items_requiring_serial_number, #line_items_with_counters, #line_total_plus_tax, #main_rep, #perform_db_total, #purge_empty_quoting_deliveries, #purge_shipping_when_no_other_lines, #remove_line_item, #require_total_reset?, #reset_discount, #set_for_recalc, #set_signature_confirmation_on_shipping_address_change, #set_totals, #shipping_conditions_changed?, #shipping_discounted, #shipping_method_changed?, #should_recalculate_shipping?, #smartinstall_data, #smartsupport_data, #store, #subtotal_cogs, #sync_shipping_line, #total_cogs

Methods inherited from ApplicationRecord

ransackable_associations, ransackable_attributes, ransackable_scopes, ransortable_attributes, #to_relation

Methods included from Models::EventPublishable

#publish_event

Instance Attribute Details

#billing_address_idObject (readonly)



135
# File 'app/models/credit_memo.rb', line 135

validates :category, :customer_id, :company_id, :billing_address_id, :shipping_address_id, :request_date, :tax_date, :document_date, :gl_date, :order_type, presence: true

#categoryObject (readonly)



135
# File 'app/models/credit_memo.rb', line 135

validates :category, :customer_id, :company_id, :billing_address_id, :shipping_address_id, :request_date, :tax_date, :document_date, :gl_date, :order_type, presence: true

#company_idObject (readonly)



135
# File 'app/models/credit_memo.rb', line 135

validates :category, :customer_id, :company_id, :billing_address_id, :shipping_address_id, :request_date, :tax_date, :document_date, :gl_date, :order_type, presence: true

#credit_order_idObject (readonly)



136
# File 'app/models/credit_memo.rb', line 136

validates :credit_order_id, presence: { if: proc { |cm| cm.category == 'rma' } }

#customer_companyObject

Returns the value of attribute customer_company.



163
164
165
# File 'app/models/credit_memo.rb', line 163

def customer_company
  @customer_company
end

#customer_idObject (readonly)



135
# File 'app/models/credit_memo.rb', line 135

validates :category, :customer_id, :company_id, :billing_address_id, :shipping_address_id, :request_date, :tax_date, :document_date, :gl_date, :order_type, presence: true

#customer_nameObject

Returns the value of attribute customer_name.



163
164
165
# File 'app/models/credit_memo.rb', line 163

def customer_name
  @customer_name
end

#do_not_set_totalsObject

Returns the value of attribute do_not_set_totals.



163
164
165
# File 'app/models/credit_memo.rb', line 163

def do_not_set_totals
  @do_not_set_totals
end

#document_dateObject (readonly)



135
# File 'app/models/credit_memo.rb', line 135

validates :category, :customer_id, :company_id, :billing_address_id, :shipping_address_id, :request_date, :tax_date, :document_date, :gl_date, :order_type, presence: true

#gl_dateObject (readonly)



135
# File 'app/models/credit_memo.rb', line 135

validates :category, :customer_id, :company_id, :billing_address_id, :shipping_address_id, :request_date, :tax_date, :document_date, :gl_date, :order_type, presence: true

#order_typeObject (readonly)



135
# File 'app/models/credit_memo.rb', line 135

validates :category, :customer_id, :company_id, :billing_address_id, :shipping_address_id, :request_date, :tax_date, :document_date, :gl_date, :order_type, presence: true

#original_invoice_idObject (readonly)



139
# File 'app/models/credit_memo.rb', line 139

validates :original_invoice_id, numericality: { allow_nil: true }

#original_invoice_refObject

Returns the value of attribute original_invoice_ref.



163
164
165
# File 'app/models/credit_memo.rb', line 163

def original_invoice_ref
  @original_invoice_ref
end

#original_order_idObject (readonly)



138
# File 'app/models/credit_memo.rb', line 138

validates :original_order_id, numericality: { allow_nil: true }

#original_order_missing_reasonObject (readonly)



140
# File 'app/models/credit_memo.rb', line 140

validates :original_order_missing_reason, presence: { if: proc { |cm| cm.original_invoice_id.nil? && !cm.fully_offset? } }

#original_order_refObject

Returns the value of attribute original_order_ref.



163
164
165
# File 'app/models/credit_memo.rb', line 163

def original_order_ref
  @original_order_ref
end

#request_dateObject (readonly)



135
# File 'app/models/credit_memo.rb', line 135

validates :category, :customer_id, :company_id, :billing_address_id, :shipping_address_id, :request_date, :tax_date, :document_date, :gl_date, :order_type, presence: true

#shipping_address_idObject (readonly)



135
# File 'app/models/credit_memo.rb', line 135

validates :category, :customer_id, :company_id, :billing_address_id, :shipping_address_id, :request_date, :tax_date, :document_date, :gl_date, :order_type, presence: true

#tax_dateObject (readonly)



135
# File 'app/models/credit_memo.rb', line 135

validates :category, :customer_id, :company_id, :billing_address_id, :shipping_address_id, :request_date, :tax_date, :document_date, :gl_date, :order_type, presence: true

Class Method Details

.available_to_applyActiveRecord::Relation<CreditMemo>

A relation of CreditMemos that are available to apply. Active Record Scope

Returns:

See Also:



159
# File 'app/models/credit_memo.rb', line 159

scope :available_to_apply, -> { where(state: %w[printed partially_offset]) }

.credit_memo_count(company_id = nil, where_conditions = nil, where_not_conditions = nil) ⇒ Object



226
227
228
229
230
231
232
# File 'app/models/credit_memo.rb', line 226

def self.credit_memo_count(company_id = nil, where_conditions = nil, where_not_conditions = nil)
  c = CreditMemo.order('id')
  c = c.where(company_id: company_id) unless company_id.nil?
  c = c.where(where_conditions) unless where_conditions.nil?
  c = c.where.not(where_not_conditions) unless where_not_conditions.nil?
  c.count
end

.for_company_idActiveRecord::Relation<CreditMemo>

A relation of CreditMemos that are for company id. Active Record Scope

Returns:

See Also:



161
# File 'app/models/credit_memo.rb', line 161

scope :for_company_id, ->(company_id) { where(company_id: company_id) }

.new_credit_memo_from_order(order) ⇒ Object



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
469
470
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
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
# File 'app/models/credit_memo.rb', line 428

def self.new_credit_memo_from_order(order)
  CreditMemo.transaction do
    memo = CreditMemo.new
    memo.category = 'rma'
    memo.credit_order = order
    if order.rma.original_invoice.present?
      memo.original_invoice = order.rma.original_invoice
      memo.report_grouping = order.rma.original_invoice.report_grouping
      memo.original_order = order.rma.original_order if order.rma.original_order.present?
      memo.order_type = order.order_type
    else
      memo.original_order_missing_reason = 'Not provided on RMA'
      memo.order_type = Order::SALES_ORDER
    end
    invoice = memo.original_invoice.nil? ? nil : memo.original_invoice
    memo.rma = order.rma
    memo.billing_address = order.billing_address
    memo.shipping_address = order.shipping_address
    unless invoice.nil?
      memo.primary_sales_rep = invoice.primary_sales_rep
      memo.secondary_sales_rep = invoice.secondary_sales_rep
      memo.local_sales_rep = invoice.local_sales_rep
    end
    # memo.account_specialist = order.account_specialist
    memo.currency = order.currency
    memo.tax_exempt = order.tax_exempt

    # Build a map between source order line items and their credit memo copies
    # to later reassign line_discounts properly
    line_item_map = {}
    from_ci_invoice = order.ci_invoice_credit_order?
    order.line_items.each do |li|
      copy = li.deep_dup
      # Clear duplicated line_discounts - they reference order's discount records
      # We'll recreate them after creating credit memo's discount records
      copy.line_discounts.clear
      copy.resource = nil
      copy.credit_rma_item_id = nil
      copy.delivery_id = nil
      if from_ci_invoice
        # Inherit the exact per-line tax from the source credit order. The
        # line item's `before_create :set_initial_tax_rate` will still
        # reassign tax_rate / tax_type / resource_tax_rate_id to the credit
        # memo's own (matching) rate; `do_not_calculate_tax = true` prevents
        # tax_total from being recomputed from rate × discounted_price, which
        # would drop marketplace-set (CI invoice) amounts that do not align
        # with our rate.
        copy.tax_rate = li.tax_rate
        copy.tax_type = li.tax_type
        copy.resource_tax_rate_id = li.resource_tax_rate_id
        copy.tax_total = li.tax_total
        copy.do_not_calculate_tax = true
      else
        copy.tax_rate = nil
        copy.tax_type = nil
        copy.resource_tax_rate_id = nil
        copy.tax_total = 0
      end
      copy.cm_category = (li.is_shipping? ? 'Freight' : 'Item')
      copy.credit_order_line_item_id = li.id
      memo.line_items << copy
      line_item_map[li.id] = copy
    end
    memo.tax_total = order.tax_total
    memo.line_total = order.line_total
    memo.total = order.total
    memo.discount = order.line_items.to_a.sum(&:coupon_amount)
    memo.shipping_cost = 0
    memo.customer = order.customer
    memo.company = order.customer.store.company
    memo.request_date = order.rma.created_at.to_datetime.to_date
    memo.tax_date = order.tax_date || order.shipped_date || Date.current
    memo.gl_date = Date.current
    memo.document_date = Date.current
    memo.original_po_number = order.rma.original_invoice.po_number if order.rma.original_invoice.present?
    memo.save!

    # Create discount records for the credit memo and build a map
    # from original discount_id => new credit memo discount_id
    discount_map = {}
    order.discounts.each do |discount|
      copy_discount = discount.dup
      copy_discount.itemizable = memo
      copy_discount.save!
      discount_map[discount.id] = copy_discount.id
    end

    # Recreate line_discounts on the copied credit memo line items with valid
    # credit memo-scoped discount_ids. If a referenced discount is missing on the
    # order (data drift), fall back to finding/creating a credit memo-level
    # discount by coupon_id to preserve amounts and avoid FK violations.
    line_item_map.each do |original_li_id, memo_li|
      original_li = order.line_items.find { |li| li.id == original_li_id }
      next unless original_li

      original_li.line_discounts.each do |ld|
        new_discount_id = discount_map[ld.discount_id]
        if new_discount_id.blank?
          # Fallback: find or create discount on credit memo by coupon_id
          memo_discount = memo.discounts.find_by(coupon_id: ld.coupon_id)
          memo_discount ||= Discount.create!(itemizable: memo, coupon_id: ld.coupon_id, amount: 0)
          new_discount_id = memo_discount.id
        end
        memo_li.line_discounts.create!(amount: ld.amount,
                                       coupon_id: ld.coupon_id,
                                       discount_id: new_discount_id)
      end
      memo_li.save!
    end

    # Recalculate discount total from line discounts
    memo.discount = memo.line_items.to_a.sum(&:coupon_amount)
    memo.approve!
    memo.printed!

    order.line_items.collect do |li|
      li.credit_rma_item.returned_line_item.resource
    rescue StandardError
      nil
    end.compact.uniq.each do |oo|
      oo.payments.each do |pp|
        pp.update(credit_memo_id: memo.id) if pp.authorized?
      end
    end
  end
end

.printedActiveRecord::Relation<CreditMemo>

A relation of CreditMemos that are printed. Active Record Scope

Returns:

See Also:



160
# File 'app/models/credit_memo.rb', line 160

scope :printed, -> { where(state: %w[printed]) }

.states_for_selectObject



222
223
224
# File 'app/models/credit_memo.rb', line 222

def self.states_for_select
  CreditMemo.state_machines[:state].states.map { |s| [s.human_name.titleize, s.name] }.sort
end

Instance Method Details

#activitiesActiveRecord::Relation<Activity>

Returns:

See Also:



126
# File 'app/models/credit_memo.rb', line 126

has_many   :activities, as: :resource, dependent: :nullify

#available_to_refundObject



334
335
336
337
338
339
340
341
342
343
344
# File 'app/models/credit_memo.rb', line 334

def available_to_refund
  if original_invoice.nil? or (rma.present? and rma.payment_method != 'Original Payment Method')
    available = BigDecimal('0.00')
  else
    available = BigDecimal('0.00')
    original_invoice.payments.can_be_refunded.each do |payment|
      available += payment.available_to_refund
    end
  end
  available
end

#balanceObject



306
307
308
# File 'app/models/credit_memo.rb', line 306

def balance
  total - funds_offset
end

#billing_addressAddress

Returns:

See Also:



118
# File 'app/models/credit_memo.rb', line 118

belongs_to :billing_address, class_name: 'Address', optional: true

#billing_customerCustomer

Returns:

See Also:



116
# File 'app/models/credit_memo.rb', line 116

belongs_to :billing_customer, class_name: 'Customer', inverse_of: :billing_credit_memos, optional: true

#build_activityObject



310
311
312
# File 'app/models/credit_memo.rb', line 310

def build_activity
  activities.new(resource: self, party: customer)
end

#can_be_refunded?Boolean

Returns:

  • (Boolean)


302
303
304
# File 'app/models/credit_memo.rb', line 302

def can_be_refunded?
  (printed? or partially_offset?) and available_to_refund > 0
end

#communicationsActiveRecord::Relation<Communication>

Returns:

See Also:



133
# File 'app/models/credit_memo.rb', line 133

has_many   :communications, -> { order(:id).reverse_order }, as: :resource, dependent: :nullify

#companyCompany

Returns:

See Also:



117
# File 'app/models/credit_memo.rb', line 117

belongs_to :company

#credit_orderOrder

Returns:

See Also:



111
# File 'app/models/credit_memo.rb', line 111

belongs_to :credit_order, class_name: 'Order', optional: true


394
395
396
# File 'app/models/credit_memo.rb', line 394

def crm_link
  UrlHelper.instance.credit_memo_path(self)
end

#currency_symbolObject



386
387
388
# File 'app/models/credit_memo.rb', line 386

def currency_symbol
  Money::Currency.new(currency).symbol
end

#customerCustomer

Returns:

See Also:



115
# File 'app/models/credit_memo.rb', line 115

belongs_to :customer, inverse_of: :credit_memos

#disable_auto_couponObject



559
560
561
# File 'app/models/credit_memo.rb', line 559

def disable_auto_coupon
  true
end

#do_not_detect_shippingObject



555
556
557
# File 'app/models/credit_memo.rb', line 555

def do_not_detect_shipping
  true
end

#editing_locked?Boolean

Returns:

  • (Boolean)


282
283
284
# File 'app/models/credit_memo.rb', line 282

def editing_locked?
  credit_order.present? or printed? or partially_offset? or fully_offset? or processing_refund?
end

#file_nameObject



398
399
400
# File 'app/models/credit_memo.rb', line 398

def file_name
  "CreditMemo_#{reference_number}.pdf"
end

#funds_fully_offset?Boolean

Returns:

  • (Boolean)


286
287
288
# File 'app/models/credit_memo.rb', line 286

def funds_fully_offset?
  funds_offset == total
end

#funds_offsetObject



298
299
300
# File 'app/models/credit_memo.rb', line 298

def funds_offset
  receipt_details.non_voided.sum(:amount) - outgoing_payment_items.applied.sum(:amount)
end

#funds_partially_offset?Boolean

Returns:

  • (Boolean)


290
291
292
# File 'app/models/credit_memo.rb', line 290

def funds_partially_offset?
  !funds_offset.zero? && !(total - funds_offset).zero?
end

#generate_pdfObject



414
415
416
417
418
419
420
421
422
423
424
425
426
# File 'app/models/credit_memo.rb', line 414

def generate_pdf
  store = original_invoice.try(:store) || company.stores.first
  file_name = "#{reference_number}_credit_memo.pdf"
  path = Rails.application.config.x.temp_storage_path.join(file_name)

  pdf = CreditMemo::PdfGenerator.new(self, store: store, show_tax_info: true).generate

  File.binwrite(path, pdf)

  upload = Upload.uploadify(path, 'credit_memo_pdf', self, file_name)
  uploads << upload
  upload
end

#get_or_regen_pdf(logger = nil) ⇒ Object



402
403
404
405
406
407
408
409
410
411
412
# File 'app/models/credit_memo.rb', line 402

def get_or_regen_pdf(logger = nil)
  logger ||= Rails.logger
  pdf = uploads.in_category('credit_memo_pdf').first
  logger.info "Retrieving Credit Memo #{id} pdf, record exists: #{!pdf.nil?}"
  unless pdf&.file_exists?
    logger.error ' * Pdf nil or file does not exist, attempting regen'
    pdf = generate_pdf
    logger.info "Pdf regenerated with upload id #{pdf.id}"
  end
  pdf
end

#invoiceInvoice

Returns:

See Also:



121
# File 'app/models/credit_memo.rb', line 121

has_one    :invoice, class_name: 'Invoice', foreign_key: :id, primary_key: :original_invoice_id

#is_build_com?Boolean

Returns:

  • (Boolean)


579
580
581
# File 'app/models/credit_memo.rb', line 579

def is_build_com?
  customer&.is_build_com?
end

#is_edi?Boolean

Returns:

  • (Boolean)


575
576
577
# File 'app/models/credit_memo.rb', line 575

def is_edi?
  invoice&.order&.is_edi_order?
end

#ledger_transactionsActiveRecord::Relation<LedgerTransaction>

Returns:

See Also:



128
# File 'app/models/credit_memo.rb', line 128

has_many   :ledger_transactions

#line_discountsActiveRecord::Relation<LineDiscount>

Returns:

See Also:



123
# File 'app/models/credit_memo.rb', line 123

has_many   :line_discounts, through: :line_items

#line_itemsActiveRecord::Relation<LineItem>

Returns:

See Also:



122
# File 'app/models/credit_memo.rb', line 122

has_many   :line_items, as: :resource, dependent: :destroy, extend: LineItemExtension, inverse_of: :resource

#nameObject



390
391
392
# File 'app/models/credit_memo.rb', line 390

def name
  "Credit Memo: #{reference_number}"
end

#no_funds_offset?Boolean

Returns:

  • (Boolean)


294
295
296
# File 'app/models/credit_memo.rb', line 294

def no_funds_offset?
  funds_offset == 0
end

#original_invoiceInvoice

Returns:

See Also:



114
# File 'app/models/credit_memo.rb', line 114

belongs_to :original_invoice, class_name: 'Invoice', optional: true

#original_orderOrder

Returns:

See Also:



113
# File 'app/models/credit_memo.rb', line 113

belongs_to :original_order, class_name: 'Order', optional: true

#outgoing_payment_itemsActiveRecord::Relation<OutgoingPaymentItem>

Returns:

See Also:



131
# File 'app/models/credit_memo.rb', line 131

has_many   :outgoing_payment_items

#outgoing_paymentsActiveRecord::Relation<OutgoingPayment>

Returns:

See Also:



132
# File 'app/models/credit_memo.rb', line 132

has_many   :outgoing_payments, through: :outgoing_payment_items

#payment_statusObject



234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
# File 'app/models/credit_memo.rb', line 234

def payment_status
  pm = outgoing_payments.applied.first
  ck = pm.try(:checks).try(:first)
  rec = receipts.fully_applied.first
  if printed?
    { status: 'Credit Memo Prepared and Awaiting Payment', color: 'orange', ref: reference_number }
  elsif pm
    if pm.category == 'check'
      if pm.queued? or pm.generated?
        { status: 'Check In Print Queue', color: 'orange', ref: reference_number }
      elsif pm.pending_review?
        { status: 'Check Pending Approval', color: 'orange', ref: reference_number }
      elsif pm.printed? or pm.reprinted?
        if ck
          mailed_out = 1.working.days.since(ck.created_at)
          if mailed_out < Time.current
            { status: "Check Mailed Out #{mailed_out.to_fs(:crm_date_only)}", color: 'green',
              preview: (ck.uploads.empty? ? nil : ck.uploads.first.attachment.encode('png').url), ref: reference_number }
          else
            { status: "Check Mailed Out #{mailed_out.to_fs(:crm_date_only)}", color: 'orange',
              preview: (ck.uploads.empty? ? nil : ck.uploads.first.attachment.encode('png').url), ref: reference_number }
          end
        else
          { status: 'Check Printed', color: 'green', ref: reference_number }
        end
      end
    else
      { status: "Refunded via #{pm.category} #{pm.payment_date.to_fs(:crm_default)}", color: 'green', ref: reference_number }
    end
  elsif rec
    if rec.category == 'Credit Card'
      { status: "Credit Card (#{rec.reference}) Refunded #{rec.receipt_date.to_fs(:crm_default)}", color: 'green', ref: reference_number }
    elsif rec.receipt_details.any? { |rd| rd.invoice_id.present? }
      { status: "Credit Redeemed #{rec.receipt_date.to_fs(:crm_default)}", color: 'green', ref: reference_number }
    else
      { status: "Refunded via #{rec.category} #{rec.receipt_date.to_fs(:crm_default)}", color: 'green', ref: reference_number }
    end
  elsif processing_refund?
    { status: 'Processing Refund', color: 'orange', ref: reference_number }
  elsif partially_offset?
    { status: 'Partially Refunded', color: 'orange', ref: reference_number }
  elsif fully_offset?
    { status: 'Fully Refunded', color: 'orange', ref: reference_number }
  else
    { status: state, color: 'red', ref: reference_number }
  end
end

#paymentsActiveRecord::Relation<Payment>

Returns:

  • (ActiveRecord::Relation<Payment>)

See Also:



127
# File 'app/models/credit_memo.rb', line 127

has_many   :payments

#prevent_recalculate_shipping?Boolean

Returns:

  • (Boolean)


330
331
332
# File 'app/models/credit_memo.rb', line 330

def prevent_recalculate_shipping?
  true
end

#process_refund(auth_hash) ⇒ Object



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
# File 'app/models/credit_memo.rb', line 346

def process_refund(auth_hash)
  # check none are less than $0
  if processing_refund?
    { success: false, error_message: 'A refund is already being processed for this credit memo' }
  elsif auth_hash.any? { |_auth_id, refund_amount| refund_amount < 0 }
    { success: false, error_message: 'All refund amounts must be greater than 0 or left blank' }
  else
    # sum up the total value of the refund
    refund_total = BigDecimal('0.00')
    auth_hash.each { |_auth_id, refund_amount| refund_total += refund_amount }
    # check refund total is not greater than the credit memo balance
    if refund_total > -balance
      { success: false, error_message: 'Total of refund is greater than balance of credit memo' }
    # check individual refund amounts are available on the selected authorization
    elsif auth_hash.any? { |auth_id, refund_amount| Payment.find(auth_id).available_to_refund < refund_amount }
      { success: false, error_message: 'Amount to refund is greater than amount available to refund on one or more payments' }
    else
      success = true
      auth_hash.each do |auth_id, refund_amount|
        payment = Payment.find(auth_id)
        res = payment.gateway_class.new(payment).refund(refund_amount, self)
        success = false unless res.success
      end
      if success == false
        { success: false, error_message: 'One or more refunds could not be processed successfully' }
      else
        { success: true, error_message: 'Refund processed successfully' }
      end
    end
  end
end

#receipt_detailsActiveRecord::Relation<ReceiptDetail>

Returns:

See Also:



129
# File 'app/models/credit_memo.rb', line 129

has_many   :receipt_details, dependent: :nullify, inverse_of: :credit_memo

#receiptsActiveRecord::Relation<Receipt>

Returns:

  • (ActiveRecord::Relation<Receipt>)

See Also:



130
# File 'app/models/credit_memo.rb', line 130

has_many   :receipts, through: :receipt_details

#rmaRma

Returns:

See Also:



112
# File 'app/models/credit_memo.rb', line 112

belongs_to :rma, optional: true

#set_repsObject



563
564
565
566
567
568
569
# File 'app/models/credit_memo.rb', line 563

def set_reps
  return unless (primary_sales_rep_id.nil? or secondary_sales_rep_id.nil? or local_sales_rep_id.nil?) and original_invoice.present?

  self.primary_sales_rep = original_invoice.primary_sales_rep if primary_sales_rep_id.nil?
  self.secondary_sales_rep = original_invoice.secondary_sales_rep if secondary_sales_rep_id.nil?
  self.local_sales_rep = original_invoice.local_sales_rep if local_sales_rep_id.nil?
end

#shipping_addressAddress Also known as: destination_address

Returns:

See Also:



119
# File 'app/models/credit_memo.rb', line 119

belongs_to :shipping_address, class_name: 'Address', optional: true

#to_sObject



571
572
573
# File 'app/models/credit_memo.rb', line 571

def to_s
  "Credit Memo # #{reference_number}"
end

#uploadsActiveRecord::Relation<Upload>

has_many :shipping_costs, -> { order(:cost) }, :as => :resource, :dependent => :destroy

Returns:

  • (ActiveRecord::Relation<Upload>)

See Also:



125
# File 'app/models/credit_memo.rb', line 125

has_many   :uploads, -> { order(:updated_at).reverse_order }, as: :resource, dependent: :destroy