2

i'm try to make a order's state to processing from complete. here is the code

class TempName_HelloWorld_IndexController extends Mage_Core_Controller_Front_Action
{
    public function indexAction()
    {
     $this->loadLayout(array('default'));
     $this->renderLayout();

     $order = Mage::getModel('sales/order');
     $order->loadByIncrementId(100000041);
     $order->setState(Mage_Sales_Model_Order::STATE_PROCESSING, true, 'Gateway has authorized the payment.');
     $order->save();
    }
}

?>

the above code can update the order state from pending/pending payment to processing, but i can't update the order state from complete to processing. Anyone can what is the problem?

2
  • What happens when you try? Do you get any errors? Apr 10, 2014 at 8:31
  • nothing happens...
    – hkguile
    Apr 10, 2014 at 8:32

1 Answer 1

5

By default you can't adjust the order state when it's complete. This is because this state is protected.

A closer look at the code tells us why:

When you call setState the following is triggered in the Mage_Sales_Model_Order class.

public function setState($state, $status = false, $comment = '', $isCustomerNotified = null)
{
    return $this->_setState($state, $status, $comment, $isCustomerNotified, true);
}

Which, as you can see bubbles directly down to _setState.

protected function _setState($state, $status = false, $comment = '',
    $isCustomerNotified = null, $shouldProtectState = false)
{
    // attempt to set the specified state
    if ($shouldProtectState) {
        if ($this->isStateProtected($state)) {
            Mage::throwException(
                Mage::helper('sales')->__('The Order State "%s" must not be set manually.', $state)
            );
        }
    }
    $this->setData('state', $state);

    // add status history
    if ($status) {
        if ($status === true) {
            $status = $this->getConfig()->getStateDefaultStatus($state);
        }
        $this->setStatus($status);
        $history = $this->addStatusHistoryComment($comment, false); // no sense to set $status again
        $history->setIsCustomerNotified($isCustomerNotified); // for backwards compatibility
    }
    return $this;
}

In which all states that are passed in are checked using the isStateProtected method.

Check that method tells us that the 'complete' state is protected. Thus is being blocked for further updates.

public function isStateProtected($state)
{
    if (empty($state)) {
        return false;
    }
    return self::STATE_COMPLETE == $state || self::STATE_CLOSED == $state;
}

When an order is complete, usually it's invoiced and shipped etc. So why would you want to adjust the state back to 'processing'? That would mean the order is not shipped anymore, while a shipment is probably already created. That will probably give you some trouble further down the road.

For now at least you know why you can't adjust the order. Hopefully this helps you!

3
  • thanks for reply, but if the operators of the eshop wrongly completed the order, so what action can i take?
    – hkguile
    Apr 14, 2014 at 5:35
  • Then you will have to reset the order to the correct state. It was just a headsup that resetting an order state from complete to something different can result in problems. So if you want to be able to do this, you will have to adjust the isStateProtected method. If this works for you, then please mark this answer as the correct one.
    – Tim Hofman
    Apr 14, 2014 at 8:53
  • Caution: the interpretation of the isStateProtected method in this answer is wrong. It doesn't check the state the order currently is, but the state that is BEING set. It's very clear by the method's implementation that it'll return false and won't do anything when setting the state to processing. May 28, 2017 at 22:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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