-
Notifications
You must be signed in to change notification settings - Fork 116
[Order Details] Allow failed orders to show receipt if eligible #15558
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Order Details] Allow failed orders to show receipt if eligible #15558
Conversation
Right now receipt eligibility relies on datePaid not being nil, but this is unreliable: - failed purchases won’t have a datePaid value - successful purchases that have switched to a different order status will keep having the datePaid value.
|
We no longer need to check if supported for dev versions
The async-await version seems to be thread-unreliable with the Order Details logic: p1745897000519949-slack-CGPNUU63E
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for starting the discussion yesterday, I didn't fully understand the issue until I reviewed the PR. While the closure based approach works, I think we can address the root cause in order details regarding the async receipt eligibility check. I'd also suggest adding a new function in the receipt eligibility use case to check for receipt eligibility given an order status for easier unit testing and simpler call from order details.
WooCommerce/Classes/ViewModels/Order Details/OrderDetailsDataSource.swift
Outdated
Show resolved
Hide resolved
WooCommerce/Classes/ViewModels/Order Details/OrderDetailsDataSource.swift
Outdated
Show resolved
Hide resolved
WooCommerce/Classes/ViewModels/Order Details/OrderDetailsDataSource.swift
Outdated
Show resolved
Hide resolved
WooCommerce/Classes/ViewModels/Order Details/Receipts/ReceiptEligibilityUseCase.swift
Outdated
Show resolved
Hide resolved
Version |
…n-receipt # Conflicts: # WooCommerce/Classes/ViewModels/Order Details/OrderDetailsDataSource.swift
Hi @iamgabrielma, lemme know if the PR is ready for review and I'll get to it tomorrow the latest! |
Thanks! While testing it after the latest changes to async rows, we seem to have introduced a bug in the Should be fine to remove this guard now that we rely on specific order status when checking the order requirements, but I'll test this today before trying to wrap up this PR 👍 |
This is ready for review @jaclync , this is simplified from the first approach:
I'm not sure why the diff for
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Works as expected, thanks for the updates it's much easier to review now! Mostly a question about support for dev/beta versions.
@@ -5,6 +5,7 @@ protocol ReceiptEligibilityUseCaseProtocol { | |||
func isEligibleForBackendReceipts(onCompletion: @escaping (Bool) -> Void) | |||
func isEligibleForSuccessfulPaymentEmailReceipts(onCompletion: @escaping (Bool) -> Void) | |||
func isEligibleForFailedPaymentEmailReceipts(paymentGatewayID: String, onCompletion: @escaping (Bool) -> Void) | |||
func meetsOrderStatusRequirement(_ orderStatus: OrderStatusEnum, onCompletion: @escaping (Bool) -> Void) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: how about keeping a consistent name isEligibleForReceipts(_ orderStatus: OrderStatusEnum, onCompletion: @escaping (Bool) -> Void)
? When I saw the function name without the implementation, I thought this function just checks for if the order status meets the requirement.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: how about making this new function async/await friendly? It'd simplify the use case in OrderDetailsDataSource
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree: 9eb0773
I'll leave the closure based for now, so I don't have to redo the tests 👍
// Checking for concrete versions to cover dev and beta versions | ||
if plugin.version.contains(minimumVersion) { | ||
return continuation.resume(returning: true) | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
❓ What are the reasons for removing the check that supports dev and beta versions?
Saw this mentioned in the PR description:
Removed the logic to handle dev woocommerce versions
When testing with Woo Beta Tester plugin or for core development, I thought it's common to have the WC version as the dev/beta versions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, this was very specific to this project: The internals of VersionHelpers
used in the same function already checks for beta and dev version that might come with Woo Beta Tester, so it will pass the check as expected. This additional check was put in place just for testing, due to how the changes were provided by core folks with specific development branches to be installed in the test site, which sometimes were behind the latest versions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm actually having a similar plugin version check in a separate PR and removing this check blocks -beta/-dev/-alpha/-rc
. From the test cases for the VersionHelpers, this blocking behavior also seems intentional:
woocommerce-ios/WooCommerce/WooCommerceTests/Extensions/VersionHelpersTests.swift
Lines 34 to 40 in d6d6c56
VersionTestCase(foundVersion: "1.0.0-dev", requiredMinimumVersion: "1.0.0", meetsMinimum: false), | |
VersionTestCase(foundVersion: "1.0.0-alpha", requiredMinimumVersion: "1.0.0", meetsMinimum: false), | |
VersionTestCase(foundVersion: "1.0.0-a", requiredMinimumVersion: "1.0.0", meetsMinimum: false), | |
VersionTestCase(foundVersion: "1.0.0-beta", requiredMinimumVersion: "1.0.0", meetsMinimum: false), | |
VersionTestCase(foundVersion: "1.0.0-b", requiredMinimumVersion: "1.0.0", meetsMinimum: false), | |
VersionTestCase(foundVersion: "1.0.0-RC1", requiredMinimumVersion: "1.0.0", meetsMinimum: false), | |
VersionTestCase(foundVersion: "1.0.0-rc1", requiredMinimumVersion: "1.0.0", meetsMinimum: false), |
If we want to support alpha/beta/dev/rc builds of the same version, I think we do need to keep this check.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we want to support alpha/beta/dev/rc builds of the same version
Interesting, I see what you mean: Anything tagged as -dev or other for the same version we're checking, is always below the non-tagged version:
po VersionHelpers.isVersionSupported(version: "9.0-dev", minimumRequired: "9.0.0")
false
po VersionHelpers.isVersionSupported(version: "9.0.1-dev", minimumRequired: "9.0.0")
true
} | ||
|
||
private extension ReceiptEligibilityUseCase { | ||
func isPluginSupported(_ pluginName: String, minimumVersion: String, onCompletion: @escaping (Bool) -> Void) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: is this still used?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is not! d2fda6c
@@ -32,11 +31,11 @@ final class ReceiptEligibilityUseCaseTests: XCTestCase { | |||
XCTAssertFalse(isEligible) | |||
} | |||
|
|||
func test_when_WooCommerce_version_is_correct_dev_version_then_returns_true() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we do decide not to support WC dev version, it might be worth keeping the test and flipping the assertion.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as above, the dev/beta versions that follow the actual core deployment process are already covered by the version helper class. This was a very specific case on how the feature was delivered by core (eg: feature released publicly on 9.7 last minute, but we had to work with 9.6 internally) so we added the tests as well. Now are no longer necessary as it's part of the correct core version.
XCTAssertFalse(isEligible) | ||
} | ||
|
||
func test_meetsOrderStatusRequirement_with_completed_status_returns_true() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: would be nice keeping the Given/When/Then comments for consistency and clearer structure of the test case. Same for other meetsOrderStatusRequirement
test cases as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
True that! fcbbcb0
stores.whenReceivingAction(ofType: SystemStatusAction.self) { action in | ||
switch action { | ||
case let .fetchSystemPlugin(_, _, onCompletion): | ||
onCompletion(plugin) | ||
default: | ||
XCTFail("Unexpected action") | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: this could be extracted to private helper function for reuse.
XCTAssertTrue(isEligible) | ||
} | ||
|
||
func test_isEligibleForFailedPaymentEmailReceipts_when_woopayments_version_is_incorrect_then_returns_false() { | ||
// Given | ||
func test_meetsOrderStatusRequirement_with_processing_status_returns_true() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: might be worth mentioning the condition when it's true (otherwise it could sound like processing status always meets the requirement) - from my understanding, it's when the WC version is above a minimum version. Same for the refunded status test case.
} | ||
case .failed: | ||
selectedPaymentGatewayID { [weak self] gatewayID in | ||
guard let gatewayID = gatewayID else { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
super nit:
guard let gatewayID = gatewayID else { | |
guard let gatewayID else { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
2b185a6 🚀
Closes: #14863
Closes: WOOMOB-104
Description
This PR updates the logic around rendering "See Receipt" in Order Details to take into account that now failed orders can also contain receipts. Before this, we only shows receipts for orders with
datePaid != nil
, but this is unreliable.Screen.Recording.2025-04-28.at.13.37.39.mov
Changes
isOrderStatusEligibleForReceipt
by checking specific order statuses, rather than rely ondatePaid
.failed
receipts if the site is eligible for sending them.isEligibleForFailedPaymentEmailReceipts to
not use async await. The mix between this bit and the rest of the closure-based logic in Order Details seems to produce inconsistent results. Ref: p1745894442252789-slack-CGPNUU63ETesting information
RELEASE-NOTES.txt
if necessary.Reviewer (or Author, in the case of optional code reviews):
Please make sure these conditions are met before approving the PR, or request changes if the PR needs improvement: