We've ended up creating a special helper for this (we call it mixedprice).
You need to overwrite getPrice and getSpecialPrice for Catalog_Model_Product:
public function getPrice()
{
return Mage::helper('catalog/mixedprice')
->getProductPrice($this);
}
public function getSpecialPrice()
{
return Mage::helper('catalog/mixedprice')
->getProductSpecialPrice($this);
}
The idea behind this helper is quite simple, but I need to give more context. We sell our clients software, no physical products. We needed some products to have fixed prices for B2B clients and some products with fixed prices for B2C clients (the end price is constant, vat ammount changes for each customer country). You can't have both obviously.
We have added column for product 'is_vat_included'. For B2B fixed we expect that to be false, for B2C fixed we expect that to be true. (so whoever maintains catalog products has to take care of it).
As you may know: there's global config for magento telling if prices are with or without tax (\Mage_Tax_Helper_Data::priceIncludesTax). We have assumed that this config should be true (you can assume opposite or make no assumptions and take this config into consideration when manipulating prices in "mixedprice" helper.
Rest is quite simple:
* if 'is_vat_included' == true for the product, do nothing special
* if 'is_vat_included' == false, send it through magento's TaxHelper to calculate price with VAT
So roughly the code would look like this for Catalog_Model_Product:
public function getPrice()
{
if($this->getIsVatIncluded()) {
return parent::getPrice();
}
return Mage::helper('tax')->getPrice(
$this, // product
parent::getPrice(), // excl. VAT
true, // ask for price inclugin Tax
null, // shipping address - we sell downloadable software, you may care more about this param
$billingAddress, // you can get it from quote
null,
null,
false, // price we're passing (parent::getPrice())doesn't include tax
false, // do not round this price (it's too soon)
)
}
This is general logic we pulled out to our "mixedprice" helper (I've inlined it here for clarity).
Please note:
1. I can't copy+paste you exact code, so this is rough idea. If you want to manage some stores with products including VAT and some stores where products exclude VAT by default - this method will be more complicated.
2. You need the same trick for product::getSpecialPrice
3. You need even more of it if you are using custom options.
4. Unit testing is your friend - we've used it like crazy (we had to deploy this on 1st of Jan 2015, it worked).
Thanks for @Jeffrey's clarification - please vote up his answer: Cross border tax settings for business clients