|
| 1 | +module Spree |
| 2 | + # Relatively simple class used to apply a {Spree::Tax::OrderTax} to a |
| 3 | + # {Spree::Order}. |
| 4 | + # |
| 5 | + # This class will create or update adjustments on the taxed items and remove |
| 6 | + # any now inapplicable tax adjustments from the order. |
| 7 | + class OrderTaxation |
| 8 | + # Create a new order taxation. |
| 9 | + # |
| 10 | + # @param [Spree::Order] order the order to apply taxes to |
| 11 | + # @return [Spree::OrderTaxation] a {Spree::OrderTaxation} object |
| 12 | + def initialize(order) |
| 13 | + @order = order |
| 14 | + end |
| 15 | + |
| 16 | + # Apply taxes to the order. |
| 17 | + # |
| 18 | + # This method will create or update adjustments on all line items and |
| 19 | + # shipments in the order to reflect the appropriate taxes passed in. It |
| 20 | + # will also remove any now inapplicable tax adjustments. |
| 21 | + # |
| 22 | + # @param [Spree::Tax::OrderTax] taxes the taxes to apply to the order |
| 23 | + # @return [void] |
| 24 | + def apply(taxes) |
| 25 | + @order.line_items.each do |item| |
| 26 | + taxed_items = taxes.line_item_taxes.select { |i| i.item_id == item.id } |
| 27 | + update_adjustments(item, taxed_items) |
| 28 | + end |
| 29 | + |
| 30 | + @order.shipments.each do |item| |
| 31 | + taxed_items = taxes.shipment_taxes.select { |i| i.item_id == item.id } |
| 32 | + update_adjustments(item, taxed_items) |
| 33 | + end |
| 34 | + end |
| 35 | + |
| 36 | + private |
| 37 | + |
| 38 | + # Walk through the taxes for an item and update adjustments for it. Once |
| 39 | + # all of the taxes have been added as adjustments, remove any old tax |
| 40 | + # adjustments that weren't touched. |
| 41 | + # |
| 42 | + # @private |
| 43 | + # @param [#adjustments] item a {Spree::LineItem} or {Spree::Shipment} |
| 44 | + # @param [Array<Spree::Tax::ItemTax>] taxed_items a list of calculated taxes for an item |
| 45 | + # @return [void] |
| 46 | + def update_adjustments(item, taxed_items) |
| 47 | + tax_adjustments = item.adjustments.select(&:tax?) |
| 48 | + |
| 49 | + active_adjustments = taxed_items.map do |tax_item| |
| 50 | + update_adjustment(item, tax_item) |
| 51 | + end |
| 52 | + |
| 53 | + # Remove any tax adjustments tied to rates which no longer match. |
| 54 | + unmatched_adjustments = tax_adjustments - active_adjustments |
| 55 | + item.adjustments.destroy(unmatched_adjustments) |
| 56 | + end |
| 57 | + |
| 58 | + # Update or create a new tax adjustment on an item. |
| 59 | + # |
| 60 | + # @private |
| 61 | + # @param [#adjustments] item a {Spree::LineItem} or {Spree::Shipment} |
| 62 | + # @param [Spree::Tax::ItemTax] tax_item calculated taxes for an item |
| 63 | + # @return [Spree::Adjustment] the created or updated tax adjustment |
| 64 | + def update_adjustment(item, tax_item) |
| 65 | + tax_adjustment = item.adjustments.detect do |adjustment| |
| 66 | + adjustment.source == tax_item.tax_rate |
| 67 | + end |
| 68 | + |
| 69 | + tax_adjustment ||= item.adjustments.new( |
| 70 | + source: tax_item.tax_rate, |
| 71 | + order_id: item.order_id, |
| 72 | + label: tax_item.label, |
| 73 | + included: tax_item.included_in_price |
| 74 | + ) |
| 75 | + tax_adjustment.update_attributes!(amount: tax_item.amount) |
| 76 | + tax_adjustment |
| 77 | + end |
| 78 | + end |
| 79 | +end |
0 commit comments