/** * @param array $items order items to modify * @param array $params 'billing' => array(...), 'shipping' => array(...), 'discount_rate' => float * @return array : tax_id => array ( rate => float, included => bool, name => string ) */ public static function apply(&$items, $params, $currency = null) { $addresses = array_intersect_key($params, array('billing' => 1, 'shipping' => 1)); $discount_rate = ifset($params['discount_rate'], 0); $tax_ids = array(); $parent_tax_id = null; foreach ($items as &$i) { if ($i['type'] == 'product') { $parent_tax_id = isset($i['product']['tax_id']) ? $i['product']['tax_id'] : (isset($i['tax_id']) ? $i['tax_id'] : 0); } if (!empty($i['product']['tax_id'])) { $tax_ids[] = $i['tax_id'] = $i['product']['tax_id']; } elseif (isset($i['service']['tax_id'])) { // inherit from product if ($i['service']['tax_id'] === '0') { if ($parent_tax_id) { $tax_ids[] = $i['tax_id'] = $parent_tax_id; } } else { $tax_ids[] = $i['tax_id'] = $i['service']['tax_id']; } } elseif (!empty($i['tax_id'])) { $tax_ids[] = $i['tax_id']; } $i['tax'] = 0; $i['tax_percent'] = 0; $i['tax_included'] = 0; } unset($i); if (empty($tax_ids)) { return array(); } $result = array(); $tm = new shopTaxModel(); $trm = new shopTaxRegionsModel(); $taxes = $tm->getById($tax_ids); foreach ($taxes as $t) { $result[$t['id']] = array('rate' => 0.0, 'included' => $t['included'], 'name' => $t['name'], 'sum_included' => 0.0, 'sum' => 0.0); // Check if there are rates based on country and region $result[$t['id']]['rate'] = $trm->getByTaxAddress($t['id'], $addresses[$t['address_type']]); } // Rates by zip code override rates by region, when applicable $main_country = wa()->getSetting('country'); foreach (array('shipping', 'billing') as $addr_type) { // ZIP-based rates are only applied to main shop country if (empty($addresses[$addr_type]['zip']) || !empty($addresses[$addr_type]['country']) && $addresses[$addr_type]['country'] !== $main_country) { continue; } $tzcm = new shopTaxZipCodesModel(); foreach ($tzcm->getByZip($addresses[$addr_type]['zip'], $addr_type, $tax_ids) as $tax_id => $rate) { $result[$tax_id]['rate'] = $rate; $result[$tax_id]['name'] = $taxes[$tax_id]['name']; } } // Compute tax values for each item, and total tax foreach ($items as &$i) { $tax_id = ifempty($i['tax_id']); $i['tax_percent'] = ifset($result[$tax_id]['rate'], 0.0); $i['tax_included'] = ifset($result[$tax_id]['included']); $p = shop_currency((1 - $discount_rate) * $i['price'] * $i['quantity'], $i['currency'], $currency, false); $r = ifset($result[$tax_id]['rate'], 0.0); if ($i['tax_included']) { $i['tax'] = $p * $r / (100.0 + $r); } else { $i['tax'] = $p * $r / 100.0; } if ($i['tax_included']) { $result[$tax_id]['sum_included'] += $i['tax']; } elseif ($i['tax']) { $result[$tax_id]['sum'] += $i['tax']; } } unset($i); return $result; }