-2

I've set up a custom sales order attribute so I can mark orders as 'sent' when they've been exported via a custom module.

My issue is it's not saving the attribute on the $_order->save() function. I've tried setSentToSage(1) and setData('sent_to_sage',1) but neither work

I've setup up the following:

Setup/InstallData.php

namespace Vendor\Module\Setup;

use Magento\Framework\Setup\InstallDataInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\ModuleDataSetupInterface;
use Magento\Sales\Setup\SalesSetupFactory;

class InstallData implements InstallDataInterface
{

    private $salesSetupFactory;

    /**
     * Constructor
     *
     * @param \Magento\Sales\Setup\SalesSetupFactory $salesSetupFactory
     */
    public function __construct(SalesSetupFactory $salesSetupFactory)
    {
        $this->salesSetupFactory = $salesSetupFactory;
    }

    /**
     * {@inheritdoc}
     */
    public function install(
        ModuleDataSetupInterface $setup,
        ModuleContextInterface $context
    ) {
        $salesSetup = $this->salesSetupFactory->create(['setup' => $setup]);
        $salesSetup->addAttribute('order', 'sent_to_sage',
            [
                'type' => 'varchar',
                'length' => 255,
                'visible' => true,
                'required' => false,
                'grid' => true,
                'user_defined' => true
            ]
        );
    }
}

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">
    <virtualType name="Magento\Sales\Model\ResourceModel\Order\Grid" type="Magento\Sales\Model\ResourceModel\Grid">
        <arguments>
            <argument name="columns" xsi:type="array">
                <item name="sent_to_sage" xsi:type="string">sales_order.sent_to_sage</item>
            </argument>
        </arguments>
    </virtualType>
</config>

Model/Orders.php

    namespace Vendor\Module\Model;

use Magento\Sales\Model\Order;

class Orders
{

  private $_order;

  public function __construct(
    Order $order,
  ){
    $this->_order = $order;
  }


    public function exportOrders()
    {   
        /*Perform export functions...*/

        /* Mark exported orders as sent */

        $this->markOrdersAsSent($order_ids);

    }

    public function markOrdersAsSent($order_ids)
    {
        if ($order_ids) {
            foreach ($order_ids as $id) {
                $_order = $this->_order->load($id);
                $_order->setSentToSage(1);
                $_order->save();
            }
        }
        return;
    }

}

Any help is appreciated. I feel I am missing something.

3
  • You missed new column to grid table !!
    – anonymous
    Commented Sep 18, 2019 at 11:06
  • sent_to_sage column has been created in sales_order table? Commented Sep 18, 2019 at 11:41
  • Yes, the column was created in sales_order. Commented Sep 30, 2019 at 8:40

4 Answers 4

1

I know this isn't the answer to your problem but when I want to update just 1 attribute I m usually do this:

public function updateOrderWithCustomAttributes($orderId,$sentToSage){
        $connection = $this->getConnection('core_write');
        $sql = "UPDATE `sales_order` SET sent_to_sage = ?  WHERE entity_id = ? ";
        $connection->query($sql,
            array($sentToSage,$orderId));
    }

I suppose you know how to do the getConnection etc. By this you don't have to load the order and save it which is very costly for the server and it is very very fast. As I said this isn't the answer but some times we don't need to spend so much time on things that we can get a workaround.

1
  • Thanks, this was the only solution that worked for me. Commented Sep 30, 2019 at 8:39
1

You can use sales order repository interface.

class name : Magento\Sales\Api\OrderRepositoryInterface

Usage: Create OrderRepositoryInterface object then load order by id

$order = $this->orderRepository->get($orderId); 

Then set value for attributes

$order->setSentToSage(1);

And save using orderRepository

$this->orderRepository->save($order);
0

Try with below code :

  protected $orderFactory;

  public function __construct(
      \Magento\Sales\Model\Order $orderFactory
  ) {
        $this->orderFactory = $orderFactory;
  }
  public function execute()
  {
    $orderId = 2;
    $order = $this->orderFactory->load($orderId);
    $order->setSentToSage(1);
    $order->save();
  }
0

Accepted Answer is work good, but there is a better and quick approach to updating order status.

if we don't need to trigger extra events or plugins of a Model and want to update only a single or a few columns just like update order status, then we can use the Zend ORM approach. I have tried to update the order status with model and repository it takes more than 3 seconds and then tries with this code it takes less than 1 second.

public function updateOrderStatus($status,$IncrementId)
{
    try {
        $where = ['increment_id = ?' => (int)$IncrementId];
        $updatedColumnValues = ["status"=>$status];
        $tableName = $this->resourceConnection->getTableName("sales_order");
        $gridTableName = $this->resourceConnection->getTableName("sales_order_grid");
        $this->resourceConnection->update($tableName, $updatedColumnValues, $where);
        $this->resourceConnection->update($gridTableName, $updatedColumnValues, $where);
    }catch (\Exception $exception){
        return $exception->getMessage();
    }
}

Resource Connection class inject in contruct method

protected $resourceConnection
use Magento\Framework\App\ResourceConnection;
$this->resourceConnection = $resourceConnection->getConnection();

Your Answer

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

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