문제

I have created a plugin which intercept the cancel function from the interface Magento\Sales\Api\OrderManagementInterface, the plugin intercept before the cancel function is called.

My problem is that when my module is activated, I can't cancel any orders, neither from the page admin/sales/order/view/order_id/10 or from the list of orders.

For example, when i click the cancel button, the text "You canceled the order." is displayed but in fact the order isn't canceled and has still the status "pending".

I have a custom table which reference the sales_order table, but the attribute referencing the table has the action on delete cascade

->addColumn(
                    'sales_order_id',
                    Table::TYPE_INTEGER,
                    10,
                    ['nullable' => false,
                    'unsigned' => true],
                    'Reference to entity_id of table sales_order'
                )
->addForeignKey(
                    $installer->getFkName('my_custom_table', 'sales_order_id', 'sales_order', 'entity_id'),
                    'sales_order_id',
                    $installer->getTable('sales_order'), /* main table name */
                    'entity_id',
                    \Magento\Framework\DB\Ddl\Table::ACTION_CASCADE
                )

But even with the action on delete cascade, before canceling an order, I'm deleting the record which is referencing to the order being cancelled.

After cancelling an order, the order is not deleted from the database and has the status cancelled, so I'm getting confused on how can my module make the cancel function bug.

The purpose of my function beforeCancel is only to remove the record with an particular id from the table referencing the sales_order table and add it into an other table having no reference.

도움이 되었습니까?

해결책 2

I found out what was wrong, nothing about the foreign key.

In order to create the plugins I first went to the interface defining the cancel order function which was declared as

     /**
     * Cancels a specified order.
     *
     * @param int $id The order ID.
     * @return bool
     */
    public function cancel($id);

So I did declare the plugin in my module/etc/di.xml

<type name="Magento\Sales\Api\OrderManagementInterface">
        <plugin name="before_cancel_order_operation"
                type="Vendor\Module\Plugin\OrderManagement"/>
</type>

Then in my Module/Plugin/OrderManagement.php file I added the function

public function beforeCancel(
        OrderManagementInterface $subject,
        int $id
    ) {
       /* Logic code */
      return true;
      }

So my thinking was since the cancel function in the OrderManagementInterface.php return a boolean (the doc is specifying that the function return a boolean), it should return true if my logic code doesn't encounter a problem.

I was wrong, returning false will lead me to an error which tells me something like 'you need to provide an id to cancel an order' returning true will lead me to an error which tells me that I can't cancel order.

I just had to remove the return...

다른 팁

I am a little bit confused about your requirement.

So far my understanding, you want to remove a record from your table which related with your cancelled Order. If this requirement then you're doing wrong bcoz of Foreign Key means when an order delete from sales_order table then a record from custom_table will be removed.

In Magento, an order is cancelled NOT means Delete the order from sales_order. It is status changed to Cancel.

So, you want to remove the record from the database table my_custom_table when order cancels then you have do below steps:

  • Remove Foreign Key related to my_custom_table's table sales_order_id column.

  • Create an after Plugin on Magento\Sales\Api\OrderManagementInterface::cancel and delete record..

Here the Plugin Class

<?php


namespace StackExchange\MagentoTest\Plugin\Magento\Sales;


class OrderManagement
{
    /**
     * @var \Magento\Sales\Model\ResourceModel\Order
     */
    private $orderResource;

    public function __construct(
     \Magento\Sales\Model\ResourceModel\Order $orderResource
    ){
        $this->orderResource = $orderResource;
    }

    public function cancel(
        \Magento\Sales\Api\OrderManagementInterface $subject,
        $result,
        $id) {

        $where = [
            ' sales_order_id = ? ' => $id
        ];
        try {
            $this->orderResource->getConnection()->delete(
                $this->orderResource->getTable('my_custom_table'),
                $where
            );
        } catch (\Exception $e) {
            throw $e;
        }
    }
}

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 magento.stackexchange
scroll top