Beispiel #1
0
 /**
  * @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;
 }