# 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