Magento Themes and Magento Extensions

Programmatically Create Magento Product Packages

Share

On a recent project I had to write a piece of code which I thought I’d share with the Magento community in case it comes in useful for anyone. I have put all the code into one ‘add to cart’ controller below for the sake of simplicity, but you could break it up into separate methods to clean up the code a bit.

In a nutshell, all products on the site have a normal price and some have a package price. If they have a package price they are capable of being purchased with other products as part of a package deal, but only two at a time. Therefore these products had to be purchased as one product using the special prices as we can’t have customers adjusting the quantities of items added to the cart. Here’s the code in myPackageController.php broken up:
1) Get individual simple product data
I send across the two product IDs, check if they have a package price and assign their prices.

1 $productA = Mage::getModel('catalog/product')->load(Mage::app()->getRequest()->getParam('a_id'));
2 $productB = Mage::getModel('catalog/product')->load(Mage::app()->getRequest()->getParam('b_id'));
3
4 $productA_price = ($productA->getPackageprice() > 0 ? $productA->getPackagePrice() : $productA->getFinalPrice());
5 $productB_price = ($productB->getPackageprice() > 0 ? $productB->getPackagePrice() : $productB->getFinalPrice());
2) Check if package product already exists, if not create it!
I now load the package product based on the SKU that I know I’m going to make, if it doesn’t exist I will create the product and save.

1 $package_product = Mage::getModel('catalog/product')->loadByAttribute('sku',$productA->getSku().'__'.$productB->getSku());
2
3 if (!$package_product) {
4
5 $package_product = Mage::getModel('catalog/product');
6 $package_product
7 ->setTypeId(Mage_Catalog_Model_Product_Type::TYPE_SIMPLE)
8 ->setWebsiteIds(array(1, 2))
9 ->setWeight(1)
10 ->setStoreId(Mage::app()->getStore()->getId())
11 ->setStatus(Mage_Catalog_Model_Product_Status::STATUS_ENABLED)
12 ->setVisibility(Mage_Catalog_Model_Product_Visibility::VISIBILITY_NOT_VISIBLE)
13 ->setTaxClassId(2)
14 ->setAttributeSetId(15)
15 ->setSku($productA->getSku().'__'.$productB->getSku())
16 ->setName("PACKAGE DEAL: ".$productA->getName().' & '.$productB->getName())
17 ->setPrice($productA_price + $productB_price)
18 ->save();

A couple of important notes here. This Magento installation has two websites attached to it. I enable this product for both stores but am only setting the price for the current store. This means that if someone creates this product in the additional (trade) store, it will not overwrite the price in the main store.

3) Set stock data for package product

The stock object is a different model to the product model so this has to be set separately. I have chosen not to count stock for this item as the stock is controlled by the other items.

1 $stockItem = Mage::getModel('cataloginventory/stock_item');
2 $stockItem->assignProduct($package_product);
3 $stockItem->setData('is_in_stock', 1);
4 $stockItem->setData('stock_id', 1);
5 $stockItem->setData('store_id', 1);
6 $stockItem->setData('manage_stock', 0);
7 $stockItem->setData('use_config_manage_stock', 0);
8 $stockItem->setData('min_sale_qty', 0);
9 $stockItem->setData('use_config_min_sale_qty', 1);
10 $stockItem->setData('max_sale_qty', 1000);
11 $stockItem->setData('use_config_max_sale_qty', 1);
12 $stockItem->save();

4) If package does exists, update the price

As the package product prices may change, I have also made it so that the price can be updated on the package product if it already exists.

1 } else {
2
3 $package_product->setStoreId(Mage::app()->getStore()->getId());
4 $package_product->setPrice($productA_price + $productB_price)->save();
5
6 }

5) Add package product to cart

We finish off by adding the newly created product to the cart and redirecting the customer to the cart.

1 $cart = Mage::getModel('checkout/cart')->init();
2 $cart->addProduct($package_product, array('qty' => 1));
3 $cart->save();
4
5 Mage::getSingleton('checkout/session')->setCartWasUpdated(true);
6 $this->_redirect('checkout/cart');

6) Decrease individual product stock

The final stage is that we need to decrease the stock of both the individual items when an order is placed. I did this with an observer on checkout_submit_all_after, which is dispatched after a successful order. The code inModel/Observer.php is pretty self-explanatory:

1 <?php class Creare_Productpackages_Model_Observer
2 {
3 public function packageDecreaseStock($observer) {
4
5 $order = $observer['order'];
6
7 $items = $order->getAllVisibleItems();
8 foreach ($items as $itemid => $item){
9
10 $product = Mage::getModel('catalog/product')->load($item->getProductId());
11 if ($product->getAttributeSetId() == 15)
12 {
13 $qty = $item->getQtyToInvoice();
14 $skus = explode('__', $product->getSku());
15
16 foreach ($skus as $sku)
17 {
18 $_product = Mage::getModel('catalog/product')->loadByAttribute('sku', $sku);
19 $stocklevel = (int)Mage::getModel('cataloginventory/stock_item')->loadByProduct($_product)->getQty();
20 $newlevel = $stocklevel-($qty);
21 if ($newlevel > 0) { $instock = 1; } else { $instock = 0; }
22 $stockItem = Mage::getModel('cataloginventory/stock_item')->assignProduct($_product);
23 $stockItem->setData('is_in_stock', $instock);
24 $stockItem->setData('qty', $newlevel);
25 $stockItem->save();
26
27 }
28 }
29 }
30 }
31 }
As I said earlier, this isn’t the complete layout of all the code but is simply here to give less experienced Magento developers an idea of what’s possible through the use of custom ‘add to cart’ controllers. Hope it comes in useful – if anyone has any comments or improvements, you’re welcome to leave them in the comments below.

Leave a Reply

You must be logged in to post a comment.