function cw_aom_get_quantity_in_stock($warehouse_id, $product_id, $order_status, $options = array(), $order_product = array(), $type = null)
{
    global $tables, $addons;
    $quantity_in_stock = strpos("PCQI", $order_status) !== false ? $order_product['amount'] : 0;
    # kornev, TOFIX
    if ($addons['product_options'] && !empty($options)) {
        $is_equal = false;
        if (!empty($order_product['product_options']) && is_array($order_product['product_options'])) {
            $order_options = array();
            foreach ($order_product['product_options'] as $cid => $o) {
                $order_options[$cid] = $o['option_id'];
            }
            $order_variant_id = cw_get_variant_id($order_options);
            $variant_id = cw_get_variant_id($options);
            $is_equal = $order_variant_id == $variant_id;
        }
        if (!$is_equal) {
            $quantity_in_stock = 0;
        }
        $quantity_in_stock += cw_warehouse_get_warehouse_avail($warehouse_id, $product_id, $type, $variant_id);
    } else {
        $quantity_in_stock += cw_warehouse_get_warehouse_avail($warehouse_id, $product_id, $type, 0);
    }
    return $quantity_in_stock;
}
    }
}
cw_load('product', 'warehouse', 'cart');
$product_info = cw_func_call('cw_product_get', array('id' => $product_id, 'user_account' => $user_account));
$smarty->assign('product', $product_info);
//include $app_main_dir.'/addons/product_options/customer/product.php';
cw_include('addons/product_options/customer/product.php');
if ($REQUEST_METHOD == "POST" && $action == "update") {
    $poptions = $_POST['product_options'];
    if (!cw_check_product_options($product_id, $poptions)) {
        cw_header_location("index.php?target=popup_poptions&target={$target}&id={$id}&err=exception");
    }
    if ($mode == 'wishlist') {
        db_query("UPDATE {$tables['wishlist']} SET options = '" . addslashes(serialize($poptions)) . "' WHERE wishlist_id = '{$id}' AND event_id = '{$eventid}'");
    } else {
        $variant_id = cw_get_variant_id($product_options, $product_id);
        $amount = cw_warehouse_get_warehouse_avail($cart['products'][$cartindex]['warehouse'], $product_id, null, $variant_id);
        //		$amount = cw_get_options_amount($poptions, $cart['products'][$cartindex]['product_id']);
        if ($amount >= $cart['products'][$cartindex]['amount']) {
            $cart['products'][$cartindex]['options'] = $poptions;
            cw_unset($cart['products'][$cartindex], 'variant_id');
        } else {
            cw_header_location("index.php?target=popup_poptions&target={$target}&id={$id}&err=avail");
        }
        # Recalculate cart totals after updating
        $products = cw_call('cw_products_in_cart', array($cart, $user_account));
        $cart = cw_func_call('cw_cart_calc', array('cart' => $cart, 'products' => $products, 'userinfo' => $user_account));
    }
    ?>
<script type="text/javascript">
<!--
function cw_ps_update_cart_products(&$cart, &$products, $user_info, $offers_ids = array())
{
    global $config, $smarty, $tables, $addons;
    static $iter;
    if (APP_AREA != 'customer') {
        return false;
    }
    if (empty($products) || !is_array($products)) {
        cw_session_unregister('ps_offers_info');
        return false;
    }
    // we should track actions here as well...
    global $action;
    $action = (string) $action;
    $tracking_actions = array('add' => 1, 'update' => 1, 'delete' => 1, 'ajax_update' => 1, 'clear_cart' => 1);
    if (empty($action) || !isset($tracking_actions[$action])) {
        return -1;
        // view cart
    }
    if ($action == 'clear_cart') {
        cw_session_unregister('ps_offers_info');
        return false;
    }
    if (!isset($iter)) {
        $iter = 0;
    }
    $ps_offers_info =& cw_session_register('ps_offers_info');
    $current_product_hash = md5(cw_ps_prods_str($products));
    echo '<pre>$current_product_hash: ', $current_product_hash, '</pre>';
    //die;
    if (!empty($ps_offers_info) && is_array($ps_offers_info)) {
        if (isset($ps_offers_info['hash_offer_free']) && !empty($ps_offers_info['hash_offer_free'])) {
            if (isset($ps_offers_info['hash_offer_free'][$current_product_hash])) {
                return $ps_offers_info['hash_offer_free'][$current_product_hash];
                //3 - already processed, we should replace the cart[products] with the existing products array
                //2 - already processed
            } else {
                $iter++;
                $ps_offers_info['hash_offer_free'][$current_product_hash] = array();
                if ($iter > 1) {
                    echo '<pre>', "\t\t!!!", "{$iter} iteration: ", "ps_offers_info['processed_prods_hash']: {$ps_offers_info['processed_prods_hash']}", '</pre>';
                    echo '<pre>', "\t\tps_offers_info['product_hash']: {$ps_offers_info['product_hash']}", '</pre>';
                    //echo '<pre>', print_r($products), '</pre>';
                }
            }
        }
        /*if (isset($ps_offers_info['processed_prods_hash']) || isset($ps_offers_info['product_hash'])) {
                    $current_product_hash = md5(cw_ps_prods_str($products));
                }
        
                if (isset($ps_offers_info['processed_prods_hash'])) {
        
                    if ($ps_offers_info['processed_prods_hash'] == $current_product_hash) {
                        return 3; //already processed, we should replace the cart[products] with the existing products array
                    }
                }
        
                if (isset($ps_offers_info['product_hash'])) {
        
                    if ($ps_offers_info['product_hash'] == $current_product_hash) {
                        return 2; //already processed
                    }
                }
        
        
                if (isset($ps_offers_info['product_hash']) || isset($ps_offers_info['processed_prods_hash'])) {
                    if ($ps_offers_info['product_hash'] != $current_product_hash && $ps_offers_info['processed_prods_hash'] != $current_product_hash && $iter > 1) {
                        echo '<pre>', "\t\t!!!", "$iter iteration: ", "ps_offers_info['processed_prods_hash']: $ps_offers_info[processed_prods_hash]", '</pre>';
                        echo '<pre>', "ps_offers_info['product_hash']: $ps_offers_info[product_hash]", '</pre>';
                        echo '<pre>', print_r($products), '</pre>';
                    }
                }*/
        /*if (isset($ps_offers_info['hash_offer_free']) && !empty($ps_offers_info['hash_offer_free'])) {
              if (!isset($ps_offers_info['hash_offer_free'][$current_product_hash]) && $iter > 1) {
                  echo '<pre>', "\t\t!!!", "$iter iteration: ", "ps_offers_info['processed_prods_hash']: $ps_offers_info[processed_prods_hash]", '</pre>';
                  echo '<pre>', "\t\tps_offers_info['product_hash']: $ps_offers_info[product_hash]", '</pre>';
                  echo '<pre>', print_r($products), '</pre>';
              }
          }*/
    }
    if (empty($offers_ids) || !isset($offers_ids['new']) || !isset($offers_ids['to_delete']) || !isset($offers_ids['suitable'])) {
        return false;
    }
    //echo '<pre>', "ps_offers_info['processed_prods_hash']: $ps_offers_info[processed_prods_hash]", '</pre>';
    //echo '<pre>', "ps_offers_info['product_hash']: $ps_offers_info[product_hash]", '</pre>';
    //die('-');
    $offers = array();
    //if (!empty($ps_offers_info) && is_array($ps_offers_info) && isset($ps_offers_info['product_hash'])) {
    if (!empty($ps_offers_info) && isset($ps_offers_info['hash_offer_free'])) {
        if (isset($ps_offers_info['added_free_prods']) && is_array($ps_offers_info['added_free_prods']) && isset($ps_offers_info['applied_offers_free']) && is_array($ps_offers_info['applied_offers_free'])) {
            // we will not restore products for free which were deleted by a customer
            $new_offers = $offers_ids['new'];
            $offers_to_delete = $offers_ids['to_delete'];
            $suitable_offers = $offers_ids['suitable'];
            if (!empty($new_offers) && is_array($new_offers)) {
                $offers = $new_offers;
            }
            $deleted_prods_exist = false;
            if (!empty($offers_to_delete)) {
                $cart_records_to_delete = array();
                foreach ($offers_to_delete as $key => $trash) {
                    $cart_records_to_delete += $ps_offers_info['applied_offers_free'][$key];
                    //unset($ps_offers_info['applied_offers_free'][$key]); //?
                }
                if (!empty($cart_records_to_delete)) {
                    foreach ($products as $key => $cart_record) {
                        if (isset($cart_records_to_delete[$cart_record['cartid']])) {
                            unset($products[$key]);
                            $deleted_prods_exist = true;
                            if (isset($ps_offers_info['added_free_prods'][$cart_record['cartid']])) {
                                //unset($ps_offers_info['added_free_prods'][$cart_record['cartid']]); //?
                            }
                        }
                    }
                }
            }
            // offers to delelete
            // let's update the products for free in the cart; their quantities and prices should be untouched
            $free_products_exist = false;
            if (!empty($suitable_offers) && is_array($suitable_offers)) {
                $cart_records_to_update = array();
                foreach ($suitable_offers as $key => $trash) {
                    $cart_records_to_update += $ps_offers_info['applied_offers_free'][$key];
                }
                //echo '<pre>$cart_records_to_update: ', print_r($cart_records_to_update), '</pre>';
                //echo '<pre>$ps_offers_info: ', print_r($ps_offers_info), '</pre>';
                //echo '<pre>before update: ', print_r($products), '</pre>';
                $free_products_exist = false;
                if (!empty($cart_records_to_update)) {
                    foreach ($products as $key => $cart_record) {
                        if (isset($cart_records_to_update[$cart_record['cartid']])) {
                            $free_products_exist = true;
                            $products[$key] = $ps_offers_info['added_free_prods'][$cart_record['cartid']];
                        }
                    }
                }
            }
            if (!empty($new_offers) && is_array($new_offers)) {
            } else {
                if ($free_products_exist == true) {
                    $products = cw_products_from_scratch($products, $user_info, false, false);
                }
                if ($deleted_prods_exist == true || $free_products_exist == true) {
                    $ps_offers_info['product_hash'] = md5(cw_ps_prods_str($products));
                    $ps_offers_info['processed_prods_hash'] = md5(cw_ps_prods_str($cart['products']));
                    $ps_offers_info['hash_offer_free'][md5(cw_ps_prods_str($products))] = 2;
                    $ps_offers_info['hash_offer_free'][md5(cw_ps_prods_str($cart['products']))] = 3;
                    //$ps_offers_info['data_hash'] = md5(cw_ps_prods_str($products) . cw_ps_address_str($user_info));
                    $ps_offers_info['hash'][md5(cw_ps_prods_str($products) . cw_ps_address_str($user_info))] = 2;
                    //die('yes');
                    return true;
                } else {
                    return 4;
                    // no new offers and cart prods were not updated
                }
            }
        }
    }
    // empty($ps_offers_info)
    if (empty($offers) && !empty($offers_ids['new'])) {
        $offers = $offers_ids['new'];
    }
    if (empty($offers) || !is_array($offers)) {
        return false;
    }
    // check if the suitable products exist...
    $fields = $from_tbls = $query_joins = $where = $groupbys = $having = $orderbys = array();
    $fields = array("{$tables['ps_bonuses']}.offer_id", 'object_id', 'quantity', "{$tables['ps_bonuses']}.offer_id as offerid", "{$tables['ps_bonuses']}.bonus_id");
    $from_tbls[] = 'ps_bonuses';
    $query_joins['ps_bonus_details'] = array('on' => "{$tables['ps_bonuses']}.bonus_id = {$tables['ps_bonus_details']}.bonus_id", 'is_inner' => 1);
    $where[] = "{$tables['ps_bonuses']}.offer_id IN ('" . implode("', '", array_keys($offers)) . "')";
    $where[] = "{$tables['ps_bonuses']}.type = '" . PS_FREE_PRODS . "'";
    $where[] = "{$tables['ps_bonus_details']}.object_type = '" . PS_OBJ_TYPE_PRODS . "'";
    $search_query = cw_db_generate_query($fields, $from_tbls, $query_joins, $where, $groupbys, $having, $orderbys);
    $free_products = cw_query_hash($search_query, 'object_id', false);
    if (empty($free_products) || !is_array($free_products)) {
        return false;
    }
    //global $ps_offers_info;
    //$ps_offers_info = array();
    $ps_offers_info['already_applied'] = true;
    //$ps_offers_info = &cw_session_register('ps_offers_info');
    //var_dump('suitable products:', $free_products);
    //return $products;
    //die(var_dump('suitable products:', $free_products));
    global $user_account;
    cw_load('warehouse');
    foreach ($free_products as $product_id => $product_data) {
        /*
         * we will add the suitable products to the cart directly to avoid the groupping of the default products
         * and special ones
         */
        $product_status = cw_query_first_cell("SELECT status FROM {$tables['products_enabled']} as pe WHERE pe.product_id = '{$product_id}' AND pe.status = '1'");
        if ($product_status != 1) {
            continue;
        }
        $product_data['quantity'] = abs(intval($product_data['quantity']));
        if (empty($product_data['quantity'])) {
            continue;
        }
        $new_product = cw_func_call('cw_product_get', array('id' => $product_id, 'user_account' => $user_account, 'info_type' => 3));
        if ($new_product['product_type'] != constant('PRODUCT_TYPE_GENERAL')) {
            if (!empty($new_product['product_type'])) {
                continue;
            }
        }
        $amount = $product_data['quantity'];
        if (!empty($addons['egoods']) && !empty($new_product['distribution'])) {
            $amount = 1;
        }
        if ($amount < $new_product['min_amount']) {
            continue;
        }
        $possible_warehouses = cw_warehouse_get_avails_customer($product_id);
        if (empty($possible_warehouses) || !is_array($possible_warehouses)) {
            $possible_warehouse = cw_warehouse_get_max_amount_warehouse($product_id);
            $possible_warehouses = array($possible_warehouse => 1);
        }
        $warehouse = array_shift(array_keys($possible_warehouses));
        //foreach($possible_warehouses as $warehouse => $tmp) {
        if (!$warehouse) {
            $possible_warehouse = cw_warehouse_get_max_amount_warehouse($product_id);
        }
        if ($addons['product_options']) {
            # Get default options
            $product_options = cw_get_default_options($product_id, $amount, @$user_account['membership_id']);
            if ($product_options === false) {
                continue;
                //continue 2;
            } elseif ($product_options === true) {
                $product_options = null;
            }
            # Get the variant_id of options
            $variant_id = cw_get_variant_id($product_options, $product_id);
            if (!empty($variant_id)) {
                $possible_warehouse = cw_warehouse_get_max_amount_warehouse($product_id, $variant_id);
                if (empty($warehouse)) {
                    $warehouse = $possible_warehouse;
                }
            } else {
                if (empty($warehouse)) {
                    $warehouse = $possible_warehouse;
                }
            }
        }
        if (empty($warehouse)) {
            $warehouse = $possible_warehouse;
        }
        // let's add a product the cart
        $free_price = 0.0;
        $cartid = cw_generate_cartid($products);
        $products[] = array("cartid" => $cartid, "product_id" => $product_id, "amount" => $amount, "options" => $product_options, "free_price" => @price_format(@$free_price), "salesman_doc_id" => 0, "distribution" => $new_product['distribution'], "variant_id" => $variant_id, "warehouse_customer_id" => $warehouse);
        //$amount = $amount - $result['added_amount'];
        //if ($amount <= 0) break;
        //}
        if (!isset($ps_offers_info['added_free_prods'])) {
            $ps_offers_info['added_free_prods'] = array();
        }
        $ps_offers_info['added_free_prods'][$cartid] = $products[count($products) - 1];
        $ps_offers_info['added_free_prods'][$cartid]['offer_id'] = $product_data['offerid'];
        $ps_offers_info['added_free_prods'][$cartid]['bonus_id'] = $product_data['bonus_id'];
        if (!isset($ps_offers_info['applied_offers_free'])) {
            $ps_offers_info['applied_offers_free'] = array();
        }
        if (!isset($ps_offers_info['applied_offers_free'][$product_data['offerid']])) {
            $ps_offers_info['applied_offers_free'][$product_data['offerid']] = array();
        }
        $ps_offers_info['applied_offers_free'][$product_data['offerid']][$cartid] = 1;
    }
    $products = cw_products_from_scratch($products, $user_info, false, false);
    //$ps_offers_info['product_hash'] = md5(serialize($products));
    $ps_offers_info['product_hash'] = md5(cw_ps_prods_str($products));
    $ps_offers_info['processed_prods_hash'] = md5(cw_ps_prods_str($cart['products']));
    $ps_offers_info['hash_offer_free'][md5(cw_ps_prods_str($products))] = 2;
    $ps_offers_info['hash_offer_free'][md5(cw_ps_prods_str($cart['products']))] = 3;
    //$ps_offers_info['data_hash'] = md5(cw_ps_prods_str($products) . cw_ps_address_str($user_info));
    $ps_offers_info['hash'][md5(cw_ps_prods_str($products) . cw_ps_address_str($user_info))] = 2;
    cw_ps_save('products', $products);
    //$ps_offers_info['processed_prods_hash'] = md5(serialize($cart['products']));
    //echo '<pre>'; print_r($ps_offers_info); echo '</pre>';
    echo '<pre>', "ps_offers_info['processed_prods_hash']: {$ps_offers_info['processed_prods_hash']}", '</pre>';
    echo '<pre>', "ps_offers_info['product_hash']: {$ps_offers_info['product_hash']}", '</pre>';
    return true;
}
function cw_gift_prepare_products($products)
{
    global $addons, $user_account;
    if (is_array($products)) {
        foreach ($products as $k => $product) {
            if (!empty($product['options'])) {
                $products[$k]['options'] = unserialize($product['options']);
                if (!empty($products[$k]['options']) && $addons['product_options']) {
                    $products[$k]['variant_id'] = cw_get_variant_id($products[$k]['options'], $product['product_id']);
                }
            }
            $products[$k]['amount_requested'] = $product['amount'];
            if ($product['amount'] > $product['amount_purchased']) {
                $products[$k]['amount'] = $product['amount'] - $product['amount_purchased'];
            }
        }
    }
    return cw_products_from_scratch($products, $user_account, true);
}
function cw_accounting_update_stock($doc_data, $product, $way, $field, $destination_warehouse_id = 0, $affect_prices = false, $movements_id = 0, $source_pwa_id = 0)
{
    global $addons, $tables;
    cw_load('product');
    # kornev
    # way = 1, the products has been purchased - we have to create new record with supplier
    #          ps: the record can be already created... if a few movements have to be generated
    # way = 2, the products has been sold - we have to decrease the most old records
    # kornev
    # if we are making the warehouse movements, we have to increase the products in one and decrease in another and visa versa
    $warehouse_customer_id = $doc_data['info']['warehouse_customer_id'];
    if ($destination_warehouse_id) {
        $warehouse_customer_id = $destination_warehouse_id;
        $way = $way == 2 ? 1 : 2;
    }
    $variant_id = 0;
    # kornev, TOFIX
    if ($addons['product_options'] && (!empty($product['extra_data']['product_options']) || !empty($product['options']))) {
        $options = !empty($product['extra_data']['product_options']) ? $product['extra_data']['product_options'] : $product['options'];
        $variant_id = cw_get_variant_id($options);
    }
    $return = array();
    if ($way == 1) {
        $return = $product['amount'];
    } elseif ($way == 2) {
        $return = -$product['amount'];
        if ($field == 'avail' && in_array($doc_data['type'], array('O', 'I', 'G', 'S'))) {
            cw_call('cw_product_run_counter', array('product_id' => $product['product_id'], 'count' => $return, 'type' => 1));
        }
    }
    //    cw_warehouse_check_avail_record($warehouse_customer_id, $product['product_id'], $variant_id);
    if ($return) {
        db_query("update {$tables['products_warehouses_amount']} set {$field} = {$field} + {$return} where product_id='{$product['product_id']}' and warehouse_customer_id=0 and variant_id='{$variant_id}'");
        cw_event('on_accounting_update_stock', array($product, $variant_id, $field, $return));
    }
    cw_warehouse_recalculate($product['product_id'], $variant_id);
    cw_func_call('cw_product_build_flat', array('product_id' => $product['product_id']));
    return $return;
}
function cw_add_to_cart(&$cart, $product_data)
{
    global $user_account;
    global $addons, $config, $top_message, $app_main_dir, $HTTP_REFERER, $app_catalogs, $tables;
    global $from, $current_area;
    $return = array();
    # Extracts to: $product_id, $amount, $product_options, $price, $warehouse_customer_id
    extract($product_data);
    $warehouse = $product_data['warehouse_customer_id'];
    cw_load('warehouse');
    $added_product = cw_func_call('cw_product_get', array('id' => $product_id, 'user_account' => $user_account, 'info_type' => 3));
    if ($added_product['product_type'] == 10) {
        $warehouse = $added_product['warehouse_customer_id'];
    }
    if (!$warehouse) {
        $possible_warehouse = cw_warehouse_get_max_amount_warehouse($product_id);
    }
    if (!empty($addons['egoods']) && !empty($added_product['distribution'])) {
        $amount = 1;
    } else {
        $amount = abs(intval($amount));
    }
    if ($amount == 0) {
        $amount = 1;
    }
    # kornev, TOFIX
    if ($addons['product_options']) {
        #
        # Prepare the product options for added products
        #
        if (!empty($product_options)) {
            # Check the received options
            if (!cw_check_product_options($product_id, $product_options)) {
                $return['redirect_to'] = "product.php?product_id={$product_id}&err=options";
                return $return;
            }
        } else {
            # Get default options
            $product_options = cw_get_default_options($product_id, $amount, @$user_account['membership_id']);
            if ($product_options === false) {
                $return['redirect_to'] = 'index.php?target=error_message&error=access_denied&id=30';
                return $return;
            } elseif ($product_options === true) {
                $product_options = "";
                unset($product_options);
            }
        }
        # Get the variant_id of options
        $variant_id = cw_get_variant_id($product_options, $product_id);
        if (!empty($variant_id)) {
            $possible_warehouse = cw_warehouse_get_max_amount_warehouse($product_id, $variant_id);
            if (empty($warehouse)) {
                $warehouse = $possible_warehouse;
            }
            # Get the variant amount
            $added_product['avail'] = cw_warehouse_get_warehouse_avail($warehouse, $product_id, null, $variant_id);
            //cw_get_options_amount($product_options, $product_id);
            if (!empty($cart['products'])) {
                foreach ($cart['products'] as $k => $v) {
                    if ($v['product_id'] == $product_id && $variant_id == $v['variant_id']) {
                        $added_product['avail'] -= $v['amount'];
                    }
                }
            }
        } else {
            if (empty($warehouse)) {
                $warehouse = $possible_warehouse;
            }
            $added_product['avail'] = cw_warehouse_get_warehouse_avail($warehouse, $product_id);
        }
    }
    /*
    kornev, the amount is checked by another function - during the calculation
    	if ($config['General']['unlimited_products'] == "N" && $added_product['product_type'] != 10) {
    		#
    		# Add to cart amount of items that is not much than in stock
    		#
    		if ($amount > $added_product['avail'])
    			$amount = $added_product['avail'];
    	}
    */
    if ($from == 'salesman' && empty($amount)) {
        $return['redirect_to'] = $app_catalogs['customer'] . "/product.php?product_id=" . $product_id;
        return $return;
    }
    if ($product_id && $amount) {
        if ($amount < $added_product['min_amount']) {
            $return['redirect_to'] = "index.php?target=error_message&error=access_denied&id=31";
            return $return;
        }
        $found = false;
        $_product = cw_array_merge($product_data, $added_product, array('options' => $product_options, 'free_price' => $price));
        // Product hash defines how to differ/join products in cart
        // Listen for the event and return own part of hash. See also default handler.
        $product_hash = cw_event('on_build_cart_product_hash', array($_product), array());
        $product_data['product_hash'] = $_product['product_hash'] = join('-', $product_hash);
        if (!empty($cart) && @$cart['products']) {
            foreach ($cart['products'] as $k => $v) {
                $product_hash = join('-', cw_event('on_build_cart_product_hash', array($v), array()));
                if ($product_hash == $_product['product_hash']) {
                    if (doubleval($v['free_price']) != $price) {
                        continue;
                    }
                    $found = true;
                    if ($cart['products'][$k]['amount'] >= 1 && (!empty($added_product['distribution']) || !empty($subscribed_product))) {
                        $cart['products'][$k]['amount'] = 1;
                        $amount = 0;
                    }
                    $cart['products'][$k]['amount'] += $amount;
                    $return['added_amount'] += $amount;
                    $return['productindex'] = $k;
                    $return['cartid'] = $v['cartid'];
                    $return['merged'] = true;
                    break;
                }
            }
        }
        if (!$found) {
            #
            # Add product to the cart
            #
            if (!empty($price)) {
                # price value is defined by customer if admin set it to '0.00'
                $free_price = abs(doubleval($price));
            }
            $cartid = cw_generate_cartid($cart['products']);
            if (empty($cart['products'])) {
                $add_to_cart_time = time();
            }
            $_product = array("cartid" => $cartid, "product_id" => $product_id, "amount" => $amount, "options" => $product_options, "free_price" => @price_format(@$free_price), "salesman_doc_id" => $salesman_doc_id, "distribution" => $added_product['distribution'], "variant_id" => $variant_id, "warehouse_customer_id" => $warehouse);
            // Add all custom fields from added products
            foreach ($product_data as $k => $v) {
                if (!isset($_product[$k])) {
                    $_product[$k] = $v;
                }
            }
            $cart['products'][] = $_product;
            // count add to cart
            cw_call('cw_product_run_counter', array('product_id' => $product_id, 'count' => 1, 'type' => 3));
            $return['added_amount'] = $amount;
            $_ak = array_keys($cart['products']);
            $return['productindex'] = end($_ak);
            $return['cartid'] = $cartid;
            $return['merged'] = false;
        }
    }
    return $return;
}
function cw_get_default_variant_id($product_id)
{
    global $tables, $config;
    # Get classes (variant type)
    $classes = cw_query_hash("SELECT {$tables['product_options']}.product_option_id FROM {$tables['product_options']}, {$tables['product_options_values']}, {$tables['product_variant_items']} WHERE {$tables['product_options']}.product_option_id = {$tables['product_options_values']}.product_option_id AND {$tables['product_options_values']}.avail = 1 AND {$tables['product_options']}.avail = 1 AND {$tables['product_options']}.product_id = '{$product_id}' AND {$tables['product_options']}.type = '' AND {$tables['product_variant_items']}.option_id = {$tables['product_options_values']}.option_id GROUP BY {$tables['product_options']}.product_option_id", "product_option_id");
    if (empty($classes)) {
        return false;
    }
    $avail_where = "";
    if ($config['General']['disable_outofstock_products'] == 'Y') {
        $avail_where = "AND pa.avail > 0";
    }
    # Detect default variant
    $def_variant_id = cw_query_first_cell("SELECT pv.variant_id FROM {$tables['product_variants']} as pv, {$tables['products_warehouses_amount']} as pa WHERE pa.variant_id=pv.variant_id and pv.product_id = '{$product_id}' AND def = 'Y' " . $avail_where);
    if (!empty($def_variant_id)) {
        $_product_options = cw_query_hash("SELECT {$tables['product_options_values']}.product_option_id, {$tables['product_options_values']}.option_id FROM {$tables['product_options_values']}, {$tables['product_variant_items']} WHERE {$tables['product_variant_items']}.variant_id = '{$def_variant_id}' AND {$tables['product_variant_items']}.option_id = {$tables['product_options_values']}.option_id", "product_option_id", false, true);
        if (count($_product_options) != count($classes)) {
            return false;
        }
        # Check exceptions
        $exceptions = cw_query_hash("SELECT exception_id, COUNT(option_id) FROM {$tables['products_options_ex']} WHERE option_id IN ('" . implode("','", $_product_options) . "') GROUP BY exception_id", "exception_id", false, true);
        if (!empty($exceptions)) {
            # Get exceptions counters
            $exception_counters = cw_query_hash("SELECT exception_id, COUNT(option_id) FROM {$tables['products_options_ex']} WHERE exception_id IN ('" . implode("','", array_keys($exceptions)) . "') GROUP BY exception_id", "exception_id", false, true);
            foreach ($exceptions as $eid => $cnt) {
                if ($exception_counters[$eid] == $cnt) {
                    $_product_options = array();
                    break;
                }
            }
            if (!empty($_product_options)) {
                # When the set of exceptions defined for a product covers not only the
                # combination of options that make the product's default variant, but
                # also a whole group of non-variant options which can be used in
                # combination with them, this check-up ensures that a different
                # (non-exceptional) combination of variant options is selected as the
                # products's default one.
                $exceptions = cw_query_hash("SELECT {$tables['product_options_values']}.product_option_id, COUNT({$tables['products_options_ex']}.exception_id) FROM {$tables['products_options_ex']}, {$tables['product_options_values']} WHERE {$tables['products_options_ex']}.option_id = {$tables['product_options_values']}.option_id AND {$tables['products_options_ex']}.exception_id IN ('" . implode("','", array_keys($exceptions)) . "') AND {$tables['products_options_ex']}.option_id NOT IN ('" . implode("','", $_product_options) . "') GROUP BY {$tables['product_options_values']}.product_option_id", "product_option_id", false, true);
                if (!empty($exceptions)) {
                    $class_counters = cw_query_hash("SELECT {$tables['product_options_values']}.product_option_id, COUNT({$tables['product_options_values']}.option_id) FROM {$tables['product_options']}, {$tables['product_options_values']} WHERE {$tables['product_options_values']}.product_option_id IN ('" . implode("','", array_keys($exceptions)) . "') AND {$tables['product_options_values']}.avail = 1 AND {$tables['product_options']}.product_option_id = {$tables['product_options_values']}.product_option_id AND {$tables['product_options']}.avail = 1 GROUP BY {$tables['product_options_values']}.product_option_id", "product_option_id", false, true);
                    foreach ($exceptions as $cid => $cnt) {
                        if (isset($class_counters[$cid]) && $class_counters[$cid] == $cnt) {
                            $_product_options = array();
                            break;
                        }
                    }
                }
            }
            unset($exceptions, $exception_counters);
        }
        if (!empty($_product_options)) {
            return $def_variant_id;
        }
    }
    # Get class options
    $options = cw_query_hash("SELECT product_option_id, option_id FROM {$tables['product_options_values']} WHERE product_option_id IN ('" . implode("','", array_keys($classes)) . "') AND avail = 1 ORDER BY orderby", "product_option_id", true, true);
    $_flag = false;
    foreach ($classes as $k => $class) {
        $classes[$k]['cnt'] = $_flag ? 0 : -1;
        $_flag = true;
        if (isset($options[$k])) {
            $classes[$k]['options'] = array_values($options[$k]);
        } else {
            unset($classes[$k]);
        }
    }
    unset($options);
    if (empty($classes)) {
        return false;
    }
    # Scan & check classes options array
    $variant_id = false;
    $first_variant_id = false;
    do {
        $product_options = array();
        $is_add = true;
        # Build full 'product_option_id->option_id' hash
        foreach ($classes as $k => $class) {
            if ($is_add) {
                if (count($class['options']) - 1 <= $class['cnt']) {
                    $class['cnt'] = 0;
                } else {
                    $is_add = false;
                    $class['cnt']++;
                }
            }
            $product_options[$k] = $class['options'][$class['cnt']];
            $classes[$k]['cnt'] = $class['cnt'];
        }
        # Check current product options array
        if (cw_check_product_options($product_id, $product_options)) {
            $variant_id = cw_get_variant_id($product_options, $product_id);
            # Save first valid variant id
            if (!$first_variant_id) {
                $first_variant_id = $variant_id;
            }
            # Check variant quantity in stock
            if ($config['General']['disable_outofstock_products'] != 'Y' || cw_query_first_cell("SELECT avail FROM {$tables['products_warehouses_amount']} WHERE variant_id = '{$variant_id}'") > 0) {
                break;
            }
            $variant_id = false;
        }
    } while (!$is_add);
    # Get first valid variant if all valid variants is out-of-stock
    if ($variant_id === false && !empty($first_variant_id)) {
        $variant_id = $first_variant_id;
    }
    return $variant_id;
}