adding quantity to related products in magento backend - php

I'm new to magento and trying to add quantity column to the grid in related products tab (edit product -> related products).
this is what I did:
overwrite related.php file:
Mage\Adminhtml\Block\Catalog\Product\Edit\Tab\Related.php
added to _prepareCollection() method this code:
$collection->joinField(
'qty',
'cataloginventory_stock_item',
'qty',
'product_id = entity_id',
'{{table}}.stock_id = 1',
'left'
);
and added to _prepareColumns() methods this code:
$this->addColumn('qty',
array(
'header' => Mage::helper('catalog')->__('QTY'),
'width' => 80,
'index' => 'qty'
Now I can see the new column but the quantity is float number (for example 100.00) and I can't filter results based on my new QTY column.
My questions:
is that all I need to add column or I have to do some thing else??
how to display QTY in integer format (for example 100 not 100.00)??
why I can't filter results based on the QTY??
any idea will be appreciated, Thanks in advance..

Quantity as integer format
'getter' => array($this, 'getFormattedQty')
public function getFormattedQty($row)
{
return intVal($row->getQtyOrdered());
}

To cover the three questions simply add the 'type' option with the value set to 'number' in the to _prepareColumns() method. Example Below:
$this->addColumn('qty', array(
'header' => Mage::helper('catalog')->__('QTY'),
'type' => 'number',
'width' => 80,
'index' => 'qty'
));
This will set the value as a whole number or integer rather than a float and will let you filter for a particular range.
I have used this myself to add the QTY to the Associated Products grid.

Related

Configurable product created programmatically doesn't show in search - Magento 1.9

I have a script that creates a configurable product and the simple products associated to it. After the creation, in the backend, all of them seems fine (stock, website, status, visibility and association between the simple products and the configurable are ok). The problem is when I try to search for the configurable product or add it to a category, it doesn't display.
All products (configurable and simple) are firstly created with this method:
private function createBaseProduct($sku)
{
$_product = Mage::getModel('catalog/product');
$_product->setSku($sku);
$_product->setAttributeSetId(4);
$_product->setTypeId('simple');
$_product->setWebsiteIDs(array(1));
$_product->setVisibility(Mage_Catalog_Model_Product_Visibility::VISIBILITY_BOTH);
$_product->setStatus(1);
$_product->setTaxClassId(0);
$_product->setStockData(array(
'use_config_manage_stock' => 0,
'manage_stock' => 1,
'is_in_stock' => 1,
'qty' => 100
));
return $_product;
}
In case the product is configurable, it then goes to this method:
private function setData($configurable)
{
$configurable->setTypeId('configurable');
$configurable->setStockData(array(
'use_config_manage_stock' => 0,
'manage_stock' => 0,
'is_in_stock' => 1,
'qty' => 0,
));
--> $configurable = $this->setAssociativeAttributes($configurable);
$configurableAttributesData = $configurable->getTypeInstance()->getConfigurableAttributesAsArray();
$configurable->setCanSaveConfigurableAttributes(true);
$configurable->setConfigurableAttributesData($configurableAttributesData);
return $configurable;
}
Where the method setAssociateAttributes() set the attributes IDs of the configurable product being created:
private function setAssociativeAttributes()
{
$configurable->getTypeInstance()->setUsedProductAttributeIds($this->configurableAttrsIds);
return $configurable;
}
After that, the configurable product returned in setData() is saved using $product->save(). Then, the simple product's are created (using the createBaseProduct() method), saved, and assigned to the configurable product using this method:
public function associateChildProduct($configurableId, $childProduct)
{
$configurable = Mage::getModel('catalog/product')->load($configurableId);
$childProducts = $configurable->getTypeInstance()->getUsedProducts();
array_push($childProducts, $childProduct);
$childProductsIds = array();
foreach($childProducts as $product) {
array_push($childProductsIds, $product->getId());
}
Mage::getResourceSingleton('catalog/product_type_configurable')
->saveProducts($configurable, $childProductsIds);
}
And all seems good, products are created and correctly assigned to configurable. But in the frontend the configurable product isn't displayed (only if I access it via URL it opens correctly, with the variations and all).
Obs.: simple products are displayed in search correctly, only the configurable is missing.
I believe there's something wrong in the configurable's data, but I can't figure it out :(
----- EDIT -----
So I debugged it a little more and seems that the problem is actually in the attribute used to create the configurable product (I'm also creating this attribute programmatically). If I save the attribute created programatically again, in my admin panel, the link between simple products and their configurable disapear (they don't show linked in the admin panel anymore).The attribute is created before the configurable product using class "CustomAttribute":
public function __construct($attrCode)
{
$attrData = array(
'group' => '',
'type' => 'varchar',
'backend' => '',
'frontend' => '',
'label' => ucfirst($attrCode),
'input' => 'select',
'class' => '',
'source' => '',
'global' => Mage_Catalog_Model_Resource_Eav_Attribute::SCOPE_GLOBAL,
'visible' => true,
'required' => false,
'user_defined' => true,
'default' => '0',
'searchable' => false,
'filterable' => false,
'comparable' => false,
'visible_on_front' => false,
'is_configurable' => true,
'unique' => false,
);
$installer = new Mage_Eav_Model_Entity_Setup('core_setup');
$installer->startSetup();
$installer->addAttribute(Mage_Catalog_Model_Product::ENTITY, $attrCode, $attributeData);
$this->addAttributeToDefaultSet();
$installer->endSetup();
}
And this attribute is set to child products (during their creation) using the following method:
private function setCustomAttribute($chidlProduct, $attrCode, $optionLabel)
{
$customAttribute = new CustomAttribute($attrCode);
$customAttribute->addOptionIfNotExists($optionLabel, $attrCode);
$optionId = $customAttribute->getOptionId($optionLabel);
$product->setData($attrCode, $optionId);
}
Where the method $customAttribute->addOptionIfNotExists() creates the attribute's option if not already created:
public function addOptionIfNotExists($optionLabel, $attrCode)
{
$value['option'] = array($optionLabel);
$order['option'] = 0;
$optionData = array(
'value' => $value,
'order' => $order
);
$attribute = Mage::getSingleton('eav/config')
->getAttribute(Mage_Catalog_Model_Product::ENTITY, $attrCode);
$attribute->setData('option', $optionData);
$attribute->save();
}
And after added the method associateChildProduct() is called to associate simple products to their configurable.
Obs.: configurable product is displayed correctly via URL, even the attribute variations are shown.
Obs2.: if I save the attribute via admin panel, delete simple products and create new ones using "Quick create" (with the same values) the configurable product is displayed in search and categories.
Just to put my comments in form of an answer, and organize it...
There are many reasons for a recently created product or one created programmatically to not being displayed in some collection.
Index
The first and most common one is related to indexation.
This could be related to issues in the cronjob (not configured, or not working properly).
You can manually trigger the reindex process by doing:
Magento 1: php shell/indexer.php reindexall
Magento 2: bin/magento indexer:reindex
Product not added to the website or not visible
Check if the product is enabled and visible in catalog. If they are simple products from a configurable product, make sure they are both enabled.
Also check if there is enough inventory of the item and if they are not marked as "out of inventory" (regardless the stock qty).
In multi website stores, check the "Website" group in the product edit page, and see if it's checked to appear in that website. Also check the product scope. Sometimes you disable the product in a inner level (i.e. store view or website).
Some condition is not met
If you believe that you've checked everything, now it's time to debug the collection.
Magento 1 and Magento 2 have the getSelect() method available in collection objects.
Find the phtml or block where your products are being looped, and find the collection variable (generally used in the foreach).
Then, add something like echo (string)$collection->getSelect().
This will show the query used to search the products. See which join or where condition is not met by your missing product.
Here's an example of category collection queries in Magento 1:
SELECT `e`.*,
`cat_index`.`position` AS `cat_index_position`,
`price_index`.`price`,
`price_index`.`tax_class_id`,
`price_index`.`final_price`,
IF(price_index.tier_price IS NOT NULL, LEAST(price_index.min_price, price_index.tier_price),
price_index.min_price) AS `minimal_price`,
`price_index`.`min_price`,
`price_index`.`max_price`,
`price_index`.`tier_price`
FROM `catalog_product_entity` AS `e`
INNER JOIN `catalog_category_product_index` AS `cat_index`
ON cat_index.product_id = e.entity_id AND cat_index.store_id = 4 AND
cat_index.visibility IN (2, 4) AND cat_index.category_id = '10'
INNER JOIN `catalog_product_index_price` AS `price_index`
ON price_index.entity_id = e.entity_id AND price_index.website_id = '4' AND
price_index.customer_group_id = 0
ORDER BY `cat_index`.`position` ASC
LIMIT 12
1 'New Arrivals' category from Magento 1 sample data.
With Ricardo Martins help I was able to debug the problem and discover that the configurable product wasn't being displayed because it's entity_id wasn't being added to the table catalog_product_index_price. This problem seems to be caused because the attribute used in the configurable product's creation had the backend_type set to varchar, instead int (Reference).
So I changed my code for attribute's creation to:
public function __construct($attrCode)
{
$attrData = array(
'group' => '',
--> 'type' => 'int',
'backend' => '',
'frontend' => '',
'label' => ucfirst($attrCode),
'input' => 'select',
'class' => '',
'source' => '',
'global' => Mage_Catalog_Model_Resource_Eav_Attribute::SCOPE_GLOBAL,
'visible' => true,
'required' => false,
'user_defined' => true,
'default' => '0',
'searchable' => false,
'filterable' => false,
'comparable' => false,
'visible_on_front' => false,
'is_configurable' => true,
'unique' => false,
);
$installer = new Mage_Eav_Model_Entity_Setup('core_setup');
$installer->startSetup();
$installer->addAttribute(Mage_Catalog_Model_Product::ENTITY, $attrCode, $attributeData);
$this->addAttributeToDefaultSet();
$installer->endSetup();
}
Where in the indicated line the attribute's backend_type is set to int. After this, the configurable product is now being correctly displayed in category and search :)

WooCommerce custom child products to variable products

I have some variable products (different 3-4 variations) with different prices. I want to add some simple products as child products (show as optional checkbox in front). I don't know how to manage that for adding to the cart.
For example let's assume I have a cellphone as main product and when user added it to it's cart it should see 3 sub product (child product) :
Handsfree (in three type of color)
Glass guard (in two type of color )
cell phone shield case ( just black)
as you can understand from above example I wanna to:
add all of this items as one product (includes handsfree, glass guard , cellphone case and cellphone itself ) and calculate it's price .I've read Add a checkbox on single product pages that adds an additional cost in Woocommerce and after that I have codes below to adding options in product edit page.
//custom product tab to woocommerce edit
function sm_wccpd_custom_product_tabs($tabs)
{
$tabs['sm_wcpa_extra_products'] = array(
'label' => __('Samanik Extra Products', 'sm-wcpa'),
'target' => 'sm_wc_extra_products_options',
'class' => array('show_if_variable'),
);
return $tabs;
}
add_filter('woocommerce_product_data_tabs', 'sm_wccpd_custom_product_tabs');
and here is tab content
function extra_products_options_product_tab_content()
{
global $post;
// Note the 'id' attribute needs to match the 'target' parameter set above
?>
<div id='sm_wc_extra_products_options' class='panel woocommerce_options_panel'><?php
?>
<div class='options_group'><?php
woocommerce_wp_checkbox(
[
'id' => '_has_extra_products',
'label' => __('has extra products', 'sm-wcpa'),
]);
woocommerce_wp_select(
[
'class' => 'multiselect attribute_values wc-enhanced-select',
'custom_attributes' => ['multiple' => 'multiple', 'style' => 'width:100% !importan;'],
'id' => '_sm_wcpa_product[]',
'label' => __('Extra Products to be add here', 'sm-wcpa'),
'value' => array_values(json_decode(get_post_meta($post->ID, '_sm_wcpa_product'), true)),
'options' => sm_wcpa_get_products_as_options(),//this is function that I pass Products as array like [product_id => product name]
]);
?></div>
</div><?php
}
// add_filter('woocommerce_product_data_tabs', 'extra_products_options_product_tab_content'); // WC 2.5 and below
add_filter('woocommerce_product_data_panels', 'extra_products_options_product_tab_content'); // WC 2.6 and up
also I can save the data and I think they are not necessary here.
now what I need to do is how to manage this in front. I mean show child products as checkbox, add price to parent price if checked, what about changing variables(those have different prices).
thanks for your patient to read my question.

How do i add status column in product grid section in manage category in magento?

How can i add status column in product grid in manage categories section? I want to add status column next to SKU.
Catalog / Manage Categories / select any category and you can able to see the mapped products under "category products". There i want to add status column.
Thanks in advance.
You can copy this file app/code/core/Mage/Adminhtml/Block/Catalog/Category/Tab/Product.php to your local folder or directly in app/code/core/Mage/Adminhtml/Block/Catalog/Category/Tab/Product.php
Line 79, just before ->addAttributeToSelect('price'),
add this code: ->addAttributeToSelect('status')
Line 128, just before $this->addColumn('price', array(, add this code:
$this->addColumn('status',
array(
'header'=> Mage::helper('catalog')->__('Status'),
'width' => '70px',
'index' => 'status',
'type' => 'options',
'options' => Mage::getSingleton('catalog/product_status')->getOptionArray(),
));
Run Compilation again if it is enabled. Refresh your page, you'll see "Status" column next to the SKU column

Company Name Column for Order Grid

I am working on Magento 1.8.1 with a theme incorporated. Multiple extensions involved as well and most are completely customized.
I have been trying to get the company name to appear on the Sales Order Grid for some time now and have had some luck.
First off, I have copied /core/Mage/Adminhtml/Block/Sales/Order/Grid.php to /local/Mage/Adminhtml/Block/Sales/Order/Grid.php.
Then I updated the code in _prepareCollection() to this:
protected function _prepareCollection()
{
$collection = Mage::getResourceModel($this->_getCollectionClass());
$collection->getSelect()->join(
array('addressTable' => 'sales_flat_order_address'),'main_table.entity_id = addressTable.parent_id AND addressTable.address_type = "billing"',array('billing_company'=>'company'));
$this->setCollection($collection);
return parent::_prepareCollection();
}
While adding the following to _prepareColumns:
$this->addColumn('company', array(
'header' => Mage::helper('sales')->__('Bill to Company'),
'index' => 'billing_company',
));
Everything is working like it should until I decided it would be really nice to have the Ship to Company as well since most of our customers buy for other companies.
To accomplish this I added the column with no problem just like I did previously:
$this->addColumn('company', array(
'header' => Mage::helper('sales')->__('Ship to Company'),
'index' => 'shipping_company',
));
The column added with no problem except it was not in the place I put it (before shipping_name), This was just adding the column no data yet.
Now to add the data, I would add another collection under _prepareCollection since the shipping information is on a different row compared to billing in the table, like this:
$collection->getSelect()->join(
array('addressTable' => 'sales_flat_order_address'),'main_table.entity_id = addressTable.parent_id AND addressTable.address_type = "shipping"',array('shipping_company'=>'company'));
But when I try this I get an error:
You cannot define a correlation name 'addressTable' more than once
I get quite a bit of conflict between the two columns as well. For instance, when I do not have the Ship to Company commented under _prepareColumns it shows the Ship to Company column where the Bill to Company column should be. There is also no data in the column. As soon as I comment Ship to Company Bill to Company appears and has the correct data.
Basically, I just need to get the Ship to Company Column to show up as well as the Bill to Company Column. Preferably next to the appropriate Name.
I have already added the Company Column to the Customer Grid and Create New Order Customer Grid with no problem as well.
Okay so my edit above was not exactly correct. The columns show up and populate just fine but after trying to search the field I was receiving an error. So after more research, I found this solution: Using column aliases in Sales Order Grid field
The answer to this question works perfect just had to change a few minor things. I attached my code below just in case someone else is looking for this solution.
protected function _prepareCollection()
{
$collection = Mage::getResourceModel($this->_getCollectionClass());
$collection->getSelect()->join(array('address_billing' => $collection->getTable("sales/order_address")),'main_table.entity_id = address_billing.parent_id AND address_billing.address_type = "billing"',array('address_billing.company as billing_company'));
$collection->getSelect()->join(array('address_shipping' => $collection->getTable("sales/order_address")),'main_table.entity_id = address_shipping.parent_id AND address_shipping.address_type = "shipping"',array('address_shipping.company as shipping_company'));
$this->setCollection($collection);
return parent::_prepareCollection();
}
Under _prepareColumns() change to this:
$this->addColumn('company', array(
'header' => Mage::helper('sales')->__('Bill to Company'),
'index' => 'billing_company',
'filter_index' => 'address_billing.company',
));
$this->addColumnAfter('shipping_company', array(
'header' => Mage::helper('sales')->__('Ship to Company'),
'index' => 'shipping_company',
'filter_index' => 'address_shipping.company',
),
'billing_name'
);
Remember I had to use the addColumnAfter function to get my shipping company column placed in the right spot.
With this fix everything is finally working the way I want it to!
Happy coding!
modify code is
protected function _prepareCollection()
{
$collection = Mage::getResourceModel($this->_getCollectionClass());
$collection->getSelect()->join(array('billing'=>'sales_flat_order_address'),'main_table.entity_id=billing.parent_id and billing.address_type="billing"',array('*'));
$collection->getSelect()->join(array('shipping'=>'sales_flat_order_address'),'main_table.entity_id=shipping.parent_id and shipping.address_type="shipping"',array('shipping.company as shipping_company'));
$this->setCollection($collection);
parent::_prepareCollection();
return Mage_Adminhtml_Block_Widget_Grid::_prepareCollection();
}
And add columns in _prepareColumns()
$this->addColumn('company', array(
'header' => Mage::helper('sales')->__(' Billing company'),
'index' => 'company',
'filter_index' => 'billing.company',
));
$this->addColumn('shipping_company', array(
'header' => Mage::helper('sales')->__(' Shipping company'),
'index' => 'shipping_company',
'filter_index' => 'shipping_company',
));

Magento custom reports: Get data from database

I need some help.
I created a custom report in Magento.
Now I want to list all products wich have been ordered in a month in my grid.
In my report are the following columns: SKU, Name, Ordered Quantity and Base Cost.
In the column "Ordered Quantity" I want to show how often a product has been ordered.
In the column "Base Cost" I want to show the total base costs (ordered quantity * base cost).
With the following code I get so correct product names and skus.
The other columns are not correct.
Can someone help me?
$this->getSelect()->reset()
->from(
array('order_items' => $this->getTable('sales/order_item')),
array(
'ordered_qty' => 'SUM(order_items.qty_ordered)',
'order_items_name' => 'order_items.name',
'base_cost' => 'SUM(order_items.base_cost)',
'sku' => 'order_items.sku'
))
->where("created_at BETWEEN '".$from."' AND '".$to."'")
->where('parent_item_id IS NULL')
->group('order_items.product_id')
->having('SUM(order_items.qty_ordered) > ?', 0)
->order(
array(
'SUM(order_items.qty_ordered) DESC'
));
Here is my solution:
$this->getSelect()->reset()
->from(
array('order_items' => $this->getTable('sales/order_item')),
array(
'ordered_qty' => 'order_items.qty_ordered',
'order_items_name' => 'order_items.name',
'vendor' => 'attrval.value',
'base_cost' => '(SUM(order_items.qty_ordered) * order_items.base_cost)',
'sku' => 'order_items.sku'
))
->joinLeft(array('p' => 'catalog_product_entity'), 'order_items.product_id = p.entity_id')
->joinLeft(array('eav' => 'eav_attribute'), 'p.entity_type_id = eav.entity_type_id')
->joinLeft(array('attr' =>'eav_attribute_option'), 'attr.attribute_id = eav.attribute_id')
->joinLeft(array('attrval' =>'eav_attribute_option_value'), 'attrval.option_id = attr.option_id')
->where("eav.attribute_code='vendor'")
->where("order_items.created_at BETWEEN '".$from."' AND '".$to."'")
->where('parent_item_id IS NULL')
->group('order_items.product_id')
->having('SUM(order_items.qty_ordered) > ?', 0)
->order(
array(
'SUM(order_items.qty_ordered) DESC'
));
It includes an additional custom attribute called 'vendor'.
To outputting the raw SQL query see Output raw SQL query from Magento collection
Format field, you can use price or currency
see http://code007.wordpress.com/2012/07/16/grid-column-types-in-magento/
$this->addColumn('some_column_id', array(
'header' => Mage::helper('core')->__('Some column name'),
'index' => 'some_column_index',
'type' => '???',
));
Types
action
checkbox
concat
country
currency
date
datetime
input
interface
ip
longtext
massaction
number
options
price
radio
select
store
text
theme
wrapline
See /app/code/core/Mage/Adminhtml/Block/Widget/Grid/Column/Renderer folder.
To make your own grid types see http://mydons.com/how-to-create-custom-column-renderer-in-magento-grid/.

Categories