} $suffix = ".inventory?product_id={$_REQUEST['product_id']}"; } if ($mode == 'update_combinations') { // Updating images fn_attach_image_pairs('combinations', 'product_option', 0, CART_LANGUAGE, array()); $inventory = db_get_hash_array("SELECT * FROM ?:product_options_inventory WHERE product_id = ?i", 'combination_hash', $_REQUEST['product_id']); foreach ($inventory as $i) { $inventory_ids[] = $i['combination_hash']; } fn_attach_aditional_image_pairs('product_option_add_additional', 'product_option', 0, CART_LANGUAGE, $inventory_ids); if (!empty($_REQUEST['inventory'])) { foreach ($_REQUEST['inventory'] as $k => $v) { db_query("UPDATE ?:product_options_inventory SET ?u WHERE combination_hash = ?s", $v, $k); if ($inventory[$k]['amount'] <= 0 && $v['amount'] > 0) { fn_send_product_notifications($_REQUEST['product_id']); } } } $suffix = ".inventory?product_id={$_REQUEST['product_id']}"; } if ($mode == 'm_delete_combinations') { foreach ($_REQUEST['combination_hashes'] as $v) { fn_delete_image_pairs($v, 'product_option'); db_query("DELETE FROM ?:product_options_inventory WHERE combination_hash = ?i", $v); } $suffix = ".inventory?product_id={$_REQUEST['product_id']}"; } // Apply global options to the selected products if ($mode == 'apply') { if (!empty($_REQUEST['apply_options']['options'])) {
function fn_exim_put_product_combination($product_id, $product_name, $combination_code, $combination, $amount, &$counter, $set_delimiter, $lang_code) { $pair_delimiter = ':'; if (!empty($combination)) { // Get product_id $object_id = 0; if (!empty($product_id)) { $object_exists = db_get_field('SELECT COUNT(*) FROM ?:products WHERE product_id = ?i', $product_id); if ($object_exists) { $object_id = $product_id; } } if (empty($object_id) && !empty($product_name)) { $object_id = db_get_field('SELECT product_id FROM ?:product_descriptions WHERE product = ?s AND lang_code = ?s', $product_name[$lang_code], $lang_code); } if (empty($object_id)) { $counter['S']++; return false; } $options = array(); $_options = explode($set_delimiter, $combination); foreach ($_options as $key => $value) { $options[$key][$lang_code] = $value; } if (!empty($options)) { $_combination = array(); foreach ($options as $option_pair) { $pair = explode($pair_delimiter, $option_pair[$lang_code]); if (is_array($pair)) { array_walk($pair, 'fn_trim_helper'); $option_id = db_get_field("SELECT o.option_id FROM ?:product_options_descriptions as d INNER JOIN ?:product_options as o ON o.option_id = d.option_id AND o.product_id = ?i WHERE d.option_name = ?s AND d.lang_code = ?s LIMIT 1", $object_id, $pair[0], $lang_code); if (empty($option_id)) { // Search for the global product options $option_id = db_get_field("SELECT o.option_id FROM ?:product_options_descriptions as d INNER JOIN ?:product_options as o ON o.option_id = d.option_id AND o.product_id = ?i WHERE d.option_name = ?s AND d.lang_code = ?s LIMIT 1", 0, $pair[0], $lang_code); } $variant_id = db_get_field("SELECT v.variant_id FROM ?:product_option_variants_descriptions as d INNER JOIN ?:product_option_variants as v ON v.variant_id = d.variant_id AND v.option_id = ?i WHERE d.variant_name = ?s AND d.lang_code = ?s LIMIT 1", $option_id, $pair[1], $lang_code); // Checkboxed do not have descriptions if (empty($variant_id) && in_array($pair[1], array('Yes', 'No'))) { $variant_id = db_get_field("SELECT variant_id FROM ?:product_option_variants WHERE option_id = ?i AND position = ?i LIMIT 1", $option_id, $pair[1] == 'Yes' ? 1 : 0); } if (empty($option_id) || empty($variant_id)) { $counter['S']++; return false; } $_combination[$option_id] = $variant_id; } } $combination = fn_get_options_combination($_combination); $combination_hash = fn_generate_cart_id($object_id, array('product_options' => $_combination)); $object_details = db_get_row('SELECT COUNT(*) as count, amount FROM ?:product_options_inventory WHERE combination_hash = ?i AND product_id = ?i', $combination_hash, $object_id); $_data = array('product_id' => $object_id, 'product_code' => $combination_code, 'combination_hash' => $combination_hash, 'combination' => $combination, 'amount' => $amount); if ($object_details['count']) { if ($object_details['amount'] <= 0 && $_data['amount'] > 0) { fn_send_product_notifications($object_id); } db_query('UPDATE ?:product_options_inventory SET ?u WHERE combination_hash = ?i', $_data, $combination_hash); fn_set_progress('echo', __('updating') . ' ' . __('product_combinations') . '...', false); $counter['E']++; } else { db_query('INSERT INTO ?:product_options_inventory ?e', $_data); fn_set_progress('echo', __('creating') . ' ' . __('product_combinations') . '...', false); $counter['N']++; } fn_set_progress('echo', '<b>' . $object_id . '</b>.<br />', false); return $combination_hash; } } $counter['S']++; return false; }
/** * Adds or updates product * * @param array $product_data Product data * @param int $product_id Product identifier * @param string $lang_code Two-letter language code (e.g. 'en', 'ru', etc.) * @return mixed ID of created/updated product or false in case of error */ function fn_update_product($product_data, $product_id = 0, $lang_code = CART_LANGUAGE) { $can_update = true; /** * Update product data (running before fn_update_product() function) * * @param array $product_data Product data * @param int $product_id Product identifier * @param string $lang_code Two-letter language code (e.g. 'en', 'ru', etc.) * @param boolean $can_update Flag, allows addon to forbid to create/update product */ fn_set_hook('update_product_pre', $product_data, $product_id, $lang_code, $can_update); if ($can_update == false) { return false; } if (fn_allowed_for('ULTIMATE')) { // check that product owner was not changed by store administrator if (Registry::get('runtime.company_id') || empty($product_data['company_id'])) { $product_company_id = db_get_field('SELECT company_id FROM ?:products WHERE product_id = ?i', $product_id); if (!empty($product_company_id)) { $product_data['company_id'] = $product_company_id; } else { if (Registry::get('runtime.company_id')) { $product_company_id = $product_data['company_id'] = Registry::get('runtime.company_id'); } else { $product_company_id = $product_data['company_id'] = fn_get_default_company_id(); } } } else { $product_company_id = $product_data['company_id']; } if (!empty($product_data['category_ids']) && !fn_check_owner_categories($product_company_id, $product_data['category_ids'])) { fn_set_notification('E', __('error'), __('product_must_have_owner_category')); return false; } if (fn_ult_is_shared_product($product_id) == 'Y') { $_product_id = fn_ult_update_shared_product($product_data, $product_id, Registry::ifGet('runtime.company_id', $product_company_id), $lang_code); } } if (fn_allowed_for('ULTIMATE') && Registry::get('runtime.company_id') && !empty($product_company_id) && Registry::get('runtime.company_id') != $product_company_id && !empty($_product_id)) { $product_id = $_product_id; $create = false; } else { $product_data['updated_timestamp'] = time(); $_data = $product_data; if (!empty($product_data['timestamp'])) { $_data['timestamp'] = fn_parse_date($product_data['timestamp']); // Minimal data for product record } elseif (empty($product_id) || isset($product_data['timestamp'])) { $_data['timestamp'] = time(); } if (empty($product_id) && Registry::get('runtime.company_id')) { $_data['company_id'] = Registry::get('runtime.company_id'); } if (!empty($product_data['avail_since'])) { $_data['avail_since'] = fn_parse_date($product_data['avail_since']); } if (isset($product_data['tax_ids'])) { $_data['tax_ids'] = empty($product_data['tax_ids']) ? '' : fn_create_set($product_data['tax_ids']); } if (isset($product_data['localization'])) { $_data['localization'] = empty($product_data['localization']) ? '' : fn_implode_localizations($_data['localization']); } if (isset($product_data['usergroup_ids'])) { $_data['usergroup_ids'] = empty($product_data['usergroup_ids']) ? '0' : implode(',', $_data['usergroup_ids']); } if (!empty($product_data['list_qty_count']) && $product_data['list_qty_count'] < 0) { $_data['list_qty_count'] = 0; } if (!empty($product_data['qty_step']) && $product_data['qty_step'] < 0) { $_data['qty_step'] = 0; } if (!empty($product_data['min_qty'])) { $_data['min_qty'] = fn_ceil_to_step(abs($product_data['min_qty']), $_data['qty_step']); } if (!empty($product_data['max_qty'])) { $_data['max_qty'] = fn_ceil_to_step(abs($product_data['max_qty']), $_data['qty_step']); } if (Registry::get('settings.General.inventory_tracking') == "N" && isset($_data['tracking'])) { unset($_data['tracking']); } if (Registry::get('settings.General.allow_negative_amount') == 'N' && isset($_data['amount'])) { $_data['amount'] = abs($_data['amount']); } $shipping_params = array(); if (!empty($product_id)) { $shipping_params = db_get_field('SELECT shipping_params FROM ?:products WHERE product_id = ?i', $product_id); if (!empty($shipping_params)) { $shipping_params = unserialize($shipping_params); } } // Save the product shipping params $_shipping_params = array('min_items_in_box' => isset($_data['min_items_in_box']) ? intval($_data['min_items_in_box']) : (!empty($shipping_params['min_items_in_box']) ? $shipping_params['min_items_in_box'] : 0), 'max_items_in_box' => isset($_data['max_items_in_box']) ? intval($_data['max_items_in_box']) : (!empty($shipping_params['max_items_in_box']) ? $shipping_params['max_items_in_box'] : 0), 'box_length' => isset($_data['box_length']) ? intval($_data['box_length']) : (!empty($shipping_params['box_length']) ? $shipping_params['box_length'] : 0), 'box_width' => isset($_data['box_width']) ? intval($_data['box_width']) : (!empty($shipping_params['box_width']) ? $shipping_params['box_width'] : 0), 'box_height' => isset($_data['box_height']) ? intval($_data['box_height']) : (!empty($shipping_params['box_height']) ? $shipping_params['box_height'] : 0)); $_data['shipping_params'] = serialize($_shipping_params); unset($_shipping_params); // add new product if (empty($product_id)) { $create = true; $product_data['create'] = true; // product title can't be empty and not set product_id if (empty($product_data['product']) || !empty($product_data['product_id'])) { fn_set_notification('E', __('error'), __('need_product_name')); return false; } $product_id = db_query("INSERT INTO ?:products ?e", $_data); if (empty($product_id)) { $product_id = false; } // // Adding same product descriptions for all cart languages // $_data = $product_data; $_data['product_id'] = $product_id; $_data['product'] = trim($_data['product'], " -"); foreach (fn_get_translation_languages() as $_data['lang_code'] => $_v) { db_query("INSERT INTO ?:product_descriptions ?e", $_data); } // update product } else { $create = false; if (isset($product_data['product']) && empty($product_data['product'])) { unset($product_data['product']); } $old_product_data = fn_get_product_data($product_id, $auth, $lang_code, '', false, false, false, false); if (isset($old_product_data['amount']) && isset($_data['amount']) && $old_product_data['amount'] <= 0 && $_data['amount'] > 0) { fn_send_product_notifications($product_id); } $arow = db_query("UPDATE ?:products SET ?u WHERE product_id = ?i", $_data, $product_id); $_data = $product_data; if (!empty($_data['product'])) { $_data['product'] = trim($_data['product'], " -"); } db_query("UPDATE ?:product_descriptions SET ?u WHERE product_id = ?i AND lang_code = ?s", $_data, $product_id, $lang_code); if ($arow === false) { fn_set_notification('E', __('error'), __('object_not_found', array('[object]' => __('product'))), '', '404'); $product_id = false; } } if ($product_id) { // Log product add/update fn_log_event('products', !empty($create) ? 'create' : 'update', array('product_id' => $product_id)); // Update product features value $product_data['product_features'] = !empty($product_data['product_features']) ? $product_data['product_features'] : array(); $product_data['add_new_variant'] = !empty($product_data['add_new_variant']) ? $product_data['add_new_variant'] : array(); fn_update_product_features_value($product_id, $product_data['product_features'], $product_data['add_new_variant'], $lang_code); fn_attach_image_pairs('p_feature_var_extra', 'p_feature_var_extra', 0, $lang_code); // Update product prices $product_data = fn_update_product_prices($product_id, $product_data); if (!empty($product_data['popularity'])) { $_data = array('product_id' => $product_id, 'total' => intval($product_data['popularity'])); db_query("INSERT INTO ?:product_popularity ?e ON DUPLICATE KEY UPDATE total = ?i", $_data, $product_data['popularity']); } fn_update_product_categories($product_id, $product_data); // Update main images pair fn_attach_image_pairs('product_main', 'product', $product_id, $lang_code); // Update additional images fn_attach_image_pairs('product_additional', 'product', $product_id, $lang_code); // Adding new additional images fn_attach_image_pairs('product_add_additional', 'product', $product_id, $lang_code); if (fn_allowed_for('ULTIMATE')) { fn_check_and_update_product_sharing($product_id); } } } /** * Update product data (running after fn_update_product() function) * * @param array $product_data Product data * @param int $product_id Product integer identifier * @param string $lang_code Two-letter language code (e.g. 'en', 'ru', etc.) * @param boolean $create Flag determines if product was created (true) or just updated (false). */ fn_set_hook('update_product_post', $product_data, $product_id, $lang_code, $create); return (int) $product_id; }
function fn_update_product_amount($product_id, $amount, $product_options, $sign) { if (Registry::get('settings.General.inventory_tracking') != 'Y') { return true; } $tracking = db_get_field("SELECT tracking FROM ?:products WHERE product_id = ?i", $product_id); if ($tracking == ProductTracking::DO_NOT_TRACK) { return true; } if ($tracking == ProductTracking::TRACK_WITHOUT_OPTIONS) { $product = db_get_row("SELECT amount, product_code FROM ?:products WHERE product_id = ?i", $product_id); $current_amount = $product['amount']; $product_code = $product['product_code']; } else { $cart_id = fn_generate_cart_id($product_id, array('product_options' => $product_options), true); $product = db_get_row("SELECT amount, product_code FROM ?:product_options_inventory WHERE combination_hash = ?i", $cart_id); $current_amount = empty($product['amount']) ? 0 : $product['amount']; if (empty($product['product_code'])) { $product_code = db_get_field("SELECT product_code FROM ?:products WHERE product_id = ?i", $product_id); } else { $product_code = $product['product_code']; } } if ($sign == '-') { $new_amount = $current_amount - $amount; // Notify administrator about inventory low stock if ($new_amount <= Registry::get('settings.General.low_stock_threshold') && !defined('ORDER_MANAGEMENT')) { // Log product low-stock $company_id = fn_get_company_id('products', 'product_id', $product_id); fn_log_event('products', 'low_stock', array('product_id' => $product_id)); $lang_code = fn_get_company_language($company_id); $lang_code = !empty($lang_code) ? $lang_code : Registry::get('settings.Appearance.backend_default_language'); $selected_product_options = $tracking == ProductTracking::TRACK_WITH_OPTIONS ? fn_get_selected_product_options_info($product_options, $lang_code) : ''; Mailer::sendMail(array('to' => 'company_orders_department', 'from' => 'default_company_orders_department', 'data' => array('product_options' => $selected_product_options, 'new_amount' => $new_amount, 'product_id' => $product_id, 'product_code' => $product_code, 'product' => db_get_field("SELECT product FROM ?:product_descriptions WHERE product_id = ?i AND lang_code = ?s", $product_id, $lang_code)), 'tpl' => 'orders/low_stock.tpl', 'company_id' => $company_id), 'A', $lang_code); } if ($new_amount < 0 && Registry::get('settings.General.allow_negative_amount') != 'Y') { return false; } } else { $new_amount = $current_amount + $amount; } fn_set_hook('update_product_amount', $new_amount, $product_id, $cart_id, $tracking); if ($tracking == ProductTracking::TRACK_WITHOUT_OPTIONS) { db_query("UPDATE ?:products SET amount = ?i WHERE product_id = ?i", $new_amount, $product_id); } else { db_query("UPDATE ?:product_options_inventory SET amount = ?i WHERE combination_hash = ?i", $new_amount, $cart_id); } if ($current_amount <= 0 && $new_amount > 0) { fn_send_product_notifications($product_id); } return true; }
function fn_exim_send_product_notifications($primary_object_ids, $import_data) { if (empty($primary_object_ids) || !is_array($primary_object_ids)) { return true; } $auth =& $_SESSION['auth']; //Send notification for all updated products. Notification will be sent only if product have subscribers. foreach ($primary_object_ids as $k => $v) { if (!empty($v['product_id'])) { $product_amount = db_get_field('SELECT amount FROM ?:products WHERE product_id = ?i', $v['product_id']); if ($product_amount > 0) { fn_send_product_notifications($v['product_id']); } } } return true; }
/** * Updates/Creates options combination * * @param array $combination_data Combination data * @param string $combination_hash Combination hash * @return string Combination hash */ function fn_update_option_combination($combination_data, $combination_hash = 0) { /** * Change parameters for updating options combination * * @param array $combination_data Combination data * @param string $combination_hash Combination hash */ fn_set_hook('update_option_combination_pre', $combination_data, $combination_hash); $inventory_amount = db_get_field('SELECT amount FROM ?:product_options_inventory WHERE combination_hash = ?s', $combination_hash); if (empty($combination_hash)) { $combination_hash = fn_generate_cart_id($combination_data['product_id'], array('product_options' => $combination_data['combination'])); $combination = fn_get_options_combination($combination_data['combination']); $product_code = fn_get_product_code($combination_data['product_id'], $combination_data['combination']); $_data = array('product_id' => $combination_data['product_id'], 'combination_hash' => $combination_hash, 'combination' => $combination, 'product_code' => !empty($product_code) ? $product_code : '', 'amount' => !empty($combination_data['amount']) ? $combination_data['amount'] : 0, 'position' => !empty($combination_data['position']) ? $combination_data['position'] : 0); db_query("REPLACE INTO ?:product_options_inventory ?e", $_data); } else { // Forbid to update options in the existing combination. Only qty/code/pos. unset($combination_data['combination']); db_query("UPDATE ?:product_options_inventory SET ?u WHERE combination_hash = ?s", $combination_data, $combination_hash); } if (isset($combination_data['amount']) && $combination_data['amount'] > 0 && $inventory_amount <= 0) { fn_send_product_notifications($combination_data['product_id']); } // Updating images fn_attach_image_pairs('combinations', 'product_option'); /** * Makes extra actions after updating options combination * * @param array $combination_data Combination data * @param string $combination_hash Combination hash * @param int $inventory_amount Previous (before update) inventory amount of the combination */ fn_set_hook('update_option_combination_pre', $combination_data, $combination_hash, $inventory_amount); return $combination_hash; }