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?
- Adding the key to a fieldset is not sufficient, unless a set method already exists on the object corresponding to that key.
- 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.
If you take a look at the current magento2.1 code base you will notice that in moduleName/etc folder there is a fieldset.xml with command to copy information from one table to another. However this DO NOT work. If you take a closer look you will also notice that there is observer that does the same exact thing. Take a look at https://github.com/magento/magento2/issues/5823
To copy from quote* to order* table you will need to use an observer and/or plugin.
In your custom Module events.xml add
<event name="sales_model_service_quote_submit_before">
<observer name="[moduelname]_sales_model_service_quote_submit_before" instance="Company\ModuleName\Observer\SaveOrderBeforeSalesModelQuoteObserver" />
</event>
Then
<?php
namespace Company\ModuleName\Observer;
use Magento\Framework\Event\ObserverInterface;
class SaveOrderBeforeSalesModelQuoteObserver implements ObserverInterface
{
/**
* List of attributes that should be added to an order.
*
* @var array
*/
private $attributes = [
'field_1_name_here',
'field_2_name_here',
'field_...._here'
];
/**
*
* @param \Magento\Framework\Event\Observer $observer
* @return $this
*/
public function execute(\Magento\Framework\Event\Observer $observer)
{
/* @var Magento\Sales\Model\Order $order */
$order = $observer->getEvent()->getData('order');
/* @var Magento\Quote\Model\Quote $quote */
$quote = $observer->getEvent()->getData('quote');
foreach ($this->attributes as $attribute) {
if ($quote->hasData($attribute)) {
$order->setData($attribute, $quote->getData($attribute));
}
}
return $this;
}
}
To copy item from quote_item to order_item, magento seem to have removed the best observer to get the job which was sales_convert_quote_item_to_order_item
. Take a look at this example that should help you copy field from quote_item to order_item table. How to "add to cart" a product with custom input field and save it to Database?
Best Answer
To copy quote item fields to sale order item fields, we need to declare these fields in fieldset.xml
app/code/Vendor/Module/etc/fieldset.xml
[EDIT]
Seem that we need to use Observer
sales_model_service_quote_submit_before
to assign the new fields: