From de2236a14297679c7952ffd2269645248b70f815 Mon Sep 17 00:00:00 2001 From: Collins Lagat Date: Sun, 2 Apr 2023 20:09:33 +0300 Subject: [PATCH] feat: refactor and complete the calculator and wrapper around the client --- app/models/spree_avior_tax/avior_tax.rb | 69 ++++++++++++++++++- .../calculator/avior_tax_calculator.rb | 49 +++++++++++-- 2 files changed, 112 insertions(+), 6 deletions(-) diff --git a/app/models/spree_avior_tax/avior_tax.rb b/app/models/spree_avior_tax/avior_tax.rb index f7c3500..4f09cb4 100644 --- a/app/models/spree_avior_tax/avior_tax.rb +++ b/app/models/spree_avior_tax/avior_tax.rb @@ -1,7 +1,72 @@ module SpreeAviorTax class AviorTax - attr_reader :order, :shipment, :client + attr_reader :order, :line_item, :shipment, :client - def initialize; end + def initialize + @client = SpreeAviorTax::Client.new client_params + end + + def calculate_for_order(order, line_item) + @order = order + @line_item = line_item + client.calculate_tax [line_item_params] + end + + def calculate_for_shipment(order, shipment) + @order = order + @shipment = shipment + client.calculate_tax [shipment_params] + end + + private + + def client_params + { + service_url: SpreeAviorTax::Config[:service_url], + token: SpreeAviorTax::Config[:token] + } + end + + def line_item_params + SpreeAviorTax::API::Input::Product.new( + date: order.updated_at.strftime('%Y%m%d'), + record_number: '523355', + seller_id: 'S00010022', + seller_location_id: '1', + seller_state: 'FL', + delivery_method: 'N', + customer_entity_code: 'T', + ship_to_address: order.tax_address.address1, + ship_to_suite: order.tax_address.address2, + ship_to_city: order.tax_address.city, + ship_to_county: 'Miami-Dade', + ship_to_state: order.tax_address.state.abbr, + ship_to_zip_code: order.tax_address.zipcode, + ship_to_zip_plus: '', + sku: line_item.variant.sku, + amount_of_sale: line_item.discounted_amount + ) + end + + def shipment_params + SpreeAviorTax::API::Input::Product.new( + date: order.updated_at.strftime('%Y%m%d'), + record_number: '523355', + seller_id: 'S00010022', + seller_location_id: '1', + seller_state: 'FL', + delivery_method: 'N', + customer_entity_code: 'T', + ship_to_address: order.tax_address.address1, + ship_to_suite: order.tax_address.address2, + ship_to_city: order.tax_address.city, + ship_to_county: 'Miami-Dade', + ship_to_state: order.tax_address.state.abbr, + ship_to_zip_code: order.tax_address.zipcode, + ship_to_zip_plus: '', + sku: '', + amount_of_sale: shipment.discounted_cost + ) + end end end diff --git a/app/models/spree_avior_tax/calculator/avior_tax_calculator.rb b/app/models/spree_avior_tax/calculator/avior_tax_calculator.rb index 94b0c08..a0bbdcc 100644 --- a/app/models/spree_avior_tax/calculator/avior_tax_calculator.rb +++ b/app/models/spree_avior_tax/calculator/avior_tax_calculator.rb @@ -3,6 +3,8 @@ module Calculator class AviorTaxCalculator < Spree::Calculator include Spree::VatPriceCalculation + CACHE_EXPIRATION_DURATION = 10.minutes + def self.description Spree.t(:avior_tax) end @@ -15,16 +17,17 @@ def compute_line_item(item) return 0 unless SpreeAviorTax::Config[:enabled] return 0 if rate.included_in_price - result = LineItemTax.call(item: item) - round_to_two_places(result.value) + round_to_two_places(tax_for_line_item(item)) end def compute_shipment(shipment) return 0 unless SpreeAviorTax::Config[:enabled] return 0 if rate.included_in_price - result = ShipmentTax.call(shipment: shipment) - round_to_two_places(result.value) + round_to_two_places(tax_for_shipment(shipment)) + rescue SpreeAviorTax::API::Errors::AviorTaxServerError => e + errors.add(:base, e.message) + Rails.logger.error "AviorTax server error: #{e.message}" end def compute_shipping_rate(_shipping_rate) @@ -36,6 +39,44 @@ def compute_shipping_rate(_shipping_rate) def rate calculable end + + def tax_for_line_item(item) + order = item.order + tax_address = order.tax_address + + rails_cache_key = cache_key(order, item, tax_address) + + Rails.cache.fetch(rails_cache_key, expires_in: CACHE_EXPIRATION_DURATION) do + response = AviorTax.new.calculate_for_order(order, item) + body = response.first + amount = BigDecimal(body.fips_tax_amount_1) + BigDecimal(body.fips_tax_amount_2) + amount + end + end + + def tax_for_shipment(shipment) + order = shipment.order + tax_address = order.tax_address + + rails_cache_key = cache_key(order, shipment, tax_address) + + Rails.cache.fetch(rails_cache_key, expires_in: CACHE_EXPIRATION_DURATION) do + response = AviorTax.new.calculate_for_shipment(order, shipment) + body = response.first + amount = BigDecimal(body.fips_tax_amount_1) + BigDecimal(body.fips_tax_amount_2) + amount + end + end + + def cache_key(order, item, address) + if item.is_a?(Spree::LineItem) + [Spree::LineItem.to_s, order.id, item.id, address.state_id, address.zipcode, item.taxable_amount, :amount_to_collect] + else + [Spree::Shipment.to_s, order.id, item.id, address.state_id, address.zipcode, item.cost, item.adjustments.reject do |adjustment| + adjustment.source_type == Spree::TaxRate.to_s + end.map(&:amount).sum.to_f, :amount_to_collect] + end + end end end end