I would like to ask you for some help or even just a comparison.
On my site I have bundles that are dimanically priced with select products, some with radio and some with default.
Magento 2 however shows two different prices between listing and product page. I have checked at code level and on the product page there is a manipulation via js that changes the price. In fact when the page loads you see a price before the update. Have you ever implemented some solution to make the same prices appear? This is the piece of code I am trying to implement but without success as it returns the same price because the products are set to default even though they are not selected on the product page.
$product = $this->productRepository->get($product_sku);
$selectionCollection = $product->getTypeInstance(true)
->getSelectionsCollection(
$product->getTypeInstance(true)->getOptionsIds($product),
$product
);
$children_ids = $this->bundleType->getChildrenIds($product->getId(), true);
$bundle_items = [];
$optionsCollection = $product->getTypeInstance(true)
->getOptionsCollection($product);
foreach ($optionsCollection as $options) {
$optionArray[$options->getOptionId()]['option_title'] = $options->getDefaultTitle();
$optionArray[$options->getOptionId()]['option_type'] = $options->getType();
if ($options->getType() !== 'checkbox' && $options->getRequired() === "1") {
foreach ($selectionCollection as $selection) {
foreach ($children_ids as $bundle_id) {
if ((array_values($bundle_id)[0] === $selection->getEntityId())
&& $options->getId() === $selection->getOptionId()) {
$price = $selection->getPrice();
$qty = $selection->getSelectionQty();
$bundle_items[] = $price * $qty;
}
}
}
}
}
$finale_price = array_sum($bundle_items);
I finally solved it by creating a function that would return the tier price. Mine is a bit more customised because I have different prices depending also on the customer group. I'll leave the code.
public function getBundlePrice($product_sku, $product_sal)
{
$product = $this->productRepository->get($product_sku);
$selectionCollection = $product->getTypeInstance(true)
->getSelectionsCollection(
$product->getTypeInstance(true)->getOptionsIds($product),
$product
);
$children_ids = $this->bundleType->getChildrenIds($product->getId(), true);
$bundle_items = [];
$optionsCollection = $product->getTypeInstance(true)
->getOptionsCollection($product);
foreach ($optionsCollection as $options) {
$optionArray[$options->getOptionId()]['option_title'] = $options->getDefaultTitle();
$optionArray[$options->getOptionId()]['option_type'] = $options->getType();
if ($options->getType() !== 'checkbox' && $options->getRequired() === "1") {
foreach ($selectionCollection as $selection) {
foreach ($children_ids as $bundle_id) {
if ((array_values($bundle_id)[0] === $selection->getEntityId())
&& $options->getId() === $selection->getOptionId()) {
$price = $selection->getPrice();
$qty = $selection->getSelectionQty();
if ($qty > 1 || $selection->getTierPrice()) {
$price = $this->getCustomPrice($selection);
} else if ($this->customerSession->getCustomer()->getGroupId() === "2") {
$price = $selection->getPartnerPrice();
}
$bundle_items[] = $price * $qty;
}
}
}
}
}
return $this->calculator->getAmount(array_sum($bundle_items), $product_sal);
}
I have a module that observes the status and writes a value into the database.
When the product is simple, it works. But when it is configurable, it writes the value of the Pattern Product and not of the Child.
if (($status !== $previousStatus) && ($status == Mage_Sales_Model_Order::STATE_PROCESSING)) {
$order = $observer->getEvent()->getOrder();
$items = $order->getAllVisibleItems();
mysql_connect('localhost', 'user', 'pass');
foreach($items as $item){
$cd = $item->getProduct()->getData('cd');
mysql_query("INSERT INTO `bd`.`table` (`id`, `cd`) VALUES (NULL, '$cd')");
}
return true;
}
How to identify if it is a configurable product, and get data from the child product?
Magento already has a connection initialised, you don't need to spin up another one directly.
You shouldn't have to specify the database you're connecting to directly.
A configurable product can contain a simple product, to access this you'll need to get the childItem.
The preferred approach for this kind of thing would be to store the products data against the order item, so that if a product is deleted etc in the future you have a full history because order items are decoupled from their products data at time of placing. Read more here: https://magento.stackexchange.com/questions/62111/what-is-the-effect-of-deleting-a-product-with-associated-orders/62142#62142
Just a FYI but getAllVisibleItems returns configurables, if you wanted to see configurables and their simples all in one collection you could use getAllItems instead
if (($status !== $previousStatus) && ($status == Mage_Sales_Model_Order::STATE_PROCESSING)) {
/** #var Mage_Sales_Model_Order $order */
$order = $observer->getData('order');
$items = $order->getAllVisibleItems();
/** #var Mage_Sales_Model_Order_Item $item */
foreach($items as $item){
$cd = $item->getProduct()->getData('cd');
//If configurable get the first child item and the cd value from it
if ($item->getProductType() === Mage_Catalog_Model_Product_Type::TYPE_CONFIGURABLE) {
$childrenItems = $item->getChildrenItems();
$childItem = reset($childrenItems);
if ($childItem instanceof Mage_Sales_Model_Order_Item) {
$cd = $childItem->getProduct()->getData('cd');
}
}
/** #var Mage_Core_Model_Resource $resource */
$resource = Mage::getSingleton('core/resource');
$writeConnection = $resource->getConnection('core_write');
$query = "INSERT INTO `table` (`cd`) VALUES ('{$cd}')";
$writeConnection->query($query);
}
return true;
}
Ignoring your SQL connection - you should revise that - take a look here:http://fishpig.co.uk/magento/tutorials/direct-sql-queries/
To get the chosen child product of a configurable product, do this;
foreach($items as $item){
// Establish product type and if configurable, load the chosen product
if ($item->getProductType() == Mage_Catalog_Model_Product_Type::TYPE_CONFIGURABLE) {
$simple = reset($item->getChildren());
$_product = $simple->getProduct();
} else {
$_product = $item->getProduct();
}
$cd = $_product->getData('cd');
mysql_query("INSERT INTO `bd`.`table` (`id`, `cd`) VALUES (NULL, '$cd')");
}
In Magento 1.9.0.1 by default, it decreases stock qty while placing an order. I want to stop decreasing stock qty while placing an order for the purpose of fake order. And I also want the functionality of increasing stock qty while order state is complete, not pending, not processing. How to do it programmatically or by setting up in Admin panel. If any one knows about it, please reply back.
Thank You
Ankan
Just simply open your admin panel, go to System->Configuration->Catalog Tab->Inventory Then click on Stack Option and change Decrease Stock When Order is Placed to NO.
Thanks,
Lovekesh
In Admin panel, System->Configuration->Catalog Tab->Inventory Then click on Stack Option and change Decrease Stock When Order is Placed to NO. So that it stops the stock qty increasing.In Model/Automatically/Complete/Order/Observer.php page, class Webspidy_Customoption_Model_Automatically_Complete_Order_Observer
{ public function __construct(){}
public function automaticallycompleteorder($observer)
{
//Mage::log('Ankan');
$order = $observer->getEvent()->getOrder();
/$orders = Mage::getModel('sales/order_invoice')->getCollection()
->addAttributeToFilter('order_id', array('eq'=>$order->getId()));/
/*if ((int)$orders->count() !== 0) {
return $this;
}*/
//Mage::log($orderstate);
//if($order->getState() == 'complete'){
if(($order->getState() == 'processing') || ($order->getState() == 'pending_payment')){
if($order->hasInvoices()){
//Mage::log($orderstate);
//Mage::log('Ankan');
//Mage::log($order->getData());
//====== Order Details ================
$orderNumber = $order->getIncrementId(); //Mage::log($orderNumber);
$orderDet = Mage::getModel('sales/order')->load($orderNumber, 'increment_id');
//Mage::log($orderDet->getData());
$orderItems = $orderDet->getItemsCollection()
->addAttributeToSelect('*')
->load();
foreach($orderItems as $orderItem){
$productId = $orderItem->getProductId();
$productOptionSku = $orderItem->getSku();
$productQty = $orderItem->getQtyOrdered();
$product = Mage::getModel('catalog/product')->load($productId);
$sku = $product->getSku();
$centralqty = $product->getStockItem()->getQty();
$values = array();
foreach ($product->getOptions() as $o) {
$p = $o->getValues();
}
foreach($p as $v)
{
$optionSku = $v->getSku();
$optionItem = $v->getQty();
//Mage::log($optionItem);
//Mage::log($productOptionSku.".....".$sku."-".$optionSku.".....".$optionItem);
if($productOptionSku == ($sku."-".$optionSku)){
if($centralqty >= ($optionItem*(int)$productQty)){
//$stockQty = (($centralqty-($optionItem*(int)$productQty))+$productQty);
$stockQty = ($centralqty-($optionItem*(int)$productQty));
}
}
}
$product->save();
//Mage::log($stockQty);
$stockItem = Mage::getModel('cataloginventory/stock_item')->loadByProduct($productId);
//$stockItem = Mage::getModel('cataloginventory/stock_item')->load($productId);
$stockItemId = $stockItem->getId();
$stockItem->setData('qty', $stockQty);//(integer)$XMLproduct->QtyInStock
$stockItem->setData('manage_stock',1);
$stockItem->save();
}
}
//======== End ======
}
}
}
And in etc/config.xml,
<global><events>
<sales_order_save_after><observers>
<webspidy_customoption_automatically_complete_order_observer>
<type>singleton</type> <class>Webspidy_Customoption_Model_Automatically_Complete_Order_Observer</class>
<method>automaticallycompleteorder</method>
</webspidy_customoption_automatically_complete_order_observer>
</observers></sales_order_save_after></events></global> After a long process, I have got a success by creating Observer in my custom module.
I am using Magento 1.9
I have tried with the following code. it's OK But i have another smart code
$stockItem = Mage::getModel('cataloginventory/stock_item')->loadByProduct($productId);
$stockItemId = $stockItem->getId();
$stockItem->setData('qty', $stockQty);
$stockItem->setData('manage_stock',1);
$stockItem->save();
My code is following:-
Mage::getModel('cataloginventory/stock')->backItemQty($productId,$new_qty);
I have a unique shop where some products incur a base fee, lets say
A photographer charges $20 for the first hour then $1 there-after.
I am passing a variable into my codeignighter cart ; so for 5 hours I would pass the variable into cart->insert();
$item['id'] = 1;
$item['qty'] = 5;
$item['base'] = 20.00;
I made some changes to the cart class so this would work and has been fine so far, what I now need and cant seem to figure this out is when there are options it considers it a different product and this fee is charged once per rowid.
I would like my class to only allow 1 charge for the item regardless of the various options.
Below are the three functions I created inside my Cart class
and I call set_base($item) in the _save_cart() function.
private function set_base($item)
{
if( $this->base_exist($item) )
{
return FALSE;
}
// Only allow the base cost for 1 row id, it doesnt matter which one, just one
$this->_base_indexes['rowid'][$item['id']] = $item['rowid'];
$this->_cart_contents['cart_total'] += $item['base'];
return TRUE;
}
private function base_exist($item)
{
if ( array_key_exists($item['id'] , $this->_base_indexes['applied']) )
{
if ( ( $item['rowid'] == $this->_base_indexes['applied'][$item['id']] ) )
{
return TRUE;
}
}
return FALSE;
}
private function base_reset()
{
$this->_base_indexes = array();
$this->_base_indexes['applied'] = array();
return $this->_base_indexes;
}
Inside _save_cart();
I call
$this->base_reset();
Inside the cart_contents() loop I have added;
if(isset($val['base']))
{
$this->set_base($val);
}
$this->_cart_contents['cart_total'] += ($val['price'] * $val['qty']);
Hope this was clear :/
OK i changed it a little bit,
the foreach loop in the save_cart function now looks like; and I can remove the three functions I had before.
foreach ($this->_cart_contents as $key => $val)
{
// We make sure the array contains the proper indexes
if ( ! is_array($val) OR ! isset($val['price']) OR ! isset($val['qty']))
{
continue;
}
if(isset($val['base']))
{
//If it doesnt exist, add the fee
if (!(isset($this->_base_indexes[$val['id']]) == $val['rowid']) )
{
$this->_base_indexes[$val['id']] = $val['rowid'];
$this->_cart_contents['cart_total'] += $val['base'];
$sub = ($this->_cart_contents[$key]['price'] * $this->_cart_contents[$key]['qty']) + $val['base'];
}
else
{
//$this->_cart_contents[$key]['base'] = 0;
$sub = ($this->_cart_contents[$key]['price'] * $this->_cart_contents[$key]['qty']);
}
}
$this->_cart_contents['cart_total'] += ($val['price'] * $val['qty']);
$this->_cart_contents['total_items'] += $val['qty'];
$this->_cart_contents[$key]['subtotal'] = $sub;
}
I am trying to add new values to an attribute option in Magento using a script to speed up the process since I have over 2,000 manufacturers.
Here is a piece of code that I used to perform exactly this task. Create a custom module (using ModuleCreator as a tool) and then create a mysql4-install-0.1.0.php under the sql/modulename_setup folder. It should contain the following (adapted to your own data, of course!).
$installer = new Mage_Eav_Model_Entity_Setup('core_setup');
$installer->startSetup();
$aManufacturers = array('Sony','Philips','Samsung','LG','Panasonic','Fujitsu','Daewoo','Grundig','Hitachi','JVC','Pioneer','Teac','Bose','Toshiba','Denon','Onkyo','Sharp','Yamaha','Jamo');
$iProductEntityTypeId = Mage::getModel('catalog/product')->getResource()->getTypeId();
$aOption = array();
$aOption['attribute_id'] = $installer->getAttributeId($iProductEntityTypeId, 'manufacturer');
for($iCount=0;$iCount<sizeof($aManufacturers);$iCount++){
$aOption['value']['option'.$iCount][0] = $aManufacturers[$iCount];
}
$installer->addAttributeOption($aOption);
$installer->endSetup();
More documentation on the Magento wiki if you want.
If you don't want to do it in a custom module, you could just create a php file that starts with:
require_once 'app/Mage.php';
umask(0);
Mage::app('default');
Answer of Jonathan is correct. But if you want to perform it without installer i.e in any other code, then you might find this helpful:
$arg_attribute = 'manufacturer';
$manufacturers = array('Sony','Philips','Samsung','LG','Panasonic','Fujitsu','Daewoo','Grundig','Hitachi','JVC','Pioneer','Teac','Bose','Toshiba','Denon','Onkyo','Sharp','Yamaha','Jamo');
$attr_model = Mage::getModel('catalog/resource_eav_attribute');
$attr = $attr_model->loadByCode('catalog_product', $arg_attribute);
$attr_id = $attr->getAttributeId();
$option['attribute_id'] = $attr_id;
foreach ($manufacturers as $key=>$manufacturer) {
$option['value'][$key.'_'.$manufacturer][0] = $manufacturer;
}
$setup = new Mage_Eav_Model_Entity_Setup('core_setup');
$setup->addAttributeOption($option);
More information can be found here.
I have created a function to dynamically add option to attribute
public function addAttributeOptions($attributeCode, $argValue)
{
$attribute = Mage::getModel('eav/config')
->getAttribute(Mage_Catalog_Model_Product::ENTITY, $attributeCode);
if ($attribute->usesSource()) {
$id = $attribute->getSource()->getOptionId($argValue);
if ($id)
return $id;
}
$value = array('value' => array(
'option' => array(
ucfirst($argValue),
ucfirst($argValue)
)
)
);
$attribute->setData('option', $value);
$attribute->save();
//return newly created option id
$attribute = Mage::getModel('eav/config')
->getAttribute(Mage_Catalog_Model_Product::ENTITY, $attributeCode);
if ($attribute->usesSource()) {
return $attribute->getSource()->getOptionId($argValue);
}
}
You can add an option to your attribute by providing code and option value
$this->addAttributeOptions('unfiorm_type', 'leotartd')
Important! (Hopefully this helps somebody, cause I was stuck like 2h with this issue)
If you are using special characters (such as ä, ö, ü, ß, ×, ...) make sure to encode them properly!
array_walk($manufacturers , create_function('&$val', '$val = utf8_encode($val);'));
Here a simple and very fast way....
Delete an option
/* My option value */
$value = 'A value';
/* Delete an option */
$options = array();
$entity_type_id = Mage::getModel('eav/entity')->setType('catalog_product')->getTypeId(); // Product Entity Type ID
$attribute = Mage::getModel('eav/entity_attribute')->loadByCode($entity_type_id, $attribute_code); // Load attribute by code
if ($attribute && $attribute->usesSource()) {
$option_id = $attribute->getSource()->getOptionId($value); // Check Option ID from value...
if ($option_id) {
$options['delete'][$option_id] = true;
$attribute->setOption($options)->save();
}
}
/* END ! */
Add or update an option
/* Add/Update an option */
$options = array();
$entity_type_id = Mage::getModel('eav/entity')->setType('catalog_product')->getTypeId(); // Product Entity Type ID
$attribute = Mage::getModel('eav/entity_attribute')->loadByCode($entity_type_id, $attribute_code); // Load attribute by code
if ($attribute && $attribute->usesSource()) {
$option_id = $attribute->getSource()->getOptionId($value); // Check Option ID...
$options['order'][$option_id] = 10; // Can be removed... Set option order...
$options['value'][$option_id] = array(
0 => $value, // Admin Store - Required !
1 => $value, // Store id 1 - If U want ! Can be removed
);
$attribute->setDefault(array($option_id)); /* If you want set option as default value */
$attribute->setOption($options)->save(); /* That's all */
}
/* END ! */
In my tutorial I am explaining how to read the options from the CSV and create the options pro grammatically.
http://www.pearlbells.co.uk/add-attribute-options-magento-scripts/
please click the tutorial for further explanation
function createAttribute($options) {
$option = array('attribute_id' =>
Mage::getModel('eav/entity_attribute')->getIdByCode(
Mage_Catalog_Model_Product::ENTITY,
'color'
)
);
for ($i = 0; $i < count($options); $i++) {
$option['value']['option'.$i][0] = $options[ $i ]; // Store View
$option['value']['option'.$i][1] = $options[ $i ]; // Default store view
$option['order']['option'.$i] = $i; // Sort Order
}
$setup = new Mage_Eav_Model_Entity_Setup('core_setup');
$setup->addAttributeOption($option);
}
Answer of Arvind Bhardwaj enter code here is correct. But if you want to perform it without installer i.e in any other code, then you might find this helpful:
Agree with Arvind but it's only works for insert the single option value and if you want to perform insert multiple option value then you just needs to replace the code from "$option['value'][$key.''.$manufacturer] = $manufacturer;" to "$option['values'][$key.''.$manufacturer] = $manufacturer;" to this.
below is the final code
require_once 'app/Mage.php';
umask(0);
Mage::app('default');
$arg_attribute = 'manufacturer';
$manufacturers = array('Sony', 'Philips', 'Samsung', 'LG', 'Panasonic', 'Fujitsu', 'Daewoo', 'Grundig', 'Hitachi', 'JVC', 'Pioneer', 'Teac', 'Bose', 'Toshiba', 'Denon', 'Onkyo', 'Sharp', 'Yamaha', 'Jamo');
$attr_model = Mage::getModel('catalog/resource_eav_attribute');
$attr = $attr_model->loadByCode('catalog_product', $arg_attribute);
$attr_id = $attr->getAttributeId();
$option['attribute_id'] = $attr_id;
foreach ($manufacturers as $key => $manufacturer) {
$option['values'][$key . '_' . $manufacturer] = $manufacturer;
}
$setup = new Mage_Eav_Model_Entity_Setup('core_setup');
$setup->addAttributeOption($option);
I hope its works for insertion multiple option.