Skip to content

Conversation

@iamgabrielma
Copy link
Contributor

@iamgabrielma iamgabrielma commented Apr 21, 2025

Closes: WOOMOB-246

This PR intercepts mapping coupons to POSItems, and filters out those that are expired (if any), so are not shown in POS while still working normally for the rest of the app:

POS App
Simulator Screenshot - iPad mini (A17 Pro) - US store - 2025-04-21 at 11 40 27 Simulator Screenshot - iPad mini (A17 Pro) - US store - 2025-04-21 at 11 40 19

Caveat: The coupon properties seem to be a bit miss leading: By the API documentation I'd expected we'd have two properties:

date_expires: The date the coupon expires, in the site's timezone.
date_expires_gmt: The date the coupon expires, as GMT (UTC).

However we only use date_expires in the app, which is received as UTC anyway from the site. ie: my testing site is in UTC+7, but the coupon expiration date assigned on creation is still in UTC:

dateExpires    Foundation.Date?    2025-04-14 00:00:00 UTC 

Testing information

  • Create a coupon, and set it expiration date to the past, publish it.
  • Navigate to Menu > Coupons > Observe how the coupon appears normally in the app as expired
  • Now in POS, observe how the coupon does not appear in the Coupon list.

  • I have considered if this change warrants user-facing release notes and have added them to 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:

  • The PR is small and has a clear, single focus, or a valid explanation is provided in the description. If needed, please request to split it into smaller PRs.
  • Ensure Adequate Unit Test Coverage: The changes are reasonably covered by unit tests or an explanation is provided in the PR description.
  • Manual Testing: The author listed all the tests they ran, including smoke tests when needed (e.g., for refactorings). The reviewer confirmed that the PR works as expected on all devices (phone/tablet) and no regressions are added.

@iamgabrielma iamgabrielma added type: task An internally driven task. feature: coupons Related to basic fulfillment such as order tracking. feature: POS labels Apr 21, 2025
@iamgabrielma iamgabrielma added this to the 22.3 milestone Apr 21, 2025
@wpmobilebot
Copy link
Collaborator

wpmobilebot commented Apr 21, 2025

App Icon📲 You can test the changes from this Pull Request in WooCommerce iOS Prototype by scanning the QR code below to install the corresponding build.

App NameWooCommerce iOS Prototype
Build Number29398
VersionPR #15527
Bundle IDcom.automattic.alpha.woocommerce
Commitc310bfe
Installation URL1tie1lekjnau8
Automatticians: You can use our internal self-serve MC tool to give yourself access to those builds if needed.

@iamgabrielma iamgabrielma marked this pull request as ready for review April 21, 2025 05:08
@iamgabrielma iamgabrielma requested a review from staskus April 21, 2025 05:08
@staskus
Copy link
Contributor

staskus commented Apr 21, 2025

However we only use date_expires in the app, which is received as UTC anyway from the site. ie: my testing site is in UTC+7, but the coupon expiration date assigned on creation is still in UTC:

This PR might explain it a bit #6686, but either way it looks like it _gmt is either not working properly or wasn't working properly. 🤔

@iamgabrielma could you check if there's a bug reported on WooCommerce? Worth creating it if it's not yet there.

@staskus staskus requested a review from Copilot April 21, 2025 12:12
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR updates the POS coupon mapping logic to filter out expired coupons so that the POS only shows valid coupons while leaving the rest of the app behavior unchanged.

  • Added filtering logic in the coupon-to-POS mapping function
  • Introduced a dedicated unit test to verify that expired coupons are excluded from the POS list

Reviewed Changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
Yosemite/YosemiteTests/PointOfSale/PointOfSaleCouponServiceTests.swift Added unit tests to check that expired coupons are filtered out
Yosemite/Yosemite/PointOfSale/PointOfSaleCouponService.swift Updated mapping function to filter expired coupons before mapping

Copy link
Contributor

@staskus staskus left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 Thanks for the work.

I tried to look for issues in tests and implementation with timezones but I think it should be alright.

Are there are any concerns you have, e.g. pagination?

Comment on lines +130 to +139
let now = Date()
let nonExpiredCoupons = coupons.filter { coupon in
guard let expirationDate = coupon.dateExpires else { return true }
return expirationDate >= now
}

return nonExpiredCoupons.compactMap { coupon in
.coupon(POSCoupon(id: UUID(),
code: coupon.code,
summary: coupon.summary(currencySettings: currencySettings)))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit; you can chain .filter { } .compact { } functional programming way

Suggested change
let now = Date()
let nonExpiredCoupons = coupons.filter { coupon in
guard let expirationDate = coupon.dateExpires else { return true }
return expirationDate >= now
}
return nonExpiredCoupons.compactMap { coupon in
.coupon(POSCoupon(id: UUID(),
code: coupon.code,
summary: coupon.summary(currencySettings: currencySettings)))
return coupons
.filter {
guard let expirationDate = $0.dateExpires else { return true }
return expirationDate >= Date()
}
.compactMap {
.coupon(
POSCoupon(
id: UUID(),
code: $0.code,
summary: $0.summary(currencySettings: currencySettings)
)
)
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TIL! I'll leave it with the existing implementation for now just because I feel it's more explicit, which makes it easier to read.

@iamgabrielma
Copy link
Contributor Author

Are there are any concerns you have, e.g. pagination?

I think we could see edge cases where pagination is not triggered correctly if we have a merchant with a bunch of coupons expired on the first fetch (~10+), and nothing else saved locally, since the infiniteScrollTriggerDeterminer merely checks the scroll position. The same could happen for subsequent pages if they happen to have a full page or results where all coupons are expired.

I don't think we should optimize for it right now, but perhaps makes a stronger case to go with "let's render expired coupons as well, rather than hide them".

@iamgabrielma iamgabrielma merged commit 42dbc46 into trunk Apr 22, 2025
16 checks passed
@iamgabrielma iamgabrielma deleted the task/woomob-246-hide-expired-coupons branch April 22, 2025 02:07
@staskus
Copy link
Contributor

staskus commented Apr 22, 2025

I think we could see edge cases where pagination is not triggered correctly if we have a merchant with a bunch of coupons expired on the first fetch (~10+), and nothing else saved locally, since the infiniteScrollTriggerDeterminer merely checks the scroll position. The same could happen for subsequent pages if they happen to have a full page or results where all coupons are expired.

@iamgabrielma got it. I don't like these edge cases. I'll bring up the question to the team.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature: coupons Related to basic fulfillment such as order tracking. feature: POS type: task An internally driven task.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants