diff --git a/uc_vat.module b/uc_vat.module index b77e0fb..37eb7da 100644 --- a/uc_vat.module +++ b/uc_vat.module @@ -456,7 +456,10 @@ function uc_vat_price_handler_alter(&$price, &$context, &$options) { if (uc_vat_exclude_vat()) { return; } - +// Don't do alterations if specific is asked. + if (isset($options['uc_vat']) && $options['uc_vat'] == FALSE) { + return; + } if (isset($context['subject']['order']->data['taxes'])) { // Use stored tax rates from an existing order if available. $tax_rates = $context['subject']['order']->data['taxes']; @@ -785,6 +788,18 @@ function uc_vat_line_item_tax($op, $order) { } /** +* Implements hook_calculate_tax() +*/ +function uc_vat_calculate_tax($order) { + $taxes = uc_taxes_calculate_tax(drupal_clone($order)); + $vats = uc_vat_calculate_vat($order); + foreach (array_keys($vats) as $id) { + $vats[$id]->amount -= $taxes[$id]->amount; + } + return $vats; +} + +/** * Calculate all taxes on an order using VAT rules. * * @see uc_taxes_calculate_tax() @@ -874,7 +889,10 @@ function uc_vat_apply_tax($order, $tax) { $taxable_amount = 0; if (is_array($order->products)) { foreach ($order->products as $item) { - $taxable_amount += uc_taxes_apply_item_tax($item, $tax); + // We call our own function for applying taxes here, because we don't want to calculate a tax + // based on a price altered by this module. If we don't do this, the calculated tax will be + // based on a price inclusive tax. + $taxable_amount += uc_vat_uc_taxes_apply_item_tax($item, $tax); } } $taxed_line_items = $tax->taxed_line_items; @@ -922,6 +940,51 @@ function uc_vat_apply_tax($order, $tax) { } /** + * Calculates tax for a single product. + * + * This function is similar to uc_taxes_apply_item_tax(), but with one difference: + * It set's an option called uc_vat to FALSE which means to this module that any + * price altering by this module should be canceled. + * If this module *does* do a price alter when applying taxes, then the tax amount + * will be based on the tax inclusive price. And taxes should be based on the tax + * *exclusive* price of course! + * + * @param object $item + * @param object $tax + * @return float + */ +function uc_vat_uc_taxes_apply_item_tax($item, $tax) { + $node = node_load($item->nid); + + // Special handling for manually added "Blank line" products. + if (!$node) { + $node = new stdClass(); + $node->type = 'blank-line'; + $node->shippable = $item->weight > 0; + } + + // Tax products if they are of a taxed type and if it is shippable if + // the tax only applies to shippable products. + if (in_array($node->type, $tax->taxed_product_types) && ($tax->shippable == 0 || $node->shippable == 1)) { + $context = array( + 'revision' => 'altered', + 'type' => 'cart_item', + 'subject' => array( + 'cart_item' => $item, + 'node' => $item->nid ? $node : FALSE, + ), + ); + $price_info = array( + 'price' => $item->price, + 'qty' => $item->qty, + ); + + // Calculate price, but bypass any alterations normally done in uc_vat. + return uc_price($price_info, $context, $options = array('uc_vat' => FALSE)); + } +} + +/** * Callback for "subtotal excluding VAT" line item. */ function uc_vat_line_item_tax_subtotal($op, $order) {