Reputation: 77
I've noticed the strange behaviour of Shopware with actual (last) payment method order which user chose and made payment using this method. So maybe someone can explain to me how is it working because now I have a lot of bugs and bottlenecks with my integration plugins (ERP, affiliates services). So let's start (our goal receive last=actual payment method which a customer chose in last time):
order
. There are order with id 0d624ffae665466db51f12eba0c1bc53
. Can I get information about last and actual payment method from here? I guess no because I didn't find it. Ok we go to the next step.order_transaction
. Hooray! Here I find all payment methods which the customer used when he/she try to pay the order. Ok what we have hereid order_id | created_at | updated_at
83042D493DC04A4290BE8D7F523DE32F 0D624FFAE665466DB51F12EBA0C1BC53 | 2022-08-25 09:04:38.474 | 2022-09-24 11:11:19.664
911DF5D15BC542E598C2F11AECDAFD61 0D624FFAE665466DB51F12EBA0C1BC53 | 2022-08-25 09:06:27.775 | NULL
Ok! According to my logic last created payment method in the table is method which user choose last aka actual. So here we are we find actual(last) payment method which user chose and made transaction with this order and it's 911DF5D15BC542E598C2F11AECDAFD61
(because it was created on 2 minutes later than 83042D493DC04A4290BE8D7F523DE32F
.
Now my ERP system or I want to change payment status because it was postpaid. The client paid it and now we ready to change status from Open to Paid. Ok I've done it and let's see what happened it Database. Our journey move to new table which has name state_machine_history
. Ok let's try to find our order using LAST transaction id 911DF5D15BC542E598C2F11AECDAFD61
and here we are.
Unfortunately we did find nothing. Ok, cheer up! Let's try use another payment method 83042D493DC04A4290BE8D7F523DE32F
.
And yes we find 7 rows (see screenshots)
So what we have payment status was changed on wrong payment method but should be changed on the last method! Now I have a lot problem because my plugin can't get right payment status for oder. Maybe I don't understand how it should works? it would be nice if someone explain me this point. My goal: my plugin should get right payment status and right payment method. Now I receive wrong status when use smth like that what was mentioned here
$criteria
->addFilter(
new EqualsFilter(
'orderNumber',
$orderNumber)
)
->addAssociation('stateMachineState')
->getAssociation('transactions')
->addSorting(new FieldSorting('createdAt'));
$order = $this->orderRepository->search($criteria, $context)->first();
UPDATE: I've changed payment status manually via admin panel (http://url.com/admin)
Upvotes: 2
Views: 648
Reputation: 77
Problem was connected with ERP integration (Xentral shop module) which pick up an order with wrong payment method and then changing payment status in the wrong payment method.
Thanks @dneustad. You and your comment help me fix it (only fix consequences in Shopware). What was done:
// module/sw-order/view/sw-order-detail-details/index.js
transaction() {
for (let i = 0; i < this.order.transactions.length; i += 1) {
if (!['cancelled', 'failed'].includes(this.order.transactions[i].stateMachineState.technicalName)) {
return this.order.transactions[i];
}
}
return this.order.transactions.last();
}
Upvotes: 0
Reputation: 13161
You're omitting the second argument when you instantiate FieldSorting
. The second argument is the direction to sort in and by default it is ascending. So you're actually currently slicing off the entry with the oldest creation date instead. You should sort in a descending direction:
new FieldSorting('createdAt', FieldSorting::DESCENDING)
Either do that or just get the last entry from the collection instead:
$transaction = $order->getTransactions()->last();
Another thing you mentioned that seemingly the wrong state was changed when you changed the transaction state in the administration.
This is the computed property that returns the transaction that is used for the transition:
// module/sw-order/view/sw-order-detail-details/index.js
transaction() {
for (let i = 0; i < this.order.transactions.length; i += 1) {
if (!['cancelled', 'failed'].includes(this.order.transactions[i].stateMachineState.technicalName)) {
return this.order.transactions[i];
}
}
return this.order.transactions.last();
}
Notice that the first transaction is returned that doesn't have the states cancelled
or failed
, unless it is the only transaction. Because that is really the only case where there should be more than one entry in order_transaction
for a single order. That is when the payment of a customer fails or is cancelled and they decide to use a different payment method. That's when you end up with two transactions for two different payment methods but one of these should always have the state cancelled
or failed
. If you end up with multiple transactions and this is not the case, then there's something wrong.
Upvotes: 3