Created
November 29, 2012 16:45
-
-
Save cmar/4170259 to your computer and use it in GitHub Desktop.
Tax Cloud Spree Integration
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class CreateSpreeTaxCloudTransactions < ActiveRecord::Migration | |
def change | |
create_table :spree_tax_cloud_transactions do |t| | |
t.references :order | |
t.string :message | |
t.timestamps | |
end | |
add_index :spree_tax_cloud_transactions, :order_id | |
end | |
end | |
class CreateSpreeTaxCloudCartItems < ActiveRecord::Migration | |
def change | |
create_table :spree_tax_cloud_cart_items do |t| | |
t.integer :index | |
t.decimal :amount, :scale => 5, :precision => 8, :default => 0 | |
t.decimal :ship_total, :scale => 5, :precision => 8, :default => 0 | |
t.references :line_item | |
t.references :tax_cloud_transaction | |
t.string :type | |
t.timestamps | |
end | |
add_index :spree_tax_cloud_cart_items, :line_item_id | |
add_index :spree_tax_cloud_cart_items, :tax_cloud_transaction_id | |
end | |
end | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Spree::Order.class_eval do | |
has_one :tax_cloud_transaction | |
self.state_machine.after_transition :to => :payment, | |
:do => :lookup_tax_cloud, | |
:if => :tax_cloud_eligible? | |
self.state_machine.after_transition :to => :complete, | |
:do => :capture_tax_cloud, | |
:if => :tax_cloud_eligible? | |
def tax_cloud_eligible? | |
ship_address.try(:state_id?) | |
end | |
def lookup_tax_cloud | |
if tax_cloud_transaction | |
tax_cloud_transaction.lookup | |
else | |
create_tax_cloud_transaction | |
tax_cloud_transaction.lookup | |
adjustments.create do |adjustment| | |
adjustment.source = self | |
adjustment.originator = tax_cloud_transaction | |
adjustment.label = 'Tax' | |
adjustment.mandatory = true | |
adjustment.eligible = true | |
adjustment.amount = tax_cloud_transaction.amount | |
end | |
end | |
end | |
def capture_tax_cloud | |
return unless tax_cloud_transaction | |
tax_cloud_transaction.capture | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Interface to the Tax Cloud SOAP API | |
module Spree | |
class TaxCloud | |
include Spree::Preferences::Preferable | |
def lookup(tax_cloud_transaction) | |
client.request(:lookup) do | |
soap.body = lookup_params(tax_cloud_transaction) | |
end | |
end | |
def lookup_params(tax_cloud_transaction) | |
order = tax_cloud_transaction.order | |
default_body.merge({ 'customerID' => order.user_id || order.number, | |
'cartID' => order.number, | |
'cartItems' => {'CartItem' => tax_cloud_transaction.cart_items.map(&:to_hash)}, | |
'origin' => destination_address(Spree::Account.first_or_default.address), | |
'destination' => destination_address(order.ship_address) }) | |
end | |
def capture(tax_cloud_transaction) | |
order = tax_cloud_transaction.order | |
client.request(:authorized_with_capture) do | |
soap.body =default_body.merge({ | |
'customerID' => order.user_id, | |
'cartID' => order.number, | |
'orderID' => order.number, | |
'dateAuthorized' => DateTime.now, | |
'dateCaptured' => DateTime.now | |
}) | |
end | |
end | |
def ping | |
client.request(:ping) do | |
soap.body = default_body | |
end | |
end | |
private | |
def client | |
@client ||= Savon::Client.new("https://api.taxcloud.net/1.0/?wsdl") | |
end | |
def default_body | |
{ 'apiLoginID' => Spree::Config.preferred_tax_cloud_api_login_id, | |
'apiKey' => Spree::Config.preferred_tax_cloud_api_key } | |
end | |
def cart_items(line_items) | |
index = 0 | |
line_items.map do |line_item| | |
{ 'CartItem' => { 'Index' => index, | |
'ItemID' => line_item.variant_id, | |
'Price' => line_item.price.to_f.to_s, | |
'Qty' => line_item.quantity }} | |
end | |
end | |
def destination_address(address) | |
{ 'Address1' => address.address1, | |
'Address2' => address.address2, | |
'City' => address.city, | |
'State' => address.state_text, | |
'Zip5' => address.zip5, | |
'Zip4' => nil } | |
end | |
def preference_cache_key(name) | |
[self.class.name, name].join('::').underscore | |
end | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Spree::TaxCloudCartItem < ActiveRecord::Base | |
belongs_to :line_item | |
belongs_to :tax_cloud_transaction | |
#validates :tax_cloud_transaction, :presence => true | |
validates :index, :tic, :sku, :price, :quantity, :presence => true | |
attr_accessible :index, :tic, :sku, :price, :quantity | |
def to_hash | |
{ | |
'Index' => index, | |
'TIC' => tic, | |
'ItemID' => sku, | |
'Price' => price.to_s, | |
'Qty' => quantity | |
} | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'spec_helper' | |
describe Spree::TaxCloudCartItem do | |
let(:line_item) { Factory.create(:line_item) } | |
it "builds a hash with the line_item properties" do | |
cart_item = Spree::TaxCloudCartItem.new(:index => 1, | |
:tic => 0, | |
:sku => 'SKU-001', | |
:quantity => 2, | |
:price => 5.99, | |
:line_item => line_item) | |
hash = cart_item.to_hash | |
hash['Index'].should eq 1 | |
hash['Price'].should eq "5.99" | |
hash['Qty'].should eq 2 | |
hash['ItemID'].should eq 'SKU-001' | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'spec_helper' | |
module Spree | |
describe TaxCloud do | |
let(:order) { Factory.build(:order, :ship_address => Factory.build(:address)) } | |
let(:tax_cloud_transaction) { | |
tax_cloud_transaction = TaxCloudTransaction.new | |
tax_cloud_transaction.order = order | |
tax_cloud_transaction.cart_items = [] | |
tax_cloud_transaction | |
} | |
before :each do | |
@account = Account.first_or_default | |
@account.address = Factory.build(:address, | |
:zipcode => '90120') | |
@account.save | |
@params = subject.lookup_params(tax_cloud_transaction) | |
end | |
it 'store account address is used for origin' do | |
@params['origin']['Address1'].should eq @account.address.address1 | |
@params['origin']['Address2'].should eq @account.address.address2 | |
@params['origin']['City'].should eq @account.address.city | |
@params['origin']['Zip5'].should eq @account.address.zipcode | |
end | |
it 'uses order ship address for destination' do | |
@params['destination']['Address1'].should eq order.ship_address.address1 | |
@params['destination']['Address2'].should eq order.ship_address.address2 | |
@params['destination']['City'].should eq order.ship_address.city | |
@params['destination']['Zip5'].should eq order.ship_address.zipcode | |
end | |
it 'order number is used for cartID' do | |
@params['CartID'].should eq order.number | |
end | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Designed to be the Originator for an Adjustment | |
# on an order | |
module Spree | |
class TaxCloudTransaction < ActiveRecord::Base | |
belongs_to :order | |
validates :order, :presence => true | |
has_one :adjustment, :as => :originator | |
has_many :cart_items, :class_name => 'TaxCloudCartItem', | |
:dependent => :destroy | |
# called when order updates adjustments | |
# should be fast! | |
def update_adjustment(adjustment, source) | |
adjustment.update_attribute_without_callbacks(:amount, amount) | |
end | |
def amount | |
cart_items.sum(&:amount) | |
end | |
def lookup | |
begin | |
create_cart_items | |
response = tax_cloud.lookup(self) | |
raise 'Tax Cloud Lookup Error' unless response.success? | |
transaction do | |
unless response.body[:lookup_response][:lookup_result][:messages].nil? | |
self.message = response.body[:lookup_response][:lookup_result][:messages][:response_message][:message] | |
end | |
self.save | |
response_cart_items = Array.wrap response.body[:lookup_response][:lookup_result][:cart_items_response][:cart_item_response] | |
response_cart_items.each do |response_cart_item| | |
cart_item = cart_items.find_by_index(response_cart_item[:cart_item_index].to_i) | |
cart_item.update_attribute(:amount, response_cart_item[:tax_amount].to_f) | |
end | |
end | |
rescue => ex | |
Exceptional.handle ex | |
end | |
end | |
def capture | |
begin | |
tax_cloud.capture(self) | |
rescue => ex | |
Exceptional.handle ex | |
end | |
end | |
private | |
def tax_cloud | |
@tax_cloud ||= TaxCloud.new | |
end | |
def create_cart_items | |
cart_items.clear | |
index = 0 | |
order.line_items.each do |line_item| | |
cart_items.create!({ | |
:index => (index += 1), | |
:tic => '0', # TODO: replace with something more meaningful | |
:sku => line_item.variant.sku.presence || line_item.variant.id, | |
:quantity => line_item.quantity, | |
:price => line_item.price.to_f, | |
:line_item => line_item | |
}) | |
end | |
cart_items.create!({ | |
:index => (index += 1), | |
:tic => '11000', | |
:sku => 'SHIPPING', | |
:quantity => 1, | |
:price => order.ship_total.to_f | |
}) | |
end | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'spec_helper' | |
describe Spree::TaxCloudTransaction do | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment