cancel
Showing results for 
Search instead for 
Did you mean: 

How to convert simple products to grouped ones programmatically?

How to convert simple products to grouped ones programmatically?

My client and me are trying to achieve something that we are maybe not supposed to do. We have a demanding set of non-standard products that include different types of product conditions, e.g. grade B ware etc. In addition product data is coming in in form of feeds from several suppliers. In order not to clutter up the product listing we would like to convert existing, manually edited simple products into grouped ones (or whatever is appropriate) with associated new simple products programmatically on the fly and vice versa whenever necessary, i.e. when there are at least two different sub products.

 

So far we managed to do this somehow, a test scenario produces the seemingly right product structure – correctly associated products are displayed in the backend, the quantities have been correct before. The problem occurs with the frontend check on 'isSaleable()' for both the grouped product and the associated products, it returns 'false' no matter what we do. When we enforce the display of the qty input boxes and add-to-cart button they will (naturally?) just product the error message 'Please specify the quantity of product(s)'. We tried to set 'is_salable' by different means throughout the code. What else is missing? Any little hint, any advice here would be appreciated!

 

The code is quite lengthy already, and probably there's already some redundancy in there because of our attempts to somehow fix this. There's a main script that fetches a product collection and compares each entry with the existing supplier feeds. The essential part then is the function call to convert the product:

 

if (sizeof($newProducts[$productsSku]) > 1 && $_product->getTypeId() == 'simple') {
$newProductQtys = createGroupedProduct($_product, $newProducts[$productsSku]);
}

 

There are 2 functions for the actual conversion process, one which creates duplicates of the master products (type = simple) and sets their values accordingly:

 

function createDuplicate($product, $values) {

	global $suppliers, $conditions_arr;

	$sku = $product->getSku();
	$newSku = $sku.'-v'.$suppliers[$values['feed']]['id'];
		
	$qty = $values['qty'];
	$feed = $values['feed'];
	$cost = $values['cost'];
	$item_condition = $values['item_condition'];
	$box_condition = $values['box_condition'];
	$notes = stripslashes($values['notes']);

	$newProduct = $product->duplicate();
	$newProduct->setTypeId('simple');
	
	$newProduct->setStoreId(0);
	$newProduct->setWebsiteIds(array(1));
	
	$newProduct->setVisibility(2);
	$newProduct->setSku($newSku);
	
	$newProduct->setData('media_gallery', array());
	$newProduct->setStatus(Mage_Catalog_Model_Product_Status::STATUS_ENABLED);
	
	$newProduct->setPrice((real)($cost + $cost*$suppliers[$feed]['price_increase']));
	$newProduct->setTaxClassId(2);
	
	$newProduct->getResource()->save($newProduct);
	$productId = $newProduct->getId();

	// Check if there is a stock item object
	$stockItem = Mage::getModel('cataloginventory/stock_item')->loadByProduct($productId);
		
	$stockItemData = $stockItem->getData();
	if (empty($stockItemData)) {
	
	    // Create the initial stock item object
	    $stockItem->setData('inventory_manage_stock_default', 1);
	    $stockItem->setData('manage_stock',1);
	    $stockItem->setData('is_in_stock', $qty ? 1 : 0);
	    $stockItem->setData('is_salable', 1);
	    $stockItem->setData('use_config_manage_stock', 1);
	    $stockItem->setData('stock_id',1);
	    $stockItem->setData('product_id',$productId);
	    $stockItem->setData('qty',$qty);
	    $stockItem->setTypeId( $newProduct->getTypeId() );
	    $stockItem->save();
	
	    // Init the object again after it has been saved so we get the full object
	    $stockItem = Mage::getModel('cataloginventory/stock_item')->loadByProduct($productId);
	}

	// Set the quantity
	$stockItem->setData('qty',$qty);
	$stockItem->setData('is_salable', 1);
	$stockItem->save();
	
	// $newProduct->assignProduct($newProduct, 1, 1);
	$newProduct->setIsSalable(1);
	
	$newProduct->setStatus(Mage_Catalog_Model_Product_Status::STATUS_ENABLED);
	$newProduct->save();
	
	$event = Mage::getSingleton('index/indexer')->logEvent($newProduct,$newProduct->getResource()->getType(),Mage_Index_Model_Event::TYPE_SAVE,false);
	Mage::getSingleton('index/indexer')->getProcessByCode('cataloginventory_stock')->setMode(Mage_Index_Model_Process::MODE_REAL_TIME)->processEvent($event);

	return $productId;

}


function createGroupedProduct($product, $newProductsArr) {

	global $suppliers;
	
	$origProductId = $product->getId();
	$sku = $product->getSku();

	$newProductId = array();
	$newProductQtys = array();
	
	$qty = 0;
	$price = 999999;
	
	$product->setTypeId('grouped');
	$product->save();
	
	foreach($newProductsArr as $key => $values) {
		
		$id = createDuplicate($product, $values);
	
		$newProductId[] = $id;
		$newProductQtys[$id] = $values['qty'];
		
		// add up all stock quantities of all slave products for master
		$qty += $values['qty'];
		
		// determine lowest price among all slave products
		$subItemPrice = (real)($values['cost'] + $values['cost']*$suppliers[$values['feed']]['price_increase']);
		if ($subItemPrice < $price) $price = $subItemPrice;
		
	}
	
	if (sizeof($newProductId) > 1) {
		$products_links = Mage::getModel('catalog/product_link_api');
		foreach($newProductId as $key => $id) {
			$products_links->assign('grouped', $origProductId, $id);
		}
	}
	
	// set new values for grouped product according to slave products values
	$product->setPrice($price);

	$product->getResource()->save($product);
	
	// Check if there is a stock item object
	$stockItem = Mage::getModel('cataloginventory/stock_item')->loadByProduct($origProductId);
	$stockItemData = $stockItem->getData();
	if (empty($stockItemData)) {
	
	    // Create the initial stock item object
	    $stockItem->setData('manage_stock',1);
	    $stockItem->setData('is_in_stock', $qty ? 1 : 0);
	    $stockItem->setData('is_salable', 1);
	    $stockItem->setData('use_config_manage_stock', 1);
	    $stockItem->setData('stock_id',1);
	    $stockItem->setData('product_id',$origProductId);
	    $stockItem->setData('qty',$qty);
	    // $stockItem->setTypeId( $product->getTypeId() );
	    $stockItem->setTypeId('grouped');
	    $stockItem->save();
	
	    // Init the object again after it has been saved so we get the full object
	    $stockItem = Mage::getModel('cataloginventory/stock_item')->loadByProduct($origProductId);
	}
	
	// Set the quantity
	$stockItem->setData('qty',$qty);
	$stockItem->setData('is_in_stock', $qty ? 1 : 0);
	$stockItem->setData('is_salable', 1);
	$stockItem->save();
	
	$product->setStatus(Mage_Catalog_Model_Product_Status::STATUS_ENABLED);
	$product->save();
	
	$event = Mage::getSingleton('index/indexer')->logEvent($product,$product->getResource()->getType(),Mage_Index_Model_Event::TYPE_SAVE,false);
	Mage::getSingleton('index/indexer')->getProcessByCode('cataloginventory_stock')->setMode(Mage_Index_Model_Process::MODE_REAL_TIME)->processEvent($event);
	
	$cache = Mage::getSingleton('core/cache');
	$cache->flush();
	
	return $newProductQtys;
	
}


We tried using the store ID '1' as well and had some success with the shopping cart when the front end used the same kind of mass-product-add-to-cart form that we integrated into the product listing. But the associated products then showed no product name and no image, and not in the admin at all.

 

If more code from the main script is necessary I will happily provide this.

 

Thank you in advance,

 

Oliver

 

1 REPLY 1

Re: How to convert simple products to grouped ones programmatically?