getAllVisibleItems(), getAllItems returns items twice - magento

I'm trying to do something really simple - get the items from an order. There seem to be three functions that Magento 1.7 provides for this.
getAllItems() : This returns all items twice. The items returned
are of type simple (not configurable)
getItemsCollection() : Ditto
getAllVisibleItems() : Ditto
Many of the answers that I've read elsewhere point to this problem being caused by 'parent' and 'child' products, but there are none in my DB. I've checked the tables that define the parent/child relationship and they are both empty.
Here's the code that I'm running :
$order = Mage::getModel("sales/order")->load($order_id, 'increment_id'); //load order by order id
$ordered_items = $order->getAllVisibleItems();
//$ordered_items = $order->getAllItems();
//$ordered_items = $order->getItemsCollection();
foreach($ordered_items as $item)
{
if($this->debug)
{
echo $item->getItemId()."</br>";
echo $item->getProductId()."</br>";
echo $item->getSku()."</br>";
echo $item->getQtyOrdered()."</br>";
echo $item->getName()."</br>";
}
echo("*************************************************</br>");
}
And the output is
6
934
1003
1.0000
ProductA
*************************************************
6
934
1003
1.0000
ProductA
*************************************************
As you can see the first figure outputted is the actual entity_id - so I'm getting real duplication of the same item?

You have to use this code
$order = Mage::getModel("sales/order")->load($order_id, 'increment_id');
$_items = $order->getItemsCollection();
foreach ($_items as $item) {
if ($item->getParentItem()) continue;
//do something
echo $item->getSku();
}

Related

Advice with Magento large productsfile csv import

I need to import 40.000 products.
These products together are generating 600.000 attribute values
There is a csv file with product info (Sku, Name, Description and Ean) and a seperate sheet with only the attributes(600K)
On each row i have:
Sku - Attribute - Value
e.g.
123 Color Green
123 Length 120
123 Size XL
456 Color White
456 Length 260
etc..
I have filtered all duplicates out which resulted in 2200 unique Attributes.
What should i Do with these attributes?
Put them all in one attributeset? Will it hurt the performance of the webshop?
And what about the attributesheet?
How should i convert the structure of the presented data so it will be usefull for for import in magent? Cause magento needs all attribute names as columnheaders?
I have tried to collect teh attribute values with VLOOKUP but run into memory problems on my MACbook Pro. Fill down one column with a formula doesn't work wit this amount of records.
Maybe there is a solution programmticly.
Thanks!
I would suggest to create product pragmatically.
Import product into a mysql table (tables) and create using magento code directly.
You can create configurable attributes and use its id when creating products.
You should think about using uRapidFlow.
While I am not a huge fan of the fact that it uses direct sql to import products, it has been around for some time and is known to be very reliable and very fast.
//add new products
$product = Mage::getModel('catalog/product');
$product->setSku($sku);
$product->setStatus(1);
$product->setName($name);
$product->setDescription($details);
$product->setShortDescription($description);
$product->setPrice(0);
$product->setTypeId('simple');
$product->setAttributeSetId(4); // enter the catalog attribute set id here
$product->setCategoryIds($categoryIds); // id of categories
$product->setWeight(1.0);
$product->setTaxClassId($taxClassId);
$product->setVisibility($visibility);
$product->setStatus($productStatus);
$product->setColor('color',$color_id); // u need to get attribute code for dropdown items
$product->setData('material', $avid);
$product->setBrand($brand);
/*$product->setStockData(
array(
'manage_stock' => 1,
'is_in_stock' => 1,
'qty' => $qty
)
);*/
// assign product to the default website
$product->setWebsiteIds(array(1,2,3,4));
try{
$product->save();
$i++;
;
}catch (Exception $e) {
echo Mage::logException($e->getMessage());
}
$id = Mage::getModel('catalog/product')->getIdBySku(trim($sku)); //get product id after create
//add dropdown items for attribute u created already, u need to make this as function to get option id before add a product
$attribute_model = Mage::getModel('eav/entity_attribute');
$attribute_options_model= Mage::getModel('eav/entity_attribute_source_table') ;
$attribute_code = $attribute_model->getIdByCode('catalog_product', $attribute_code);
$attribute = $attribute_model->load($attribute_code);
$attribute_table = $attribute_options_model->setAttribute($attribute);
$options = $attribute_options_model->getAllOptions(false);
foreach($options as $option)
{
if (strtolower($option['label']) == strtolower($label))
{
$optionId=$option['value'];
break;
}
}
//u need to run thru a loop to add products

Magento: count products using stock quantity

I'm new in magento.
I'm wondering how I can count all products using stock quantity. For example, I have
category 1
product one - stock 10
product two - stock 5
category 2
product three - stock 10
The result of the sum of all products should be 25
Actually, I'm using
<?php
$prods = Mage::getModel('catalog/product')->getCollection();
Mage::getSingleton('catalog/product_visibility')->addVisibleInCatalogFilterToCollection($prods);
$count = number_format(count($prods));
echo $count;
?>
but this counts the products without stock quantity.
Thanks for your help.
Untested but this should get you what you need…
$stockItemCollection = Mage::getModel('cataloginventory/stock_item')
->getCollection();
$stockTotal = array_sum($stockItemCollection->getColumnValues('qty'));
This should work, too. The reports collection joins together all the quote_items. But I'm not sure wether any order status is considered
$collection = Mage::getResourceModel('reports/product_sold_collection');
$collection->addOrderedQty();
// EDIT reading the question is all
$sum = 0;
foreach($collection as $product) {
$sum += $product->getOrderedQty();
}
echo $sum;

how to count items in an order(when item status=Mixed) using orderid in magento?

I am trying to count total number of items in an order but I am unable to do so correctly.
I am using this code -
$total=0;
$order = Mage::getModel('sales/order')->load($oid);
$items = $order->getAllItems();
foreach($items as $item){
$qty = $item->getQtyToInvoice();
$total = $total + $qty;
}
echo "total :".$total;
This print correct result if the items status in orders is shipped but if the item status is mixed ,it prints 0 .
Are you simply looking for the number of items ordered, regardless of its shipped/invoiced/refunded status?
If so then then replace getQtyToInvoice() with getQtyOrdered().
For example:
foreach($items as $item){
$qty = $item->getQtyOrdered();
}
To answer the question in the comments: "I am also looking for the number of items shipped"
$item->getQtyShipped()

PHP - How to accomplish this if?

I am creating an order cart.
On the page that displays the cart, it checks if a value stored in the session $order corresponds with an id of a row in a mysql table. If this match exists, then the corresponding row is returned.
Within this process, I am trying to retrieve the quantity value stored in the session $quantity that corresponds to the id of the row in the table.
Each value in $order and $quantityis assigned a name, which is the id of the item they were added from.
This is the code that adds the order to the cart:
if (isset($_POST['action']) and $_POST['action'] == 'Order')
{
// Add item to the end of the $_SESSION['order'] array
$_SESSION['order'][$_POST['id']] = $_POST['id'];
$_SESSION['quantity'][$_POST['id']] = $_POST['quantity'];
header('Location: .');
exit();
}
This is the code on the cart page:
foreach ($order as $item)
foreach ($quantity as $amount)
{
mysql_data_seek( $productsSql, 0); //<- this line, to reset the pointer for every EACH.
while($row = mysql_fetch_assoc($productsSql))
{
$itId = $row['id'];
$itDesc = $row['desc'];
$itPrice1 = $row['price1'];
if ($item == $itId)
{
$pageContent .= '
<tr>
<td>'.$itDesc.'</td>
<td>'.if ($item[''.$itId.''] == $amount[''.$itId.'']) {echo $amount}.'</td>
<td>R'.number_format($itPrice1*$amount, 2).'</td>
</tr>
';
}
}
}
This row is producing a syntax error:
<td>'.if ($item[''.$itId.''] == $amount[''.$itId.'']) {echo $amount}.'</td>
What is the problem here for starters?
Secondly, how would I need to do to accomplish the task that I am facing?
Any input on this would be greatly appreciated!
Could you try this?
<td>'.($item[$itId] == $amount[$itId] ? $amount : '').'</td>
This is a ternary operator, look at http://en.wikipedia.org/wiki/Ternary_operation
You can't simply add conditional statements like that while you're building a string.
You can do this, however
<td>' . ($item[$itId] == $amount[$itId]) ? $amount : null . '</td>
but you should use a more legible method.
Another issue you may get is if $amount is an array, you won't be able to print it as a string. If, however, $amount is an object with ArrayAccess interface, you can print it with the __toString() method; but that's another story.
The code for creating the cart page has several issues.
You walk over items and over quantities, which will probably give you duplicate outputs.
$item is a plain string, so I wonder what $item[$itId] is supposed to do?
You walk over your complete result set several times which actually is not necessary. I really hope that "$productSql" isn't a "select * from product", otherwhise this might get REAL slow in production mode.
I suggest creating a good SQL for getting the data and using this as a basis for filling the page:
// note this has SQL-injection issues, so you really need to make sure that $order contains no crap
$productsSql = mysql_query("select * from product where id in (".join($order, ',').")");
// you now have a result set with all products from your order.
while($row = mysql_fetch_assoc($productsSql))
{
$itId = $row['id'];
$itDesc = $row['desc'];
$itPrice1 = $row['price1'];
// session contains the quantity array mapping ID -> Quantity, so grab it from there
$itQuantity = $quantity[$itId];
// finally calculate the price
$itPrice = number_format($itPrice1*$itQuantity, 2);
// now you have all data for your template and can just insert it.
// if you use double quotes you can put the $xyz into the string directly
$pageContent .= "
<tr>
<td>$itDesc</td>
<td>$itQuanty</td>
<td>R $itPrice</td>
</tr>
";
}

Magento - addStoreFilter not working?

When getting a product collection in Magento, I would expect the StoreFilter to do just that, filter by the current store. But I can't get it to work.
Say I have 2 stores set up like so:
And both stores have a different root category. Main Store is the default sample data, Store2 has just one product I added. I would have thought that using the store filter, only products within the root category of the current store would show up. But I'm getting every product showing. I'm testing this by placing the following in my category view template:
$store_id = Mage::app()->getStore()->getId();
$_testproductCollection = Mage::getResourceModel('reports/product_collection')
->setStoreId($storeId)
->addStoreFilter($store_id)
->addAttributeToSelect('*');
$_testproductCollection->load();
foreach($_testproductCollection as $_testproduct){
echo $this->htmlEscape($_testproduct->getName());
};
If I echo the store ID, it's giving me the correct number. I have only one product in Store 2, so why am I getting every product from all stores returned? I can set every product in Main Store to not show in Store2 and then add a visibility filter, but that would take forever.
Also, I just noticed, if I echo the products store ID, I get the current ID, not the store it's assigned to:
echo $_testproduct->getStoreId()
What's going on?
UPDATE (April 8 2011):
OK, so I tried joining the fields so that the store_id is included (as suggested below), the section of code {{table}}.store_id = 1 is just setting all the products to have a store_id of 1. How can I just get the store_id associated with the product?
$_testproductCollection = Mage::getResourceModel('catalog/product_collection');
$_testproductCollection->joinField('store_id', 'catalog_category_product_index', 'store_id', 'product_id=entity_id', '{{table}}.store_id = 1', 'left');
$_testproductCollection->getSelect()->distinct(true);
$_testproductCollection->addAttributeToSelect('*')->load();
foreach($_testproductCollection as $_testproduct){
echo $this->htmlEscape($_testproduct->getName())."<br/>";
echo "STORE IS ".$_testproduct->getData('store_id')."<br/>";
};
If I check the catalog_category_product_index table of my db, the store_id's are correct.
$_testproductCollection should look like this $_testproductCollection = Mage::getResourceModel('reports/product_collection')->addAttributeToSelect('*')->addStoreFilter().
If You print SELECT from that collection You will see that there ain't any store column, so addStoreFilter() can't apply WHERE.
You should use joinField() on Your collection and add store_id column from catalog_product_entity_varchar table.
EDIT
Sorry to keep You waiting ;)
$collection = Mage::getResourceModel('catalog/product_collection');
$collection->joinField('store_id', 'catalog_category_product_index', 'store_id', 'product_id=entity_id', '{{table}}.store_id = 1', 'left');
$collection->getSelect()->distinct(true);
This should do the trick, but just to be sure, please check if you're getting right products :)
This worked for me:
Mage::app()->setCurrentStore($storeId);
$productCollection = Mage::getModel('catalog/product')
->getCollection()
->addStoreFilter()
->addAttributeToSelect(array('sku','price'));
OK, I think this works, haven't tested too much but seems to have done the trick. You need to first get your stores root category id, then join some fields so you have access to the products "category_id", then filter using that:
$_rootcatID = Mage::app()->getStore()->getRootCategoryId();
$_testproductCollection = Mage::getResourceModel('catalog/product_collection')
->joinField('category_id','catalog/category_product','category_id','product_id=entity_id',null,'left')
->addAttributeToFilter('category_id', array('in' => $_rootcatID))
->addAttributeToSelect('*');
$_testproductCollection->load();
foreach($_testproductCollection as $_testproduct){
echo $this->htmlEscape($_testproduct->getName())."<br/>";
};
I think
You don't need to do any joins as the magento's setStoreId() will work.
$collection = Mage::getModel("catalog/product")
->getCollection()
->setStoreId(1) //change store Id according your needs
->addAttributeToSelect(array('name','url','sku'))
->setPageSize(20);
This will get maximum 20 products from store id 1

Resources