/** * For a given {product, product attribute} gets warehouse list * * @param int $product_id ID of the product * @param int $product_attribute_id Optional, uses 0 if this product does not have attributes * @param int $shop_id Optional, ID of the shop. Uses the context shop id (@see JeproshopContext::shop) * @return array Warehouses (ID, reference/name concatenated) */ public static function getProductWarehouseList($product_id, $product_attribute_id = 0, $shop_id = null) { $db = JFactory::getDBO(); // if it's a pack, returns warehouses if and only if some products use the advanced stock management if (JeproshopProductPack::isPack($product_id)) { $warehouses = JeproshopWarehouseModelWarehouse::getPackWarehouses($product_id); /*$res = array(); foreach ($warehouses as $warehouse) $res[]['id_warehouse'] = $warehouse; */ return $warehouses; } $share_stock = false; if ($shop_id === null) { if (JeproshopShopModelShop::getShopContext() == JeproshopShopModelShop::CONTEXT_GROUP) { $shop_group = JeproshopShopModelShop::getContextShopGroup(); } else { $shop_group = JeproshopContext::getContext()->shop->getShopGroup(); $shop_id = (int) JeproshopContext::getContext()->shop->shop_id; } $share_stock = $shop_group->share_stock; } else { $shop_group = JeproshopShopModelShop::getGroupFromShop($shop_id); $share_stock = $shop_group->share_stock; } if ($share_stock) { $shop_ids = JeproshopShopModelShop::getShops(true, (int) $shop_group->shop_group_id, true); } else { $shop_ids = array((int) $shop_id); } $query = "SELECT warehouse_product_location.warehouse_id, CONCAT(warehouse.reference, ' - ', warehouse.name)"; $query .= " AS name FROM " . $db->QuoteName('#__jeproshop_warehouse_product_location') . " AS warehouse_product_location"; $query .= " INNER JOIN " . $db->quoteName('#__jeproshop_warehouse_shop') . " AS warehouse_shop ON(warehouse_shop."; $query .= "warehouse_id = warehouse_product_location.warehouse_id AND shop_id IN (" . implode(',', array_map('intval', $shop_ids)); $query .= " )) INNER JOIN " . $db->quoteName('#__jeproshop_warehouse') . " AS warehouse ON (warehouse.warehouse_id = warehouse_shop."; $query .= "warehouse_id ) WHERE product_id = " . (int) $product_id . " AND product_attribute_id = " . (int) $product_attribute_id; $query .= " AND warehouse.deleted = 0 GROUP BY warehouse_product_location.warehouse_id"; $db->setQuery($query); return $db->loadObjectList(); }
public static function getItemTable($product_id, $lang_id, $full = false) { if (!JeproshopProductPack::isFeaturePublished()) { return array(); } $db = JFactory::getDBO(); $query = "SELECT product.*, product_shop.*, product_lang.*, MAX(image_shop." . $db->quoteName('image_id') . ") image_id, image_lang." . $db->quoteName('legend'); $query .= ", category_lang." . $db->quoteName('name') . " AS default_category, pack.quantity AS pack_quantity, product_shop." . $db->quoteName('default_category_id'); $query .= ", pack.product_pack_id FROM " . $db->quoteName('#__jeproshop_pack') . " AS pack LEFT JOIN " . $db->quoteName('#__jeproshop_product') . " AS product ON("; $query .= "product.product_id = pack.product_item_id) LEFT JOIN " . $db->quoteName('#__jeproshop_product_lang') . " AS product_lang ON(product.product_id = product_lang."; $query .= "product_id AND product_lang.lang_id = " . (int) $lang_id . JeproshopShopModelShop::addSqlRestrictionOnLang('product_lang') . ") LEFT JOIN "; $query .= $db->quoteName('#__jeproshop_image') . " AS image ON( image.product_id = product.product_id )" . JeproshopShopModelShop::addSqlAssociation('product', FALSE, 'image_shop.cover = 1'); $query .= " LEFT JOIN " . $db->quoteName('#__jeproshop_image_lang') . " AS image_lang ON (image.image_id = image_lang.image_id AND image_lang.lang_id = " . (int) $lang_id . " ) "; $query .= JeproshopShopModelShop::addSqlAssociation('product') . " LEFT JOIN " . $db->quoteName('#__jeproshop_category_lang') . " AS category_lang ON product_shop."; $query .= $db->quoteName('default_category_id') . " = category_lang." . $db->quoteName('category_id') . " AND category_lang." . $db->quoteName('lang_id') . " = " . (int) $lang_id; $query .= JeproshopShopModelShop::addSqlRestrictionOnLang('category_lang') . " WHERE product_shop." . $db->quoteName('shop_id') . " = " . (int) JeproshopContext::getContext()->shop->shop_id; $query .= " AND pack." . $db->quoteName('product_pack_id') . " = " . (int) $product_id . " GROUP BY product_shop.product_id"; $db->setQuery($query); $result = $db->loadObjectList(); foreach ($result as &$line) { $line = JeproshopProductModelProduct::getTaxesInformations($line); } if (!$full) { return $result; } $array_result = array(); foreach ($result as $prow) { if (!JeproshopProductPack::isPack($prow->product_id)) { $array_result[] = JeproshopProductModelProduct::getProductProperties($lang_id, $prow); } } return $array_result; }
public function renderView($tpl = null) { $app = JFactory::getApplication(); if (!isset($this->context) && null == $this->context) { $this->context = JeproshopContext::getContext(); } if (!isset($this->context->cart)) { $this->context->cart = new JeproshopCartModelCart(); } if (!$this->context->controller->isInitialized()) { $this->initialize(); } $useSSL = isset($this->context->controller->ssl_enabled) && $this->context->controller->ssl_enabled && $app->input->get('enable_ssl') || JeproshopTools::usingSecureMode() ? true : false; $protocol_content = $useSSL ? 'https://' : 'http://'; $this->loadObject(); if (JeproshopProductPack::isPack((int) $this->product->product_id) && !JeproshopProductPack::isInStock((int) $this->product->product_id)) { $this->product->quantity = 0; } $this->product->description = $this->transformDescriptionWithImg($this->product->description); // Assign to the template the id of the virtual product. "0" if the product is not downloadable. $virtual = JeproshopProductDownloadModelProductDownload::getIdFromProductId((int) $this->product->product_id); $this->assignRef('virtual', $virtual); $customization_form_target = JeproshopTools::safeOutput(urldecode($_SERVER['REQUEST_URI'])); $this->assignRef('customization_form_target', $customization_form_target); $delete_picture = $app->input->get('delete_picture'); if ($app->input->get('submit_customized_datas')) { // If cart has not been saved, we need to do it so that customization fields can have an id_cart // We check that the cookie exists first to avoid ghost carts if (!$this->context->cart->cart_id && isset($_COOKIE[$this->context->cookie->getName()])) { $this->context->cart->add(); $this->context->cookie->cart_id = (int) $this->context->cart->cart_id; } $this->pictureUpload(); $this->textRecord(); $this->formTargetFormat(); } else { if (isset($delete_picture) && !$this->context->cart->deleteCustomizationToProduct($this->product->product_id, $app->input->get('delete_picture'))) { $this->errors[] = JText::_('An error occurred while deleting the selected picture.'); } } $pictures = array(); $text_fields = array(); if ($this->product->customizable) { $files = $this->context->cart->getProductCustomization($this->product->product_id, JeproshopProductModelProduct::CUSTOMIZE_FILE, true); foreach ($files as $file) { $pictures['pictures_' . $this->product->product_id . '_' . $file['index']] = $file['value']; } $texts = $this->context->cart->getProductCustomization($this->product->product_id, JeproshopProductModelProduct::CUSTOMIZE_TEXT_FIELD, true); foreach ($texts as $text_field) { $text_fields['textFields_' . $this->product->product_id . '_' . $text_field['index']] = str_replace('<br />', "\n", $text_field['value']); } } $this->assignRef('pictures', $pictures); $this->assignRef('textFields', $text_fields); $this->product->customization_required = false; $customizationFields = $this->product->customizable ? $this->product->getCustomizationFields($this->context->language->lang_id) : false; if (is_array($customizationFields)) { foreach ($customizationFields as $customizationField) { if ($this->product->customization_required = $customizationField['required']) { break; } } } // Assign template vars related to the category + execute hooks related to the category $this->assignCategory(); // Assign template vars related to the price and tax $this->assignPriceAndTax(); // Assign template vars related to the images $this->assignImages(); // Assign attribute groups to the template $this->assignAttributesGroups(); // Assign attributes combinations to the template $this->assignAttributesCombinations(); // Pack management $pack_items = $this->product->cache_is_pack ? JeproshopProductPack::getItemTable($this->product->product_id, $this->context->language->lang_id, true) : array(); $this->assignRef('packItems', $pack_items); $packs = JeproshopProductPack::getPacksTable($this->product->product_id, $this->context->language->lang_id, true, 1); $this->assignRef('packs', $packs); if (isset($this->category->category_id) && $this->category->category_id) { $return_link = JeproshopTools::safeOutput($this->context->controller->getCategoryLink($this->category)); } else { $return_link = 'javascript: history.back();'; } if (!$this->context->controller->useMobileTheme()) { } //'stock_management' => Configuration::get('PS_STOCK_MANAGEMENT'), // 'customizationFields' => $customizationFields, $accessories = $this->product->getAccessories($this->context->language->lang_id); $this->assignRef('accessories', $accessories); $enable_jqzoom = JeproshopSettingModelSetting::getValue('enable_jqzoom'); $this->assignRef('jqZoomEnabled', $enable_jqzoom); $manufacturer = new JeproshopManufacturerModelManufacturer((int) $this->product->manufacturer_id, $this->context->language->lang_id); $this->assignRef('product_manufacturer', $manufacturer); $features = $this->product->getFrontFeatures($this->context->language->lang_id); $this->assignRef('features', $features); $attachments = $this->product->cache_has_attachments ? $this->product->getAttachments($this->context->language->lang_id) : array(); $this->assignRef('attachments', $attachments); $display_discount_price = JeproshopSettingModelSetting::getValue('display_discount_price'); $this->assignRef('display_discount_price', $display_discount_price); $this->assignRef('return_link', $return_link); $content_only = $app->input->get('content_only'); $this->assignRef('content_only', $content_only); $last_quantities = JeproshopSettingModelSetting::getValue('last_quantities'); $this->assignRef('last_quantities', $last_quantities); $display_quantities = JeproshopSettingModelSetting::getValue('display_quantities'); $this->assignRef('display_quantities', $display_quantities); $allow_out_of_stock_ordering = JeproshopSettingModelSetting::getValue('allow_out_of_stock_ordering'); $this->assignRef('allow_out_of_stock_ordering', $allow_out_of_stock_ordering); $catalog_mode = (bool) (JeproshopSettingModelSetting::getValue('catalog_mode') || !JeproshopGroupModelGroup::getCurrent()->show_prices); $this->assignRef('catalog_mode', $catalog_mode); $extra_left = null; $this->assignRef('extra_left', $extra_left); $extra_right = null; $this->assignRef('extra_right', $extra_right); parent::display($tpl); }
/** * Update product quantity * * @param integer $quantity Quantity to add (or substract) * @param $product_id * @param null $product_attribute_id * @param bool $customization_id * @param string $operator Indicate if quantity must be increased or decreased * @param int $address_delivery_id * @param JeproshopShopModelShop $shop * @param bool $auto_add_cart_rule * @return bool|int * @internal param int $id_product Product ID * @internal param int $id_product_attribute Attribute ID if needed */ public function updateQuantity($quantity, $product_id, $product_attribute_id = null, $customization_id = false, $operator = 'up', $address_delivery_id = 0, JeproshopShopModelShop $shop = null, $auto_add_cart_rule = true) { if (!$shop) { $shop = JeproshopContext::getContext()->shop; } $db = JFactory::getDBO(); if (JeproshopContext::getContext()->customer->customer_id) { if ($address_delivery_id == 0 && (int) $this->address_delivery_id) { // The $id_address_delivery is null, use the cart delivery address $address_delivery_id = $this->address_delivery_id; } elseif ($address_delivery_id == 0) { // The $id_address_delivery is null, get the default customer address $address_delivery_id = (int) JeproshopAddressModelAddress::getCustomerFirstAddressId((int) JeproshopContext::getContext()->customer->customer_id); } elseif (!JeproshopCustomerModelCustomer::customerHasAddress(JeproshopContext::getContext()->customer->customer_id, $address_delivery_id)) { // The $id_address_delivery must be linked with customer $address_delivery_id = 0; } } $quantity = (int) $quantity; $product_id = (int) $product_id; $product_attribute_id = (int) $product_attribute_id; $product = new JeproshopProductModelProduct($product_id, false, JeproshopSettingModelSetting::getValue('default_lang'), $shop->shop_id); if ($product_attribute_id) { $combination = new JeproshopCombinationModelCombination((int) $product_attribute_id); if ($combination->product_id != $product_id) { return false; } } /* If we have a product combination, the minimal quantity is set with the one of this combination */ if (!empty($product_attribute_id)) { $minimal_quantity = (int) JeproshopAttributeModelAttribute::getAttributeMinimalQty($product_attribute_id); } else { $minimal_quantity = (int) $product->minimal_quantity; } if (!JeproshopValidator::isLoadedObject($product, 'product_id')) { die(Tools::displayError()); } if (isset(self::$_nbProducts[$this->cart_id])) { unset(self::$_nbProducts[$this->cart_id]); } if (isset(self::$_totalWeight[$this->cart_id])) { unset(self::$_totalWeight[$this->cart_id]); } if ((int) $quantity <= 0) { return $this->deleteProduct($product_id, $product_attribute_id, (int) $customization_id); } elseif (!$product->available_for_order || JeproshopSettingModelSeting::getValue('catalog_mode')) { return false; } else { /* Check if the product is already in the cart */ $result = $this->containsProduct($product_id, $product_attribute_id, (int) $customization_id, (int) $address_delivery_id); /* Update quantity if product already exist */ if ($result) { if ($operator == 'up') { $query = "SELECT stock.out_of_stock, IFNULL(stock.quantity, 0) as quantity FROM " . $db->quoteName('#__jeproshop_product') . " AS product" . JeproshopProductModelProduct::sqlStock('p', $product_attribute_id, true, $shop); $query .= " WHERE product.product_id = " . $product_id; $db->setQuery($query); $result2 = $db->loadObject(); $product_qty = (int) $result2->quantity; // Quantity for product pack if (JeproshopProductPack::isPack($product_id)) { $product_qty = JeproshopProductPack::getQuantity($product_id, $product_attribute_id); } $new_qty = (int) $result->quantity + (int) $quantity; $qty = '+ ' . (int) $quantity; if (!JeproshopProductModelProduct::isAvailableWhenOutOfStock((int) $result2->out_of_stock)) { if ($new_qty > $product_qty) { return false; } } } else { if ($operator == 'down') { $qty = '- ' . (int) $quantity; $new_qty = (int) $result->quantity - (int) $quantity; if ($new_qty < $minimal_quantity && $minimal_quantity > 1) { return -1; } } else { return false; } } /* Delete product from cart */ if ($new_qty <= 0) { return $this->deleteProduct((int) $product_id, (int) $product_attribute_id, (int) $customization_id); } else { if ($new_qty < $minimal_quantity) { return -1; } else { $query = "UPDATE " . $db->quoteName('#__jeproshop_cart_product') . " SET " . $db->quoteName('quantity') . " = " . $db->quoteName('quantity') . $qty . ", "; $query .= $db->quoteName('date_add') . " = NOW() WHERE " . $db->quoteName('product_id') . " = " . (int) $product_id; $query .= (!empty($product_attribute_id) ? " AND " . $db->quoteName('product_attribute_id') . " = " . (int) $product_attribute_id : "") . " AND " . $db->quoteName('cart_id') . " = " . (int) $this->cart_id; $query .= (JeproshopSettingModelSeting::getValue('allow_multi_shipping') && $this->isMultiAddressDelivery() ? " AND " . $db->quoteName('address_delivery_id') . " = " . (int) $address_delivery_id : "") . " LIMIT 1"; $db->setQuery($query); $db->query(); } } } elseif ($operator == 'up') { $sql = 'SELECT stock.out_of_stock, IFNULL(stock.quantity, 0) as quantity FROM ' . _DB_PREFIX_ . 'product p ' . Product::sqlStock('p', $product_attribute_id, true, $shop) . ' WHERE p.id_product = ' . $product_id; $result2 = Db::getInstance()->getRow($sql); // Quantity for product pack if (Pack::isPack($product_id)) { $result2['quantity'] = Pack::getQuantity($product_id, $product_attribute_id); } if (!Product::isAvailableWhenOutOfStock((int) $result2['out_of_stock'])) { if ((int) $quantity > $result2['quantity']) { return false; } } if ((int) $quantity < $minimal_quantity) { return -1; } $result_add = Db::getInstance()->insert('cart_product', array('id_product' => (int) $product_id, 'id_product_attribute' => (int) $product_attribute_id, 'id_cart' => (int) $this->cart_id, 'id_address_delivery' => (int) $address_delivery_id, 'id_shop' => $shop->shop_id, 'quantity' => (int) $quantity, 'date_add' => date('Y-m-d H:i:s'))); if (!$result_add) { return false; } } } // refresh cache of self::_products $this->_products = $this->getProducts(true); $this->update(true); $context = Context::getContext()->cloneContext(); $context->cart = $this; Cache::clean('getContextualValue_*'); if ($auto_add_cart_rule) { CartRule::autoAddToCart($context); } if ($product->customizable) { return $this->updateCustomizationQuantity((int) $quantity, (int) $customization_id, (int) $product_id, (int) $product_attribute_id, (int) $address_delivery_id, $operator); } else { return true; } }
private function initQuantitiesForm() { if (!$this->context->controller->default_form_language) { $this->languages = $this->context->controller->getLanguages(); } if ($this->product->product_id) { if ($this->product_exists_in_shop) { //Get all product_attribute_id $attributes = $this->product->getAttributesResume($this->context->language->lang_id); if (empty($attributes)) { $attributes[] = new JObject(); $attributes[0]->set('product_attribute_id', 0); $attributes[0]->set('attribute_designation', ''); } /** get available quantities **/ $available_quantity = array(); $product_designation = array(); foreach ($attributes as $attribute) { $product_attribute_id = is_object($attribute) ? $attribute->product_attribute_id : $attribute['product_attribute_id']; $attribute_designation = is_object($attribute) ? $attribute->attribute_designation : $attribute['attribute_designation']; // Get available quantity for the current product attribute in the current shop $available_quantity[$product_attribute_id] = JeproshopStockAvailableModelStockAvailable::getQuantityAvailableByProduct((int) $this->product->product_id, $product_attribute_id); // Get all product designation $product_designation[$product_attribute_id] = rtrim($this->product->name[$this->context->language->lang_id] . ' - ' . $attribute_designation, ' - '); } $show_quantities = true; $shop_context = JeproshopShopModelShop::getShopContext(); $shop_group = new JeproshopShopGroupModelShopGroup((int) JeproshopShopModelShop::getContextShopGroupID()); // if we are in all shops context, it's not possible to manage quantities at this level if (JeproshopShopModelShop::isFeaturePublished() && $shop_context == JeproshopShopModelShop::CONTEXT_ALL) { $show_quantities = false; // if we are in group shop context } elseif (JeproshopShopModelShop::isFeaturePublished() && $shop_context == JeproshopShopModelShop::CONTEXT_GROUP) { // if quantities are not shared between shops of the group, it's not possible to manage them at group level if (!$shop_group->share_stock) { $show_quantities = false; } } else { // if we are in shop context // if quantities are shared between shops of the group, it's not possible to manage them for a given shop if ($shop_group->share_stock) { $show_quantities = false; } } $stock_management = JeproshopSettingModelSetting::getValue('stock_management'); $this->assignRef('stock_management', $stock_management); $has_attribute = $this->product->hasAttributes(); $this->assignRef('has_attribute', $has_attribute); // Check if product has combination, to display the available date only for the product or for each combination $db = JFactory::getDBO(); if (JeproshopCombinationModelCombination::isFeaturePublished()) { $query = "SELECT COUNT(product_id) FROM " . $db->quoteName('#__jeproshop_product_attribute') . " WHERE "; $query .= " product_id = " . (int) $this->product->product_id; $db->setQuery($query); $countAttributes = (int) $db->loadResult(); } else { $countAttributes = false; } $this->assignRef('count_attributes', $countAttributes); // if advanced stock management is active, checks associations $advanced_stock_management_warning = false; if (JeproshopSettingModelSetting::getValue('advanced_stock_management') && $this->product->advanced_stock_management) { $product_attributes = JeproshopProductModelProduct::getProductAttributesIds($this->product->product_id); $warehouses = array(); if (!$product_attributes) { $warehouses[] = JeproshopWarehouseModelWarehouse::getProductWarehouseList($this->product->product_id, 0); } foreach ($product_attributes as $product_attribute) { $ws = JeproshopWarehouseModelWarehouse::getProductWarehouseList($this->product->product_id, $product_attribute->product_attribute_id); if ($ws) { $warehouses[] = $ws; } } $warehouses = JeproshopTools::arrayUnique($warehouses); if (empty($warehouses)) { $advanced_stock_management_warning = true; } } if ($advanced_stock_management_warning) { JError::raiseWarning(500, JText::_('If you wish to use the advanced stock management, you must:')); JError::raiseWarning(500, '- ' . JText::_('associate your products with warehouses.')); JError::raiseWarning(500, '- ' . JText::_('associate your warehouses with carriers.')); JError::raiseWarning(500, '- ' . JText::_('associate your warehouses with the appropriate shops.')); } $pack_quantity = null; // if product is a pack if (JeproshopProductPack::isPack($this->product->product_id)) { $items = JeproshopProductPack::getItems((int) $this->product->product_id, JeproshopSettingModelSetting::getValue('default_lang')); // gets an array of quantities (quantity for the product / quantity in pack) $pack_quantities = array(); foreach ($items as $item) { if (!$item->isAvailableWhenOutOfStock((int) $item->out_of_stock)) { $pack_id_product_attribute = JeproshopProductModelProduct::getDefaultAttribute($item->product_id, 1); $pack_quantities[] = JeproshopProductModelProduct::getQuantity($item->id, $pack_id_product_attribute) / ($item->pack_quantity !== 0 ? $item->pack_quantity : 1); } } // gets the minimum if (count($pack_quantities)) { $pack_quantity = $pack_quantities[0]; foreach ($pack_quantities as $value) { if ($pack_quantity > $value) { $pack_quantity = $value; } } } if (!JeproshopWarehouseModelWarehouse::getPackWarehouses((int) $this->product->product_id)) { $this->displayWarning($this->l('You must have a common warehouse between this pack and its product.')); } } $this->assignRef('attributes', $attributes); $this->assignRef('available_quantity', $available_quantity); $this->assignRef('pack_quantity', $pack_quantity); $stock_management_active = JeproshopSettingModelSetting::getValue('advanced_stock_management'); $this->assignRef('stock_management_active', $stock_management_active); $this->assignRef('product_designation', $product_designation); $this->assignRef('show_quantities', $show_quantities); $order_out_of_stock = JeproshopSettingModelSetting::getValue('allow_out_of_stock_ordering'); $this->assignRef('order_out_of_stock', $order_out_of_stock); /*'token_preferences' => Tools::getAdminTokenLite('AdminPPreferences'), 'token' => $this->token, 'languages' => $this->_languages, 'id_lang' => $this->context->language->id ));*/ } else { JError::raiseWarning(500, JText::_('You must save the product in this shop before managing quantities.')); } } else { JError::raiseWarning(500, JText::_('You must save this product before managing quantities.')); } }
/** * For a given pack, tells if it has at least one product using the advanced stock management * * @param int $product_id pack id * @return bool */ public static function usesAdvancedStockManagement($product_id) { if (!JeproshopProductPack::isPack($product_id)) { return false; } $products = JeproshopProductPack::getItems($product_id, JeproshopSettingModelSetting::getValue('default_lang')); foreach ($products as $product) { // if one product uses the advanced stock management if ($product->advanced_stock_management == 1) { return true; } } // not used return false; }