Пример #1
0
/**
 * Calculate products and shipping taxes
 *
 * @param array $cart Cart data
 * @param array $group_key Group number
 * @param array $group_products Products data
 * @param array $shipping_rates
 * @param array $auth Auth data
 * @return boolean Always false
 */
function fn_calculate_taxes(&$cart, $group_key, &$group_products, &$shipping_rates, $auth)
{
    /**
     * Prepare params before applying products and shipping taxes to cart
     *
     * @param array $cart           Cart data
     * @param array $group_products Products data
     * @param array $shipping_rates
     * @param array $auth           Auth data
     */
    fn_set_hook('calculate_taxes_pre', $cart, $group_products, $shipping_rates, $auth);
    $calculated_data = array();
    if (Registry::get('settings.General.tax_calculation') == 'unit_price') {
        // Tax calculation method based on UNIT PRICE
        // Calculate product taxes
        foreach ($group_products as $k => $product) {
            $taxes = fn_get_product_taxes($k, $cart, $group_products);
            if (empty($taxes)) {
                continue;
            }
            if (isset($product['subtotal'])) {
                if ($product['price'] == $product['subtotal'] && $product['amount'] != 1) {
                    $price = fn_format_price($product['price']);
                } else {
                    $price = fn_format_price($product['subtotal'] / $product['amount']);
                }
                $calculated_data['P_' . $k] = fn_calculate_tax_rates($taxes, $price, $product['amount'], $auth, $cart);
                $group_products[$k]['tax_summary'] = array('included' => 0, 'added' => 0, 'total' => 0);
                // tax summary for 1 unit of product
                $cart['products'][$k]['tax_summary'] = array('included' => 0, 'added' => 0, 'total' => 0);
                // tax summary for 1 unit of product
                // Apply taxes to product subtotal
                if (!empty($calculated_data['P_' . $k])) {
                    foreach ($calculated_data['P_' . $k] as $_k => $v) {
                        $group_products[$k]['taxes'][$_k] = $v;
                        $cart['products'][$k]['taxes'][$_k] = $v;
                        if ($taxes[$_k]['price_includes_tax'] != 'Y') {
                            $group_products[$k]['tax_summary']['added'] += $v['tax_subtotal'];
                            $cart['products'][$k]['tax_summary']['added'] += $v['tax_subtotal'];
                        } else {
                            $group_products[$k]['tax_summary']['included'] += $v['tax_subtotal'];
                            $cart['products'][$k]['tax_summary']['included'] += $v['tax_subtotal'];
                        }
                    }
                    $group_products[$k]['tax_summary']['total'] = $group_products[$k]['tax_summary']['added'] + $group_products[$k]['tax_summary']['included'];
                    $cart['products'][$k]['tax_summary']['total'] = $cart['products'][$k]['tax_summary']['added'] + $cart['products'][$k]['tax_summary']['included'];
                }
            }
        }
        // Calculate shipping taxes
        if (!empty($shipping_rates)) {
            foreach ($shipping_rates as $shipping_id => $shipping) {
                $taxes = fn_get_shipping_taxes($shipping_id, $shipping_rates, $cart);
                if (!empty($taxes)) {
                    $shipping_rates[$shipping_id]['taxes'] = array();
                    $calculate_rate = true;
                    if (!empty($cart['chosen_shipping'][$group_key]) && $cart['chosen_shipping'][$group_key] == $shipping_id) {
                        $calculated_data['S_' . $group_key . '_' . $shipping_id] = fn_calculate_tax_rates($taxes, $shipping['rate'], 1, $auth, $cart);
                        if (!empty($calculated_data['S_' . $group_key . '_' . $shipping_id])) {
                            foreach ($calculated_data['S_' . $group_key . '_' . $shipping_id] as $__k => $__v) {
                                if ($taxes[$__k]['price_includes_tax'] != 'Y') {
                                    $cart['display_shipping_cost'] += Registry::get('settings.Appearance.cart_prices_w_taxes') == 'Y' ? $__v['tax_subtotal'] : 0;
                                    $cart['tax_subtotal'] += $__v['tax_subtotal'];
                                }
                                if ($cart['stored_taxes'] == 'Y') {
                                    $cart['taxes'][$__k]['applies']['S_' . $group_key . '_' . $shipping_id] = $__v['tax_subtotal'];
                                }
                            }
                            $shipping_rates[$shipping_id]['taxes']['S_' . $group_key . '_' . $shipping_id] = $calculated_data['S_' . $group_key . '_' . $shipping_id];
                            $calculate_rate = false;
                        }
                    }
                    if ($calculate_rate) {
                        $cur_shipping_rates = fn_calculate_tax_rates($taxes, $shipping['rate'], 1, $auth, $cart);
                        if (!empty($cur_shipping_rates)) {
                            $shipping_rates[$shipping_id]['taxes'] = $cur_shipping_rates;
                        }
                    }
                }
            }
            foreach ($shipping_rates as $shipping_id => $shipping) {
                // Calculate taxes for each shipping rate
                $taxes = fn_get_shipping_taxes($shipping_id, $shipping_rates, $cart);
                $shipping_rates[$shipping_id]['taxed_price'] = 0;
                unset($shipping_rates[$shipping_id]['inc_tax']);
                if (!empty($taxes)) {
                    $shipping_rates[$shipping_id]['taxes'] = array();
                    $tax = fn_calculate_tax_rates($taxes, fn_format_price($shipping['rate']), 1, $auth, $cart);
                    $shipping_rates[$shipping_id]['taxes'] = $tax;
                    if (!empty($tax) && Registry::get('settings.Appearance.cart_prices_w_taxes') == 'Y') {
                        foreach ($tax as $_id => $_tax) {
                            if ($_tax['price_includes_tax'] != 'Y') {
                                $shipping_rates[$shipping_id]['taxed_price'] += $_tax['tax_subtotal'];
                            }
                        }
                        $shipping_rates[$shipping_id]['inc_tax'] = true;
                    }
                    if (!empty($shipping_rates[$shipping_id]['rate']) && $shipping_rates[$shipping_id]['taxed_price'] > 0) {
                        $shipping_rates[$shipping_id]['taxed_price'] += $shipping_rates[$shipping_id]['rate'];
                    }
                }
            }
        }
    } else {
        // Tax calculation method based on SUBTOTAL
        // Calculate discounted subtotal
        if (!isset($cart['subtotal_discount'])) {
            $cart['subtotal_discount'] = 0;
        }
        $discounted_subtotal = $cart['subtotal'] - $cart['subtotal_discount'];
        if ($discounted_subtotal < 0) {
            $discounted_subtotal = 0;
        }
        // Get discount distribution coefficient (DDC) between taxes
        if ($cart['subtotal'] > 0) {
            $ddc = $discounted_subtotal / $cart['subtotal'];
        } else {
            $ddc = 1;
        }
        //
        // Group subtotal by taxes
        //
        $subtotal = array();
        // Get products taxes
        foreach ($group_products as $cart_id => $product) {
            $taxes = fn_get_product_taxes($cart_id, $cart, $group_products);
            if (!empty($taxes)) {
                foreach ($taxes as $tax_id => $tax) {
                    if (empty($subtotal[$tax_id])) {
                        $subtotal[$tax_id] = fn_init_tax_subtotals($tax);
                    }
                    $_subtotal = $product['price'] == $product['subtotal'] && $product['amount'] != 1 ? fn_format_price($product['price'] * $product['amount']) : $product['subtotal'];
                    $subtotal[$tax_id]['subtotal'] += $_subtotal;
                    $subtotal[$tax_id]['applies']['P'] += $_subtotal;
                    $subtotal[$tax_id]['applies']['items']['P'][$cart_id] = true;
                    if (isset($product['company_id'])) {
                        if (!isset($subtotal[$tax_id]['group'][$group_key])) {
                            $subtotal[$tax_id]['group'][$group_key]['products'] = 0;
                        }
                        $subtotal[$tax_id]['group'][$group_key]['products'] += $_subtotal;
                        $priority_stack['products'][$group_key] = -1;
                        $applied_taxes['products'][$group_key] = 0;
                    }
                }
            }
        }
        // Get shipping taxes
        if (!empty($shipping_rates)) {
            foreach ($shipping_rates as $shipping_id => $shipping) {
                // Calculate taxes for each shipping rate
                $taxes = fn_get_shipping_taxes($shipping_id, $shipping_rates, $cart);
                $shipping_rates[$shipping_id]['taxed_price'] = 0;
                unset($shipping_rates[$shipping_id]['inc_tax']);
                // Display shipping with taxes at cart/checkout page
                if (!empty($taxes)) {
                    $shipping_rates[$shipping_id]['taxes'] = array();
                    $tax = fn_calculate_tax_rates($taxes, fn_format_price($shipping['rate']), 1, $auth, $cart);
                    $shipping_rates[$shipping_id]['taxes'] = $tax;
                    if (!empty($tax) && Registry::get('settings.Appearance.cart_prices_w_taxes') == 'Y') {
                        foreach ($tax as $_id => $_tax) {
                            if ($_tax['price_includes_tax'] != 'Y') {
                                $shipping_rates[$shipping_id]['taxed_price'] += $_tax['tax_subtotal'];
                            }
                        }
                        $shipping_rates[$shipping_id]['inc_tax'] = true;
                    }
                    if (!empty($shipping_rates[$shipping_id]['rate']) && $shipping_rates[$shipping_id]['taxed_price'] > 0) {
                        $shipping_rates[$shipping_id]['taxed_price'] += $shipping_rates[$shipping_id]['rate'];
                    }
                }
                if (!isset($cart['chosen_shipping'][$group_key]) || $cart['chosen_shipping'][$group_key] != $shipping_id) {
                    continue;
                }
                // Add shipping taxes to "tax" array
                if (!empty($taxes)) {
                    foreach ($taxes as $tax_id => $tax) {
                        if (empty($subtotal[$tax_id])) {
                            $subtotal[$tax_id] = fn_init_tax_subtotals($tax);
                        }
                        $subtotal[$tax_id]['subtotal'] += $shipping['rate'];
                        $subtotal[$tax_id]['applies']['S'] += $shipping['rate'];
                        $subtotal[$tax_id]['applies']['items']['S'][$group_key][$shipping_id] = true;
                        /*                        if (!isset($subtotal[$tax_id]['groups'][$group_key]['shippings'])) {
                                                    $subtotal[$tax_id]['groups'][$group_key]['shippings'] = 0;
                                                }
                        
                                                $subtotal[$tax_id]['groups'][$group_key]['shippings'] += $shipping['rate'];*/
                        $priority_stack['shippings'][$group_key] = -1;
                        $applied_taxes['shippings'][$group_key] = 0;
                    }
                }
            }
        }
        if (!empty($subtotal)) {
            $subtotal = fn_sort_array_by_key($subtotal, 'priority');
        }
        // Apply DDC and calculate tax rates
        $calculated_taxes = array();
        if (empty($priority_stack)) {
            $priority_stack['products'][0] = -1;
            $priority_stack['shippings'][0] = -1;
            $applied_taxes['products'][0] = 0;
            $applied_taxes['shippings'][0] = 0;
        }
        foreach ($subtotal as $tax_id => $_st) {
            if (empty($_st['tax_id'])) {
                $_st['tax_id'] = $tax_id;
            }
            $product_tax = fn_calculate_tax_rates(array($_st), fn_format_price($_st['applies']['P'] * $ddc), 1, $auth, $cart);
            $shipping_tax = fn_calculate_tax_rates(array($_st), fn_format_price($_st['applies']['S']), 1, $auth, $cart);
            if (empty($product_tax) && empty($shipping_tax)) {
                continue;
            }
            if (empty($_st['groups'])) {
                $_st['groups'][0]['products'] = $_st['applies']['P'];
                $_st['groups'][0]['shippings'] = $_st['applies']['S'];
            }
            foreach ($_st['groups'] as $group_key => $applies) {
                $apply_tax_stack = array('products' => 0, 'shippings' => 0);
                if (!isset($priority_stack['products'][$group_key])) {
                    $priority_stack['products'][$group_key] = -1;
                }
                if (!isset($priority_stack['shippings'][$group_key])) {
                    $priority_stack['shippings'][$group_key] = -1;
                }
                if ($priority_stack['products'][$group_key] < 0 && !empty($applies['products'])) {
                    $priority_stack['products'][$group_key] = $_st['priority'];
                } elseif (!empty($applies['products']) && $priority_stack['products'][$group_key] != $_st['priority']) {
                    $apply_tax_stack['products'] = $applied_taxes['products'][$group_key];
                    $priority_stack['products'][$group_key] = $_st['priority'];
                }
                if ($priority_stack['shippings'][$group_key] < 0 && !empty($applies['shippings'])) {
                    $priority_stack['shippings'][$group_key] = $_st['priority'];
                } elseif (!empty($applies['shippings']) && $priority_stack['shippings'][$group_key] != $_st['priority']) {
                    $apply_tax_stack['shippings'] = $applied_taxes['shippings'][$group_key];
                    $priority_stack['shippings'][$group_key] = $_st['priority'];
                }
                if (empty($calculated_data[$tax_id])) {
                    $calculated_data[$tax_id] = empty($product_tax) ? reset($shipping_tax) : reset($product_tax);
                }
                if (!empty($applies['products'])) {
                    $products_tax = fn_calculate_tax_rates(array($_st), fn_format_price($applies['products'] * $ddc + $apply_tax_stack['products']), 1, $auth, $cart);
                } else {
                    $products_tax[$tax_id]['tax_subtotal'] = 0;
                }
                if (!empty($applies['shippings'])) {
                    $shippings_tax = fn_calculate_tax_rates(array($_st), fn_format_price($applies['shippings'] + $apply_tax_stack['shippings']), 1, $auth, $cart);
                } else {
                    $shippings_tax[$tax_id]['tax_subtotal'] = 0;
                }
                if (!isset($applied_taxes['products'][$group_key])) {
                    $applied_taxes['products'][$group_key] = 0;
                }
                if (!isset($applied_taxes['shippings'][$group_key])) {
                    $applied_taxes['shippings'][$group_key] = 0;
                }
                if ($_st['price_includes_tax'] != 'Y') {
                    $applied_taxes['products'][$group_key] += $products_tax[$tax_id]['tax_subtotal'];
                    $applied_taxes['shippings'][$group_key] += $shippings_tax[$tax_id]['tax_subtotal'];
                }
                if (!isset($calculated_data[$tax_id]['applies']['P'])) {
                    $calculated_data[$tax_id]['applies']['P'] = 0;
                }
                if (!isset($calculated_data[$tax_id]['applies']['S'])) {
                    $calculated_data[$tax_id]['applies']['S'] = 0;
                }
                $calculated_data[$tax_id]['applies']['P'] += $products_tax[$tax_id]['tax_subtotal'];
                $calculated_data[$tax_id]['applies']['S'] += $shippings_tax[$tax_id]['tax_subtotal'];
                $calculated_data[$tax_id]['applies']['items'] = $_st['applies']['items'];
                $calculated_data[$tax_id]['tax_subtotal'] = $calculated_data[$tax_id]['applies']['P'] + $calculated_data[$tax_id]['applies']['S'];
            }
        }
    }
    /**
     * Processes products data after applying products and shipping taxes to cart)
     *
     * @param array $cart            Cart data
     * @param array $group_products  Products data
     * @param array $shipping_rates  Shipping rates data
     * @param array $auth            Auth data
     * @param array $calculated_data Payment taxes data
     */
    fn_set_hook('calculate_taxes_post', $cart, $group_products, $shipping_rates, $auth, $calculated_data);
    return $calculated_data;
}
Пример #2
0
function fn_calculate_taxes(&$cart, &$cart_products, &$shipping_rates, $auth)
{
    $calculated_data = array();
    if (Registry::get('settings.General.tax_calculation') == 'unit_price') {
        // Tax calculation method based on UNIT PRICE
        // Calculate product taxes
        foreach ($cart_products as $k => $product) {
            $taxes = fn_get_product_taxes($k, $cart, $cart_products);
            if (empty($taxes)) {
                continue;
            }
            if (isset($product['subtotal'])) {
                $price = fn_format_price($product['subtotal'] / $product['amount']);
                $calculated_data['P_' . $k] = fn_calculate_tax_rates($taxes, $price, $product['amount'], $auth, $cart);
                $cart_products[$k]['tax_summary'] = array('included' => 0, 'added' => 0, 'total' => 0);
                // tax summary for 1 unit of product
                // Apply taxes to product subtotal
                if (!empty($calculated_data['P_' . $k])) {
                    foreach ($calculated_data['P_' . $k] as $_k => $v) {
                        $cart_products[$k]['taxes'][$_k] = $v;
                        if ($taxes[$_k]['price_includes_tax'] != 'Y') {
                            $cart_products[$k]['tax_summary']['added'] += $v['tax_subtotal'];
                        } else {
                            $cart_products[$k]['tax_summary']['included'] += $v['tax_subtotal'];
                        }
                    }
                    $cart_products[$k]['tax_summary']['total'] = $cart_products[$k]['tax_summary']['added'] + $cart_products[$k]['tax_summary']['included'];
                }
            }
        }
        // Calculate shipping taxes
        if (!empty($shipping_rates)) {
            foreach ($shipping_rates as $shipping_id => $shipping) {
                $taxes = fn_get_shipping_taxes($shipping_id, $shipping_rates, $cart);
                if (!empty($taxes)) {
                    $shipping_rates[$shipping_id]['taxes'] = array();
                    $calculate_rate = true;
                    if (!empty($cart['shipping'][$shipping_id])) {
                        foreach ($cart['shipping'][$shipping_id]['rates'] as $k => $v) {
                            $calculated_data['S_' . $shipping_id . '_' . $k] = fn_calculate_tax_rates($taxes, $v, 1, $auth, $cart);
                            if (!empty($calculated_data['S_' . $shipping_id . '_' . $k])) {
                                foreach ($calculated_data['S_' . $shipping_id . '_' . $k] as $__k => $__v) {
                                    if ($taxes[$__k]['price_includes_tax'] != 'Y') {
                                        $cart['display_shipping_cost'] += Registry::get('settings.Appearance.cart_prices_w_taxes') == 'Y' ? $__v['tax_subtotal'] : 0;
                                        $cart['tax_subtotal'] += $__v['tax_subtotal'];
                                    }
                                    if ($cart['stored_taxes'] == 'Y') {
                                        $cart['taxes'][$__k]['applies']['S_' . $shipping_id . '_' . $k] = $__v['tax_subtotal'];
                                    }
                                }
                                $shipping_rates[$shipping_id]['taxes']['S_' . $shipping_id . '_' . $k] = $calculated_data['S_' . $shipping_id . '_' . $k];
                                $calculate_rate = false;
                            }
                        }
                    }
                    if ($calculate_rate) {
                        foreach ($shipping['rates'] as $k => $v) {
                            if (isset($shipping['rates'][$k])) {
                                $cur_shipping_rates = fn_calculate_tax_rates($taxes, $v, 1, $auth, $cart);
                                if (!empty($cur_shipping_rates)) {
                                    $shipping_rates[$shipping_id]['taxes']['S_' . $shipping_id . '_' . $k] = $cur_shipping_rates;
                                }
                            }
                        }
                    }
                }
            }
        }
    } else {
        // Tax calculation method based on SUBTOTAL
        // Calculate discounted subtotal
        if (!isset($cart['subtotal_discount'])) {
            $cart['subtotal_discount'] = 0;
        }
        $discounted_subtotal = $cart['original_subtotal'] - $cart['subtotal_discount'];
        // Get discount distribution coefficient (DDC) between taxes
        $ddc = $discounted_subtotal / $cart['original_subtotal'];
        //
        // Group subtotal by taxes
        //
        $subtotal = array();
        // Get products taxes
        foreach ($cart_products as $k => $product) {
            $taxes = fn_get_product_taxes($k, $cart, $cart_products);
            if (!empty($taxes)) {
                foreach ($taxes as $tax_id => $tax) {
                    if (empty($subtotal[$tax_id])) {
                        $subtotal[$tax_id] = $tax;
                        $subtotal[$tax_id]['subtotal'] = $subtotal[$tax_id]['applies']['P'] = $subtotal[$tax_id]['applies']['S'] = 0;
                        $subtotal[$tax_id]['applies']['items']['P'] = $subtotal[$tax_id]['applies']['items']['S'] = array();
                    }
                    $subtotal[$tax_id]['subtotal'] += $product['subtotal'];
                    $subtotal[$tax_id]['applies']['P'] += $product['subtotal'];
                    $subtotal[$tax_id]['applies']['items']['P'][$k] = true;
                }
            }
        }
        // Get shipping taxes
        if (!empty($shipping_rates)) {
            foreach ($shipping_rates as $shipping_id => $shipping) {
                // Calculate taxes for each shipping rate
                $taxes = fn_get_shipping_taxes($shipping_id, $shipping_rates, $cart);
                if (!empty($taxes)) {
                    $shipping_rates[$shipping_id]['taxes'] = array();
                    foreach ($shipping['rates'] as $k => $v) {
                        $tax = fn_calculate_tax_rates($taxes, fn_format_price($v), 1, $auth, $cart);
                        $shipping_rates[$shipping_id]['taxes']['S_' . $shipping_id . '_' . $k] = $tax;
                    }
                }
                if (!isset($cart['shipping'][$shipping_id])) {
                    continue;
                }
                if (!empty($taxes)) {
                    foreach ($taxes as $tax_id => $tax) {
                        if (empty($subtotal[$tax_id])) {
                            $subtotal[$tax_id] = $tax;
                            $subtotal[$tax_id]['subtotal'] = $subtotal[$tax_id]['applies']['P'] = $subtotal[$tax_id]['applies']['S'] = 0;
                            $subtotal[$tax_id]['applies']['items']['P'] = $subtotal[$tax_id]['applies']['items']['S'] = array();
                        }
                        $subtotal[$tax_id]['subtotal'] += array_sum($cart['shipping'][$shipping_id]['rates']);
                        $subtotal[$tax_id]['applies']['S'] += array_sum($cart['shipping'][$shipping_id]['rates']);
                        $subtotal[$tax_id]['applies']['items']['S'][$shipping_id] = true;
                    }
                }
            }
        }
        // Apply DDC and calculate tax rates
        $calculated_taxes = array();
        foreach ($subtotal as $tax_id => $_st) {
            if (empty($_st['tax_id'])) {
                $_st['tax_id'] = $tax_id;
            }
            $tax = fn_calculate_tax_rates(array($_st), fn_format_price($_st['applies']['P'] * $ddc + $_st['applies']['S']), 1, $auth, $cart);
            if (empty($tax)) {
                continue;
            }
            $calculated_data[$tax_id] = reset($tax);
            $products_tax = fn_calculate_tax_rates(array($_st), fn_format_price($_st['applies']['P'] * $ddc), 1, $auth, $cart);
            $calculated_data[$tax_id]['applies']['P'] = $products_tax[$tax_id]['tax_subtotal'];
            $shipping_tax = fn_calculate_tax_rates(array($_st), fn_format_price($_st['applies']['S']), 1, $auth, $cart);
            $calculated_data[$tax_id]['applies']['S'] = $shipping_tax[$tax_id]['tax_subtotal'];
            $calculated_data[$tax_id]['tax_subtotal'] = $products_tax[$tax_id]['tax_subtotal'] + $shipping_tax[$tax_id]['tax_subtotal'];
            $calculated_data[$tax_id]['applies']['items'] = $_st['applies']['items'];
        }
    }
    fn_apply_calculated_taxes($calculated_data, $cart);
    return false;
}