mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-01-30 21:27:17 +00:00
112 lines
3.2 KiB
Ruby
112 lines
3.2 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
class VoucherAdjustmentsService
|
|
def initialize(order)
|
|
@order = order
|
|
end
|
|
|
|
# The tax part of the voucher is stored as explained below:
|
|
# * tax included in price: included_tax field of the voucher adjustment
|
|
# * tax exckuded from price: as an extra voucher adjustment, with label starting by "Tax "
|
|
#
|
|
def update
|
|
return if @order.nil?
|
|
|
|
# Find open Voucher Adjustment
|
|
return if @order.voucher_adjustments.empty?
|
|
|
|
# We only support one voucher per order right now, we could just loop on voucher_adjustments
|
|
adjustment = @order.voucher_adjustments.first
|
|
|
|
# Calculate value
|
|
voucher = adjustment.originator
|
|
amount = voucher.compute_amount(@order)
|
|
|
|
# It is quite possible to have an order with both tax included in and tax excluded from price.
|
|
# We should be able to caculate the relevant amount apply the current calculation.
|
|
#
|
|
# For now we just assume it is either all tax included in price or all tax excluded from price.
|
|
if @order.additional_tax_total.positive?
|
|
handle_tax_excluded_from_price(voucher)
|
|
elsif @order.included_tax_total.positive?
|
|
handle_tax_included_in_price(amount, voucher)
|
|
else
|
|
adjustment.amount = amount
|
|
adjustment.save
|
|
end
|
|
end
|
|
|
|
def voucher_included_tax
|
|
return 0.0 if @order.voucher_adjustments.empty?
|
|
|
|
# We only support one voucher per order for now
|
|
@order.voucher_adjustments.first.included_tax
|
|
end
|
|
|
|
def voucher_excluded_tax
|
|
return 0.0 if @order.voucher_adjustments.voucher_tax.empty?
|
|
|
|
@order.voucher_adjustments.voucher_tax.first.amount
|
|
end
|
|
|
|
private
|
|
|
|
def handle_tax_excluded_from_price(voucher)
|
|
voucher_rate = voucher.rate(@order)
|
|
adjustment = @order.voucher_adjustments.first
|
|
|
|
# Adding the voucher tax part
|
|
tax_amount = voucher_rate * @order.additional_tax_total
|
|
|
|
update_tax_adjustment_for(adjustment, tax_amount)
|
|
|
|
# Update the adjustment amount
|
|
adjustment_amount = voucher_rate * (@order.pre_discount_total - @order.additional_tax_total)
|
|
|
|
adjustment.update_columns(
|
|
amount: adjustment_amount,
|
|
updated_at: Time.zone.now
|
|
)
|
|
end
|
|
|
|
def update_tax_adjustment_for(adjustment, tax_amount)
|
|
adjustment_attributes = {
|
|
originator: adjustment.originator,
|
|
order: @order,
|
|
label: "Tax #{adjustment.label}",
|
|
mandatory: false,
|
|
state: 'open',
|
|
tax_category: nil,
|
|
included_tax: 0
|
|
}
|
|
|
|
# Update the amount if tax adjustment already exist, create if not
|
|
tax_adjustment = @order.adjustments.find_or_initialize_by(adjustment_attributes)
|
|
tax_adjustment.amount = tax_amount
|
|
|
|
# Add metada so we know which voucher adjustment is Tax related
|
|
tax_adjustment.metadata ||= AdjustmentMetadata.new(
|
|
enterprise: adjustment.originator.enterprise,
|
|
fee_name: "Tax",
|
|
fee_type: "Voucher"
|
|
)
|
|
|
|
tax_adjustment.save
|
|
end
|
|
|
|
def handle_tax_included_in_price(amount, voucher)
|
|
included_tax = voucher.rate(@order) * @order.included_tax_total
|
|
|
|
# Update Adjustment
|
|
adjustment = @order.voucher_adjustments.first
|
|
|
|
return unless amount != adjustment.amount || included_tax != 0
|
|
|
|
adjustment.update_columns(
|
|
amount:,
|
|
included_tax:,
|
|
updated_at: Time.zone.now
|
|
)
|
|
end
|
|
end
|