Designing proper taxes support in a webshop

I've been working on creating a new website for my webshop, using Drupal 6, Ubercart D2 and 100+ modules (the drupal way :)

I've fixed several bugs in modules along the way (and ofcourse sent fixes upstream - even got to be co-maintainer of a module, so that I could release a new version with  my fixes, and have added other fixes as I needed them :) and especially working with uc_discounts_alt have exposed me to an issue the current taxes support cannot handle.

As I know people are working on Drupal Commerce and Ubercart 3.x, and many of them are from countries outside of EU, where the tax rules aren't as specific and hard to support, I figured I'd try to document the problems and how I think it can be solved.

In the following I'll be talking about orderlines (which in ubercart is either items or line_items- the requirement for both is the same in regard to taxes, so I've rolled them into one :)

Taxes in the EU is quite the oddity - they are very specific and can depend on the item you're selling, the size of it and many other peculiar things. Here's a few examples of the challenges:

  • In the UK there's a different tax rate for childrens clothings
    This means you have to have calculate tax seperately pr. item+attribute kombination. Ubercart has an option to have seperate SKU pr. item/attribute combination, and since there's a SKU for each orderline - you "just" need to setup the proper conditions for the taxrules (pr. current tax workings in ubercart that is).
  • In Spain they have more than 1 set of taxes, which MUST ALL have a seperate orderline on an invoice (orders and invoices are NOT the same - as the Ubercart devs seem to think - see note1 :) - they have a negative tax as well
    The exact rules of when and where this tax applies is unclear, but my design proposal will support it.
  • In Sweden (and many other countries) they have seperate tax rates for seperate kind of products.
    Books has a lower taxrate (I think it's 12%) than other items (which is ~25%).

My proposal to solve this is simple:

  • You need to be able to apply taxrates as detailed, as f.ex. putting SKU's (which includes the SKU's pr. item+attribute combination) in a taxonomy and setting a taxrate pr. taxonomy.
  • $price object (that's the name for what is used for prices on orderlines  today, using uc_price) must include $price (excl. taxes) and $taxamount
    This enables each module who manipulates an orderlines price to also manipulate the taxes for it.
    This is needed for especially discounts.
  • Another way to do this, is to say that each module which has hook with an $item or $price object - MUST implement a tax_hook - so the taxes module can ask them what the equivalent taxes are (often they'll just do nothing and leave them where they are - but discounts is special here).

If you want a flexible discounts system, you'll want to be able to say f.ex. 10% discount on any combination of books and magazines. Only in sweden they have a different tax rate, and since the discount module is the ONLY module that knows which items were discounted to give the total discount, it must also calculate the tax amount of the discount total. It would ofcourse do this, by asking the tax module (calling uc_price in ubercart kinda works for this - except it also allows multicurrency stuff - you'd need a seperate tax function/hook IMHO) for each item that is part of the discount and then calculating the tax part (it gets a new total - so if it subtracts the original total - it has the tax amount) as well for the discount orderline.

Shipping has some of the same issues - see note2.

This was my thoughts - I hope they can be of use to any of the people designing the new (and hopefully great) Drupal commerce solutions (or any other commerce solution) - and I will certainly ensure that they have the link to this - and can read it if they see fit.

* Note1) Invoices (in EU) can be based on orders, and if so refer to the ordernumber (so you can ensure there's no duplicates) AND must have a sequential (with no holes in the numbering sequence) numbering scheme. If you create an invoice for a client, and he returns the whole order (in which case you have to return the entire amount - incl. shipping - this is an EU requirement) then you have to create a new invoice (called a credit note) - which is the exact same - only with negative amounts. This can use a seperate numbering scheme, if one so chooses. Invoices also MUST show the VAT number of the company.

* note2) Shipping in DK f.ex. has a concept of "regular shipping" which is tax excempt and quite expensive, but they also have a b2b shipping offering, where you MUST check the given VAT number against the VAT registry and ensure the address in the registry matches the delivery address, otherwise you may get fined if using b2b shipping methods for none-company adresses (I just got a notice of this, the other day :( - thrusting customers is not always an option :) b2b shipping methods are NOT tax excempt, so the current ubercart way of choosing if the shipping orderline is tax excempt or not simply does not work. You need to be able to set tax rules pr. shipping method available.

Feel free to comment, if you have relevant insight :)

3 comments on Designing proper taxes support in a webshop

  1. Anonymous
    Fri, 11/05/2010 - 15:13
    In Germany we still have the problem with shipping cost calculation - for all companies providing shippment services (except "Deutsche Post") you have to calculate shipping taxes proportional to the products taxes. In this case we have to find a way to calculate these costs - for current version of ubercart i created a patch for uc_vat module. Would be nice to include such features directly into commerce / ubercart - i would cause some more configuraton options esp. for european markets.
  2. Anonymous
    Fri, 05/21/2010 - 14:05
    Klavs. I could not agree with you more. There seems little understanding and even less support from Ubercart for EU users. I have previously been using Drupal 5, Ubercart 1 and uc_taxes_prices which supports showing prices including tax (although you will need to edit the code to make it more UK friendly), however this module DOES NOT support attributes with prices. (see comments in the module download page) Having now spent some time trying to fix this module to include support for attributes I have found that there is NO support for adjusting attributes within the core. This show's a fundamental lack of understanding on the developers side into the way that tax works outside of the US. None of my UK clients are clear on VAT on shipping. Most are happy to leave the site how it is. Children's clothes are 0% VAT and to solve this I have created a separate class called "no vat", and some customers prefer that their prices are shown "ex VAT" to wholesale or "business" customers. To solve this issue I have stored "price_inc_vat" and "price_ex_vat" into the $node and displayed the correct one depending on user role. Finally in the UK it is required that the VAT number is displayed on all invoices (currently this is supported by a 3rd party module) The issue, though, is how do we present our argument to the core developers. It seems that UC has now gone down a path that would make it difficult to back-step and make these essential changes. Without these changes UC are restricting their target audience to those outside the EU and those without strict Tax rules.
  3. Anonymous
    Wed, 05/19/2010 - 23:21
    Hi Klavs, I've just run straight into this issue with our soon-to-be-released drupal 6.0 ucart 2 website. Naively, I'd assumed when I read that ucart "does taxes" that it could do them appropriately for the UK. Our VAT rules seem similar to other EU countries but perhaps less severe. The issue is (and your proposal might well address this, I didn't know enough about ucart internals to be sure), that differential tax rates may need to be applied to different product options. Our example: books. Paper books are zero rated for VAT. ebooks are not; yet an ebook is just an option on a specific publication. We can't implement this at the moment, so an ebook and its corresponding pbook have to be separate products, which is a pain for both customers and us.