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); }
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); }