Exemplo n.º 1
0
function fn_calculate_cart_content(&$cart, $auth, $calculate_shipping = 'A', $calculate_taxes = true, $options_style = 'F', $apply_cart_promotions = true)
{
    $shipping_rates = array();
    $product_groups = array();
    $cart_products = array();
    $cart['subtotal'] = $cart['display_subtotal'] = $cart['original_subtotal'] = $cart['amount'] = $cart['total'] = $cart['discount'] = $cart['tax_subtotal'] = 0;
    $cart['use_discount'] = false;
    $cart['shipping_required'] = false;
    $cart['shipping_failed'] = $cart['company_shipping_failed'] = false;
    $cart['stored_taxes'] = empty($cart['stored_taxes']) ? 'N' : $cart['stored_taxes'];
    $cart['display_shipping_cost'] = $cart['shipping_cost'] = 0;
    $cart['coupons'] = empty($cart['coupons']) ? array() : $cart['coupons'];
    $cart['recalculate'] = isset($cart['recalculate']) ? $cart['recalculate'] : false;
    $cart['free_shipping'] = array();
    $cart['options_style'] = $options_style;
    $cart['products'] = !empty($cart['products']) ? $cart['products'] : array();
    fn_add_exclude_products($cart, $auth);
    if (isset($cart['products']) && is_array($cart['products'])) {
        $amount_totals = array();
        if (Registry::get('settings.General.disregard_options_for_discounts') == 'Y') {
            foreach ($cart['products'] as $k => $v) {
                if (!empty($amount_totals[$v['product_id']])) {
                    $amount_totals[$v['product_id']] += $v['amount'];
                } else {
                    $amount_totals[$v['product_id']] = $v['amount'];
                }
            }
        }
        // Collect product data
        foreach ($cart['products'] as $k => $v) {
            $cart['products'][$k]['amount_total'] = isset($amount_totals[$v['product_id']]) ? $amount_totals[$v['product_id']] : $v['amount'];
            $_cproduct = fn_get_cart_product_data($k, $cart['products'][$k], false, $cart, $auth);
            if (empty($_cproduct)) {
                // FIXME - for deleted products for OM
                fn_delete_cart_product($cart, $k);
                continue;
            }
            $cart_products[$k] = $_cproduct;
        }
        fn_set_hook('calculate_cart_items', $cart, $cart_products, $auth);
        // Apply cart promotions
        if ($apply_cart_promotions == true && $cart['subtotal'] >= 0) {
            if (!empty($cart['stored_subtotal_discount'])) {
                $prev_discount = $cart['subtotal_discount'];
            }
            $cart['applied_promotions'] = fn_promotion_apply('cart', $cart, $auth, $cart_products);
            if (!empty($cart['stored_subtotal_discount'])) {
                $cart['subtotal_discount'] = $prev_discount;
            }
        }
        fn_check_promotion_notices();
        if (Registry::get('settings.General.disable_shipping') == 'Y') {
            $cart['shipping_required'] = false;
        }
        if (!empty($cart['change_cart_products'])) {
            $location = fn_get_customer_location($auth, $cart);
            $product_groups = Shippings::groupProductsList($cart_products, $location);
            if (!empty($cart['product_groups']) && count($product_groups) == count($cart['product_groups'])) {
                foreach ($product_groups as $key_group => $group) {
                    $cart['product_groups'][$key_group]['products'] = $group['products'];
                }
            } else {
                if (!empty($cart['chosen_shipping']) && count($cart['chosen_shipping']) == count($product_groups)) {
                    $cart['calculate_shipping'] = true;
                }
                if (!empty($cart['product_groups']) && count($cart['product_groups']) !== count($product_groups)) {
                    unset($cart['product_groups']);
                }
            }
            unset($cart['change_cart_products']);
            $cart['stored_taxes'] = 'N';
        }
        if (!empty($cart['calculate_shipping']) || empty($cart['product_groups'])) {
            $location = fn_get_customer_location($auth, $cart);
            $product_groups = Shippings::groupProductsList($cart_products, $location);
            $shippings = array();
            if ($cart['shipping_required'] !== false) {
                $cart['shipping_required'] = false;
                foreach ($product_groups as $key_group => $group) {
                    if ($group['shipping_no_required'] === false) {
                        $cart['shipping_required'] = true;
                        break;
                    }
                }
            }
            foreach ($product_groups as $key_group => $group) {
                if ($cart['shipping_required'] === false) {
                    $product_groups[$key_group]['free_shipping'] = true;
                    $product_groups[$key_group]['shipping_no_required'] = true;
                }
                $product_groups[$key_group]['shippings'] = array();
                $shippings_group = Shippings::getShippingsList($group);
                // Adding a shipping method from the created order, if the shipping is not yet in the list.
                if (!empty($cart['chosen_shipping']) && !empty($cart['shipping']) && !empty($cart['order_id'])) {
                    foreach ($cart['shipping'] as $shipping) {
                        if (!isset($shippings_group[$shipping['shipping_id']])) {
                            $shippings_group[$shipping['shipping_id']] = $shipping;
                        }
                    }
                }
                foreach ($shippings_group as $shipping_id => $shipping) {
                    if (!empty($shipping['service_params']['max_weight_of_box'])) {
                        $_group = Shippings::repackProductsByWeight($group, $shipping['service_params']['max_weight_of_box']);
                    } else {
                        $_group = $group;
                    }
                    $_shipping = $shipping;
                    $_shipping['package_info'] = $_group['package_info'];
                    $_shipping['keys'] = array('group_key' => $key_group, 'shipping_id' => $shipping_id);
                    $shippings[] = $_shipping;
                    $shipping['group_key'] = $key_group;
                    $shipping['rate'] = 0;
                    if (in_array($shipping_id, $cart['free_shipping']) || $group['free_shipping']) {
                        $shipping['free_shipping'] = true;
                    }
                    $product_groups[$key_group]['shippings'][$shipping_id] = $shipping;
                }
            }
            if (!empty($cart['calculate_shipping'])) {
                $rates = Shippings::calculateRates($shippings);
                foreach ($rates as $rate) {
                    $g_key = $rate['keys']['group_key'];
                    $sh_id = $rate['keys']['shipping_id'];
                    if ($rate['price'] !== false) {
                        $rate['price'] += !empty($product_groups[$g_key]['package_info']['shipping_freight']) ? $product_groups[$g_key]['package_info']['shipping_freight'] : 0;
                        $product_groups[$g_key]['shippings'][$sh_id]['rate'] = empty($product_groups[$g_key]['shippings'][$sh_id]['free_shipping']) ? $rate['price'] : 0;
                    } else {
                        unset($product_groups[$g_key]['shippings'][$sh_id]);
                    }
                }
            }
            $cart['product_groups'] = $product_groups;
        }
        $product_groups =& $cart['product_groups'];
        // FIXME
        $cart['shipping_cost'] = 0;
        $cart['shipping'] = array();
        if (empty($cart['chosen_shipping'])) {
            $cart['chosen_shipping'] = array();
            if (fn_allowed_for('ULTIMATE') && Registry::get('settings.Checkout.display_shipping_step') != 'Y' && !empty($cart['calculate_shipping'])) {
                foreach ($product_groups as $key_group => $group) {
                    if (!empty($group['shippings'])) {
                        $first_shipping = reset($group['shippings']);
                        $cart['chosen_shipping'][$key_group] = $first_shipping['shipping_id'];
                    }
                }
            }
        }
        $count_shipping_failed = 0;
        foreach ($product_groups as $key_group => $group) {
            if (!empty($cart['calculate_shipping']) && (!isset($cart['chosen_shipping'][$key_group]) || empty($group['shippings'][$cart['chosen_shipping'][$key_group]])) && !$group['free_shipping']) {
                $cart['chosen_shipping'][$key_group] = key($group['shippings']);
            }
            if ($group['shipping_no_required']) {
                unset($cart['chosen_shipping'][$key_group]);
            }
            if (!isset($cart['chosen_shipping'][$key_group]) && !$group['free_shipping'] && !$group['shipping_no_required']) {
                $count_shipping_failed++;
                $cart['company_shipping_failed'] = true;
            }
            foreach ($group['shippings'] as $shipping_id => $shipping) {
                if (isset($cart['chosen_shipping'][$key_group]) && $cart['chosen_shipping'][$key_group] == $shipping_id) {
                    $cart['shipping_cost'] += $shipping['rate'];
                }
            }
            if (!empty($group['shippings']) && isset($cart['chosen_shipping'][$key_group])) {
                $shipping = $group['shippings'][$cart['chosen_shipping'][$key_group]];
                $shipping_id = $shipping['shipping_id'];
                if (empty($cart['shipping'][$shipping_id])) {
                    $cart['shipping'][$shipping_id] = $shipping;
                    $cart['shipping'][$shipping_id]['rates'] = array();
                }
                $cart['shipping'][$shipping_id]['rates'][$key_group] = $shipping['rate'];
            }
        }
        $cart['display_shipping_cost'] = $cart['shipping_cost'];
        if (!empty($product_groups) && count($product_groups) == $count_shipping_failed) {
            $cart['shipping_failed'] = true;
        }
        foreach ($cart['chosen_shipping'] as $key_group => $shipping_id) {
            if (!empty($product_groups[$key_group]) && !empty($product_groups[$key_group]['shippings'][$shipping_id])) {
                $shipping = $product_groups[$key_group]['shippings'][$shipping_id];
                $shipping['group_name'] = $product_groups[$key_group]['name'];
                $product_groups[$key_group]['chosen_shippings'] = array($shipping);
            } else {
                unset($cart['chosen_shipping'][$key_group]);
            }
        }
        fn_apply_stored_shipping_rates($cart);
        fn_set_hook('calculate_cart_taxes_pre', $cart, $cart_products, $product_groups, $calculate_taxes, $auth);
        $calculated_taxes_summary = array();
        foreach ($product_groups as $key_group => &$group) {
            foreach ($group['products'] as $cart_id => $product) {
                if (!empty($cart_products[$cart_id])) {
                    $group['products'][$cart_id] = $cart_products[$cart_id];
                }
            }
            // Calculate taxes
            if ($calculate_taxes == true && $auth['tax_exempt'] != 'Y') {
                $calculated_taxes = fn_calculate_taxes($cart, $key_group, $group['products'], $group['shippings'], $auth);
                if (empty($calculated_taxes_summary)) {
                    $calculated_taxes_summary = array();
                }
                foreach ($calculated_taxes as $tax_id => $tax) {
                    if (empty($calculated_taxes_summary[$tax_id])) {
                        $calculated_taxes_summary[$tax_id] = $calculated_taxes[$tax_id];
                    } else {
                        $calculated_taxes_summary[$tax_id]['tax_subtotal'] += $calculated_taxes[$tax_id]['applies']['S'];
                        $calculated_taxes_summary[$tax_id]['applies']['S'] += $calculated_taxes[$tax_id]['applies']['S'];
                        $calculated_taxes_summary[$tax_id]['tax_subtotal'] += $calculated_taxes[$tax_id]['applies']['P'];
                        $calculated_taxes_summary[$tax_id]['applies']['P'] += $calculated_taxes[$tax_id]['applies']['P'];
                    }
                }
            } elseif ($cart['stored_taxes'] != 'Y') {
                $cart['taxes'] = $cart['tax_summary'] = array();
            }
            unset($group);
        }
        fn_apply_calculated_taxes($calculated_taxes_summary, $cart);
        // /FIXME
        fn_set_hook('calculate_cart_taxes_post', $cart, $cart_products, $shipping_rates, $calculate_taxes, $auth);
        $cart['subtotal'] = $cart['display_subtotal'] = 0;
        fn_update_cart_data($cart, $cart_products);
        foreach ($cart['products'] as $product_code => $product) {
            foreach ($product_groups as $key_group => $group) {
                if (in_array($product_code, array_keys($group['products']))) {
                    $product_groups[$key_group]['products'][$product_code] = $product;
                }
            }
        }
        // Calculate totals
        foreach ($product_groups as $key_group => $group) {
            foreach ($group['products'] as $product_code => $product) {
                $_tax = !empty($product['tax_summary']) ? $product['tax_summary']['added'] / $product['amount'] : 0;
                $cart_products[$product_code]['display_price'] = $cart_products[$product_code]['price'] + (Registry::get('settings.Appearance.cart_prices_w_taxes') == 'Y' ? $_tax : 0);
                $cart_products[$product_code]['subtotal'] = $cart_products[$product_code]['price'] * $product['amount'];
                $cart_products[$product_code]['display_subtotal'] = $cart_products[$product_code]['display_price'] * $product['amount'];
                if (!empty($product['tax_summary'])) {
                    $cart_products[$product_code]['tax_summary'] = $product['tax_summary'];
                }
                $cart['subtotal'] += $cart_products[$product_code]['subtotal'];
                $cart['display_subtotal'] += $cart_products[$product_code]['display_subtotal'];
                $cart['products'][$product_code]['display_price'] = $cart_products[$product_code]['display_price'];
                $product_groups[$key_group]['products'][$product_code]['display_price'] = $cart_products[$product_code]['display_price'];
                $cart['tax_subtotal'] += !empty($product['tax_summary']) ? $product['tax_summary']['added'] : 0;
                $cart['total'] += ($cart_products[$product_code]['price'] - 0) * $product['amount'];
                if (!empty($product['discount'])) {
                    $cart['discount'] += $product['discount'] * $product['amount'];
                }
            }
        }
        if (Registry::get('settings.General.tax_calculation') == 'subtotal') {
            $cart['tax_subtotal'] += !empty($cart['tax_summary']['added']) ? $cart['tax_summary']['added'] : 0;
        }
        $cart['subtotal'] = fn_format_price($cart['subtotal']);
        $cart['display_subtotal'] = fn_format_price($cart['display_subtotal']);
        $cart['total'] += $cart['tax_subtotal'];
        $cart['total'] = fn_format_price($cart['total'] + $cart['shipping_cost']);
        if (!empty($cart['subtotal_discount'])) {
            $cart['total'] -= $cart['subtotal_discount'] < $cart['total'] ? $cart['subtotal_discount'] : $cart['total'];
        }
    }
    /**
     * Processes cart data after calculating all prices and other data (taxes, shippings etc)
     *
     * @param array  $cart               Cart data
     * @param array  $cart_products      Cart products
     * @param array  $auth               Auth data
     * @param string $calculate_shipping // 1-letter flag
     *      A - calculate all available methods
     *      E - calculate selected methods only (from cart[shipping])
     *      S - skip calculation
     * @param bool $calculate_taxes       Flag determines if taxes should be calculated
     * @param bool $apply_cart_promotions Flag determines if promotions should be applied to the cart
     */
    fn_set_hook('calculate_cart', $cart, $cart_products, $auth, $calculate_shipping, $calculate_taxes, $apply_cart_promotions);
    if (!empty($cart['calculate_shipping']) || empty($cart['product_groups'])) {
        $cart['product_groups'] = $product_groups;
    }
    $cart['recalculate'] = false;
    $cart['calculate_shipping'] = false;
    /**
     * Processes cart data after calculating all prices and other data (taxes, shippings etc) including products group
     *
     * @param array  $cart               Cart data
     * @param array  $auth               Auth data
     * @param string $calculate_shipping // 1-letter flag
     *      A - calculate all available methods
     *      E - calculate selected methods only (from cart[shipping])
     *      S - skip calculation
     * @param bool   $calculate_taxes Flag determines if taxes should be calculated
     * @param string $options_style   1-letter flag
     *      "F" - Full option information (with exceptions)
     *      "I" - Short info
     *      "" - "Source" info. Only ids array (option_id => variant_id)
     * @param bool  $apply_cart_promotions Flag determines if promotions should be applied to the cart
     * @param array $cart_products         Cart products
     * @param array $product_groups        Products grouped by packages, suppliers, vendors
     */
    fn_set_hook('calculate_cart_post', $cart, $auth, $calculate_shipping, $calculate_taxes, $options_style, $apply_cart_promotions, $cart_products, $product_groups);
    return array($cart_products, $product_groups);
}
Exemplo n.º 2
0
function fn_calculate_cart_content(&$cart, $auth, $calculate_shipping = 'A', $calculate_taxes = true, $options_style = 'F', $apply_cart_promotions = true)
{
    $shipping_rates = array();
    $cart_products = array();
    $cart['subtotal'] = $cart['original_subtotal'] = $cart['amount'] = $cart['total'] = $cart['discount'] = $cart['tax_subtotal'] = 0;
    $cart['use_discount'] = false;
    $cart['shipping_required'] = false;
    $cart['shipping_failed'] = false;
    $cart['stored_taxes'] = empty($cart['stored_taxes']) ? 'N' : $cart['stored_taxes'];
    $cart['display_shipping_cost'] = $cart['shipping_cost'] = 0;
    $cart['coupons'] = empty($cart['coupons']) ? array() : $cart['coupons'];
    $cart['recalculate'] = isset($cart['recalculate']) ? $cart['recalculate'] : false;
    $cart['free_shipping'] = array();
    $cart['options_style'] = $options_style;
    fn_add_exclude_products($cart, $auth);
    if (isset($cart['products']) && is_array($cart['products'])) {
        // Collect product data
        foreach ($cart['products'] as $k => $v) {
            $_cproduct = fn_get_cart_product_data($k, $cart['products'][$k], false, $cart, $auth);
            if (empty($_cproduct)) {
                // FIXME - for deleted products for OM
                unset($cart['products'][$k]);
                continue;
            }
            $cart_products[$k] = $_cproduct;
        }
        fn_set_hook('calculate_cart_items', $cart, $cart_products, $auth);
        // Apply cart promotions
        if ($apply_cart_promotions == true && $cart['subtotal'] > 0 && empty($cart['order_id'])) {
            fn_promotion_apply('cart', $cart, $auth, $cart_products);
        }
        if (Registry::get('settings.Shippings.disable_shipping') == 'Y') {
            $cart['shipping_required'] = false;
        }
        // Apply shipping fee
        if ($calculate_shipping != 'S' && $cart['shipping_required'] == true) {
            if (defined('CACHED_SHIPPING_RATES') && $cart['recalculate'] == false) {
                $shipping_rates = $_SESSION['shipping_rates'];
            } else {
                $shipping_rates = fn_calculate_shipping_rates($cart, $cart_products, $auth, $calculate_shipping == 'E');
            }
            fn_apply_cart_shipping_rates($cart, $cart_products, $auth, $shipping_rates);
            if (!empty($cart['stored_shipping'])) {
                $total_cost = 0;
                foreach ($cart['shipping'] as $sh_id => $method) {
                    if (isset($cart['stored_shipping'][$sh_id])) {
                        $piece = fn_format_price($cart['stored_shipping'][$sh_id] / count($method['rates']));
                        foreach ($method['rates'] as $k => $v) {
                            $cart['shipping'][$sh_id]['rates'][$k] = $piece;
                            $total_cost += $piece;
                        }
                        if (($sum = array_sum($cart['shipping'][$sh_id]['rates'])) != $cart['stored_shipping'][$sh_id]) {
                            $deviation = $cart['stored_shipping'][$sh_id] - $sum;
                            $value = reset($cart['shipping'][$sh_id]['rates']);
                            $key = key($cart['shipping'][$sh_id]['rates']);
                            $cart['shipping'][$sh_id]['rates'][$key] = $value + $deviation;
                            $total_cost += $deviation;
                        }
                    } else {
                        if (!empty($method['rates'])) {
                            $total_cost += array_sum($method['rates']);
                        }
                    }
                }
                $cart['shipping_cost'] = $total_cost;
            }
        } else {
            if (!empty($cart['shipping'])) {
                $cart['chosen_shipping'] = $cart['shipping'];
            }
            $cart['shipping'] = $shipping_rates = array();
            $cart['shipping_cost'] = 0;
        }
        $cart['display_shipping_cost'] = $cart['shipping_cost'];
        // Calculate taxes
        if ($cart['subtotal'] > 0 && $calculate_taxes == true && $auth['tax_exempt'] != 'Y') {
            fn_calculate_taxes($cart, $cart_products, $shipping_rates, $auth);
        } elseif ($cart['stored_taxes'] != 'Y') {
            $cart['taxes'] = array();
        }
        $cart['subtotal'] = $cart['display_subtotal'] = 0;
        fn_update_cart_data($cart, $cart_products);
        // Calculate totals
        foreach ($cart_products as $k => $v) {
            $_tax = !empty($cart_products[$k]['tax_summary']) ? $cart_products[$k]['tax_summary']['added'] / $v['amount'] : 0;
            $cart_products[$k]['display_price'] = $cart_products[$k]['price'] + (Registry::get('settings.Appearance.cart_prices_w_taxes') == 'Y' ? $_tax : 0);
            $cart_products[$k]['subtotal'] = $cart_products[$k]['price'] * $v['amount'];
            $cart_products[$k]['display_subtotal'] = $cart_products[$k]['display_price'] * $v['amount'];
            $cart['subtotal'] += $cart_products[$k]['subtotal'];
            $cart['display_subtotal'] += $cart_products[$k]['display_subtotal'];
            $cart['products'][$k]['display_price'] = $cart_products[$k]['display_price'];
            $cart['tax_subtotal'] += !empty($cart_products[$k]['tax_summary']) ? $cart_products[$k]['tax_summary']['added'] : 0;
            $cart['total'] += ($cart_products[$k]['price'] - 0) * $v['amount'];
            if (!empty($v['discount'])) {
                $cart['discount'] += $v['discount'] * $v['amount'];
            }
        }
        if (Registry::get('settings.General.tax_calculation') == 'subtotal') {
            $cart['tax_subtotal'] += !empty($cart['tax_summary']['added']) ? $cart['tax_summary']['added'] : 0;
        }
        $cart['subtotal'] = fn_format_price($cart['subtotal']);
        $cart['display_subtotal'] = fn_format_price($cart['display_subtotal']);
        $cart['total'] += $cart['tax_subtotal'];
        $cart['total'] = fn_format_price($cart['total'] + $cart['shipping_cost']);
        if (!empty($cart['subtotal_discount'])) {
            $cart['total'] -= $cart['subtotal_discount'] < $cart['total'] ? $cart['subtotal_discount'] : $cart['total'];
        }
    }
    if (fn_check_suppliers_functionality()) {
        $cart['companies'] = fn_get_products_companies($cart_products);
        $cart['have_suppliers'] = fn_check_companies_have_suppliers($cart['companies']);
    }
    fn_set_hook('calculate_cart', $cart, $cart_products, $auth, $calculate_shipping, $calculate_taxes, $apply_cart_promotions);
    $cart['recalculate'] = false;
    return array($cart_products, $shipping_rates);
}