I have been looking for a module to allow a client to be able to still purchase an item if the stock level is 0. Is this feature available in OpenCart 1.5.x?
I have set the product to 2-3 days, however on the site front-end it still shows the product as out of stock. Is there away to alert the client of the 2-3 day delay, and still allow the client to purchase?
First you need to change the function that prevents an out of stock item from going to checkout. Go to catalog/controller/checkout/checkout.php and change
public function index() {
// Validate cart has products and has stock.
if ((!$this->cart->hasProducts() && empty($this->session->data['vouchers'])) || (!$this->cart->hasStock() && !$this->config->get('config_stock_checkout'))) {
$this->redirect($this->url->link('checkout/cart'));
}
to
public function index() {
// Validate cart has products and has stock.
if (!$this->cart->hasProducts() && empty($this->session->data['vouchers'])) {
$this->redirect($this->url->link('checkout/cart'));
}
I don't remember if it blocks you from adding it to the cart in the first place so let me know. Good luck David!
Update
To change "Out of Stock" on the product page, I have changed it myself with the settings in the store so if that isn't working for you then you can go into catalog/controller/product/product.php and where you see
if ($product_info['quantity'] <= 0) {
$this->data['stock'] = $product_info['stock_status'];
} elseif ($this->config->get('config_stock_display')) {
$this->data['stock'] = $product_info['quantity'];
} else {
$this->data['stock'] = $this->language->get('text_instock');
}
Change to:
if ($product_info['quantity'] <= 0) {
$this->data['stock'] = "2-3 Days";
} elseif ($this->config->get('config_stock_display')) {
$this->data['stock'] = $product_info['quantity'];
} else {
$this->data['stock'] = $this->language->get('text_instock');
}
Change the text within those brackets to whichever phrase works for you.
This is a feature built into OpenCart as standard. The setting should be on the "Option" tab in your settings page
First find
if (!$option_value['subtract'] || ($option_value['quantity'] > 0)) {
and replace with
if (1==1 || !$option_value['subtract'] || ($option_value['quantity'] > 0)) {
Related
Following is the observer.php file for an extension that restricts Cash On Delivery Payment Method Based On Pincode On The Checkout Page.
This extension works perfectly fine with the built in Cash On Delivery Payment Method in Magento.
My issue is that, when a customer on my website goes to the checkout page to complete his order, the cash on delivery payment method is not visible initially. Only when the customer enters his Zip Code, and if that particular zip code is available for COD, the COD payment method appears. If that zipcode is not eligible, the COD option continues to be invisible.
I want the COD option to be visible initially when the zip code has not been entered and after the customer enters the zip code and if that zip code is not available, a message should be displayed saying that COD is not available.
I know this particular code needs to be altered a bit to achieve that. Kindly help me out if possible.
Observer.php
class Mfp_Cod_Model_Observer {
public function getCashOnDelvery(Varien_Event_Observer $observer)
{
$event = $observer->getEvent();
$method = $event->getMethodInstance();
$result = $event->getResult();
$isModuleEnable = Mage::getStoreConfig('cod/cod/enable');
if ($isModuleEnable) {
if ($method->getCode() == 'msp_cashondelivery' ) {
$quote = Mage::getSingleton('checkout/cart')->getQuote();
$add = $quote->getShippingAddress();
$postcode = $add->getData('postcode');
$comparisonMode = Mage::getStoreConfig('cod/cod/mode');
$zipCodes = Mage::getStoreConfig('cod/cod/zipcode');
$isExist = false;
if (trim($zipCodes) == '') {
$result->isAvailable = true;
} else {
if(strpos($zipCodes, $postcode) !== false) {
$isExist = true;
}
if ($isExist != true) {
$zipCodesArray = explode(',', nl2br($zipCodes));
if (count($elementLineArray) > 1) {
foreach ($zipCodesArray as $codzipLine) {
$elementLineArray = explode('-', $codzipLine);
if (count($elementLineArray) == 2 && ( $postcode >= $elementLineArray[0] && $postcode <= $elementLineArray[1] )) {
$isExist = true;
break;
} else if($postcode == $codzipLine) {
$isExist = true;
break;
}
}
}
}
$returnValue = '';
$returnValue = ($isExist)?true:false;
$result->isAvailable = $returnValue;
}
}
}
}
}
you can simply check if zipcode is not added like :
after
$postcode = $add->getData('postcode');
add
if(!isset($postcode) || empty($postcode)) {
return true;
}
In order to get shipping address of checkout page use
$address = $observer->getEvent()->getOrder()
->getShippingAddress();
in $address object you will get complete information of shipping address including postcode.
I have an extension to provide different rates for shipping, this module has got an option in the admin panel that let you choose the free shipping method if the cart price rule is met( if cart price rule requirement are respected, then set this method as free).
The problem is that I can choose only one method, but in the same country I offer 2 different carrier to delivery the package (lowest price for different regions) and this is a problem.
The extension save the value in the core_config_data table under path=carriers/premiumrate/free_method. I don't have clear how magento access this information so I have run these comand through SSH:
grep -rnw 'app' -e "carriers/premiumrate/free_method"
with no result, so I have tried:
grep -rnw 'app' -e "free_method"
Results:
app/code/core/Mage/Shipping/Helper/Data.php:159: $freeMethod = Mage::getStoreConfig('carriers/' . $arr[0] . '/free_method', $storeId);
app/code/core/Mage/Shipping/Model/Carrier/Abstract.php:56: protected $_freeMethod = 'free_method';
Next search:
grep -rnw 'app' -e "freeMethod"
Result:
app/code/core/Mage/Shipping/Helper/Data.php:159: $freeMethod = Mage::getStoreConfig('carriers/' . $arr[0] . '/free_method', $storeId);
app/code/core/Mage/Shipping/Helper/Data.php:160: return $freeMethod == $arr[1];
app/code/core/Mage/Shipping/Model/Carrier/Abstract.php:343: $freeMethod = $this->getConfigData($this->_freeMethod);
app/code/core/Mage/Shipping/Model/Carrier/Abstract.php:344: if (!$freeMethod) {
app/code/core/Mage/Shipping/Model/Carrier/Abstract.php:351: if ($item->getMethod() == $freeMethod) {
app/code/core/Mage/Shipping/Model/Carrier/Abstract.php:363: $this->_setFreeMethodRequest($freeMethod);
app/code/core/Mage/Shipping/Model/Carrier/Abstract.php:373: && $rate->getMethod() == $freeMethod
So I opened app/code/core/Mage/Shipping/Model/Carrier/Abstract.php and these are the lines (370-378; I have added the complete function at the bottom) that I have found interesting:
if (count($rates) > 1) {
foreach ($rates as $rate) {
if ($rate instanceof Mage_Shipping_Model_Rate_Result_Method
&& $rate->getMethod() == $freeMethod
) {
$price = $rate->getPrice();
}
}
}
Is it the correct place that I have to edit?
if I remove the if condition, will I destroy my site?
What should I do to set any shipping free if the cart rule is
active/valid?
Is there a better way to find out what I have to edit
instead of random grep?
Complete function:
protected function _updateFreeMethodQuote($request)
{
if ($request->getFreeMethodWeight() == $request->getPackageWeight() || !$request->hasFreeMethodWeight()) {
return;
}
$freeMethod = $this->getConfigData($this->_freeMethod);
if (!$freeMethod) {
return;
}
$freeRateId = false;
if (is_object($this->_result)) {
foreach ($this->_result->getAllRates() as $i=>$item) {
if ($item->getMethod() == $freeMethod) {
$freeRateId = $i;
break;
}
}
}
if ($freeRateId === false) {
return;
}
$price = null;
if ($request->getFreeMethodWeight() > 0) {
$this->_setFreeMethodRequest($freeMethod);
$result = $this->_getQuotes();
if ($result && ($rates = $result->getAllRates()) && count($rates)>0) {
if ((count($rates) == 1) && ($rates[0] instanceof Mage_Shipping_Model_Rate_Result_Method)) {
$price = $rates[0]->getPrice();
}
if (count($rates) > 1) {
foreach ($rates as $rate) {
if ($rate instanceof Mage_Shipping_Model_Rate_Result_Method
&& $rate->getMethod() == $freeMethod
) {
$price = $rate->getPrice();
}
}
}
}
} else {
/**
* if we can apply free shipping for all order we should force price
* to $0.00 for shipping with out sending second request to carrier
*/
$price = 0;
}
/**
* if we did not get our free shipping method in response we must use its old price
*/
if (!is_null($price)) {
$this->_result->getRateById($freeRateId)->setPrice($price);
}
}
I am interested in implementing an "order again" function for OpenCart, with a button located in the order history list under account/order. This button would take all this particular order's products (and its associated options) and add them all back to the cart.
The following code I have allows me to loop through my product as well as its respective product options depending on the order ID.
$products = $this->model_account_order->getOrderProducts(
$this->request->get['order_id']
);
foreach ($products as $product) {
$options = $this->model_account_order->getOrderOptions(
$this->request->get['order_id'],
$product['order_product_id']
);
foreach ($product['option'] as $option) {
// Implement custom logic
}
}
I have no issues at the moment to get the products that I have already ordered. What I do not understand what to do and need help on is - how do I use this [if this is the way to add items to cart] to add the items back to the cart?
By knowing the product ID and quantities (and options if any) you can just call:
$this->cart->add($product_id, $quantity, $options); // use array() instead of $options if there are none
for each product respectively. $options is an array, to see what structure it has to have look into the AJAX request when adding a product with options to the cart (I think it's single array with product_option_id as key and option_value as value).
Try this
$this->cart->add($product_id, $quantity, $options);
This is actually already implemented on the customer side of the cart. Here's the code contained in the /catalog/controller/account/order.php that does exactly what you want (1.5.5.1 in this particular case)
if (isset($this->request->get['order_id'])) {
$order_info = $this->model_account_order->getOrder($this->request->get['order_id']);
if ($order_info) {
$order_products = $this->model_account_order->getOrderProducts($this->request->get['order_id']);
foreach ($order_products as $order_product) {
$option_data = array();
$order_options = $this->model_account_order->getOrderOptions($this->request->get['order_id'], $order_product['order_product_id']);
foreach ($order_options as $order_option) {
if ($order_option['type'] == 'select' || $order_option['type'] == 'radio') {
$option_data[$order_option['product_option_id']] = $order_option['product_option_value_id'];
} elseif ($order_option['type'] == 'checkbox') {
$option_data[$order_option['product_option_id']][] = $order_option['product_option_value_id'];
} elseif ($order_option['type'] == 'text' || $order_option['type'] == 'textarea' || $order_option['type'] == 'date' || $order_option['type'] == 'datetime' || $order_option['type'] == 'time') {
$option_data[$order_option['product_option_id']] = $order_option['value'];
} elseif ($order_option['type'] == 'file') {
$option_data[$order_option['product_option_id']] = $this->encryption->encrypt($order_option['value']);
}
}
$this->session->data['success'] = sprintf($this->language->get('text_success'), $this->request->get['order_id']);
$this->cart->add($order_product['product_id'], $order_product['quantity'], $option_data);
}
$this->redirect($this->url->link('checkout/cart'));
}
}
Upon investigation and posting on the OpenCart website, it turns out reorder is already a functionality in OpenCart, but we never enabled it [or someone disabled it months ago]. We had to renable it by adding a button and attributed the reorder link under /catalog/controller/account/order.php.
We also added some custom logic in our:
if ($order_option['type'] == 'select' || $order_option['type'] == 'radio') {
$option_data[$order_option['product_option_id']] = $order_option['product_option_value_id'];
} elseif ($order_option['type'] == 'checkbox') {
$option_data[$order_option['product_option_id']][] = $order_option['product_option_value_id'];
} elseif ($order_option['type'] == 'text' || $order_option['type'] == 'textarea' || $order_option['type'] == 'date' || $order_option['type'] == 'datetime' || $order_option['type'] == 'time') {
$option_data[$order_option['product_option_id']] = $order_option['value'];
} elseif ($order_option['type'] == 'file') {
$option_data[$order_option['product_option_id']] = $this->encryption->encrypt($order_option['value']);
}
Since we have a custom option type called checkbox+quantity. For the future users, please make sure to add your custom option type logic to this logical statement.
Thanks Jay for pointing this out as well.
Dear stackoverflow code experts. I have a query relating to opencart stock.
The frontend product page has option of displaying Stock, either in terms of availability (Available or Out of Stock) or in terms of quantity in actual numbers.
Is it possible to display it in some other way? eg. I want that if the stock quantity is less than or equal to 5, then it should display quantity, else display the text: Available.
Or in a more sophisticated manner, if product quantity is greater than 5 or zero, then display text, else display quantity in number.
I understand it may have to do something with ../catalog/controller/product/product.php file.
I am not an expert in coding. Please help me.
Thank you.
It's simple.
First set "display stock" to Yes
admin panel>system>setting>options set display stock to "YES"
now
//catalog>controller>product>product.php
Find (around line 282)
if ($product_info['quantity'] <= 0) {
$this->data['stock'] = $product_info['stock_status'];
} elseif ($this->config->get('config_stock_display')) {
$this->data['stock'] = $product_info['quantity'];
} else {
$this->data['stock'] = $this->language->get('text_instock');
}
Replace With
if ($product_info['quantity'] <= 0) {
$this->data['stock'] = $product_info['stock_status'];
} elseif ($this->config->get('config_stock_display') && $product_info['quantity'] <= 5) {
$this->data['stock'] = $product_info['quantity'];
} else {
$this->data['stock'] = $this->language->get('text_instock');
}
Hope this helps
Edit the file catalog/controller/product/category.php
Step : 1
Find the code:
if ($this->config->get('config_review_status')) {
$rating = (int)$result['rating'];
} else {
$rating = false;
}
Add the following just below the above code :
if ($result['quantity'] <= 0) {
$rstock = $result['stock_status'];
} elseif ($this->config->get('config_stock_display')) {
$rstock = "Stoc: " . $result['quantity'];
} else {
$rstock = "In stoc";
}
Step : 2
Find :
'thumb' => $image,
Add the following just after the above line
'stoc' => $rstock,
Step 3
Edit the file catalog/view/theme/yourtheme/template/product/category.tpl
Find :
<div class="cart">
Add the following :
<?php echo $product['stoc']; ?>
And now the stock will appear for products in category page.
You can do the same for search (the files would be search.php and search.tpl - in the same folders as the category)
You can see a more detailed tutorial at :
http://www.aleixcortadellas.com/main/2009/09/09/742/
http://forum.opencart.com/viewtopic.php?t=27137
http://forum.opencart.com/viewtopic.php?t=66506
All of the above uses the same idea, but implemented in different ways. But this should help you solve your problem.
Hope this helps.
I want to show
out of stock
on my product page and I change the status from admin and is updated in admin but on my product page there is also same
In Stock
and product page code is
if ($product_info['quantity'] <= 0) {
$this->data['stock'] = $product_info['stock_status'];
} elseif ($this->config->get('config_stock_display')) {
$this->data['stock'] = $product_info['quantity'];
} else{
$this->data['stock'] = $this->language->get('text_instock');
}
and language page is
$_['text_outstock'] = 'Out of Stock';
Now what condition is used there?
As far as I understand your issue, you can set it directly in the Admin to show 'out of stock' message.
You need to set it both in the general settings AND in the invidividual product.
Currently, because you did not set your Admin settings correctly, $product_info['stock_status'] does not display 'out of stock'.
However, if you insist of modifying the code, you need to use the following:
if ($product_info['quantity'] <= 0) {
//out of stock message
$this->data['stock'] = $this->language->get('text_outstock');
} elseif ($this->config->get('config_stock_display')) {
//in stock, and displaying exact quantity
$this->data['stock'] = $product_info['quantity'];
} else{
//in stock, but just display a message not exact quantity
$this->data['stock'] = $this->language->get('text_instock');
}
Hope this helps!