AspDotNetStoreFront sales tax integration with CertiTAX

By at August 09, 2009 12:59
Filed Under: AspDotNetStorefront, SQLCLR

During a recent freelance engagement I stumbled upon an interesting challenge:

This was for an eCommerce website based on the popular AspDotNetStorefront package. ASPDNSF is a capable piece of software that allows for a multitude of customization options to tailor the website to operator needs. This particular eCommerce operation was based out of New York state and their requirements were the accurate calculation of sales tax for all orders that are to be shipped to NY. The ASPDNSF package allows for customization of tax rates at various geographical levels such as State, Region and ZipCode. For New York State however the zipcode is not granular enough to guarantee an uniform tax rate for all adresses that fall within. So 2 different addresses that happen to be in the same zipcode can possibly fall under different tax jurisdictions with different applicable rates.

Fortunately there are online vendors that exist that do precisely this sort of thing (for a fee of course). One such vendor is CCH. CCH publishes a webservice that makes it possible to perform various tax calculations based on specific adress information.

I'll describe a way to integrate an online realtime tax rate lookup system with no code changes to the ASPDNSF package. This solution will work for those installations that use Sql Server 2005/2008 as their data store.

We begin by creating a new DLL project in Visual Studio 2008 (the C# Express 2008 version works just fine as well) and call it CCHTaxRateLookup.

Add a Web Reference to https://webservices.esalestax.net/CertiTAX.NET/CertiCalc.asmx?WSDL and rename the Web reference name to : CertiTAX.NET.SalesTaxOnlineCalc

webservice

add the following code

using System; 
using System.Data.SqlTypes; 
using CCHTaxRateLookup.CertiTAX.NET.SalesTaxOnlineCalc; 
using Microsoft.SqlServer.Server; 
 
public class UserDefinedFunctions 
{ 
    [SqlFunction(DataAccess = DataAccessKind.Read, IsDeterministic = true)]
 
    public static SqlDouble CCHTaxRateLookup(string address1, string address2, 
                                             string city, string zipCode, 
                                             string merchantKey, string sku) 
    { 
        var address = new Address 
                          { 
                              Street1 = address1, 
                              Street2 = address2, 
                              City = city, 
                              PostalCode = zipCode, 
                              Nation = "USA" 
                          }; 
 
        var order = new Order 
                        { 
                            Address = address, 
                            Nexus = "POSH", 
                            SerialNumber = merchantKey, 
                            CalculateTax = true, 
                            ConfirmAddress = false, 
                            LineItems = new OrderLineItem[1] 
                        }; 
 
        var li = new OrderLineItem 
                     { 
                         ItemId = "Item1", 
                         Quantity = 1, 
                         ExtendedPrice = Decimal.Parse("10000.00"), 
                         StockingUnit = sku 
                     }; 
 
        order.LineItems[0] = li; 
 
        try 
        { 
            var calc = new CertiCalc(); 
            TaxTransaction tx = calc.Calculate(order); 
            return new SqlDouble(Convert.ToDouble(tx.TotalTax)/100); 
        } 
        catch 
        { 
            return new SqlDouble(0.00); 
        } 
    } 
}

This little snippet creates a “dummy” order with a single line item and submits it to the webservice for determining the proper tax rate. The price for the item is set to $10000.00 which will give us a 3 digit accuracy for expressing the resulting tax rate. You may want to setup a dummy taxable SKU with the web service before hand to ensure the item will get taxed. This particular eCommerce site had a very small number of SKU’s they sell online making it easier to setup a single rate lookup and use the built-in tax calculation functionality in ASPDNSF.

Compile the DLL and register the assembly with Sql Server. Since we have a Web Reference there will also be a CCHTaxRateLookup.XmlSerializers.dll located in the build directory, this DLL will also be required registered with Sql Server.

Note:  you may also need to set the ‘clr enabled’ option on the server and mark your ASPDNSF database as TRUSTWORTHY if your database is not setup to host assemblies.

Now that we have the assembly registered we need to create a function that points to our SQLCLR so that we can call it using T-SQL.

USE [ASPDNSFDatabase] 
GO 
 
CREATE FUNCTION [dbo].[CCHTaxRateLookup](@address1 [nvarchar](200), @address2 [nvarchar](200), @city [nvarchar](50), @zipCode [nvarchar](10), @merchantKey [nvarchar](50), @sku [nvarchar](30)) 
RETURNS [float] WITH EXECUTE AS CALLER 
AS 
: none; padding: 0px;">EXTERNAL NAME [CCHTaxRateLookup].[UserDefinedFunctions].[CCHTaxRateLookup] 
 0px;">GO
 

--------

At this point you should be able to test the function using Query Analyzer.

sqlquery

Notice the 2 different tax rates returned for 2 addresses that happen to be in the same zipcode.

With all this plumbing in place we are now ready to inject our enhanced sales tax rate information directly into ASPDNSF. The key point of injection is a stored procedure called aspdnsf_GetCartSubTotalAndTax. Before we move forward with this its useful to remember that this stored proc gets called an awful lot and reaching out to a webservice from SQLCLR for each call can be a rather costly operation. One solution to speed up the lookups is to create a separate lookup table that associates a particular AddressId with the proper taxrate.

CREATE TABLE [dbo].[AddressTaxRate](
    [AddressID] [int] NOT NULL,
    [TaxRate] [float] NOT NULL
) ON [PRIMARY]
 
GO

This will allow us to cache the taxrate lookups for a given address and not hit the expensive web service everytime the procedure is called. ( and it gets called a lot ).

With all this in place we are ready to modify the stored aspdnsf_GetCartSubTotalAndTax procedure as follows :

{...}
-- Calculate item Tax 
declare @vatroundingmethod int
select @vatroundingmethod = case configvalue when 'true' then 1 else 0 end from dbo.appconfig with (nolock) where [name] = 'VAT.RoundPerItem'
-- these are the variables we'll need to populate
DECLARE @TAXRATE FLOAT;
DECLARE @address1 VARCHAR(200);
DECLARE @address2 VARCHAR(200);
DECLARE @state2 VARCHAR(20);
DECLARE @city VARCHAR(50);
DECLARE @zip VARCHAR(10);
DECLARE @ShipAddressID INT;
-- lookup the shipping address and initialize the variables
SELECT @address1 = a.Address1, @address2 = a.Address2, @city = a.City, @zip = a.Zip, @state2 = a.State,
        @ShipAddressID = a.AddressID
FROM Customer c JOIN Address a ON c.ShippingAddressID = a.AddressID 
WHERE c.CustomerID = @customerid
-- we only do this for NY
IF @state2 = 'NY'
    BEGIN
        -- have we seen this address before ?
        IF EXISTS (SELECT TaxRate FROM AddressTaxRate WHERE AddressId = @ShipAddressID)
        BEGIN
            SELECT @TAXRATE = TaxRate FROM AddressTaxRate WHERE AddressId = @ShipAddressID
        END
        ELSE
        BEGIN
            -- no, make the webservice call and find the tax rate
            SELECT @TAXRATE = dbo.CCHTaxRateLookup(@address1, @address2, @city, @zip, 'YOUR_KEY_HERE', 'SKU2')
            -- make a note of it for subsequent calls
            INSERT INTO AddressTaxRate (AddressId, TaxRate) VALUES (@ShipAddressID, @TAXRATE)
        END
    END
ELSE
    BEGIN
        SELECT @TAXRATE = 0
    END
-- apply the taxrate on all taxable items in shopping cart
 
UPDATE @tblsubtotal
SET Tax = CASE sc.IsTaxable  
            WHEN 1 THEN 
                case @vatroundingmethod     
                  when 1 then round(FinalDiscountedPrice*((isnull(cr.taxrate, 0)+isnull(sr.taxrate, 0)+isnull(zr.taxrate, 0))/100), 2)*Qty    
                   else round((FinalDiscountedPrice*Qty)*(@TAXRATE/100), 2)                      
                   end 
            ELSE 0 
           END
{...}

 

You may also wish to move the webservice call out of the proc altogether and place it inside an UPDATE/INSERT trigger on the Address table as a further optimization.

Useful links : The New York State Department of Taxation and Finance makes available this particular page to perform address based sales tax rate lookups on an ad-hoc basis.

Comments

2/26/2010 4:25:31 PM #

Fatcow Review

Should I get a VPS? At the moment I am using lunarpages but they keep turning off my websites because of high server overload. Im getting about 2,000 UV a day. What brand should I get?

Fatcow Review United States | Reply

3/2/2010 2:01:40 PM #

wow mobile

WoW Mobiles is awesome! I get free mobile service with t-mobile because I refered 3 people to wow. You can too!

wow mobile United States | Reply

3/19/2010 11:04:43 PM #

Bulgarian Property

I like the blog, but could not find how to subscribe to receive the updates by email.

Bulgarian Property United States | Reply

3/20/2010 11:35:18 PM #

cheap prom Dresses

could not find how to subscribe to receive the updates by email.

cheap prom Dresses People's Republic of China | Reply

3/22/2010 6:12:54 AM #

black halo dresses

i run a wordpress blog about black halo dresses, I think I will change to this blogengine system as it is a lot nicer than mine.

black halo dresses United Kingdom | Reply

3/25/2010 3:31:07 PM #

Jado Faucet

Fresh content, nice layout. Love the blog.

Jado Faucet United States | Reply

3/28/2010 6:55:08 AM #

Back link

What a spazmatical blog! I can really feel that you really know what a lot about this kinda stuff.

Back link Taiwan | Reply

4/6/2010 2:17:30 PM #

essay writer

Hi! I've just realized that your site  appears to have a few code errors at the side of the page. I don't know if other people are getting this same error when browsing? I'm using a different browser than most people so I don't know if that's creating the is

essay writer United States | Reply

4/19/2010 11:16:23 AM #

Denny Snodderly

Fantastic post! I initially found your site a week or so ago, and I website the very same day. I have a few good ideas for some upcoming posts you could write. I'll shoot you an email later on. Continue the good work. Smile

Denny Snodderly United States | Reply

4/21/2010 5:43:54 AM #

Braden

I tried this and I ran into this:

Could not find Type 'UserDefinedFunctions' in assembly 'CCHTaxRateLookup'.

I registered the assemblies.  This is the first time I have tried this.

Thanks,

Braden

Braden United States | Reply

4/27/2010 1:45:58 PM #

Get ripped body

I really enjoy reading the articles on this blog. I'll bookmark this so I can read more later. Thanks again for sharing this free online

Get ripped body United States | Reply

4/27/2010 5:37:27 PM #

bum marketing

if i upgrade my blog, is it going to keep my same settings?

bum marketing United States | Reply

4/29/2010 5:33:02 AM #

Braden

I solved my problem...I forgot the namespace!  

Braden United States | Reply

5/9/2010 11:20:12 PM #

best shoppingcart

To begin with i want to express gratitude with regard to this kind of information it is not often you stumble upon a post that's properly presented as well as useful I have been seeking information relating to this subject for a really long time.

best shoppingcart Zimbabwe | Reply

5/16/2010 11:23:45 AM #

CFD

I run a blog and have been considering changing to blogengine for some time. Thanks for the info

CFD New Zealand | Reply

5/17/2010 5:50:26 PM #

Nickolas Hegdahl

Thanks for such a cool blog. Working in community services kind of sucks sometimes. I hate finding sites that just have zero info, jobcommunity in Australia i like the only one i've really visited that is any good.

Nickolas Hegdahl Australia | Reply

6/3/2010 8:44:38 AM #

Tansu by Greentea Design

Fantastic post! I'm bookmarking this site for future reference.

Tansu by Greentea Design United States | Reply

6/5/2010 7:35:54 AM #

Multivariate Testing and Digital Optimization

Multivariate testing can also be applied to email body content and mobile web pages.

Multivariate Testing and Digital Optimization South Africa | Reply

6/8/2010 3:12:23 AM #

mississauga real estate agent

Thanks for this amazing article. I am refreshed after reading this. Thank you!

mississauga real estate agent United States | Reply

6/10/2010 9:39:21 AM #

list of burlington real estate agents

Thank you for taking the time to write this brilliant article. I'll be sure to share this with my friends. Thank you!

list of burlington real estate agents United States | Reply

6/14/2010 8:08:04 PM #

Condos

This article about condo provides the light by which we can observe the reality. this is nice 1 and provides in depth information. thanks for this good article Good publish..
...Valuable info for all.I will suggest my close friends to read this for certain

Condos United States | Reply

6/15/2010 5:20:05 AM #

good thesis statement

Good points in your write-up, you've a useful blog site here. Appreciate the ideas.

good thesis statement United States | Reply

6/16/2010 4:24:37 PM #

txt msgs

The presence of such high quality posts is very rare these days over the internet. I personally liked the information

txt msgs United States | Reply

6/17/2010 5:39:52 AM #

ringtones

I really enjoy reading this blog, very informative. Thanks for posting.

ringtones United States | Reply

6/18/2010 5:46:45 AM #

starcraft 2 beta

Any of you guys play PC Games?  If so I don't suppose any of you have been looking into Blizzard's new RTS?

starcraft 2 beta United States | Reply

6/18/2010 1:42:15 PM #

media storage

This is definitely a blog worth following.  Youve got a great deal to say about this subject, and so much knowledge.  I think that you know how to make people listen to what you have to say, especially with an issue thats so important.  Im glad to know this blog.  Two big thumbs up, man!

media storage United States | Reply

6/18/2010 6:19:54 PM #

Arletta Jarocki

Found your web site and decided to use a fast read, not what a usually do but nice one. Nice to see a blog for any change that isn’t full of spam and rubbish, and in fact makes some sense. Anyway, wonderful write up.

Arletta Jarocki United States | Reply

6/21/2010 11:06:51 PM #

films

Sites like this need to be discovered, thanks a lot.

films United States | Reply

6/22/2010 8:02:18 PM #

car classifieds

I really appreciate this cool article. From there i get something very useful. Thanks for the info.

car classifieds United States | Reply

6/25/2010 2:42:51 AM #

Gaming pc cheap

Beautiful blog! Information like this is what i like. I always love to learn. Bookmarked!

Gaming pc cheap United States | Reply

6/25/2010 3:39:07 AM #

shrek the 4

Incredibly helpful publish!

shrek the 4 United States | Reply

6/25/2010 6:17:32 AM #

Free Articles

Thank you for sharing these helpful tutorials. I'm looking forward for more informative information in your blog site. I will see to it that any update here will not be missed by my eyesight. Keep writing helpful article...

Free Articles United States | Reply

6/26/2010 3:02:56 PM #

Bridgett Smallwood

I can’t tell why yahoo sent me to this site but I should probably I have been certainly intrigued by the posts you have sourced together. How many month did it take this many arriving to your blog? I am rather new to this web site stuff.

Bridgett Smallwood United States | Reply

7/1/2010 8:14:19 PM #

nike rift

thanks for sharing the code.

nike rift People's Republic of China | Reply

7/6/2010 2:28:19 AM #

professional website design

Nice see such an informative article and useful for the integration. you explained it in a very nice way. thanks for sharing.

professional website design United States | Reply

7/7/2010 10:01:59 AM #

Gregg Guedry

Hmm strange this post is totaly irrelevant to the search question  I entered in bing but it was listed on the first page.

Gregg Guedry Spain | Reply

7/8/2010 8:11:09 PM #

Wiley Shatto

Thanks for the blog post!  Really helpful information.

Wiley Shatto Croatia | Reply

7/14/2010 5:25:22 AM #

no fee work at home jobs

blogging is always a good way to explore your ideas and view for entire world...And commenting for such nice post is also necessary...it consider like an appreciation

no fee work at home jobs United States | Reply

7/17/2010 9:57:26 PM #

netbook specials

Wonderfully written post, thanks!

netbook specials United States | Reply

7/20/2010 12:33:56 AM #

7 day diet

I really loved reading your blog. It was very well authored and easy to undertand. Unlike other blogs I have read which are really not tht good. I also found your entries very interesting. In fact after reading, I had to go show it to my friend and he ejoyed it as well!

7 day diet United States | Reply

7/21/2010 10:25:12 PM #

phone number reverse

I must say one thing that you are truly a mind blowing writer

phone number reverse United States | Reply

7/24/2010 5:16:08 AM #

timmy

My home we've got numerous vacation home owners - So we were hit super hard with the real estate down turn

timmy Belgium | Reply

7/24/2010 5:14:02 PM #

Myrtle Beach Short Sales

The marketplace is ruthless - hopefully it's going to swing back our way soon too

Myrtle Beach Short Sales Korea | Reply

8/4/2010 8:22:07 AM #

Attic Lady

You've just given me a great idea to blog about...Thanks man, keep up the good work!

Attic Lady United States | Reply

8/6/2010 6:48:34 AM #

Car service

I came from search engines, looking for references about automotive. Thank you for making a great article.

Car service United States | Reply

8/9/2010 7:34:01 AM #

Alfred Harbour

Helpful site, where did u come up with the information with this posting? I'm pleased I discovered it though, ill be checking back soon to see what extra content u have.

Alfred Harbour Sri Lanka | Reply

8/10/2010 4:39:53 AM #

mark

The marketplace is cynical - with any luck , it's going to swing back our way soon too

mark Uzbekistan | Reply

8/10/2010 3:20:49 PM #

Jonathon Hedquist

ohh�nice submit but really?

Jonathon Hedquist Yemen | Reply

8/11/2010 4:06:53 PM #

Sparen

Congratulations for the marvelous posting! I found your post very interesting, I think you are a marvelous author. I just bookmarked your blog and will come back again. Keep up the marvelous work, I wish you a nice day!

Sparen United States | Reply

9/1/2010 3:18:38 AM #

cena oc iac

W dzisiejszej dobie żyjemy bardzo szybko, ciagle gdzieś się śpieszymy, także nasze potrzeby ciągle rosną. Bywa również tak, niestety coraz częściej że dotyka nas "dziura finansowa". Nie jednokronie w takim wypadku sięgamy po kredyt czy pożyczkę. Działając pod wpływem impulsu, a także sugerując się reklamami podejmujemy decyzje szubko i bez zastanowienia. Chodzi tu jednak o nasze pieniądze, warto więc dobrze zastanowić się zanim pdejmiemy jakieś zobowiązania finansowe.Zanim zdecydujesz się na kredyt, pożyczkę czy też inny produkt finansowy, porównaj ze sobą wszystkie oferty, wczytaj się dokładnie w umowę, policz całkowity koszt zaciągniętych zobowiązań na kalkulatorze kredytowym, zrób symulację spłat odsetek i rat. Zapraszamy na naszą stronę. Znajdziesz na niej ranking najpopularniejszych ofert oraz wszystkie niezbędne narzędzia aby poznać wszystkie dokładne szczegóły kredytu.

cena oc iac Poland | Reply

9/5/2010 12:08:01 PM #

free 360 live codes

I was wondering what is up with that hilarious gravatar??? I know 5am is early and I'm not looking my best at that hour, but I hope I don't look like this! I might however make that face if I'm asked to do 100 pushups. lol

free 360 live codes United States | Reply

Add comment


(Will show your Gravatar icon)

  Country flag

biuquote
  • Comment
  • Preview
Loading