Exemple #1
0
 /**
  * Returns the tax calculator associated to this order detail.
  * @since 1.5.0.1
  * @return TaxCalculator
  */
 public function getTaxCalculator()
 {
     return OrderDetail::getTaxCalculatorStatic($this->id);
 }
 /**
  * Marked as deprecated but should not throw any "deprecated" message
  * This function is used in order to keep front office backward compatibility 14 -> 1.5
  * (Order History)
  *
  * @deprecated
  */
 public function setProductPrices(&$row)
 {
     $tax_calculator = OrderDetail::getTaxCalculatorStatic((int) $row['id_order_detail']);
     $row['tax_calculator'] = $tax_calculator;
     $row['tax_rate'] = $tax_calculator->getTotalRate();
     $row['product_price'] = Tools::ps_round($row['unit_price_tax_excl'], 2);
     $row['product_price_wt'] = Tools::ps_round($row['unit_price_tax_incl'], 2);
     $group_reduction = 1;
     if ($row['group_reduction'] > 0) {
         $group_reduction = 1 - $row['group_reduction'] / 100;
     }
     $row['product_price_wt_but_ecotax'] = $row['product_price_wt'] - $row['ecotax'];
     $row['total_wt'] = $row['total_price_tax_incl'];
     $row['total_price'] = $row['total_price_tax_excl'];
 }
 public function getProductTaxesBreakdown()
 {
     $tmp_tax_infos = array();
     foreach ($this->order_slip->getOrdersSlipDetail((int) $this->order_slip->id) as $order_slip_details) {
         $tax_calculator = OrderDetail::getTaxCalculatorStatic((int) $order_slip_details['id_order_detail']);
         $tax_amount = $tax_calculator->getTaxesAmount($order_slip_details['amount_tax_excl']);
         if ($this->order->useOneAfterAnotherTaxComputationMethod()) {
             foreach ($tax_amount as $tax_id => $amount) {
                 $tax = new Tax((int) $tax_id);
                 if (!isset($total_tax_amount[$tax->rate])) {
                     $tmp_tax_infos[$tax->rate]['name'] = $tax->name;
                     $tmp_tax_infos[$tax->rate]['total_price_tax_excl'] = $order_slip_details['amount_tax_excl'];
                     $tmp_tax_infos[$tax->rate]['total_amount'] = $amount;
                 } else {
                     $tmp_tax_infos[$tax->rate]['total_price_tax_excl'] += $order_slip_details['amount_tax_excl'];
                     $tmp_tax_infos[$tax->rate]['total_amount'] += $amount;
                 }
             }
         } else {
             $infos = array('total_price_tax_excl' => 0, 'total_amount' => 0);
             $tax_rate = 0;
             foreach ($tax_amount as $tax_id => $amount) {
                 $tax = new Tax((int) $tax_id);
                 $tax_rate += $tax->rate;
                 $infos['total_price_tax_excl'] += $order_slip_details['amount_tax_excl'];
                 $infos['total_amount'] += $amount;
             }
             $tmp_tax_infos[(string) number_format($tax_rate, 3)] = $infos;
         }
     }
     return $tmp_tax_infos;
 }
 public function getProductTaxesBreakdown()
 {
     $tmp_tax_infos = array();
     $infos = array('total_price_tax_excl' => 0, 'total_amount' => 0);
     foreach ($this->order_slip->getOrdersSlipDetail((int) $this->order_slip->id) as $order_slip_details) {
         $tax_calculator = OrderDetail::getTaxCalculatorStatic((int) $order_slip_details['id_order_detail']);
         $tax_amount = $tax_calculator->getTaxesAmount($order_slip_details['amount_tax_excl']);
         if ($this->order->useOneAfterAnotherTaxComputationMethod()) {
             foreach ($tax_amount as $tax_id => $amount) {
                 $tax = new Tax((int) $tax_id);
                 if (!isset($total_tax_amount[$tax->rate])) {
                     $tmp_tax_infos[$tax->rate]['name'] = $tax->name;
                     $tmp_tax_infos[$tax->rate]['total_price_tax_excl'] = $order_slip_details['amount_tax_excl'];
                     $tmp_tax_infos[$tax->rate]['total_amount'] = $amount;
                 } else {
                     $tmp_tax_infos[$tax->rate]['total_price_tax_excl'] += $order_slip_details['amount_tax_excl'];
                     $tmp_tax_infos[$tax->rate]['total_amount'] += $amount;
                 }
             }
         } else {
             $tax_rate = 0;
             foreach ($tax_amount as $tax_id => $amount) {
                 $tax = new Tax((int) $tax_id);
                 $tax_rate = $tax->rate;
                 $infos['total_price_tax_excl'] += (double) Tools::ps_round($order_slip_details['amount_tax_excl'], 2);
                 $infos['total_amount'] += (double) Tools::ps_round($amount, 2);
             }
             $tmp_tax_infos[(string) number_format($tax_rate, 3)] = $infos;
         }
     }
     // Delete ecotax from the total
     $ecotax = $this->order_slip->getEcoTaxTaxesBreakdown();
     if ($this->order_slip->order_slip_type == 1) {
         foreach ($tmp_tax_infos as $rate => &$row) {
             $row['total_price_tax_excl'] -= Db::getInstance()->getValue('SELECT `value_tax_excl` FROM ' . _DB_PREFIX_ . 'order_cart_rule WHERE id_order = ' . $this->order_slip->id_order);
             $row['total_amount'] -= Db::getInstance()->getValue('SELECT `value` FROM ' . _DB_PREFIX_ . 'order_cart_rule WHERE id_order = ' . $this->order_slip->id_order) - $row['total_price_tax_excl'];
         }
     }
     if ($ecotax) {
         foreach ($tmp_tax_infos as $rate => &$row) {
             if (!isset($ecotax[$rate])) {
                 continue;
             }
             $row['total_price_tax_excl'] -= $ecotax[$rate]['ecotax_tax_excl'];
             $row['total_amount'] -= $ecotax[$rate]['ecotax_tax_incl'] - $ecotax[$rate]['ecotax_tax_excl'];
         }
     }
     return $tmp_tax_infos;
 }
 /**
  * By default this function was made for invoice, to compute tax amounts and balance delta (because of computation made on round values).
  * If you provide $limitToOrderDetails, only these item will be taken into account. This option is usefull for order slip for example,
  * where only sublist of the order is refunded.
  *
  * @param $limitToOrderDetails Optional array of OrderDetails to take into account. False by default to take all OrderDetails from the current Order.
  * @return array A list of tax rows applied to the given OrderDetails (or all OrderDetails linked to the current Order).
  */
 public function getProductTaxesDetails($limitToOrderDetails = false)
 {
     $round_type = $this->round_type;
     if ($round_type == 0) {
         // if this is 0, it means the field did not exist
         // at the time the order was made.
         // Set it to old type, which was closest to line.
         $round_type = Order::ROUND_LINE;
     }
     // compute products discount
     $order_discount_tax_excl = $this->total_discounts_tax_excl;
     $free_shipping_tax = 0;
     $product_specific_discounts = array();
     $expected_total_base = $this->total_products - $this->total_discounts_tax_excl;
     foreach ($this->getCartRules() as $order_cart_rule) {
         if ($order_cart_rule['free_shipping'] && $free_shipping_tax === 0) {
             $free_shipping_tax = $this->total_shipping_tax_incl - $this->total_shipping_tax_excl;
             $order_discount_tax_excl -= $this->total_shipping_tax_excl;
             $expected_total_base += $this->total_shipping_tax_excl;
         }
         $cart_rule = new CartRule($order_cart_rule['id_cart_rule']);
         if ($cart_rule->reduction_product > 0) {
             if (empty($product_specific_discounts[$cart_rule->reduction_product])) {
                 $product_specific_discounts[$cart_rule->reduction_product] = 0;
             }
             $product_specific_discounts[$cart_rule->reduction_product] += $order_cart_rule['value_tax_excl'];
             $order_discount_tax_excl -= $order_cart_rule['value_tax_excl'];
         }
     }
     $products_tax = $this->total_products_wt - $this->total_products;
     $discounts_tax = $this->total_discounts_tax_incl - $this->total_discounts_tax_excl;
     // We add $free_shipping_tax because when there is free shipping, the tax that would
     // be paid if there wasn't is included in $discounts_tax.
     $expected_total_tax = $products_tax - $discounts_tax + $free_shipping_tax;
     $actual_total_tax = 0;
     $actual_total_base = 0;
     $order_detail_tax_rows = array();
     $breakdown = array();
     // Get order_details
     $order_details = $limitToOrderDetails ? $limitToOrderDetails : $this->getOrderDetailList();
     $order_ecotax_tax = 0;
     $tax_rates = array();
     foreach ($order_details as $order_detail) {
         $id_order_detail = $order_detail['id_order_detail'];
         $tax_calculator = OrderDetail::getTaxCalculatorStatic($id_order_detail);
         // TODO: probably need to make an ecotax tax breakdown here instead,
         // but it seems unlikely there will be different tax rates applied to the
         // ecotax in the same order in the real world
         $unit_ecotax_tax = $order_detail['ecotax'] * $order_detail['ecotax_tax_rate'] / 100.0;
         $order_ecotax_tax += $order_detail['product_quantity'] * $unit_ecotax_tax;
         $discount_ratio = 0;
         if ($this->total_products > 0) {
             $discount_ratio = ($order_detail['unit_price_tax_excl'] + $order_detail['ecotax']) / $this->total_products;
         }
         // share of global discount
         $discounted_price_tax_excl = $order_detail['unit_price_tax_excl'] - $discount_ratio * $order_discount_tax_excl;
         // specific discount
         if (!empty($product_specific_discounts[$order_detail['product_id']])) {
             $discounted_price_tax_excl -= $product_specific_discounts[$order_detail['product_id']];
         }
         $quantity = $order_detail['product_quantity'];
         foreach ($tax_calculator->taxes as $tax) {
             $tax_rates[$tax->id] = $tax->rate;
         }
         foreach ($tax_calculator->getTaxesAmount($discounted_price_tax_excl) as $id_tax => $unit_amount) {
             $total_tax_base = 0;
             switch ($round_type) {
                 case Order::ROUND_ITEM:
                     $total_tax_base = $quantity * Tools::ps_round($discounted_price_tax_excl, _PS_PRICE_COMPUTE_PRECISION_, $this->round_mode);
                     $total_amount = $quantity * Tools::ps_round($unit_amount, _PS_PRICE_COMPUTE_PRECISION_, $this->round_mode);
                     break;
                 case Order::ROUND_LINE:
                     $total_tax_base = Tools::ps_round($quantity * $discounted_price_tax_excl, _PS_PRICE_COMPUTE_PRECISION_, $this->round_mode);
                     $total_amount = Tools::ps_round($quantity * $unit_amount, _PS_PRICE_COMPUTE_PRECISION_, $this->round_mode);
                     break;
                 case Order::ROUND_TOTAL:
                     $total_tax_base = $quantity * $discounted_price_tax_excl;
                     $total_amount = $quantity * $unit_amount;
                     break;
             }
             if (!isset($breakdown[$id_tax])) {
                 $breakdown[$id_tax] = array('tax_base' => 0, 'tax_amount' => 0);
             }
             $breakdown[$id_tax]['tax_base'] += $total_tax_base;
             $breakdown[$id_tax]['tax_amount'] += $total_amount;
             $order_detail_tax_rows[] = array('id_order_detail' => $id_order_detail, 'id_tax' => $id_tax, 'tax_rate' => $tax_rates[$id_tax], 'unit_tax_base' => $discounted_price_tax_excl, 'total_tax_base' => $total_tax_base, 'unit_amount' => $unit_amount, 'total_amount' => $total_amount);
         }
     }
     if (!empty($order_detail_tax_rows)) {
         foreach ($breakdown as $data) {
             $actual_total_tax += Tools::ps_round($data['tax_amount'], _PS_PRICE_COMPUTE_PRECISION_, $this->round_mode);
             $actual_total_base += Tools::ps_round($data['tax_base'], _PS_PRICE_COMPUTE_PRECISION_, $this->round_mode);
         }
         $order_ecotax_tax = Tools::ps_round($order_ecotax_tax, _PS_PRICE_COMPUTE_PRECISION_, $this->round_mode);
         $tax_rounding_error = $expected_total_tax - $actual_total_tax - $order_ecotax_tax;
         if ($tax_rounding_error !== 0) {
             Tools::spreadAmount($tax_rounding_error, _PS_PRICE_COMPUTE_PRECISION_, $order_detail_tax_rows, 'total_amount');
         }
         $base_rounding_error = $expected_total_base - $actual_total_base;
         if ($base_rounding_error !== 0) {
             Tools::spreadAmount($base_rounding_error, _PS_PRICE_COMPUTE_PRECISION_, $order_detail_tax_rows, 'total_tax_base');
         }
     }
     return $order_detail_tax_rows;
 }