Magento - Show out of stock products last - magento

I am using Magento 1.9 and I have this code line that i am using in /app/code/local/Mage/Catalog/Block/Product/List.php :
$this->_productCollection = $layer->getProductCollection()
->joinField(
'inventory_in_stock',
'cataloginventory_stock_item',
'is_in_stock',
'product_id=entity_id',
'is_in_stock>=0',
'left')
->setOrder('inventory_in_stock','desc');
but nothing happened.
Can someone help me?
Thank in advance!

You must add this code :
$this->getSelect()->joinLeft(
array('_inventory_table'=>$this->getTable('cataloginventory/stock_item')),
"_inventory_table.product_id = e.entity_id",
array('is_in_stock', 'manage_stock')
);
$this->addExpressionAttributeToSelect('on_top',
'(CASE WHEN (((_inventory_table.use_config_manage_stock = 1) AND (_inventory_table.is_in_stock = 1)) OR ((_inventory_table.use_config_manage_stock = 0) AND (1 - _inventory_table.manage_stock + _inventory_table.is_in_stock >= 1))) THEN 1 ELSE 0 END)',
array());
$this->getSelect()->order('on_top DESC');
Just before
if ($attribute == 'price' && $storeId != 0) {
in app/code/core/Mage/Catalog/Model/Resource/Eav/Mysql4/Product/Collection.php
Or in app/code/core/Mage/Catalog/Model/Resource/Product/Collection.php if you have Magento 1.7.0.0
or you can used this magento module
http://www.magentocommerce.com/magento-connect/show-out-of-stocks-products-at-bottom.html

Related

Catalog Price Rules applied to special_price

First question on stackoverflow...i am excited :)
Currently magento is using the special price if its lower than the applied catalog price rule. If the catalog price rule makes the product cheaper than the special price, then the catalog price rule defines the shop price.
I am looking for an elegant way to make catalog price rules be applied
to the special price (additionally). Maybe there is some store config for it? Maybe
there is some neat observer way?
Thank you so much!
Works up to current Magento 1.9.3.10. Just tested it in a project after update. Josef tried another approach which might work as well.
I am sad to say, I solved my first real stackoverflow question for my own:
Goto Mage_CatalogRule_Model_Resource_Rule
Goto method _getRuleProductsStmt
Add this to the initial select of the method before the first original ->from:
$select->from(null, array('default_price' => new Zend_Db_Expr("CASE
WHEN pp_default_special.value THEN pp_default_special.value ELSE
pp_default_normal.value END")));
Add this after the first join() has happened
$specialPriceAttr = Mage::getSingleton('eav/config')
->getAttribute(Mage_Catalog_Model_Product::ENTITY, 'special_price');
$specialPriceTable = $specialPriceAttr->getBackend()->getTable();
$specialPriceAttributeId= $specialPriceAttr->getId();
$joinCondition2 = '%1$s.entity_id=rp.product_id AND (%1$s.attribute_id=' . $specialPriceAttributeId . ')
AND %1$s.store_id=%2$s';
$select->join(
array('pp_default_special'=>$specialPriceTable),
sprintf($joinCondition2, 'pp_default_special', Mage_Core_Model_App::ADMIN_STORE_ID), null
);
How it works:
When a catalog price rule is applied (via backend or cron) the db table catalogrule_product_price is populated. The above SQL magic joins the special_price (if exists) to the resultset as column default_value, if no special_price is found the regular price gets joined.
The result has been checked and is working.
Have fun! And dont hack the core!
There seem to be some changes in newer Magento releases!
For 1.9 i had to:
copy app/code/core/Mage/CatalogRule/Model/Action/Index/Refresh.php to app/code/local/Mage/CatalogRule/Model/Action/Index/Refresh.php
Change _prepareTemporarySelect.
I post the function in full here. Joins for special_price are added and then the price added to the selection of the price field. It still prefers group prices, becuas I never use them, but that can be changed easily!
protected
function _prepareTemporarySelect(Mage_Core_Model_Website $website)
{
/** #var $catalogFlatHelper Mage_Catalog_Helper_Product_Flat */
$catalogFlatHelper = $this->_factory->getHelper('catalog/product_flat');
/** #var $eavConfig Mage_Eav_Model_Config */
$eavConfig = $this->_factory->getSingleton('eav/config');
$priceAttribute = $eavConfig->getAttribute(Mage_Catalog_Model_Product::ENTITY, 'price');
$specialPriceAttr = Mage::getSingleton('eav/config')->getAttribute(Mage_Catalog_Model_Product::ENTITY, 'special_price');
$specialPriceTable = $specialPriceAttr->getBackend()->getTable();
$specialPriceAttributeId = $specialPriceAttr->getId();
$select = $this->_connection->select()->from(array(
'rp' => $this->_resource->getTable('catalogrule/rule_product')
) , array())->joinInner(array(
'r' => $this->_resource->getTable('catalogrule/rule')
) , 'r.rule_id = rp.rule_id', array())->where('rp.website_id = ?', $website->getId())->order(array(
'rp.product_id',
'rp.customer_group_id',
'rp.sort_order',
'rp.rule_product_id'
))->joinLeft(array(
'pg' => $this->_resource->getTable('catalog/product_attribute_group_price')
) , 'pg.entity_id = rp.product_id AND pg.customer_group_id = rp.customer_group_id' . ' AND pg.website_id = rp.website_id', array())->joinLeft(array(
'pgd' => $this->_resource->getTable('catalog/product_attribute_group_price')
) , 'pgd.entity_id = rp.product_id AND pgd.customer_group_id = rp.customer_group_id' . ' AND pgd.website_id = 0', array());
$storeId = $website->getDefaultStore()->getId();
if ($catalogFlatHelper->isEnabled() && $storeId && $catalogFlatHelper->isBuilt($storeId))
{
$select->joinInner(array(
'p' => $this->_resource->getTable('catalog/product_flat') . '_' . $storeId
) , 'p.entity_id = rp.product_id', array());
$priceColumn = $this->_connection->getIfNullSql($this->_connection->getIfNullSql('pg.value', 'pgd.value') , $this->_connection->getIfNullSql('p.special_price', 'p.price'));
}
else
{
$select->joinInner(array(
'pd' => $this->_resource->getTable(array(
'catalog/product',
$priceAttribute->getBackendType()
))
) , 'pd.entity_id = rp.product_id AND pd.store_id = 0 AND pd.attribute_id = ' . $priceAttribute->getId() , array())->joinLeft(array(
'pspd' => $specialPriceTable
) , 'pspd.entity_id = rp.product_id AND (pspd.attribute_id=' . $specialPriceAttributeId . ')' . 'AND pspd.store_id = 0', array())->joinLeft(array(
'p' => $this->_resource->getTable(array(
'catalog/product',
$priceAttribute->getBackendType()
))
) , 'p.entity_id = rp.product_id AND p.store_id = ' . $storeId . ' AND p.attribute_id = pd.attribute_id', array())->joinLeft(array(
'psp' => $specialPriceTable
) , 'psp.entity_id = rp.product_id AND (psp.attribute_id=' . $specialPriceAttributeId . ')' . 'AND psp.store_id = ' . $storeId, array());
$priceColumn = $this->_connection->getIfNullSql($this->_connection->getIfNullSql('pg.value', 'pgd.value') , $this->_connection->getIfNullSql('psp.value', $this->_connection->getIfNullSql('pspd.value', $this->_connection->getIfNullSql('p.value', 'pd.value'))));
}
$select->columns(array(
'grouped_id' => $this->_connection->getConcatSql(array(
'rp.product_id',
'rp.customer_group_id'
) , '-') ,
'product_id' => 'rp.product_id',
'customer_group_id' => 'rp.customer_group_id',
'from_date' => 'r.from_date',
'to_date' => 'r.to_date',
'action_amount' => 'rp.action_amount',
'action_operator' => 'rp.action_operator',
'action_stop' => 'rp.action_stop',
'sort_order' => 'rp.sort_order',
'price' => $priceColumn,
'rule_product_id' => 'rp.rule_product_id',
'from_time' => 'rp.from_time',
'to_time' => 'rp.to_time'
));
return $select;
}
I fixed it in another way. It was just easy to put into the price field for example 100 and then into special price field 90 when there was 10% discount on product page but now I removed special price from product page and just created catalog price rule 10% discount to that product(s) and now other rules also work:)

Configurable Product turn Out of Stock when all child product are out of stock

Hey guys i got a little dilema. I am running Magento ver. 1.7.0.2
When you create a configurable product you must set the stock "in stock" and then you add the other additional products with different stock.
When the additional products stock goes to 0 the main configurable product still is "in stock".
I want that when all the additional products stock goes to 0 then the main configurable product stock to turn into "out of stock".
I am using this custom code for "out of stock" products to appear always at the bottom page. And unless the configurable product dont receive the option "out of stock" it cant go to bottom page.
$this->getSelect()->joinLeft(array('_inventory_table'=>$this->getTable('cataloginventory/stock_item')),"_inventory_table.product_id = e.entity_id",array('is_in_stock', 'manage_stock'));
$this->addExpressionAttributeToSelect('on_top','(CASE WHEN (((_inventory_table.use_config_manage_stock = 1) AND (_inventory_table.is_in_stock = 1)) OR ((_inventory_table.use_config_manage_stock = 0) AND (1 - _inventory_table.manage_stock + _inventory_table.is_in_stock >= 1))) THEN 1 ELSE 0 END)',array());
$this->getSelect()->order('on_top DESC');
Have you made sure you have the correct Magento settings?
Inventory "Show Out Of Stock" = "No"
Configurable product Manage Stock = "No"
Simple product /Manage Stock = "Yes"
I don't know if this would work for you but I think you can solve this from the template itself on the file "app/base/default/template/catalog/product/view.phtml", the line of code that says:
<?php if ($_product->isSaleable() && $this->hasOptions()):?>
<?php echo $this->getChildChildHtml('container2', '', true, true) ?>
<? else : ?>
enter code here
<?php endif ?>
if you base it from the original file in the base template you may see this code starting from line 100 as you can see if all the options of the configurable product is empty it means that all products are already sold out causing it not to display the form fields necessary for adding it to the cart.
I hope this helps. :)
Add this code
$this->getSelect()->joinLeft(
array('_inventory_table'=>$this->getTable('cataloginventory/stock_item')),
"_inventory_table.product_id = e.entity_id",
array('is_in_stock', 'manage_stock')
);
$this->addExpressionAttributeToSelect('on_top',
'(CASE WHEN (((_inventory_table.use_config_manage_stock = 1) AND (_inventory_table.is_in_stock = 1)) OR ((_inventory_table.use_config_manage_stock = 0) AND (1 - _inventory_table.manage_stock + _inventory_table.is_in_stock >= 1))) THEN 1 ELSE 0 END)',
array());
$this->getSelect()->order('on_top DESC');
before line:
if ($attribute == 'price' && $storeId != 0) {
in files:
app/code/core/Mage/Catalog/Model/Resource/Eav/Mysql4/Product/Collection.php
or in app/code/core/Mage/Catalog/Model/Product/Collection.php if you have Magento 1.7.0.0 +

php undefined variables error when displaying pdf with mpdf

i have been in crisis for over 2 days with this pdf thing.Its not showing any error in the resulting action page,still not displaying in pdf document.Can anyone plz sort this this out, maybe a simple one i guess not sure.The code is below.
Anyways thanks in advance,all.
<?php
if(isset($_POST['email'])){
$email = $_POST['email'];
$fileno = $_POST['fileno'];
$header = $_POST['header'];
$day = $_POST['day'];
$month = $_POST['month'];
$year = $_POST['year'];
$stime = $_POST['stime'];
$venue = $_POST['venue'];
$meettype = $_POST['meettype'];
$Itchair = $_POST['Itchair'];
$mem_pres = $_POST['mem_pres'];
$invite = $_POST['invite'];
$head = $_POST['head'];
$slno = $_POST['slno'];
$subject = $_POST['subject'];
$decision = $_POST['decision'];
$incharge = $_POST['incharge'];
$date = $_POST['date'];
$remarks = $_POST['remarks'];
}
include("MPDF54/mpdf.php");
$mpdf=new mPDF('c','A4','','' , 0 , 0 , 0 , 0 , 0 , 0);
$mpdf->SetDisplayMode('fullpage');
$mpdf->list_indent_first_level = 0;
$mpdf->WriteHTML(file_get_contents("http://localhost/Bescom/besc_latest.php?email=$email&fileno=$fileno&header=$header&day=$day&month=$month&year=$year&stime=$stime&venue=$venue&meettype=$meettype&Itchair=$Itchair&mem_pres=$mem_pres&invite=$invite&head=$head&slno=$slno&subject=$subject&decision=$decision&date=$date&incharge=$incharge&remarks=$remarks"));
$mpdf->Output();
?>
Add following at top of mpdf.php
error_reporting(0);
This will resolved the issue.

Timepicker that removes times as they're selected (ajax)

I'm building a booking form for a moving business that uses a calendar combined with a start and end time. I built the timepicker with Formidable Pro, and it allows me to check "unique" on time fields which automatically removes them on the selected date. However it doesn't automatically remove the times from within the range between start and end times (ie: if someone chooses to rent a truck from 1am-3am I need 1am,2am,and 3am to be removed from future options but right now it only removes 1am and 3am) . I need to write ajax to remove the in-between times from the options. I'm not sure where to begin. This is the current ajax_time_ options function. Any push in the right direction would be appreciated.
function ajax_time_options(){
global $frmpro_settings, $frmdb, $wpdb;
//posted vars = $time_field, $date_field, $step, $start, $end, $date, $clock
extract($_POST);
$time_key = str_replace('field_', '', $time_field);
$date_key = str_replace('field_', '', $date_field);
if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', trim($date)))
$date = FrmProAppHelper::convert_date($date, $frmpro_settings->date_format, 'Y-m-d');
$date_entries = FrmEntryMeta::getEntryIds("fi.field_key='$date_key' and meta_value='$date'");
$opts = array('' => '');
$time = strtotime($start);
$end = strtotime($end);
$step = explode(':', $step);
$step = (isset($step[1])) ? ($step[0] * 3600 + $step[1] * 60) : ($step[0] * 60);
$format = ($clock) ? 'H:i' : 'h:i A';
while($time <= $end){
$opts[date($format, $time)] = date($format, $time);
$time += $step;
}
if($date_entries and !empty($date_entries)){
$used_times = $wpdb->get_col("SELECT meta_value FROM $frmdb->entry_metas it LEFT JOIN $frmdb->fields fi ON (it.field_id = fi.id) WHERE fi.field_key='$time_key' and it.item_id in (". implode(',', $date_entries).")");
if($used_times and !empty($used_times)){
$number_allowed = apply_filters('frm_allowed_time_count', 1, $time_key, $date_key);
$count = array();
foreach($used_times as $used){
if(!isset($opts[$used]))
continue;
if(!isset($count[$used]))
$count[$used] = 0;
$count[$used]++;
if((int)$count[$used] >= $number_allowed)
unset($opts[$used]);
}
unset($count);
}
}
echo json_encode($opts);
die();
}

Magento grouped products label question

I have tier pricing setup for one of my products in Magento. Is there any way to change the "Buy 2 for $321.60 each" to "Buy 2-4 for $321.60 each" and "Buy 5+ for $205.52 each"? It won't always be these numbers (could be "Buy 3-4" or something).
The display logic for tier prices is located in app/design/frontend/watercare/default/template/catalog/product/view/tierprices.phtml
Replace the last else block with:
<?php
$_format = 'Buy %1$s for %2$s each';
if($index === count($_tierPrices) - 1)
{
$_format = 'Buy %1$s+ for %2$s each';
}
else
{
$_next = $_tierPrices[$index + 1];
$_qty = $_next['price_qty'] - 1;
if($_qty > 0) $_format = 'Buy %1$s-' . $_qty . ' for %2$s each';
}
echo $this->__($_format, $_price['price_qty'], $_price['formated_price']);
?>
This will make sure that the last tier price will always be {num}+ and the ones before it will be
2 - {num - 1}.
a quick fix to the code above (It wasn't working correctly for me in 1.7.0.2)
$_qty would stay the same for all the tiers a fix would be.
<?php
$_format = 'Buy %1$s for %2$s each';
if($index === count($_tierPrices) - 1)
{
$_format = 'Buy %1$s+ for %2$s each';
}
else
{
$i = $i + 1;
$_next = $_tierPrices[$index + $i];
$_qty = $_next['price_qty'] -1;
if($_qty > 0) $_format = 'Buy %1$s-' . $_qty . ' for %2$s each';
}
echo $this->__($_format, $_price['price_qty'], $_price['formated_price']);
?>

Resources