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

Was it helpful?

Solution

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="Magento\Quote\Model\Quote\Item\ToOrderItem">
        <plugin name="company_mymodule\Sales_Quote_Item_ToOrderItem" type="Company\MyModule\Plugin\QuoteItemToOrderItemPlugin" />
    </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 Company\MyModule\Plugin;

use Magento\Framework\Serialize\SerializerInterface;


class QuoteItemToOrderItemPlugin
{



    public function aroundConvert(\Magento\Quote\Model\Quote\Item\ToOrderItem $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

OTHER TIPS

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 Magento\Eav\Setup\EavSetup;
use Magento\Eav\Setup\EavSetupFactory;
use Magento\Framework\DB\Ddl\Table;
use Magento\Framework\Setup\InstallDataInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\ModuleDataSetupInterface;
use Magento\Sales\Setup\SalesSetupFactory;
use Magento\Quote\Setup\QuoteSetupFactory;

/**
 * @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(
            \Magento\Catalog\Model\Product::ENTITY,
            'custom_attribute',
            [
                'type'                    => 'int',
                'label'                   => 'Custom Attribute',
                'input'                   => 'select',
                'global'                  => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::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]\Observer\SetItemCustomAttribute" />
    </event>
</config>

app/code/Vendor/Module/Observer/SetItemCustomAttribute.php

<?php
namespace [Vendor]\[Module]\Observer;

use Magento\Framework\Event\ObserverInterface;

class SetItemCustomAttribute implements ObserverInterface
{
    /**
     * @param \Magento\Framework\Event\Observer $observer
     * @return void
     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
     */
    public function execute(\Magento\Framework\Event\Observer $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="Magento\Quote\Model\Quote\Item\ToOrderItem">
        <plugin name="custom_attribute_quote_to_order_item" type="[Vendor]\[Module]\Plugin\CustomAttributeQuoteToOrderItem"/>
    </type>
</config>

app/code/Vendor/Module/Plugin/CustomAttributeQuoteToOrderItem.php

<?php
namespace [Vendor]\[Module]\Plugin;

class CustomAttributeQuoteToOrderItem
{
    public function aroundConvert(
        \Magento\Quote\Model\Quote\Item\ToOrderItem $subject,
        \Closure $proceed,
        \Magento\Quote\Model\Quote\Item\AbstractItem $item,
        $additional = []
    ) {
        /** @var $orderItem \Magento\Sales\Model\Order\Item */
        $orderItem = $proceed($item, $additional);
        $orderItem->setCustomAttribute($item->getCustomAttribute());
        return $orderItem;
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with magento.stackexchange
scroll top