问题
I am using a cron job to change all "pending" net-banking orders to "payment-pending"
(this is to solve my problem : Why is state not transitioning to "payment_pending" for orders cancelled at gateway?)
This is my code- [EDITED]
const MINUTES_DELAY = 15; //Orders younger than this are not changed
public function run() {
// date_default_timezone_set('Asia/Kolkata');
$old_time = time() - (self::MINUTES_DELAY*60);
$out = date('d.m.y h:i:s A', $old_time)."\n";
$out .= date('d.m.y h:i:s A')."\n";
file_put_contents('/home/vinayak/cron.txt', '1'.$out, FILE_APPEND); //Out1
$orders = Mage::getModel('sales/order')->getCollection()
->addFieldToFilter('status', 'pending')
->addFieldToFilter('cod_fee', array('null' => true))
->addAttributeToSelect('customer_email')
->addAttributeToSelect('created_at')
;
foreach ($orders as $order) {
if (strtotime($order->getCreatedAt()) < $old_time){
$order->setState('pending_payment', true)->save();
$out .= $order->getCustomerEmail()." @ ".$order->getCreatedAt()."\n";
}
}
file_put_contents('/home/vinayak/cron.txt', '2'.$out, FILE_APPEND); //Out2
return true;
}
I have checked that cron is working. But the state/status is not changing. I am not getting error now.
[EDITED] Problem Now - I am getting output marked as "out1" in the code, but not the "out2"
After varying the code, I have seen that, whenever if
condition is true the problem (above) occurs. This points out the problem with the line $order->setState('pending_payment', true)->save();
(I have commented out the other line in if
, and the problem persists, but if I comment out this line out2 gets printed). It seems as if the execution gets stuck up at this line (infinite loop? or some internal problem?)
What's wrong with $order->setState('pending_payment', true)->save();
? Any other way to accomplish the said thing?
Can I also filter by order "creation time", so that I don't change the state for order, which was created seconds ago.[SOLVED]
Thanks!
回答1:
just try to put $order->setState('pending_payment');
$order->setStatus('pending_payment');
$order->save();
I think you are not changing order status that might create problem.
回答2:
Finally solved my problem. Now the job works exactly as intended!
This is the working program-
const MINUTES_DELAY = 15; //Orders younger than this are not changed
const OUT_FILE = '/home/vinayak/cron.txt';
public function run() {
$old_time = time() - (self::MINUTES_DELAY*60);
$out = "-------------------------------------------\n";
$out .= date('d.m.y h:i:s A')."\n";
$orders = Mage::getModel('sales/order')->getCollection()
->addFieldToFilter('status', 'pending')
->addFieldToFilter('cod_fee', array('null' => true))
;
foreach ($orders as $order) {
if (strtotime($order->getCreatedAt()) < $old_time) {
try{
$id = $order->getIncrementId();
Mage::getModel('sales/order')
->loadByIncrementId($id)
->setState('pending_payment', true)
->save();
$out .= $id."\n";
} catch (Exception $e) {
$out .= "Caught exception : ".$e->getMessage()."\n";
}
}
}
file_put_contents(self::OUT_FILE, $out, FILE_APPEND);
return true;
}
Hope this helps someone.
回答3:
I have yet to master the Zend queries, so I'm always writing proper MySQL queries when interacting directly with the database. Keep in mind, order status is non-flexible until newer versions of Magento (unless you buy extension).
mysql> select status from sales_flat_order group by status;
+-----------------+
| status |
+-----------------+
| canceled |
| closed |
| complete |
| pending |
| pending_payment |
| processing |
+-----------------+
6 rows in set (0.00 sec)
mysql> select state from sales_flat_order group by state;
+-----------------+
| state |
+-----------------+
| canceled |
| closed |
| complete |
| new |
| pending_payment |
| processing |
+-----------------+
6 rows in set (1.03 sec)
To help myself understand table structure, I wrote a php script to make a CSV of all the tables with fields. So you could get the first bit with SELECT entity_id, state, status, created_at, increment_id FROM sales_flat_order WHERE status="pending"
. I looked and didn't see "cod_fee" in any of the fieldnames present in my 1.4.2 installation. Note the format of the output of the above query:
SELECT entity_id, state, status, created_at, increment_id FROM sales_flat_order WHERE status="pending";
+-----------+------------+---------+---------------------+--------------+
| entity_id | state | status | created_at | increment_id |
+-----------+------------+---------+---------------------+--------------+
| 2493 | new | pending | 2011-09-14 18:09:47 | 200025332 |
| 2683 | complete | pending | 2011-10-04 17:19:07 | 200025523 |
| 2686 | new | pending | 2011-10-04 20:43:52 | 200025526 |
| 3022 | processing | pending | 2011-11-15 01:11:34 | 200025849 |
| 3428 | complete | pending | 2012-01-12 17:56:57 | 200026236 |
| 4493 | processing | pending | 2012-04-11 16:16:55 | 200027230 |
| 5071 | new | pending | 2012-05-21 18:05:43 | 200027759 |
| 5091 | new | pending | 2012-05-22 17:48:11 | 200027779 |
...
| 5399 | new | pending | 2012-06-14 17:46:46 | 200028069 |
| 5443 | new | pending | 2012-06-18 18:50:55 | 200028111 |
| 5486 | new | pending | 2012-06-20 21:18:24 | 200028152 |
| 5491 | new | pending | 2012-06-20 23:54:53 | 200028157 |
+-----------+------------+---------+---------------------+--------------+
23 rows in set (0.79 sec)
来源:https://stackoverflow.com/questions/11079915/how-to-change-the-order-state-programmatically-inside-a-cron-job