Add a quote item with a info_buyRequest buy request - magento

I would like to get product price with options price using a custom module that calculates product price by formula, i like to use the function without adding the product to the cart.
The function get a quote item paramter
public function getProductFinalPrice($item, $forReindex = false, $storeId = null)
So i thought about add a quote item with a info_buyRequest buy request
I tried this
$product = $this->_objectManager->create('Magento\Catalog\Model\Product')->load(5862);
$customOptions = $this->_objectManager->get('Magento\Catalog\Model\Product\Option')->getProductOptionCollection($product);
$item = $this->_objectManager->create('Magento\Quote\Model\Quote\Item');
$options = $this->_objectManager->get('Magento\Quote\Model\ResourceModel\Quote\Item\Collection');
$quote = $this->cart->getQuote();
$quote->addProduct($product);
$quote->save();
$options->setQuote($quote);
//$options->addItemFilter($item->getId());
$item->setQuote($quote)->setProduct($product)->setQty($qty);
foreach ($options as $option) {
$item->addOption($option);
}
$infoBuyRequest = [
"info_buyRequest" => [
"uenc" => "aHR0cHM6Ly93d3cud2V0YWcuY2EvZW5fY2EvbmFtZS10YWdzL25hbWUtdGFncy1pbnNwaXJhdGlvbi9jdXN0b20tbmFtZS10YWctb3JkZXIv",
"product" => 5862,
"qty" => $qty
]
];
$option = $this->_objectManager->create(
\Magento\Quote\Model\Quote\Item\Option::class,
['data' => $infoBuyRequest]
);
$item->addOption($option);
$item->setProductOptions($infoBuyRequest);
var_dump($this->_getBuyRequest($item));
var_dump($this->_getBuyRequest($item)); return
object(Magento\Framework\DataObject)#3647 (1) {
["_data":protected]=>
array(2) {
["original_qty"]=>
NULL
["qty"]=>
int(100)
}
}
I like to get something with info_buyrequest
[
"info_buyRequest" => [
"uenc" => "aHR0cHM6Ly93d3cud2V0YWcuY2EvZW5fY2EvbmFtZS10YWdzL25hbWUtdGFncy1pbnNwaXJhdGlvbi9jdXN0b20tbmFtZS10YWctb3JkZXIv",
"product" => 5862,
"qty" => $qty
]
]
This is the function _getBuyRequest
public function _getBuyRequest($item) {
$option = $item->getOptionByCode('info_buyRequest');
if ($option) {
$value = json_decode($option->getValue(), true); //in M2.2 json used for the buy request
if (is_null($value))
$value = unserialize($option->getValue()); //in M<2.2 the buy request is serialized
} else
$value = [];
$buyRequest = new \Magento\Framework\DataObject($value);
// Overwrite standard buy request qty, because item qty could have changed since adding to quote
$buyRequest->setOriginalQty($buyRequest->getQty())
->setQty($item->getQty() * 1);
return $buyRequest;
}
So how to add info_buyRequest? i would like to load options in the quote item.

foreach($quoteData->getAllVisibleItems() as $_item) {
print_r($_item->getBuyRequest());
}
Use this method $_item->getBuyRequest().
getBuyRequest already a method defined in quote model for info_buyRequest

Related

How to show same product attribute sort on compare page Magento

i am not sure why the sorting of a product attribute on compare page is not working same as on product page. Like on product page the atribute sort is
on product page
1 name
2 new attribute
3 new attribute1
4 color
but on comapre page when i am comp[aring the 2 products has same attributes the attribute sort order becomes
on compare page
1 name
2 color
3 new attribute
4 new attribute1
I have googled a lot to find answer but unable to find. Please help me to fix this issue.
Below are the functions which i find
public function getComparableAttributes()
{
if (is_null($this->_comparableAttributes)) {
$this->_comparableAttributes = array();
$setIds = $this->_getAttributeSetIds();
if ($setIds) {
$attributeIds = $this->_getAttributeIdsBySetIds($setIds);
$select = $this->getConnection()->select()
->from(array('main_table' => $this->getTable('eav/attribute')))
->join(
array('additional_table' => $this->getTable('catalog/eav_attribute')),
'additional_table.attribute_id=main_table.attribute_id'
)
->joinLeft(
array('al' => $this->getTable('eav/attribute_label')),
'al.attribute_id = main_table.attribute_id AND al.store_id = ' . (int) $this->getStoreId(),
array('store_label' => $this->getConnection()->getCheckSql('al.value IS NULL', 'main_table.frontend_label', 'al.value'))
)
->where('additional_table.is_comparable=?', 1)
->where('main_table.attribute_id IN(?)', $attributeIds);
$attributesData = $this->getConnection()->fetchAll($select);
if ($attributesData) {
$entityType = Mage_Catalog_Model_Product::ENTITY;
Mage::getSingleton('eav/config')
->importAttributesData($entityType, $attributesData);
foreach ($attributesData as $data) {
$attribute = Mage::getSingleton('eav/config')
->getAttribute($entityType, $data['attribute_code']);
$this->_comparableAttributes[$attribute->getAttributeCode()] = $attribute;
}
unset($attributesData);
}
}
}
return $this->_comparableAttributes;
}
/**
* Load Comparable attributes
*
* #return Mage_Catalog_Model_Resource_Product_Compare_Item_Collection
*/
public function loadComparableAttributes()
{
$comparableAttributes = $this->getComparableAttributes();
$attributes = array();
foreach ($comparableAttributes as $attribute) {
$attributes[] = $attribute->getAttributeCode();
}
$this->addAttributeToSelect($attributes);
return $this;
}
bUt i cant understand how to filter it by sort order .Please suggest
check the modifications in function below:
the file used is vendor/magento/module-catalog/Model/ResourceModel/Product/Compare/Item/Collection.php
But this is not the best way to do it. you need to override it as per Magento Standards.
I am working on it, will update shortly.
public function getComparableAttributes()
{
if ($this->_comparableAttributes === null) {
$this->_comparableAttributes = [];
$setIds = $this->_getAttributeSetIds();
if ($setIds) {
$attributeIds = $this->_getAttributeIdsBySetIds($setIds);
$select = $this->getConnection()->select()->from(
['main_table' => $this->getTable('eav_attribute')]
)->join(
['additional_table' => $this->getTable('catalog_eav_attribute')],
'additional_table.attribute_id=main_table.attribute_id'
)->joinLeft(
['al' => $this->getTable('eav_attribute_label')],
'al.attribute_id = main_table.attribute_id AND al.store_id = ' . (int)$this->getStoreId(),
[
'store_label' => $this->getConnection()->getCheckSql(
'al.value IS NULL',
'main_table.frontend_label',
'al.value'
)
]
)
->joinLeft( //add sort order to sort the attributes as per backend sort. -- Abid
['as' => $this->getTable('eav_entity_attribute')],
'as.attribute_id = main_table.attribute_id'
)
->where(
'additional_table.is_comparable=?',
1
)->where(
'main_table.attribute_id IN(?)',
$attributeIds
)
->order('as.sort_order') //sort by sort_order -- Abid
;
$attributesData = $this->getConnection()->fetchAll($select);
if ($attributesData) {
$entityType = \Magento\Catalog\Model\Product::ENTITY;
$this->_eavConfig->importAttributesData($entityType, $attributesData);
foreach ($attributesData as $data) {
$attribute = $this->_eavConfig->getAttribute($entityType, $data['attribute_code']);
$this->_comparableAttributes[$attribute->getAttributeCode()] = $attribute;
}
unset($attributesData);
}
}
}
return $this->_comparableAttributes;
}
On product page attributes are sorted like in attribute set.
On compare page attributes are not sorted at all.
You can rewrite function getComparableAttributes in class Mage_Catalog_Model_Resource_Product_Compare_Item_Collection and implement your own sort logic.
But note, that this function differs in different Magento versions. You can try to use free extension ET Advanced Compare or take part of code from this extension (code is available on bitbucket.org. link i on extension page)

Convert magento admin quote into a multi address order

Say I have a quote from the admin create order with all the products already entered, how could I go about writing some code to add multiple shipping addresses and assign the item to the address.
Ive got some code working, based loosely off the frontend multiship model. The problem I'm having is adding the multiple address and assigning the items to the quote. If I have a standard quote, how can I add the multiple addresses?
I've already tried :
$address = Mage::getModel('customer/address')->load($addressID);
$quote->addShippingAddress($address);
Which seems to only hold one address
The whole function:
public function createMultiOrders() {
// print_r($_POST);
$items = $_POST['item'];
$itemsByAddress = array();
$billingInfo = array();
$session = Mage::getSingleton('adminhtml/session_quote');
$quote = $session->getQuote();
//first we are reorganizing the data provided by javascript into an array based on address ID's
foreach ($items as $key => $item) {
$addID = $item['addressID'];
$itemID = $key;
$qty = $item['qty'];
$itemsByAddress[$addID][] = array('itemID' => $itemID, 'qty' => $qty);
}
// print_r($itemsByAddress);
//now that we have an array of items, seperated by which addressid they goto, we can create the order for each address
foreach ($itemsByAddress as $addressID => $items) {
$address = Mage::getModel('customer/address')->load($addressID);
$quote->addShippingAddress($address);
echo"<br/>address id is $addressID, items are: <br/>";
foreach ($items as $item) {
// $address->addItem($_item);
///add items to order
// echo"id before is $item<br/>";
$itemID = explode('-_', $item['itemID']);
$itemID = $itemID[0];
$qty = $item['qty'];
echo "itemid is $itemID, qty is " . $qty . " <br/><br/><br/><br/>";
}
}
//print_r(get_class_methods($quote));
$shippingAddresses = $quote->getAllShippingAddresses();
try {
foreach ($shippingAddresses as $address) {
$order = $this->_prepareOrder($address);
$orders[] = $order;
Mage::dispatchEvent(
'checkout_type_multishipping_create_orders_single', array('order' => $order, 'address' => $address)
);
}
foreach ($orders as $order) {
$order->place();
$order->save();
if ($order->getCanSendNewEmailFlag()) {
$order->sendNewOrderEmail();
}
$orderIds[$order->getId()] = $order->getIncrementId();
}
Mage::getSingleton('core/session')->setOrderIds($orderIds);
Mage::getSingleton('checkout/session')->setLastQuoteId($quote->getId());
$quote->setIsActive(false)->save();
Mage::dispatchEvent('checkout_submit_all_after', array('orders' => $orders, 'quote' => $quote));
return $this;
} catch (Exception $e) {
Mage::dispatchEvent('checkout_multishipping_refund_all', array('orders' => $orders));
throw $e;
}
Ok I solved the issue and successfully was able to write a script to turn an ordinary admin order into a multi address order. One of the mistakes that messed with me the entire time was the way I loaded the admin quote:
I was loading the session like this
$session = Mage::getSingleton('adminhtml/session_quote');
and it should be
$session = Mage::getModel('adminhtml/session_quote');
Now, as far as assigning each of the quote items to an address, the final code looks like:
$address = Mage::getModel('customer/address')->load($addressID);
echo"<br/>address id is $addressID<br/>";
echo"quote address not set, adding shipping address <br/>";
$quoteAddress = Mage::getModel('sales/quote_address')->importCustomerAddress($address);
$quote->addShippingAddress($quoteAddress);
$quoteAddressItem = $quoteAddress->getItemByQuoteItemId($quoteItem->getId());
if ($quoteAddressItem) {
echo"increasing item quantitiy for quote address<br/>";
// $quoteAddressItem->setQty((int) ($quoteAddressItem->getQty() + $qty));
} else {
echo"setting customer id for quote item<br/>";
$quoteItem->setCustomerAddressId($quoteAddress->getCustomerAddressId());
echo"adding item to quote address<br/>";
$quoteAddress->addItem($quoteItem)->setQuote($quote);
echo"adding item to quote collection<br/>";
if (!$quoteAddress->getItemsCollection()->getItemById($quoteItem->getId())) {
$quoteAddress->getItemsCollection()->addItem($quoteItem)->save();
}
$quoteAddress->setCollectShippingRates(TRUE);
$quoteAddress->collectShippingRates();
$quoteAddress->save();
$quoteItem->save();
$quote->save();
}

Magento sets null value for non-selected attribute value in admin. It affects the frontend display. How to deal with it?

I've created a new attribute (type: dropdown) that is not a required field.
At this moment, every product shows in the frontend "my attribute: n/a".
After save anything in some product, magento write a null value inside catalog_product_entity_int table for this attribute.
But in the frontend the attribute now appear as "my attribute: No" instead of "N/A".
It looks like a bug, since I didn't touch in the attribute while editing the new product.
Is there a way to deal with it or to apply some rule in my phtml?
Actually this is not a bug. It's a feature.
N/A is displayed when there is no record in the table catalog_product_entity_int for that attribute.
When you add an attribute there are no values for that attribute for any product, but as soon as you save a product that has that attribute, a null value is inserted in the table (as you stated). So no value is different from null value.
All the magic happens here Mage_Catalog_Block_Product_View_Attributes::getAdditionalData().
These are the lines that interest you:
if (!$product->hasData($attribute->getAttributeCode())) { // no value in the database
$value = Mage::helper('catalog')->__('N/A');
} elseif ((string)$value == '') { // empty value in the database
$value = Mage::helper('catalog')->__('No');
}
If you want to change anything override this method.
If you change anything you might want to take a look at Mage_Catalog_Block_Product_Compare_List::getProductAttributeValue().
The same system is used for displaying attribute values in the compare products list.
I've ended up to create 2 observers... One that overrides getValue from Mage_Eav_Model_Entity_Attribute_Frontend_Default and other to override getAdditionalData in Mage_Catalog_Block_Product_View_Attributes as follows:
<?php
class Namespace_Module_Model_Entity_Attribute_Frontend_Default extends Mage_Eav_Model_Entity_Attribute_Frontend_Default{
public function getValue(Varien_Object $object)
{
$value = $object->getData($this->getAttribute()->getAttributeCode());
if (in_array($this->getConfigField('input'), array('select','boolean'))) {
$valueOption = $this->getOption($value);
if (!$valueOption) {
$opt = Mage::getModel('eav/entity_attribute_source_boolean');
$options = $opt->getAllOptions();
if ($options && !is_null($value)) { //added !is_null
foreach ($options as $option) {
if ($option['value'] == $value ) {
$valueOption = $option['label'];
}
}
}
}
$value = $valueOption;
} elseif ($this->getConfigField('input') == 'multiselect') {
$value = $this->getOption($value);
if (is_array($value)) {
$value = implode(', ', $value);
}
}
return $value;
}
}
and
<?php
class Namespace_Module_Block_Product_View_Attributes extends Mage_Catalog_Block_Product_View_Attributes
{
public function getAdditionalData(array $excludeAttr = array())
{
$data = array();
$product = $this->getProduct();
$attributes = $product->getAttributes();
foreach ($attributes as $attribute) {
if ($attribute->getIsVisibleOnFront() && !in_array($attribute->getAttributeCode(), $excludeAttr)) {
$value = $attribute->getFrontend()->getValue($product);
if (!$product->hasData($attribute->getAttributeCode()) || (string)$value == '') { //modified
$value = Mage::helper('catalog')->__('N/A');
} elseif ($attribute->getFrontendInput() == 'price' && is_string($value)) {
$value = Mage::app()->getStore()->convertPrice($value, true);
}
if (is_string($value) && strlen($value)) {
$data[$attribute->getAttributeCode()] = array(
'label' => $attribute->getStoreLabel(),
'value' => $value,
'code' => $attribute->getAttributeCode()
);
}
}
}
return $data;
}
}

Display multi-option customer attribute within customer management admin grid

Okay so with Customer Attributes I have a multi-option selection that I have added to the Manage Customers Grid.
$prodCode = Mage::getSingleton('eav/config')->getAttribute('customer','prod_codes');
$prodCodeOptions = $prodCode->getSource()->getAllOptions(false);
$prodOptions = array();
foreach($prodCodeOptions as $k)
$prodOptions[$k['value']] = $k['label'];
$this->addColumn('prod_codes', array(
'header' => Mage::helper('customer')->__('Product Code'),
'width' => '100',
'index' => 'prod_codes',
'type' => 'options',
'options' => $prodOptions,
'filter_condition_callback'
=> array($this, '_filterProdOptionsCondition'),
));
I do have my attribute added to the collection at the top of my Grid.php:
->addAttributeToSelect('prod_codes')
Here is my _filterProdOptionsCondition method:
protected function _filterProdOptionsCondition($collection, $column) {
if(!$value = $column->getFilter()->getValue()) {
return;
}
$this->getCollection()->addFieldToFilter('prod_codes', array('finset' => $value));
#print($collection->getSelectSql());
}
Now this work fine and dandy if I only have ONE of the options selected, once I apply more than one option to the customers attribute I will get a blank results within the admin grid, however it IS still searchable.
A close look with the print($collection->getSelectSql()); uncommented I see that the attribute ID values are being returned in an comma delimited list.
Now onto my question with that background laid out, is there a method or "Magento" way to display these multi-options within the admin grid I'm just unaware of? Or do I need to simply get the comma values exploded and call for a new collection to build out the display values? Any help appreciated!
Appears I had to extend the Column renderer to anticipate comma values and simply render them, I'm amazed this isn't built in since the functionality exists to create the multioptions attributes but no grid display option for it.
app/code/local/Mage/Adminhtml/Block/Widget/Grid/Column/Renderer/Options.php
public function render(Varien_Object $row)
{
$options = $this->getColumn()->getOptions();
$showMissingOptionValues = (bool)$this->getColumn()->getShowMissingOptionValues();
if (!empty($options) && is_array($options)) {
$value = $row->getData($this->getColumn()->getIndex());
if (is_array($value)) {
$res = array();
foreach ($value as $item) {
if (isset($options[$item])) {
$res[] = $options[$item];
}
elseif ($showMissingOptionValues) {
$res[] = $item;
}
}
return implode(', ', $res);
}
elseif (isset($options[$value])) {
return $options[$value];
} elseif (is_string($value)) { // <--- MY CHANGES HERE
$values = explode(',', $value);
$returnOptions = "";
foreach($values as $k=>$v) {
$returnOptions .= $options[$v]. ", ";
}
return substr($returnOptions, 0, -2);
}
return '';
}
}

How to send Product Selected Custom Option Sku Field to cart page in Magento

I am working in a scenario I want to send Product selected Custom Option SKU in cart page have founded the array which is sent to cart in case of custom options.
Here is a Function called getProductOptions() in which Product Option Array is created and sent to cart. At this point, I want to send selected Custom Option SKU field to cart.
I have the following code:
public function getProductOptions()
{
$options = array();
if ($optionIds = $this->getItem()->getOptionByCode('option_ids')) {
$options = array();
foreach (explode(',', $optionIds->getValue()) as $optionId) {
if ($option = $this->getProduct()->getOptionById($optionId)) {
//echo $optionId;
echo "hhhhhhhhhhhhh";
//print_r( $option->getId());
//echo Mage::getModel('catalog/product')->getOptionSku($option);
//die();
//print_r( $option->getOptionSku());
//echo Mage_Catalog_Model_Product_Option_Type_Select::getOptionSku());
$quoteItemOption = $this->getItem()->getOptionByCode('option_' . $option->getId());
//echo $option->getQuoteItemOption($quoteItemOption);
$group = $option->groupFactory($option->getType())
->setOption($option)
->setQuoteItemOption($quoteItemOption);
$options[] = array(
'label' => $option->getTitle(),
'value' => $group->getFormattedOptionValue($quoteItemOption->getValue()),
'print_value' => $group->getPrintableOptionValue($quoteItemOption->getValue()),
'option_id' => $option->getId(),
'option_type' => $option->getType(),
'custom_view' => $group->isCustomizedView(),
'option_sku'=>//What should i call here to send Selected option SKU to this Array
);
}
}
if ($addOptions = $this->getItem()->getOptionByCode('additional_options')) {
$options = array_merge($options, unserialize($addOptions->getValue()));
}
}
return $options;
}
It looks like the bit you're missing is
'option_sku' => $this->getItem()->getSku()
Don't modify the block itself, just change the rendered template to add a for this field. Grab the data from the $_item variable, and echo it out to the user. That should require no modifications of the block.

Resources