I need to add my custom detail in cart along with product detail and transfer these details in order too. I want to use additional option functionality for this.
1 Answer
- For AddtoCart add events.xml file in app/code/[VendorName]/CustomModule/etc/frontend folder
<event name="checkout_cart_product_add_after">
<observer name="customprice" instance="[VendorName]\CustomModule\Observer\CustomPrice" />
</event>
- Create CustomPrice.php file on [VendorName]\CustomModule\Observer folder
<?php
namespace [VendorName]\CustomModule\Observer;
use Magento\Framework\Event\ObserverInterface;
use Magento\Framework\App\RequestInterface;
use Magento\Framework\Serialize\Serializer\Json;
use Magento\Framework\App\ObjectManager;
class CustomPrice implements ObserverInterface
{
/**
*
* @var type \Magento\CatalogRule\Model\Rule
*/
protected $rule;
/**
*
* @param RequestInterface $request
* @param \Magento\CatalogRule\Model\Rule $rule
*/
public function __construct(
\Magento\Framework\App\RequestInterface $request,
\Magento\CatalogRule\Model\Rule $rule,
Json $serializer = null
)
{
$this->rule = $rule;
$this->_request = $request;
$this->serializer = $serializer ?: ObjectManager::getInstance()->get(Json::class);
}
/**
*
* @param \Magento\Framework\Event\Observer $observer
*/
public function execute(\Magento\Framework\Event\Observer $observer) {
$optionsSize = $this->_request->getPost('options-size')?$this->_request->getPost('options-size'):'';
$optionsFinish = $this->_request->getPost('options-finish')?$this->_request->getPost('options-finish'):'';
$optionsCminch = $this->_request->getPost('options-finish')?$this->_request->getPost('cminch'):'in';
$customizationDetails = $this->_request->getPost('customization_details')?$this->_request->getPost('customization_details'):'';
/* Default option */
$item = $observer->getEvent()->getData('quote_item');
$item = ( $item->getParentItem() ? $item->getParentItem() : $item );
$product = $item->getProduct();
$candidates['value'] = 0.00;
$candidates['order_quantity'] = 0;
if($product->getTypeId() != 'giftvoucher'){
$finishOption = array(
'label' => 'Finish',
'value' => 'Natural',
);
$sizeOption = array(
'label' => 'Size',
'value' => $product->getDefaultHeight().' W X '.$product->getDefaultWidth().' H inch',
);
$productId = $product->getId();
if($optionsSize || $optionsFinish)
{
$customPrice = $item->getProduct()->getFinalPrice();
$productId = $this->_request->getPost('product');
if($optionsSize)
{
$customSize = explode(':',$optionsSize);
$unitPrice = $product->getUnitPrice();
$fixedPrice = $product->getFixedPrice();
$customPrice = ceil(($unitPrice*$customSize[0]*$customSize[1]/10000)+$fixedPrice);
if($optionsCminch=='cm')
{
$sizeOption = array(
'label' => 'Size',
'value' => $customSize[0].' W X '.$customSize[1].' H cm',
);
}else{
$sizeOption = array(
'label' => 'Size',
'value' => round($customSize[0]*0.393701).' W X '.round($customSize[1]*0.393701).' H inch',
);
}
//$itemsOptions[] = $sizeOption;
$weight = round(($customSize[0] * $customSize[1] / 10000) * 18);
$weight = ceil(2.20462 * $weight);
$item->setWeight($weight);
}
if($optionsFinish){
$customFinish = json_decode(trim($optionsFinish), true);
$customPrice = $customPrice + ceil($customPrice*$customFinish['price']/100);
$finishOption = array(
'label' => 'Finish',
'value' => $customFinish['title'],
);
//$itemsOptions[] = $finishOption;
}
if($customizationDetails){
$customizationArray = array(
'label' => 'Details',
'value' => $customizationDetails,
);
$itemsOptions['Details'] = $customizationArray;
}
//$item->getCustomTierPrice($customPrice);
$objectManager = \Magento\Framework\App\ObjectManager::getInstance(); // Instance of Object Manager
$priceHelper = $objectManager->create('Magento\Framework\Pricing\Helper\Data'); // Instance of Pricing Helper
$customPrice = $priceHelper->currency($customPrice, false, false);
$customCalculatedPrice = round($this->rule->calcProductPriceRule($product,$customPrice));
if($customCalculatedPrice){
$customPrice = $customCalculatedPrice;
}
//$customPrice = round($customPrice);
$item->setCustomPrice($customPrice);
$item->setOriginalCustomPrice($customPrice);
}
$itemsOptions['finishOption'] = $finishOption;
$itemsOptions['sizeOption'] = $sizeOption;
$itemAllOptions = [];
foreach ($itemsOptions as $itemsOption) {
$itemAllOptions[] = $itemsOption;
}
$item->addOption(
array(
'product' => $productId,
'code' => 'additional_options',
'value' => $this->serializer->serialize($itemAllOptions)
)
);
$item->getProduct()->setIsSuperMode(true);
$currencysymbol = $objectManager->get('Magento\Store\Model\StoreManagerInterface');
$currency = $currencysymbol->getStore()->getCurrentCurrencyCode();
$catalogSession = $objectManager->get('\Magento\Catalog\Model\Session');
$candidates['value'] = $customPrice * $item->getProduct()->getQty();
$candidates['product_id'] = $productId;
$candidates['order_quantity'] = $item->getProduct()->getQty();
$candidates['currency'] = $currency;
$catalogSession->setPrestAddToCart($candidates);
$logger->info(print_r($candidates, true));
}/* end product type condition */
}
}
- For after submit quote and order place. Create events.xml file in app/code/[VendorName]/CustomModule/etc folder
<event name="sales_model_service_quote_submit_before">
<observer name="ordercustomoption" instance="[VendorName]\CustomModule\Observer\OrderCustomOption" />
</event>
- Create OrderCustomOption.php file on [VendorName]\CustomModule\Observer folder
<?php
namespace [VendorName]\CustomModule\Observer;
use Magento\Framework\Event\ObserverInterface;
use Magento\Framework\Serialize\Serializer\Json;
use Magento\Framework\App\ObjectManager;
class OrderCustomOption implements ObserverInterface
{
public function __construct(
Json $serializer = null
) {
$this->serializer = $serializer ?: ObjectManager::getInstance()->get(Json::class);
}
public function execute(\Magento\Framework\Event\Observer $observer)
{
try {
$quote = $observer->getQuote();
$order = $observer->getOrder();
$quoteItems = [];
// Map Quote Item with Quote Item Id
foreach ($quote->getAllVisibleItems() as $quoteItem) {
$quoteItems[$quoteItem->getId()] = $quoteItem;
}
foreach ($order->getAllVisibleItems() as $orderItem) {
$quoteItemId = $orderItem->getQuoteItemId();
$quoteItem = $quoteItems[$quoteItemId];
$additionalOptions = $quoteItem->getOptionByCode('additional_options');
if(isset($additionalOptions)){
// Get Order Item's other options
$options = $orderItem->getProductOptions();
// Set additional options to Order Item
$options['additional_options'] = $this->serializer->unserialize($additionalOptions->getValue());
$orderItem->setProductOptions($options);
}
}
} catch (\Exception $e) {
echo $e->getMessage();
}
}
private function getQuoteItemById($id)
{
if(empty($this->quoteItems))
{
/* @var \Magento\Quote\Model\Quote\Item $item */
foreach($this->quote->getItems() as $item)
{
//filter out config/bundle etc product
if(!$item->getParentItemId() && $item->getProductType() == \Magento\Catalog\Model\Product\Type::TYPE_SIMPLE)
{
$this->quoteItems[$item->getId()] = $item;
}
}
}
if(array_key_exists($id, $this->quoteItems))
{
return $this->quoteItems[$id];
}
return null;
}
}
-
Worked for me, pretty much a plug and play solution (don't try to put the events.xml in the frontend dir - it needs to be global. One minor note, the method
getQuoteItemById
doesn't seem to be called, should it be removed? Aug 30, 2022 at 14:30