The question:
I have followed this:
https://www.siphor.com/adding-custom-attributes-to-magento-2-quotes-and-orders/
It works well when creating custom attributes and adding data quote but after checkout, quote is not saved in table sales_orders_item.
Please help me ! I have been thinking a lot but the problem is still not resolved.
Thanks very much
The Solutions:
Below are the methods you can try. The first solution is probably the best. Try others if the first one doesn’t work. Senior developers aren’t just copying/pasting – they read the methods carefully & apply them wisely to each case.
Method 1
You can follow the steps below to save the quote-item custom field to sales_orders_item custom fields
** Note:**
1) Assume custom field data is successfully saved in quote_item table. So the steps only describe how to save quote-item custom field value to sales_orders_item
2) Assume your custom filed name is my_custom_attribute in both quote_item and sales_orders_item table
2) Assume you are using a custom module names “Company_MyModule“
step 1)
Create a di.xml under MAGENTO-ROOT/app/code/Company/MyModule/etc/di.xml
File: MAGENTO-ROOT/app/code/Company/MyModule/etc/di.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<type name="MagentoQuoteModelQuoteItemToOrderItem">
<plugin name="company_mymoduleSales_Quote_Item_ToOrderItem" type="CompanyMyModulePluginQuoteItemToOrderItemPlugin" />
</type>
</config>
step 2)
Create the plugin class QuoteItemToOrderItemPlugin.php under MAGENTO-ROOT/app/code/Company/MyModule/Plugin
File: MAGENTO-ROOT/app/code/Company/MyModule/Plugin/QuoteItemToOrderItemPlugin.php
<?php
namespace CompanyMyModulePlugin;
use MagentoFrameworkSerializeSerializerInterface;
class QuoteItemToOrderItemPlugin
{
public function aroundConvert(MagentoQuoteModelQuoteItemToOrderItem $subject, callable $proceed, $quoteItem, $data)
{
// get order item
$orderItem = $proceed($quoteItem, $data);
// get your custom attribute from quote_item .
$quoteItemMycustomAttribValue = $quoteItem->getMyCustomAttribite();
//set custom attribute to sales_order_item
$orderItem->setMyCustomAttribite($quoteItemMycustomAttribValue);
return $orderItem;
}
}
step 3)
Run Di compile commands
php bin/magento setup:di:compile
Method 2
app/code/Vendor/Module/etc/catalog_attributes.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Catalog:etc/catalog_attributes.xsd">
<group name="quote_item">
<attribute name="custom_attribute"/>
</group>
</config>
app/code/Vendor/Module/Setup/InstallData.php
<?php
namespace [Vendor][Module]Setup;
use MagentoEavSetupEavSetup;
use MagentoEavSetupEavSetupFactory;
use MagentoFrameworkDBDdlTable;
use MagentoFrameworkSetupInstallDataInterface;
use MagentoFrameworkSetupModuleContextInterface;
use MagentoFrameworkSetupModuleDataSetupInterface;
use MagentoSalesSetupSalesSetupFactory;
use MagentoQuoteSetupQuoteSetupFactory;
/**
* @codeCoverageIgnore
*/
class InstallData implements InstallDataInterface
{
/**
* EAV setup factory
*
* @var EavSetupFactory
*/
private $eavSetupFactory;
/**
* @var QuoteSetupFactory
*/
private $quoteSetupFactory;
/**
* @var SalesSetup
*/
private $salesSetupFactory;
/**
* InstallData constructor.
* @param EavSetupFactory $eavSetupFactory
* @param QuoteSetupFactory $quoteSetupFactory
*/
public function __construct(
EavSetupFactory $eavSetupFactory,
QuoteSetupFactory $quoteSetupFactory,
SalesSetupFactory $salesSetupFactory
)
{
$this->eavSetupFactory = $eavSetupFactory;
$this->quoteSetupFactory = $quoteSetupFactory;
$this->salesSetupFactory = $salesSetupFactory;
}
public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context)
{
/** @var EavSetup $eavSetup */
$eavSetup = $this->eavSetupFactory->create(['setup' => $setup]);
/** @var QuoteSetup $quoteSetup */
$quoteSetup = $this->quoteSetupFactory->create(['setup' => $setup]);
/** @var SalesSetup $salesSetup */
$salesSetup = $this->salesSetupFactory->create(['setup' => $setup]);
/**
* Add attributes to the eav/attribute
*/
$eavSetup->addAttribute(
MagentoCatalogModelProduct::ENTITY,
'custom_attribute',
[
'type' => 'int',
'label' => 'Custom Attribute',
'input' => 'select',
'global' => MagentoEavModelEntityAttributeScopedAttributeInterface::SCOPE_GLOBAL,
'visible' => true,
'required' => false,
'user_defined' => true,
'default' => '',
'searchable' => false,
'filterable' => false,
'comparable' => false,
'visible_on_front' => false,
'used_in_product_listing' => false,
'unique' => false,
'option' => [
'values' => [
'Option 1',
'Option 2',
'Option 3'
],
]
]
);
$attributeSetId = $eavSetup->getDefaultAttributeSetId('catalog_product');
$eavSetup->addAttributeToSet(
'catalog_product',
$attributeSetId,
'General',
'custom_attribute'
);
$attributeOptions = [
'type' => Table::TYPE_TEXT,
'visible' => true,
'required' => false
];
$quoteSetup->addAttribute('quote_item', 'custom_attribute', $attributeOptions);
$salesSetup->addAttribute('order_item', 'custom_attribute', $attributeOptions);
}
}
app/code/Vendor/Module/etc/events.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
<event name="sales_quote_item_set_product">
<observer name="set_item_custom_attribute" instance="[Vendor][Module]ObserverSetItemCustomAttribute" />
</event>
</config>
app/code/Vendor/Module/Observer/SetItemCustomAttribute.php
<?php
namespace [Vendor][Module]Observer;
use MagentoFrameworkEventObserverInterface;
class SetItemCustomAttribute implements ObserverInterface
{
/**
* @param MagentoFrameworkEventObserver $observer
* @return void
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
public function execute(MagentoFrameworkEventObserver $observer)
{
$quoteItem = $observer->getQuoteItem();
$product = $observer->getProduct();
$quoteItem->setCustomAttribute($product->getAttributeText('custom_attribute'));
}
}
app/code/Vendor/Module/etc/fieldset.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="lib/internal/Magento/Framework/Object/etc/fieldset.xsd">
<scope id="global">
<fieldset id="quote_convert_item">
<field name="custom_attribute">
<aspect name="to_order_item" />
</field>
</fieldset>
</scope>
</config>
app/code/Vendor/Module/etc/di.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<type name="MagentoQuoteModelQuoteItemToOrderItem">
<plugin name="custom_attribute_quote_to_order_item" type="[Vendor][Module]PluginCustomAttributeQuoteToOrderItem"/>
</type>
</config>
app/code/Vendor/Module/Plugin/CustomAttributeQuoteToOrderItem.php
<?php
namespace [Vendor][Module]Plugin;
class CustomAttributeQuoteToOrderItem
{
public function aroundConvert(
MagentoQuoteModelQuoteItemToOrderItem $subject,
Closure $proceed,
MagentoQuoteModelQuoteItemAbstractItem $item,
$additional = []
) {
/** @var $orderItem MagentoSalesModelOrderItem */
$orderItem = $proceed($item, $additional);
$orderItem->setCustomAttribute($item->getCustomAttribute());
return $orderItem;
}
}
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0