mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-01-25 20:46:48 +00:00
134 lines
3.7 KiB
Ruby
134 lines
3.7 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
class Invoice
|
|
class DataPresenter
|
|
attr_reader :invoice
|
|
|
|
delegate :data, :date, to: :invoice
|
|
|
|
FINALIZED_NON_SUCCESSFUL_STATES = %w(canceled returned).freeze
|
|
|
|
extend Invoice::DataPresenterAttributes
|
|
|
|
attributes :additional_tax_total, :currency, :included_tax_total, :payment_total,
|
|
:shipping_method_id, :state, :total, :number, :note, :special_instructions,
|
|
:completed_at
|
|
|
|
attributes_with_presenter :bill_address, :customer, :distributor, :ship_address,
|
|
:shipping_method, :order_cycle
|
|
|
|
array_attribute :sorted_line_items, class_name: 'LineItem'
|
|
array_attribute :all_eligible_adjustments, class_name: 'Adjustment'
|
|
array_attribute :payments, class_name: 'Payment'
|
|
|
|
# if any of the following attributes is updated, a new invoice should be generated
|
|
invoice_generation_attributes :additional_tax_total, :all_eligible_adjustments, :bill_address,
|
|
:included_tax_total, :payments, :payment_total, :ship_address,
|
|
:shipping_method_id, :sorted_line_items, :total
|
|
|
|
# if any of the following attributes is updated, the latest invoice should be updated
|
|
invoice_update_attributes :note, :special_instructions, :state,
|
|
:all_eligible_adjustments, :payments
|
|
|
|
def initialize(invoice)
|
|
@invoice = invoice
|
|
end
|
|
|
|
def has_taxes_included
|
|
included_tax_total > 0
|
|
end
|
|
|
|
def total_tax
|
|
additional_tax_total + included_tax_total
|
|
end
|
|
|
|
def order_completed_at
|
|
return nil if data[:completed_at].blank?
|
|
|
|
Time.zone.parse(data[:completed_at])
|
|
end
|
|
|
|
def checkout_adjustments(exclude: [], reject_zero_amount: true)
|
|
adjustments = all_eligible_adjustments
|
|
|
|
adjustments.reject! { |a| a.originator_type == 'Spree::TaxRate' }
|
|
|
|
if exclude.include? :line_item
|
|
adjustments.reject! { |a|
|
|
a.adjustable_type == 'Spree::LineItem'
|
|
}
|
|
end
|
|
|
|
if reject_zero_amount
|
|
adjustments.reject! { |a| a.amount == 0 }
|
|
end
|
|
|
|
adjustments
|
|
end
|
|
|
|
def display_checkout_taxes_hash
|
|
totals = OrderTaxAdjustmentsFetcher.new(nil).totals(all_tax_adjustments)
|
|
|
|
totals.map do |tax_rate, tax_amount|
|
|
{
|
|
amount: Spree::Money.new(tax_amount, currency: order.currency),
|
|
percentage: number_to_percentage(tax_rate.amount * 100, precision: 1),
|
|
rate_amount: tax_rate.amount,
|
|
}
|
|
end.sort_by { |tax| tax[:rate_amount] }
|
|
end
|
|
|
|
def all_tax_adjustments
|
|
all_eligible_adjustments.select { |a| a.originator_type == 'Spree::TaxRate' }
|
|
end
|
|
|
|
def invoice_date
|
|
date
|
|
end
|
|
|
|
def paid?
|
|
data[:payment_state] == 'paid' || data[:payment_state] == 'credit_owed'
|
|
end
|
|
|
|
def outstanding_balance?
|
|
!new_outstanding_balance.zero?
|
|
end
|
|
|
|
def new_outstanding_balance
|
|
if state.in?(FINALIZED_NON_SUCCESSFUL_STATES)
|
|
-payment_total
|
|
else
|
|
total - payment_total
|
|
end
|
|
end
|
|
|
|
def outstanding_balance_label
|
|
new_outstanding_balance.negative? ? I18n.t(:credit_owed) : I18n.t(:balance_due)
|
|
end
|
|
|
|
def last_payment
|
|
payments.max_by(&:created_at)
|
|
end
|
|
|
|
def last_payment_method
|
|
last_payment&.payment_method
|
|
end
|
|
|
|
def display_outstanding_balance
|
|
Spree::Money.new(new_outstanding_balance, currency: currency)
|
|
end
|
|
|
|
def display_checkout_tax_total
|
|
Spree::Money.new(total_tax, currency: currency)
|
|
end
|
|
|
|
def display_checkout_total_less_tax
|
|
Spree::Money.new(total - total_tax, currency: currency)
|
|
end
|
|
|
|
def display_total
|
|
Spree::Money.new(total, currency: currency)
|
|
end
|
|
end
|
|
end
|