One of our customers recently approached us to add an in-store pickup module to their Magento website. No problem, this is a pretty simple task and we quickly setup the module. However, the customer then notified us that they needed to start charging their city tax for orders that are picked up from one of their stores. After much searching, I didn’t find many leads on how to do this, so now that I have figured it out I thought I would post it here in case someone else had the same problem. I am going to stick to the high level abstraction on most of this and assume you know how to build a Magento module.

First, you need to create your module and add an observer that hooks into the event you want to set the tax rate after. In our case, we are changing the rate after the user chooses shipping, so we created an observer on the checkout_controller_onepage_save_shipping_method event.

Second, you’ll need to set up a customer group and assign it a new tax rate. Do this through the Magento admin.

The trick is that you can’t set the tax rate on the quote item iteslf. If you dig into the Magento code, you’ll find that when you get the tax rate on the quote, it actually returns it from the customer group and not the quote.

If the user is logged in, you actually have to change their tax group and save the user. If they are checking out as a guest, you can simply set the customer tax group on the quote itself.


// We need this quote
$quote = $observer->getEvent()->getQuote();
// get our shipping address
$shipping_address = $quote->getShippingAddress();
// get our selected shipping method
$shipping_method = $shipping_address->getShippingMethod();
// if our shipping method is selected
if ($shipping_method == "storepickupmodule_pickup") {
// get our session object
$session = Mage::getSingleton('customer/session');
// load the customer from the session
$customer = $session->getCustomer();
// if this customer is logged in
if ($session->isLoggedIn()) {
// Set our group id to whatever we need it to be (be sure to get the correct id from your group)
$customer->setGroupId($NewGroupId)->save();
} else {
$quote->setCustomerGroupId($NewGroupId)->save();
$quote->setTotalsCollectedFlag(false)->collectTotals()->save();
}
}

In our case, the site isn’t using groups in any special way (everyone is in the General group) so we don’t have to worry about setting the user back to a default group etc. However, you might want to add another observer to change the user back after checkout, etc.

I know it’s pretty basic, I hope this helps someone out that might be struggling with this task.