15

I am building a custom module in magento 2 that have a custom discount. I am trying to copy the discount from quote, quote item to order and order item. In magento 1, I declare in config.xml like this:

<fieldsets>
    <sales_convert_quote_address>
        <custom_discount_amount><to_order>*</to_order></custome_discount_amount>
        <base_custom_discount_amount><to_order>*</to_order></base_custome_discount_amount>
    </sales_convert_quote_address>
    <sales_convert_quote_item>
        <custome_discount_amount><to_order_item>*</to_order_item></custome_discount_amount>
        <base_custom_discount_amount><to_order_item>*</to_order_item></base_custom_discount_amount>
    </sales_convert_quote_item>
</fieldsets> 

and my custom discount amount was copied to tables: sales_flat_order and sales_flat_order_item as expected.

In Magento 2, I created a file name: fieldset.xml with this code:

<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="sales_convert_quote_item">
        <field name="custom_discount_amount">
            <aspect name="to_order_item" />
        </field>
        <field name="base_custom_discount_amount">
            <aspect name="to_order_item" />
        </field>
    </fieldset>         
      <fieldset id="sales_convert_quote_address">
        <field name="custom_discount_amount">
            <aspect name="to_order" />
        </field>
        <field name="base_custom_discount_amount">
            <aspect name="to_order" />
        </field>
    </fieldset>   
</scope>

but there is no success. What else I need to do in magento 2 to make it works? Can you guys please help me?

3 Answers 3

9

It appears fieldsets are no longer an option for moving custom data fields around. Not clear if this is intentional, or a side-effect of other changes.

I just ran into the same problem with payments. I traced that back to \Magento\Quote\Model\Quote\Payment\ToOrderPayment::convert():

public function convert(Payment $object, $data = [])
{
    $paymentData = $this->objectCopyService->getDataFromFieldset(
        'quote_convert_payment',
        'to_order_payment',
        $object
    );

    $orderPayment = $this->orderPaymentFactory->create();
    $this->dataObjectHelper->populateWithArray(
        $orderPayment,
        array_merge($paymentData, $data),
        '\Magento\Sales\Api\Data\OrderPaymentInterface'
    );
    $orderPayment->setAdditionalInformation(
        array_merge(
            $object->getAdditionalInformation(),
            [Substitution::INFO_KEY_TITLE => $object->getMethodInstance()->getTitle()]
        )
    );
    // set directly on the model
    $orderPayment->setCcNumber($object->getCcNumber());
    $orderPayment->setCcCid($object->getCcCid());

    return $orderPayment;
}

It starts by processing the fieldset to copy data from $object into the $paymentData array, but then feeds that array into \Magento\Framework\Api\DataObjectHelper::populateWithArray() to actually set the values on the target object (here, $orderPayment).

Rather than directly adding the data array to the object as in Magento 1, DataObjectHelper looks for 'set__' or 'setIs__' methods corresponding to each key, and then calls those methods with the value. If such method does not exist, the data key is skipped entirely.

Quote addresses and items are processed the same way, in \Magento\Quote\Model\Quote\Address\ToOrderAddress and \Magento\Quote\Model\Quote\Item\ToOrderItem respectively.

What does that mean?

  1. Adding the key to a fieldset is not sufficient, unless a set method already exists on the object corresponding to that key.
  2. It appears that copying custom fields from quote to order will require either overriding the target class to add the necessary setter method(s) (via dependency injection), or using observers like sales_model_service_quote_submit_before to copy the data manually.

Also note that the quote module has its own fieldsets defined, including quote_convert_address and quote_convert_item. It does not appear that the sales_convert_quote* fieldsets are in use anymore.

3
  • :- i am confusing from your answer, i just under stood moving data from quote to order was removed in magebnto2 , then how to do it for my custom fields ? can you post the code, in my answer i gave fix for core magento issue(check my answer above ) , do you have any other solution for this issue ? Dec 15, 2015 at 4:02
  • did you get any solution Oct 18, 2019 at 12:05
  • using event sales_model_service_quote_submit_before helped me. Sep 25, 2020 at 10:08
5

Magento2 sales convert from quote to order and its item is not working
quote Convert model for quote to order and its item is moved from sales module to Quote module in Magento2 But its not working

<fieldset id="sales_convert_quote">
            <field name="custom_field">
                <aspect name="to_order" />
            </field>
        </fieldset>        
        <fieldset id="quote_convert_item">
            <field name="custom_sku">
                <aspect name="to_order_item" />
            </field>
        </fieldset> 

convert from order and order item to invoice, shipment and Creditmemo is working fine in Magento2

below is the fix for convert quote to order in magento2 else you need to write event to move all filed value from quote to order table magento2a\app\code\Sugarcode\Test\etc\fieldset.xml

    <?xml version="1.0"?>
<!--
/**
 * Copyright © 2015 Magento. All rights reserved.
 * See COPYING.txt for license details.
 */
-->
<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="sales_convert_quote">
            <field name="custom_field">
                <aspect name="to_order" />
            </field>
        </fieldset>        
        <fieldset id="quote_convert_item">
            <field name="custom_sku">
                <aspect name="to_order_item" />
            </field>
        </fieldset>         
        <fieldset id="sales_convert_order">
            <field name="custom_field">
                <aspect name="to_quote" />
                <aspect name="to_invoice" />
                <aspect name="to_shipment" />
                <aspect name="to_cm" />
            </field>
        </fieldset>        
        <fieldset id="sales_convert_order_item">
            <field name="custom_sku">
                <aspect name="to_quote_item" />
                <aspect name="to_invoice_item" />
                <aspect name="to_shipment_item" />
                <aspect name="to_cm_item" />
            </field>            
        </fieldset>
    </scope>
</config>


app\code\Magento\Quote\Model\QuoteManagement.php (line no 428 )

before

$billingAddress = $this->quoteAddressToOrderAddress->convert(
            $quote->getBillingAddress(),
            [
                'address_type' => 'billing',
                'email' => $quote->getCustomerEmail()
            ]
        );

in function submitQuote() add below code

$order=$this->quoteAddressToOrder->convert($quote->getBillingAddress(), $orderData);

change in app\code\Magento\Quote\Model\Quote\Item\ToOrderItem.php (lin no around 78)

after

$orderItem = $this->orderItemFactory->create();

in function convert() add below code

$this->objectCopyService->copyFieldsetToTarget('quote_convert_item', 'to_order_item', $item, $orderItem);

it will work fine but
make sure as i mention above fieldset.xml should be there in you custom module and also you should write event to set product attribute once product is added to cart as like in magento1.x and also you should set custom filed in quote table then only it will copy from quote and item to order and its item

1
  • Pradeep. Is it still not supported?
    – awavi
    Mar 2, 2016 at 0:18
0

I've been looking into this, and in Magento\GiftMessage module, there is also conversion of fields (fieldset.xml):

<fieldset id="sales_convert_quote_address">
    <field name="gift_message_id">
        <aspect name="to_order" />
    </field>
</fieldset>

The way they add it to order is via observer (Observer/SalesEventQuoteSubmitBeforeObserver.php, registered in etc/frontend/events.xml):

public function execute(\Magento\Framework\Event\Observer $observer)
{
    $observer->getEvent()->getOrder()->setGiftMessageId($observer->getEvent()->getQuote()->getGiftMessageId());

    return $this;
}

So, I guess, this is a viable option to consider.

3
  • It is possible to have Magento 2 automatically copy values for orders, payments etc. by using extension attributes. However, creating extension attributes for order_items requires custom observers in order to handle the loading and saving of data to the quote_item and order_item objects. Because of this, it is much simpler to follow the approach suggested above to add a column to the relevant tables and use a single observer method to copy the data across. Sadly, Magento have tried to make the extensibility in v2 so flexible that it requires too much boilerplate to make it worth our time. Jun 15, 2016 at 10:34
  • @epson121 : could you share your events.xml in this case? Jul 25, 2016 at 12:04
  • @IpsitaRout you can check default Magento code (app/code/Magento/GiftMessage/etc/frontend/events.xml ) or check this excerpt: <event name="sales_model_service_quote_submit_before"> <observer name="giftmessage" instance="Magento\GiftMessage\Observer\SalesEventQuoteSubmitBeforeObserver" shared="false" /> </event>
    – epson121
    Jul 25, 2016 at 12:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.