repeatability of the problem - whether it is easy to repeat or happens randomly
Always happens on first transaction of an order.
steps to repeat - what you think caused the problem, ideally these steps should be repeated until they are as simple as possible and still cause the problem
* Install Drupal kickstart.
* Install and enabled commerce_authnet (i don't believe processor matters).
* Install my module posted in comment #16 which adds logging.
* Purchase an item from the homepage.
* Check watchdog to see if any logging was entered from pe_commerce module.
You'll notice that hook_commerce_payment_order_paid_in_full() was never called.
desired outcome of the steps - that is, what you WANT to have happen
I want hook_commerce_payment_order_paid_in_full() to get called.
actual outcome of your steps - this is the essence of your problem
I believe the transaction is getting entered into `commerce_payment_transaction_revision` table with a revision_id of 0 initially, then once commerce_payment_transaction_save() is finished, it's updated with a proper revision number.
Because of this, the query in commerce_payment_transaction_load_multiple() is not able to get the valid transaction and returns NULL or an empty array.
If this is a big problem, I would like to see a temporary fix from #18 to get applied to -dev.
Originally posted by @skov
In mymodule.module:
function mymodule_commerce_payment_order_paid_in_full($transaction) {
drupal_set_message(t('Paid in full'));
}Does not display "Paid in full" message after completing a payment. Does this hook only apply to Rules?
| Comment | File | Size | Author |
|---|---|---|---|
| #27 | 1212482.patch | 1.65 KB | damien tournoud |
| #26 | commerce_payment_fix.patch | 2.04 KB | dippers |
| #18 | commerce_payment-paid_in_full-1212482.patch | 832 bytes | j0rd |
| #16 | pe_commerce.tgz | 3.95 KB | j0rd |
Comments
Comment #1
skov commentedRelated to #1038846: Provide a way to track totals of things (like payments) and filter Views by them
Comment #2
skov commentedIt appears payment transactions using both the "commerce_payment_example.module" and "commerce_paypal.module" create a payment transaction in the following order:
However, rules_invoke_all('commerce_payment_order_paid_in_full', ...) hook resides within commerce_order_commerce_payment_transaction_insert(...) which is not called in the above save function.
Perhaps the save function should also run the commerce_payment_order_paid_in_full hook?
Comment #3
rszrama commentedActually, we are invoking this event with rules_invoke_all('commerce_payment_order_paid_in_full', ...), so the corresponding hook should be getting invoked. After adding your hook implementation did you clear your cache? Drupal 7 keeps a registry of hook implementations, so you have to clear the cache after adding an implementation to a module to ensure it gets rebuilt.
Comment #4
skov commentedYes, I cleared the cache. I can only get the (module and rules) hook to fire if I apply a second payment to an order.
Comment #5
rszrama commentedCurious... to debug you might add
drupal_set_message('<pre>'. print_r($balance, TRUE) .'</pre>');to line 355 of commerce_payment.module. Perhaps there's some floating point math error preventing it from recognizing the order is paid in full.Comment #6
skov commentedInstalled fresh commerce kickstart with d7.4 and latest dev commerce, rules, views, entity, addressfield.
As suggested in #5, added message to line 355 of commerce_payment.module. I created a new order, completed checkout, and paid using "example payment" module. There is no (dsm) message displayed. i.e. line 355 is never run.
However, when I go to the order payments, and add second payment (even a $0 payment), the (dsm) message then shows:
So, line 355 is run after adding second payment. Adding a third payment (or more) does not trigger line 355, as
$order->data['commerce_payment_order_paid_in_full_invoked'] is now TRUE.
I also created the rule:
This rules also only fires on second payment using payment_ui, showing "Paid in Full" along with the balance array from line 355.
Comment #7
j0rd commentedSame issue. Gonna do some debugging.
Comment #8
j0rd commentedI can't find anywhere commerce_order_commerce_payment_transaction_update() is called. Which in turn calls commerce_order_commerce_payment_transaction_insert(), which in turn calls hook_commerce_payment_order_paid_in_full().
At least in the Drupal Commerce code base. Nor in commerce_paypal or commerce_authnet.
Are these contrib modules too old and need to be updated to use these new hooks or something?
Comment #9
j0rd commentedcommerce_checkout_form_submit() does all sorts of things with clearing + restoring messages (aka dpm(), drupal_set_message()) may not be displaying as expected and should not be relied on. watchdog may be the best place to do debugging here.
Comment #10
j0rd commentedBalance for what ever reason is not 0. it's set to the full amount.
Here's my debug from watchdog.
Comment #11
j0rd commentedOk, I've taken this as far as I can go.
The problem is in the workflow,
function commerce_payment_order_balance($order, $totals = array()) is not able to get at the most recent transaction. I believe this is because the revision is not yet in the database.
On the other hand, the primary entry is in database (commerce_payment_transaction), just not the revision table (commerce_payment_transaction_revision) for what ever reason.
This is returning 0 results.
$transactions = commerce_payment_transaction_load_multiple(array(), array('order_id' => $order->order_id));Even is you pass $reset = TRUE into load_multiple.
I know the original entry is in the database because I've added this debugging statement:
I've added this to debug in includes/entity.inc around line 196
To confirm the transaction is entered correctly after it's all said and done, I've copied the query outputted from includes/entity.inc and put it in here
Here's the workflow from my logs:
This means that commerce_order_commerce_payment_transaction_update() & commerce_order_commerce_payment_transaction_insert() are called before commerce_payment_transaction_save() exits.
I believe after commerce_payment_transaction_save() exists, the revision is entered, but not before. Here lies the issue.
I have no idea how to fix.
There's also a bug in this work flow which eats all the DPM()'s . I believe this bug should also be resolved, as it hurts the ease of debugging this critical part of the code.
Comment #12
rfaySubscribe
Comment #13
j0rd commentedSince many people will require this functionality for triggering functionality once sales are finished, I consider it a release blocker, so I'm moving this to critical.
Comment #14
j0rd commentedI can confirm this bug on a default install of commerce kickstart when testing a transaction with commerce_authnet.
Comment #15
rfayThanks for the research.
We need a more complete description of the bug. Can you please give a complete synopsis?
From http://drupal.org/node/73179:
Probably updating the issue summary (the node body) would be a great place for this.
Comment #16
j0rd commentedHere's a debug module you can enable into your vanilla Drupal Commerce install debug the bug.
It logs two hooks into watchdog under the 'debug' type.
These are the hooks:
Keep in mind, in order for Paid in Full to be called $balance1 has to be equal or less than Zero. Currently it's not applying the amount of the transaction against the balance of the order for reasons I've mentioned previously.
$balance2 is some logic I've added to show that we can in fact get this working with proper use of function calls.
I'm going to hack my own core to get this to move forward for the site I'm working on, but this needs to get resolved.
Comment #17
j0rd commentedGetting another error now after a failed transaction (which was failed by bad code).
Now while I realize this error is caused by a different issue, I believe this is the cause of the problem.
When the transaction is saved into commerce_payment_transaction it initially has a revision_id of 0. Then after the commerce_payment_transaction_save() is finished, a revision is created & the entry in commerce_payment_transaction revision_id is updated.
This error is coming about because of a compilation error in pe_commerce_commerce_payment_transaction_insert() which is called before commerce_payment_transaction_save() is finished. Since pe_commerce_commerce_payment_transaction_insert() die()'d and commerce_payment_transaction_save() was never completed, the revision ID was never updated. Then when I tried to do another transaction, it tried to store it into commerce_payment_transaction table, but because there's already an entry with revision_id = 0, it fails.
Comment #18
j0rd commentedHere's a patch. I consider this a temporary solution as it doesn't solve the root issue.
Comment #19
rfayStill requesting #15.
Comment #20
drupal_was_my_past commentedsub
Comment #21
j0rd commentedI updated the description rfay with additional info. Re-activating this bug.
Comment #22
rfayThanks so much! Setting to CNR (#18) although j0rd says that is probably not the real fix.
Comment #23
tim_dj-- too quick --
Comment #24
dippers commentedI have a similar problem with the condition 'Order balance comparison' attached to the event 'After saving a new commerce payment transaction' in a rule. The current payment transaction is not included in the balance comparison.
The problem seems to be caused by the database transaction processing. The rules processing is invoked after drupal_write_record has been called in DrupalCommerceEntitytController::save but drupal_write_record DOES NOT write data to disc it justs adds the record to the database transaction object. The payment transaction data is not committed to disc until the DatabaseTransaction is destroyed (and __destruct() called) when commerce_payment_transaction_save exits.
This seems to be a general problem to ensure the commerce data is committed to disc before rules processing is invoked.
Comment #25
dippers commentedI think #24 might have been a slight diversion. I changed my MySQL tables for commerce_payment_transaction and commerce_payment_transaction_revision from InnoDB to MyISAM since MyISAM does not support database transactions. This did not fix the problem although the data was now on disk before the rules and hooks handling was invoked.
The problem is now that the revision_id for the base table is not updated until after the rules and hooks have been run. This is still in DrupalCommerceEntitytController::save. The code
which sets the revision id needs to be run before invoke. If the lines
are replaced with the above the rules and hooks work.
This is a change to a core commerce class so I'm not sure if it will get committed just to solve this particular problem but I cannot see any other way around it.
In summary two changes are required:
1. Make sure your commerce database tables are MyISAM
2. Move the revision id update in the base table to before the rules and hooks are invoked
Comment #26
dippers commentedPatch for #25.
Comment #27
damien tournoud commentedI agree we should run the hooks after the full update has been performed. That's actually a bug in my initial revision support patch :)
Better patch attached, please don't credit me.
Comment #28
rszrama commentedCommitted Damien's patch for this. Tests worked fine. On a side note, some of the monkeying we're doing for messages in the checkout form are the reason you don't ever see messages displayed. I tested by using watchdog() in a custom PHP action.
Comment #29
dippers commentedDamien, given InnoDB is the default mySQL engine for D7 this functionality is still 'broken' without changing the table to MyISAM. Is there a plan to handle this?
Comment #30
rszrama commentedIt sounds like that's unrelated. I didn't do any database adjustments and it worked just fine in my testing w/ InnoDB tables. As such I don't think there's anything more to do here. With the latest patch on InnoDB can you provide me with a set of steps to reproduce an error? If so, it might be a separate issue.
Also, I should've added that I'll be addressing the missing messages in a follow-up issue.
Comment #32
farhadhf commentedI have this problem too, hook_commerce_payment_order_paid_in_full does not get called, applied patch in #18, but it still doesn't work.
commerce kickstart profile - commerce 1.1
Comment #33
dippers commentedI've just updated a site to commerce 7.x-1.2 and this problem has re-emerged! It seems when a transaction is saved the order_balance calculation retrieves out of date transaction status information when calculating how much has been paid.
Looking at the code there has been a new section added after the previous patch in commerce.controller.inc:
I am concerned that the cache is set AFTER the hooks are invoked and therefore any transaction reloads carried out in the hooks (as is done in commerce_payment_order_balance) get old entity cache data rather than the new entity.
This seems to be a new level of caching which I don't fully undertand yet but could it be a possible cause of hook_commerce_payment_order_paid_in_full() not firing?
Comment #34
dippers commentedComment #35
helior commentedYup. This was actually fixed in #1427780: hook_commerce_payment_order_paid_in_full() does NOT fire due to DrupalCommerceEntityController::save bug and will be released in Commerce 7.x-1.3
Comment #36
_redfog commentedI had an issue with "hook_commerce_payment_order_paid_in_full" that sometimes hasn't been called.
I think it's since we've updated rules module.
I've just updated to Commerce from 7.x-1.2 to 7.x-1.3, and it rocks !
Thanks a lot !!
ps: just for information, no long ago, we've updated Drupal core too (from 7.12 to 7.14)
Comment #37
rszrama commentedGlad to hear it.
Comment #37.0
rszrama commentedUpdated description as per rfay request.