I'm having some troubles figuring out how to change the order of the totals in the transactional email templates (In Magento).
Basicly I want the 'Tax' row to be at the very bottom - below 'Grand total incl. tax'.
I know that this is the code, that prints the rows. But I can't seem to figure out how to change the order of the rows.
<?php foreach ($this->getTotals() as $_code => $_total): ?>
<?php if ($_total->getBlockName()): ?>
<?php echo $this->getChildHtml($_total->getBlockName(), false); ?>
<?php else:?>
<tr class="<?php echo $_code?>">
<td <?php echo $this->getLabelProperties()?>>
<?php if ($_total->getStrong()):?>
<?php echo $this->escapeHtml($_total->getLabel());?>
<?php else:?>
<?php echo $this->escapeHtml($_total->getLabel());?>
<?php endif?>
</td>
<td <?php echo $this->getValueProperties()?>>
<?php if ($_total->getStrong()):?>
<?php echo $this->formatValue($_total) ?>
<?php else:?>
<?php echo $this->formatValue($_total) ?>
<?php endif?>
</td>
</tr>
<?php endif?>
Could anyone be of help with this problem?
Thanks and have a wonderful day!
Method 1: Modifying the theme template file.
Copy app/design/frontend/base/sales/order/totals.phtml to your theme file and open it.
Add the following to the top of it.
if($tax = $this->getTotal('tax'))
{
$this->removeTotal('tax');
$this->addTotal($tax, 'grand_total');
}
This code will remove the tax from the totals list, then re-add it below the Grand Total. You should move the totals.phtml file into your custom theme folder so upgrades won't override it.
Method 2: Overriding the core block file.
You can do the same patch by overriding the core Totals block by doing the following:
Copy app/code/core/Mage/Sales/Block/Order/Totals.php to app/code/local/Mage/Sales/Block/Order/Totals.php
Open app/code/local/Mage/Sales/Block/Order/Totals.php and change the getTotals() function to the following:
public function getTotals($area=null)
{
//Move tax below grand_total
if($tax = $this->getTotal('tax'))
{
$this->removeTotal('tax');
$this->addTotal($tax, 'grand_total');
}
$totals = array();
if ($area === null) {
$totals = $this->_totals;
} else {
$area = (string)$area;
foreach ($this->_totals as $total) {
$totalArea = (string) $total->getArea();
if ($totalArea == $area) {
$totals[] = $total;
}
}
}
return $totals;
}
Related
I have a category with simple two-level structure like this:
Category #1
- Subcategory
- Subcategory
- ...
Category #2
- Subcategory
- Subcategory
- ...
Currently to filter by subcategories - you have to select top-level category first.
How to show subcategories of all top-level categories in layered navigation filter?
Note: Subcategories should by effected by other selected attribute filter.
While experimenting with Magento files I've found the answer to my question.
Copy app/code/core/Mage/Catalog/Model/Layer/Filter/Category.php to app/code/local/Mage/Catalog/Model/Layer/Filter/Category.php
Open copied file. And replace _getItemsData with code below:
/**
* Get data array for building category filter items
*
* #return array
*/
protected function _getItemsData()
{
$key = $this->getLayer()->getStateKey().'_SUBCATEGORIES';
$data = $this->getLayer()->getAggregator()->getCacheData($key);
if ($data === null) {
// Get root category
$root_category = Mage::getModel('catalog/category')->load(2);
// Get main categories
$data = array();
$main_categories = $root_category->getChildrenCategories();
foreach ($main_categories as $main_category) {
if (!$main_category->getIsActive()) continue; // Ommit inactive
// Get sub categories to list
$sub_categories = $main_category->getChildrenCategories();
// Add count to subcategories
$this->getLayer()->getProductCollection()
->addCountToCategories($sub_categories);
foreach ($sub_categories as $sub_category) {
// Ommit inactive and zero product count sub categories
if ($sub_category->getIsActive() || !$sub_category->getProductCount()) continue;
// Output subcategories
$data[] = array(
'label' => Mage::helper('core')->htmlEscape($sub_category->getName()),
'value' => $sub_category->getId(),
'count' => $sub_category->getProductCount(),
'parent' => $main_category->getName(), // Store parent name to group in template
);
}
}
$tags = $this->getLayer()->getStateTags();
$this->getLayer()->getAggregator()->saveCacheData($data, $key, $tags);
}
return $data;
}
You might be interested in rewriting some other functions such as getResetValue, etc.
I had to rewrite template to group subcategories by main categories.
Result (sorry cant post images directly):
Before:
http://i.stack.imgur.com/skZpi.png
After:
http://i.stack.imgur.com/QxPhq.png
you can use the below code to show all subcategories of a current category in your sidebar or wherever
<?php $_helper = Mage::helper('catalog/category') ?>
<?php $_categories = $_helper->getStoreCategories() ?>
<?php $currentCategory = Mage::registry('current_category') ?>
<?php if (count($_categories) > 0): ?>
<ul>
<?php foreach($_categories as $_category): ?>
<li>
<a href="<?php echo $_helper->getCategoryUrl($_category) ?>">
<?php echo $_category->getName() ?>
</a>
<?php $_category = Mage::getModel('catalog/category')->load($_category->getId()) ?>
<?php $_subcategories = $_category->getChildrenCategories() ?>
<?php if (count($_subcategories) > 0): ?>
<ul>
<?php foreach($_subcategories as $_subcategory): ?>
<li>
<a href="<?php echo $_helper->getCategoryUrl($_subcategory) ?>">
<?php echo $_subcategory->getName() ?>
</a>
</li>
<?php endforeach; ?>
</ul>
<?php endif; ?>
</li>
<?php endforeach; ?>
</ul>
<?php endif; ?>
Whenever I search a product using the search box, on the left side there is a filter by category. The code that creates this filter is this one:
<dl id="narrow-by-list">
<?php $_filters = $this->getFilters() ?>
<?php foreach ($_filters as $_filter): ?>
<?php if($_filter->getItemsCount()): ?>
<?php if($_filter->getName() != "Category"){ ?>
<dt><?php echo $this->__($_filter->getName()) ?></dt>
<dd>
<?php echo $_filter->getHtml() ?>
</dd>
<?php } endif; ?>
<?php endforeach; ?>
</dl>
This shows only the main category in the filter, and I'd like to show its subcategories. I tried to set another category programmatically with this code:
<?php
$layer = Mage::getSingleton('catalog/layer');
$_categ = Mage::getModel('catalog/category')->load(5);
$layer->setCurrentCategory($_categ);
?>
... but nothing changed. Any thoughts?
When you try to set the other category on the layer singleton from a template, it's too late as all the treatments were already applied.
What you can do is to copy the file app/code/core/Mage/CatalogSearch/Model/Layer.php into app/code/local/Mage/CatalogSearch/Model/ and to add a modified version of the base Mage_Catalog_Model_Layer::getCurrentCategory() method, looking like this :
public function getCurrentCategory()
{
$category = $this->getData('current_category');
if (is_null($category)) {
if ($category = Mage::registry('current_category')) {
$this->setData('current_category', $category);
}
else {
$category = Mage::getModel('catalog/category')->load(5); // Put here the ID of the category you want to use as basis for category filtering
$this->setData('current_category', $category);
}
}
return $category;
}
How can I get a specific category level from Magento, my category setup looks like this now.
root_catalog
|-Shop
|-Shoes
|-T-shirts
|-Brands
|-Nike
|-Womens
|-Mens
|-Adidas
|-Asics
<?php if( $category = Mage::getModel('catalog/category')->load( $categories[1]) ): ?>
<?php echo $category->getName(); ?>
<?php endif ?>
When calling $category->getName(); I would like to only display the Brand Name, is that possible?
You can get category level from
$category = Mage::getModel('catalog/category')->load( $categories[1]) )->getLevel()
and then check with your brand name category level, if match then display name.
e.g. suppose brand category level is 3
<?php if( $category = Mage::getModel('catalog/category')->load( $categories[1]) ): ?>
<?php if($category->getLevel() == 3)
echo $category->getName(); ?>
<?php endif ?>
<?php endif ?>
ANKIT's answer is good, but it could be improved by actually query-ing the specific levels instead of loading the whole collection and doing a conditional. Take for example if you want to get all categories in a specific level:
<ul>
<?php $categories = Mage::getModel('catalog/category')
->getCollection()
// magic is prepared here..
->addAttributeToSelect('*')
// then the magic happens here:
->addAttributeToFilter('level', array('eq'=>2))
->load();
foreach($categories as $category):
?>
<li>$category->getName()</li>
<?php endforeach; ?>
</ul>
<?php
$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$product = $objectManager->get('Magento\Framework\Registry')->registry('current_product');
$categories = $product->getCategoryIds(); /*will return category ids array*/
foreach($categories as $category){
$cat = $objectManager->create('Magento\Catalog\Model\Category')->load($category);
if ($cat->getLevel() == 2) {
$catName = $cat->getName().","; ?>
<div class="brand_bg">
<label><?php /* #escapeNotVerified */ echo __('Category :') ?></label>
<?php echo $catName; ?>
</div>
<?php } ?>
<?php } ?>
?>
I created Attribute Sets with more Grouped attributes inside. In admin, the custom attributes are displayed in groups (tabs) like I created them. But, on the product page, all the attributes are listed together, without displaying the Attribute Group Name before listing the Attributes in that Group.
How can I display also the Attribute Group names, not only the attributes? If you could show me on the default template, I will do it accordingly in my custom template.
Thank you!
Ok, I found an answer and I hope it will be useful to others in search for the same thing.
First, I'm using Magento 1.5.0.
Second, I found the answer in German here, with an extension already created, but the installation failed.
So, I added /app/code/local/Mage/Catalog/Block/Product/View/Attributesgroups.php with the following code:
<?php
class Mage_Catalog_Block_Product_View_Attributesgroups extends Mage_Core_Block_Template
{
protected $_product = null;
function getProduct()
{
if (!$this->_product) {
$this->_product = Mage::registry('product');
}
return $this->_product;
}
public function getAdditionalData(array $excludeAttr = array())
{
$data = array();
$product = $this->getProduct();
$attributes = $product->getAttributes();
foreach ($attributes as $attribute) {
if ($attribute->getIsVisibleOnFront() && !in_array($attribute->getAttributeCode(), $excludeAttr)) {
$value = $attribute->getFrontend()->getValue($product);
// TODO this is temporary skipping eco taxes
if (is_string($value)) {
if (strlen($value) && $product->hasData($attribute->getAttributeCode())) {
if ($attribute->getFrontendInput() == 'price') {
$value = Mage::app()->getStore()->convertPrice($value,true);
} elseif (!$attribute->getIsHtmlAllowedOnFront()) {
$value = $this->htmlEscape($value);
}
$group = 0;
if( $tmp = $attribute->getData('attribute_group_id') ) {
$group = $tmp;
}
$data[$group]['items'][ $attribute->getAttributeCode()] = array(
'label' => $attribute->getFrontend()->getLabel(),
'value' => $value,
'code' => $attribute->getAttributeCode()
);
$data[$group]['attrid'] = $attribute->getId();
}
}
}
}
// Noch Titel lesen
foreach( $data AS $groupId => &$group ) {
$groupModel = Mage::getModel('eav/entity_attribute_group')->load( $groupId );
$group['title'] = $groupModel->getAttributeGroupName();
}
return $data;
}
}
Then, I created the /app/design/frontend/default/YOUR_TEMPLATE/template/catalog/product/view/attributesgroups.phtml file with the following content:
<?php
$_helper = $this->helper('catalog/output');
$_product = $this->getProduct()
?>
<?php if($_additionalgroup = $this->getAdditionalData()): ?>
<div class="box-collateral box-additional">
<h2><?php echo $this->__('Additional Information') ?></h2>
<?php $i=0; foreach ($_additionalgroup as $_additional): $i++; ?>
<h3><?php echo $this->__( $_additional['title'] )?></h3>
<table class="data-table" id="product-attribute-specs-table-<?php echo $i?>">
<col width="25%" />
<col />
<tbody>
<?php foreach ($_additional['items'] as $_data): ?>
<tr>
<th class="label"><?php echo $this->htmlEscape($this->__($_data['label'])) ?></th>
<td class="data"><?php echo $_helper->productAttribute($_product, $_data['value'], $_data['code']) ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<script type="text/javascript">decorateTable('product-attribute-specs-table-<?php echo $i?>')</script>
<?php endforeach; ?>
</div>
<?php endif;?>
Last step was to modify /app/design/frontend/default/YOUR_TEMPLATE/layout/catalog.xml in line 223, and replaced
<block type="catalog/product_view_attributes" name="product.attributes" as="additional" template="catalog/product/view/attributes.phtml">
with
<block type="catalog/product_view_attributesgroups" name="product.attributes" as="additional" template="catalog/product/view/attributesgroups.phtml">
I repeat, this answer does NOT belong to me, I just translated what I found. Many thanks to the beautiful people who ended my three days of search with a clean and simple answer: WebGuys.DE
Also, thanks to #rpSetzer who cared to help!
Iterate through all the attributes and create an array of groups. In each group you put the attributes that belong to it. Then it's simple to display them the way you wanted.
Here is an implementation that is very close to what you need.
Thanks for translation : additionnal information for those who may need :
For 1st step, if the folder /app/code/local/Mage/Catalog/Block/Product/View/ doesn't exist, create it ! with correct persmissions and place the file Attributesgroups.php there
If you have different store views (for different languages), and you want to use correct translation for each attribute label, here is want you need to do :
In the file Attributesgroups.php
Replace 'label' => $attribute->getFrontend()->getLabel(), with'label' => $attribute->getStoreLabel(),
Similar to the question asked at:
Magento - Show Custom Attributes in Grouped Product table
I'd like to display attributes of simple products in the grouped product page.
However, I need it to work such that you do not explicitly specify which attributes get displayed. Instead, it displays all the attributes that would get displayed on the simple product view of that product.
I've tried variations of:
(from /template/catalog/product/view/type/grouped.phtml)
<?php foreach ($_associatedProducts as $_item): ?>
<tr>
<td><?php echo $this->htmlEscape($_item->getName()) ?></td>
<!-- important problem part -->
<?php foreach ($_item->getAttributes() as $arr): ?>
<td><?php echo $arr->getData() ?></td>
<?php endforeach; ?>
<!-- end of problem part -->
<td class="a-right">
<?php echo $this->getPriceHtml($_item, true) ?>
</td>
<?php if ($_product->isSaleable()): ?>
<td class="a-center">
<?php if ($_item->isSaleable()) : ?>
View
<?php else: ?>
<p class="availability"><span class="out-of-stock"><?php echo $this->__('Out of stock.') ?></span></p>
<?php endif; ?>
</td>
<?php endif; ?>
</tr>
<?php endforeach; ?>
And other variations, however, I cannot limit the attributes being displayed to just the ones I need (i.e. just the additional attributes displayed on the simple product view; those set as Viewable on Frontend). Any ideas?
The class Mage_Catalog_Block_Product_View_Attributes method getAdditionalData() should point you toward how to limit the variables to only those that are selected as Viewable on Frontend. Its getAdditionalData method is referenced in the product view block.
The steps to solving this would be the following:
1. Create a new Magento module with the intent to override the grouped product block.
2. Create the new grouped product block, stealing liberally from the getAdditionalData() method of Mage_Catalog_Block_Product_View_Attributes.
3. Create a new template based on /template/catalog/product/view/type/grouped.phtml to back your custom block.
4. Override the block in your module's config.xml (see: Overriding catalog/breadcrumbs and catalog/products/view, Magento forums)
This has the consequence that all your grouped products in the catalog will behave this way. If you need to be more selective, then I think a reasonable thing to do would be to add a custom attribute to catalog products (preferably set up in the custom module you just created!) in order to toggle the behavior, and program a check for that toggle into your template.
Add after $_product = $this->getProduct();
/* CODE TO GET ATTRIBUTES */
$gridattributes = array();
$attributes = $_product->getAttributes();
foreach ($attributes as $attribute) {
if ($attribute->getIsVisibleOnFront() && !in_array($attribute->getAttributeCode(), $excludeAttr)) {
$value = $attribute->getFrontend()->getValue($_product);
if (!$_product->hasData($attribute->getAttributeCode())) {
$value = Mage::helper('catalog')->__('N/A');
} elseif ((string)$value == '') {
$value = Mage::helper('catalog')->__('No');
} elseif ($attribute->getFrontendInput() == 'price' && is_string($value)) {
$value = Mage::app()->getStore()->convertPrice($value, true);
}
if (is_string($value) && strlen($value)) {
$gridattributes[$attribute->getAttributeCode()] = array(
'label' => $attribute->getStoreLabel(),
'value' => $value,
'code' => $attribute->getAttributeCode()
);
}
}
}
?>
Add after <th><?php echo $this->__('Product Name') ?></th>:
foreach($gridattributes as $attrib){
echo '<th>'.$this->htmlEscape($attrib[label]).'</th>';
}
Add after <td><?php echo $this->htmlEscape($_item->getName()) ?></td>:
foreach($gridattributes as $attribname=>$attribval){
echo '<td>'.$this->htmlEscape($_item->getData($attribname)).'</td>';
}